Merge PR 1493 [TRAFODION-2821] Trafodion core code base needs to be thread safe 
diff --git a/core/sql/exp/exp_function.cpp b/core/sql/exp/exp_function.cpp
index a65c120..8d9426f 100644
--- a/core/sql/exp/exp_function.cpp
+++ b/core/sql/exp/exp_function.cpp
@@ -2550,7 +2550,7 @@
       break;
       
     case REC_BIN32_SIGNED:
-      *(Lng32 *)sec = labs(*(Lng32 *)op_data[1]);
+      sec = *(Lng32 *)op_data[1];
       if(sec < 0 )
       {
         ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
diff --git a/core/sql/optimizer/Inlining.cpp b/core/sql/optimizer/Inlining.cpp
index f8d7b66..e93e33b 100644
--- a/core/sql/optimizer/Inlining.cpp
+++ b/core/sql/optimizer/Inlining.cpp
@@ -1888,7 +1888,7 @@
 			     NABoolean isIMInsert,
 			     NABoolean useInternalSyskey,
                              NABoolean isForUpdateOrMergeUpdate,
-                             NABoolean isForMerge, // mergeDelete OR mergeUpdate
+                             NABoolean mergeDeleteWithInsertOrMergeUpdate,
 			     NABoolean isEffUpsert)
 {
    
@@ -1906,7 +1906,8 @@
   // that correspond to the base table. Hence we introduce 
   // robustDelete below. This flag could also be called 
   // isIMOnAUniqueIndexForMerge
-  NABoolean robustDelete = (isForMerge && index->isUniqueIndex()) || (isEffUpsert && index->isUniqueIndex());
+  NABoolean robustDelete = (mergeDeleteWithInsertOrMergeUpdate && index->isUniqueIndex()) || 
+                           (isEffUpsert && index->isUniqueIndex());
 
   tableCorrName.setCorrName(isIMInsert ?  NEWCorr : OLDCorr);
   
@@ -2127,8 +2128,15 @@
   if (getOperatorType() == REL_UNARY_DELETE ||
       getOperatorType() == REL_UNARY_UPDATE ||
       isEffUpsert)
-    
-    indexDelete = indexOp = createIMNode(bindWA,
+    {
+      NABoolean mergeDeleteWithInsertOrMergeUpdate = isMerge();
+      if (mergeDeleteWithInsertOrMergeUpdate && 
+          (getOperatorType() == REL_UNARY_DELETE) && 
+          (!insertValues()))
+        // merge delete without an insert
+        mergeDeleteWithInsertOrMergeUpdate = FALSE;
+      
+      indexDelete = indexOp = createIMNode(bindWA,
 					 tableCorrName,
                                          indexCorrName,
 					 index,
@@ -2136,8 +2144,9 @@
 					 FALSE,
     			       		 useInternalSyskey,
                                          isForUpdateOrMergeUpdate,
-                                         isMerge(),
+                                         mergeDeleteWithInsertOrMergeUpdate,
 					 isEffUpsert);
+    }
 
   if ((getOperatorType() == REL_UNARY_UPDATE) || isEffUpsert){
     indexOp = new (bindWA->wHeap()) Union(indexDelete, indexInsert, 
diff --git a/core/sql/sqlcomp/CmpSeabaseDDL.h b/core/sql/sqlcomp/CmpSeabaseDDL.h
index f1f9429..c6ff74b 100644
--- a/core/sql/sqlcomp/CmpSeabaseDDL.h
+++ b/core/sql/sqlcomp/CmpSeabaseDDL.h
@@ -129,10 +129,21 @@
 
 #include "CmpSeabaseDDLmd.h"
 
-// The value HBase uses for checking key length is HConstants.MAX_ROW_LENGTH.
-// The rowID length limit in HBase is enforced in HBase modules Put.java and
-// Mutation.java. (The above was true as of HBase 1.0.0.)
-#define MAX_HBASE_ROWKEY_LEN 32767
+// The define below gives the maximum rowID length that we will permit
+// for Trafodion tables and indexes. The actual HBase limit is more 
+// complicated: For Puts, HBase compares the key length to 
+// HConstants.MAX_ROW_LENGTH (= Short.MAX_VALUE = 32767). It raises an
+// exception if the key length is greater than that. But there are also
+// some internal data structures that HBase uses (the WAL perhaps?) that
+// are keyed. Experiments show that a Trafodion key of length n causes
+// a hang if n + strlen(Trafodion object name) + 16 > 32767. The HBase
+// log in these cases shows an IllegalArgumentException Row > 32767 in
+// this case. So it seems best to limit Trafodion key lengths to something
+// sufficiently smaller than 32767 so we don't hit these hangs. A value
+// of 32000 seems safe, since the longest Trafodion table name will be
+// TRAFODION.something.something, with each of the somethings topping out
+// at 256 bytes.
+#define MAX_HBASE_ROWKEY_LEN 32000
 
 #define SEABASEDDL_INTERNAL_ERROR(text)                                   \
    *CmpCommon::diags() << DgSqlCode(-CAT_INTERNAL_EXCEPTION_ERROR) 	  \
diff --git a/core/sql/sqlcomp/CmpSeabaseDDLindex.cpp b/core/sql/sqlcomp/CmpSeabaseDDLindex.cpp
index 030d76c..2e35ac0 100644
--- a/core/sql/sqlcomp/CmpSeabaseDDLindex.cpp
+++ b/core/sql/sqlcomp/CmpSeabaseDDLindex.cpp
@@ -239,14 +239,6 @@
      keyInfoArray[i].hbaseColQual = new(CTXTHEAP) char[strlen(qualNumStr)+1];
      strcpy((char*)keyInfoArray[i].hbaseColQual, qualNumStr);
     }
-
-  if (keyLength > MAX_HBASE_ROWKEY_LEN )
-    {
-      *CmpCommon::diags() << DgSqlCode(-CAT_ROWKEY_LEN_TOO_LARGE)
-                              << DgInt0(keyLength)
-                              << DgInt1(MAX_HBASE_ROWKEY_LEN);
-      return -1;
-    }
   
   if ((syskeyOnly) &&
       (hasSyskey))
@@ -396,6 +388,14 @@
       i++;
     }
 
+  if (keyLength > MAX_HBASE_ROWKEY_LEN )
+    {
+      *CmpCommon::diags() << DgSqlCode(-CAT_ROWKEY_LEN_TOO_LARGE)
+                              << DgInt0(keyLength)
+                              << DgInt1(MAX_HBASE_ROWKEY_LEN);
+      return -1;
+    }
+
   return 0;
 }
 
diff --git a/core/sql/ustat/hs_globals.cpp b/core/sql/ustat/hs_globals.cpp
index a437d97..7267862 100644
--- a/core/sql/ustat/hs_globals.cpp
+++ b/core/sql/ustat/hs_globals.cpp
@@ -5052,7 +5052,7 @@
           }
         else
           {
-            sprintf(sbuf, "%d", col.precision+2);
+            sprintf(sbuf, "%d,0", col.precision+2); // for seconds cast below
             typeName = getIntTypeForInterval(group, 60 * (Int64)pow(10, col.precision));
           }
         group->ISSelectExpn.append("cast(cast(")
@@ -5076,7 +5076,7 @@
           }
         else
           {
-            sprintf(sbuf, "%d", col.precision+4);
+            sprintf(sbuf, "%d,0", col.precision+4); // for seconds cast below
             typeName = getIntTypeForInterval(group, 60 * 60 * (Int64)pow(10, col.precision));
           }
         group->ISSelectExpn.append("cast(cast(")
@@ -5100,7 +5100,7 @@
           }
         else
           {
-            sprintf(sbuf, "%d", col.precision+5);
+            sprintf(sbuf, "%d,0", col.precision+5); // for seconds cast below
             typeName = getIntTypeForInterval(group, 24 * 60 * 60 * (Int64)pow(10, col.precision));
           }
         group->ISSelectExpn.append("cast(cast(")