You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafodion.apache.org by sa...@apache.org on 2017/01/04 23:06:43 UTC

[03/10] incubator-trafodion git commit: Changes to support new syntax and implementation empty_blob/empty_clob for insert/updates Changes to support new syntax for updating a lob directly through a lobhandle without scanning the table.This is done via

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/7baf325f/core/sql/optimizer/RelExeUtil.h
----------------------------------------------------------------------
diff --git a/core/sql/optimizer/RelExeUtil.h b/core/sql/optimizer/RelExeUtil.h
index dfaef7a..f786eeb 100644
--- a/core/sql/optimizer/RelExeUtil.h
+++ b/core/sql/optimizer/RelExeUtil.h
@@ -575,7 +575,8 @@ public:
     HBASE_UNLOAD_TASK_        = 36,
     ORC_FAST_AGGR_            = 37,
     GET_QID_                  = 38,
-    HIVE_TRUNCATE_            = 39
+    HIVE_TRUNCATE_            = 39,
+    LOB_UPDATE_UTIL_          = 40
   };
 
   ExeUtilExpr(ExeUtilType type,
@@ -2160,6 +2161,84 @@ public:
   NABoolean withCreate_;
 };
 
+
+class ExeUtilLobUpdate : public ExeUtilExpr
+{
+public:
+  enum UpdateFromType
+  {
+     FROM_BUFFER_, FROM_FILE_, FROM_STRING_,FROM_EXTERNAL_, NOOP_
+  };
+  enum UpdateActionType
+  {
+    ERROR_IF_EXISTS_=1, TRUNCATE_EXISTING_,APPEND_, REPLACE_ 
+  };
+  
+  
+ ExeUtilLobUpdate(ItemExpr * handle, 
+		   UpdateFromType fromType,
+		   Int64 bufaddr=0,
+		   Int64 updateSize=0,
+                  UpdateActionType updateAction=UpdateActionType::ERROR_IF_EXISTS_,
+		   RelExpr * childNode = NULL,
+		   CollHeap *oHeap = CmpCommon::statementHeap())
+   : ExeUtilExpr(LOB_UPDATE_UTIL_, CorrName("dummyUpdateLobName"),
+		 NULL, childNode, 
+		 NULL, CharInfo::UnknownCharSet, oHeap),
+    handle_(handle),
+    fromType_(fromType),
+    bufAddr_(bufaddr),
+     updateSize_(updateSize),
+     updateAction_(updateAction)
+   
+    {
+     
+    };
+
+  virtual Int32 getArity() const { return (child(0) ? 1 : 0); }
+  
+  virtual NABoolean isExeUtilQueryType() { return TRUE; }
+
+  //virtual NABoolean producesOutput() { return (toType_ == TO_STRING_ ? TRUE : FALSE); }
+  virtual NABoolean producesOutput() { return  TRUE ; }
+  virtual RelExpr * copyTopNode(RelExpr *derivedNode = NULL,
+				CollHeap* outHeap = 0);
+  
+  virtual RelExpr * bindNode(BindWA *bindWAPtr);
+
+  virtual void transformNode(NormWA & normWARef,
+			     ExprGroupId & locationOfPointerToMe);
+
+  virtual RelExpr * normalizeNode(NormWA & normWARef);
+
+  virtual void pushdownCoveredExpr(const ValueIdSet & outputExpr,
+				   const ValueIdSet & newExternalInputs,
+				   ValueIdSet & predicatesOnParent,
+				   const ValueIdSet * setOfValuesReqdByParent,
+				   Lng32 childIndex
+				   );
+  
+  virtual RelExpr * preCodeGen(Generator * generator,
+			       const ValueIdSet & externalInputs,
+			       ValueIdSet &pulledNewInputs);
+  
+  // method to do code generation
+  virtual short codeGen(Generator*);
+
+  
+
+  
+
+ private:
+  //  NAString handle_;
+  ItemExpr * handle_;
+  UpdateFromType fromType_;
+  Int32 updateAction_;
+  Int64 bufAddr_;
+  Int64 updateSize_;
+  
+  
+};
 class ExeUtilLobShowddl : public ExeUtilExpr
 {
 public:

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/7baf325f/core/sql/optimizer/SynthType.cpp
----------------------------------------------------------------------
diff --git a/core/sql/optimizer/SynthType.cpp b/core/sql/optimizer/SynthType.cpp
index 8c78d85..6be7689 100644
--- a/core/sql/optimizer/SynthType.cpp
+++ b/core/sql/optimizer/SynthType.cpp
@@ -6559,16 +6559,20 @@ const NAType *LOBoper::synthesizeType()
 const NAType *LOBinsert::synthesizeType()
 {
   // Return blob type
-
-  ValueId vid1 = child(0)->getValueId();
-  const NAType &typ1 = (NAType&)vid1.getType();
+  ValueId vid1;
+  const NAType *typ1 = NULL;
+  if (child(0))
+    {
+      vid1 = child(0)->getValueId();
+      typ1 = &vid1.getType();
+    }
 
   if ((obj_ == STRING_) ||
       (obj_ == FILE_) ||
       (obj_ == EXTERNAL_) ||
       (obj_ == LOAD_))
     {
-      if (typ1.getTypeQualifier() != NA_CHARACTER_TYPE)
+      if (typ1->getTypeQualifier() != NA_CHARACTER_TYPE)
 	{
 	  // 4221 The operand of a $0~String0 function must be character.
 	  *CmpCommon::diags() << DgSqlCode(-4221) << DgString0("LOBINSERT")
@@ -6578,7 +6582,7 @@ const NAType *LOBinsert::synthesizeType()
     }
   else if (obj_ == LOB_)
     {
-      if (typ1.getTypeQualifier() != NA_LOB_TYPE)
+      if (typ1->getTypeQualifier() != NA_LOB_TYPE)
 	{
 	  // 4043 The operand of a $0~String0 function must be blob
 	  *CmpCommon::diags() << DgSqlCode(-4221) << DgString0("LOBINSERT")
@@ -6588,7 +6592,7 @@ const NAType *LOBinsert::synthesizeType()
     }
   else if (obj_ == BUFFER_)
     {
-     if (typ1.getTypeQualifier() != NA_NUMERIC_TYPE)
+     if (typ1->getTypeQualifier() != NA_NUMERIC_TYPE)
 	{
 	  // 4043 The operand of a $0~String0 function must be blob
 	  *CmpCommon::diags() << DgSqlCode(-4221) << DgString0("LOBINSERT")
@@ -6596,6 +6600,9 @@ const NAType *LOBinsert::synthesizeType()
 	  return NULL;
 	} 
     }
+  else if(obj_ == EMPTY_LOB_)
+    {
+    }
   else 
     {
       // 4221 The operand of a $0~String0 function must be character.
@@ -6603,17 +6610,19 @@ const NAType *LOBinsert::synthesizeType()
 			  << DgString1("BLOB");
       return NULL;
     }
+  
+    
 
   NAType * result = NULL;
   if (lobFsType() == REC_BLOB)
     {
       result = new HEAP SQLBlob(lobSize(), Lob_Invalid_Storage,
-				typ1.supportsSQLnull());
+				(obj_ ==EMPTY_LOB_) ? FALSE:typ1->supportsSQLnull());
     }
   else if (lobFsType() == REC_CLOB)
     {
       result = new HEAP SQLClob(lobSize(), Lob_Invalid_Storage,
-				typ1.supportsSQLnull());
+				(obj_ == EMPTY_LOB_)? FALSE:typ1->supportsSQLnull());
     }
     
   return result;
@@ -6623,11 +6632,20 @@ const NAType *LOBupdate::synthesizeType()
 {
   // Return blob type
 
-  ValueId vid1 = child(0)->getValueId();
-  const NAType &typ1 = (NAType&)vid1.getType();
+  ValueId vid1,vid2 ;
+  const NAType *typ1,*typ2 = NULL;
 
-  ValueId vid2 = child(1)->getValueId();
-  const NAType &typ2 = (NAType&)vid2.getType();
+  if(child(0))
+    {
+      vid1= child(0)->getValueId();
+      typ1 = &vid1.getType();
+    }
+
+  if(child(1))
+    {
+      vid2 = child(1)->getValueId();
+      typ2 = &vid2.getType();
+    }
 
  
 
@@ -6635,7 +6653,7 @@ const NAType *LOBupdate::synthesizeType()
       (obj_ == FILE_) ||
       (obj_ == EXTERNAL_))
     {
-      if (typ1.getTypeQualifier() != NA_CHARACTER_TYPE)
+      if (typ1->getTypeQualifier() != NA_CHARACTER_TYPE)
 	{
 	  // 4221 The operand of a $0~String0 function must be character.
 	  *CmpCommon::diags() << DgSqlCode(-4221) << DgString0("LOBUPDATE")
@@ -6645,7 +6663,7 @@ const NAType *LOBupdate::synthesizeType()
     }
   else if (obj_ == LOB_)
     {
-      if (typ1.getTypeQualifier() != NA_LOB_TYPE)
+      if (typ1->getTypeQualifier() != NA_LOB_TYPE)
 	{
 	  // 4043 The operand of a $0~String0 function must be blob
 	  *CmpCommon::diags() << DgSqlCode(-4221) << DgString0("LOBUPDATE")
@@ -6655,7 +6673,7 @@ const NAType *LOBupdate::synthesizeType()
     }
   else if (obj_ == BUFFER_)
     {
-     if (typ1.getTypeQualifier() != NA_NUMERIC_TYPE)
+     if (typ1->getTypeQualifier() != NA_NUMERIC_TYPE)
 	{
 	  // 4043 The operand of a $0~String0 function must be blob
 	  *CmpCommon::diags() << DgSqlCode(-4221) << DgString0("LOBUPDATE")
@@ -6672,6 +6690,9 @@ const NAType *LOBupdate::synthesizeType()
 	  return NULL;
 	} 
     }
+  else if (obj_ == EMPTY_LOB_)
+    {
+    }
   else 
     {
       // 4221 The operand of a $0~String0 function must be character.
@@ -6681,18 +6702,18 @@ const NAType *LOBupdate::synthesizeType()
     }
 
   NAType * result = NULL;
-  if (typ2.getFSDatatype() == REC_BLOB)
+  if (typ2->getFSDatatype() == REC_BLOB)
     {
-      SQLBlob &blob = (SQLBlob&)typ2;
+      SQLBlob &blob = (SQLBlob&)*typ2;
       result = new HEAP SQLBlob(blob.getLobLength(), Lob_Invalid_Storage,
-				typ2.supportsSQLnull());
+				(obj_ ==EMPTY_LOB_) ? FALSE:typ2->supportsSQLnull());
     }
-  else if (typ2.getFSDatatype() == REC_CLOB)
+  else if (typ2->getFSDatatype() == REC_CLOB)
     {
-      SQLClob &clob = (SQLClob&)typ2;
+      SQLClob &clob = (SQLClob&)*typ2;
 
       result = new HEAP SQLClob(clob.getLobLength(), Lob_Invalid_Storage,
-				typ2.supportsSQLnull());
+				(obj_ ==EMPTY_LOB_) ? FALSE:typ2->supportsSQLnull());
     }
     
   return result;

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/7baf325f/core/sql/parser/ParKeyWords.cpp
----------------------------------------------------------------------
diff --git a/core/sql/parser/ParKeyWords.cpp b/core/sql/parser/ParKeyWords.cpp
index 0cb1aec..89173b5 100644
--- a/core/sql/parser/ParKeyWords.cpp
+++ b/core/sql/parser/ParKeyWords.cpp
@@ -596,11 +596,13 @@ ParKeyWord ParKeyWords::keyWords_[] = {
   ParKeyWord("LOAD",               TOK_LOAD,        NONRESTOKEN_|SECOND_),
   ParKeyWord("LOADTOLOB",          TOK_LOADTOLOB,   NONRESTOKEN_),
   ParKeyWord("LOAD_ID",            TOK_LOAD_ID,     NONRESTOKEN_),
-  ParKeyWord("LOB",                TOK_LOB,         NONRESTOKEN_),
+  ParKeyWord("LOB",                TOK_LOB,         NONRESTOKEN_|SECOND_),
   ParKeyWord("LOBLENGTH",          TOK_LOBLENGTH,   NONRESTOKEN_),
   ParKeyWord("LOBTOBUFFER",        TOK_LOBTOBUFFER, NONRESTOKEN_),
   ParKeyWord("LOBTOFILE",          TOK_LOBTOFILE, NONRESTOKEN_),
   ParKeyWord("LOBTOSTRING",        TOK_LOBTOSTRING, NONRESTOKEN_),
+  ParKeyWord("EMPTY_BLOB",         TOK_EMPTY_BLOB, NONRESTOKEN_),
+  ParKeyWord("EMPTY_CLOB",         TOK_EMPTY_CLOB, NONRESTOKEN_),
   ParKeyWord("LOCAL",              TOK_LOCAL,       ANS_|RESWORD_),
   ParKeyWord("LOCALTIME",          TOK_LOCALTIME,   COMPAQ_|RESWORD_),
   ParKeyWord("LOCALTIMESTAMP",     TOK_LOCALTIMESTAMP, COMPAQ_|RESWORD_),
@@ -1146,7 +1148,7 @@ ParKeyWord ParKeyWords::keyWords_[] = {
   ParKeyWord("UNPUBLISH",          TOK_UNPUBLISH,   NONRESTOKEN_),
   ParKeyWord("UNREGISTER",         TOK_UNREGISTER,  NONRESTOKEN_),
   ParKeyWord("UNSIGNED",           TOK_UNSIGNED,    NONRESTOKEN_),
-  ParKeyWord("UPDATE",             TOK_UPDATE,      ANS_|RESWORD_|MPWORD_),
+  ParKeyWord("UPDATE",             TOK_UPDATE,      FIRST_|ANS_|RESWORD_|MPWORD_),
   ParKeyWord("UPD",                TOK_UPD,         NONRESTOKEN_),
   ParKeyWord("UPDATE_STATS",       TOK_UPDATE_STATS,	  NONRESTOKEN_),
   ParKeyWord("UPGRADE",                TOK_UPGRADE,         NONRESTOKEN_),

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/7baf325f/core/sql/parser/sqlparser.y
----------------------------------------------------------------------
diff --git a/core/sql/parser/sqlparser.y b/core/sql/parser/sqlparser.y
index f1cbee2..1abe244 100755
--- a/core/sql/parser/sqlparser.y
+++ b/core/sql/parser/sqlparser.y
@@ -754,6 +754,8 @@ static void enableMakeQuotedStringISO88591Mechanism()
 %token <tokval> TOK_LOBTOFILE
 %token <tokval> TOK_LOBTOSTRING
 %token <tokval> TOK_EXTERNALTOSTRING
+%token <tokval> TOK_EMPTY_BLOB
+%token <tokval> TOK_EMPTY_CLOB
 %token <tokval> TOK_INSERT
 %token <tokval> TOK_INSERT_ONLY
 %token <tokval> TOK_INS
@@ -1146,7 +1148,8 @@ static void enableMakeQuotedStringISO88591Mechanism()
 %token <tokval> TOK_UNLOCK              /* Tandem extension */
 %token <tokval> TOK_UNSIGNED            /* Tandem extension non-reserved word */
 %token <tokval> TOK_UPDATE		
-%token <tokval> TOK_UPDATE_STATS		
+%token <tokval> TOK_UPDATE_STATS
+%token <tokval> TOK_UPDATE_LOB		
 %token <tokval> TOK_UPD
 %token <tokval> TOK_UPGRADE
 %token <tokval> TOK_UPPER
@@ -2019,6 +2022,7 @@ static void enableMakeQuotedStringISO88591Mechanism()
 %type <item>                    insert_obj_to_lob_function
 %type <item>                    update_obj_to_lob_function
 %type <item>                    select_lob_to_obj_function
+%type <item>                    insert_empty_blob_clob
 %type <stringval>    		date_format
 %type <tokval>    		trim_spec
 %type <na_type>   		proc_arg_data_type
@@ -2813,6 +2817,7 @@ static void enableMakeQuotedStringISO88591Mechanism()
 %type <relx>                    exe_util_get_lob_info
 %type <relx>                    exe_util_populate_in_memory_statistics
 %type <relx>                    exe_util_lob_extract
+%type <relx>                    exe_util_lob_update
 %type <relx>                    unload_statement
 %type <relx>                    load_statement
 %type <boolean>                 load_sample_option
@@ -12914,6 +12919,7 @@ insert_value_expression_list_paren : '(' insert_value_expression_list_comma ')'
 				  		
 insert_value_expression : value_expression 
                           | insert_obj_to_lob_function
+                          | insert_empty_blob_clob
 
 insert_obj_to_lob_function : 
 			    TOK_STRINGTOLOB '(' value_expression ')'
@@ -12949,7 +12955,14 @@ insert_obj_to_lob_function :
                                   
                                   $$ = new (PARSERHEAP()) LOBinsert( $3, $5, LOBoper::EXTERNAL_);
 				}
-
+insert_empty_blob_clob : TOK_EMPTY_BLOB '(' ')' 
+                    {
+                      $$ = new (PARSERHEAP()) LOBinsert(NULL,NULL,LOBoper::EMPTY_LOB_);
+                    }
+                 | TOK_EMPTY_CLOB '(' ')'
+                    {
+                      $$ = new (PARSERHEAP()) LOBinsert(NULL,NULL,LOBoper::EMPTY_LOB_);
+                    }
 update_obj_to_lob_function : 
 			    TOK_STRINGTOLOB '(' value_expression ')'
 			        {
@@ -13008,7 +13021,18 @@ update_obj_to_lob_function :
 				  YYERROR;
 				  $$ = new (PARSERHEAP()) LOBupdate( $3, NULL, NULL,LOBoper::LOAD_, TRUE);
 				}
-
+                          | TOK_EMPTY_BLOB '(' ')' 
+                               {
+                                 ItemExpr *dummy = new (PARSERHEAP())ConstValue(0);                              
+                                  $$ = new (PARSERHEAP()) LOBupdate(dummy,NULL,NULL,LOBoper::EMPTY_LOB_,FALSE);
+                               }
+                          | TOK_EMPTY_CLOB '(' ')'
+                              {
+                                ItemExpr *dummy = new (PARSERHEAP())ConstValue(0);                                
+                                 $$ = new (PARSERHEAP()) LOBupdate(dummy,NULL,NULL,LOBoper::EMPTY_LOB_,FALSE);
+                               }
+ 
+                                
 select_lob_to_obj_function : TOK_LOBTOFILE '(' value_expression ',' literal ')'
 			        {
 				  
@@ -13045,6 +13069,7 @@ select_lob_to_obj_function : TOK_LOBTOFILE '(' value_expression ',' literal ')'
 				}
                            
 
+
 table_value_constructor : TOK_VALUES '(' insert_value_expression_list ')' 
 				{
 					$$ = new (PARSERHEAP()) Tuple($3->reverseTree());
@@ -14804,9 +14829,14 @@ interactive_query_expression:
                                 {
 				  $$ = finalize($1);
 				}
-				| unload_statement {
+              | unload_statement 
+                                {
 				  $$ = finalize($1);
 				}
+              | exe_util_lob_update
+                                {
+                                  $$ = finalize($1);
+                                }
               | exe_util_init_hbase
                                 {
 				  $$ = finalize($1);
@@ -16253,6 +16283,71 @@ TOK_SIZE points to the address of an Int64 container This size is the input spec
                  */
 	       }
 
+exe_util_lob_update :   TOK_UPDATE_LOB '(' TOK_LOB QUOTED_STRING ',' TOK_LOCATION NUMERIC_LITERAL_EXACT_NO_SCALE ',' TOK_SIZE NUMERIC_LITERAL_EXACT_NO_SCALE  ')' 
+               {
+                 /* TOK_LOCATION points to a caller allocated data buffer with 
+                 LOB data . TOK_SIZE is the  size is the input specified by 
+                 user for length to update. On return, it will give the caller 
+                 the size that was updated */
+                 Int64 bufAddr = atoInt64($7->data());
+		 Int64 size = atoInt64($10->data());
+		 
+		 ConstValue * handle = new(PARSERHEAP()) ConstValue(*$4);
+                 ExeUtilLobUpdate *llu =  
+                   new (PARSERHEAP ()) ExeUtilLobUpdate
+		   (handle, 
+		    ExeUtilLobUpdate::FROM_BUFFER_,
+		    bufAddr, size, ExeUtilLobUpdate::REPLACE_,0);
+
+		 $$ = llu;
+               } 
+              |  TOK_UPDATE_LOB '(' TOK_LOB QUOTED_STRING ',' TOK_LOCATION NUMERIC_LITERAL_EXACT_NO_SCALE ',' TOK_SIZE NUMERIC_LITERAL_EXACT_NO_SCALE ',' TOK_APPEND')'    
+               {
+                 /* TOK_LOCATION points to a caller allocated data buffer with 
+                 LOB data . TOK_SIZE is the  size is the input specified by 
+                 user for length to update. On return, it will give the caller 
+                 the size that was updated */
+                 Int64 bufAddr = atoInt64($7->data());
+		 Int64 size = atoInt64($10->data());
+		 
+		 ConstValue * handle = new(PARSERHEAP()) ConstValue(*$4);
+                 ExeUtilLobUpdate *llu =  
+                   new (PARSERHEAP ()) ExeUtilLobUpdate
+		   (handle, 
+		    ExeUtilLobUpdate::FROM_BUFFER_,
+		    bufAddr, size, ExeUtilLobUpdate::APPEND_,0);
+
+		 $$ = llu;
+               }
+              | TOK_UPDATE_LOB '(' TOK_LOB QUOTED_STRING ',' TOK_EMPTY_BLOB '(' ')'')' 
+               {
+                 /* Truncate and insert empty_blob */
+                 
+		 
+		 ConstValue * handle = new(PARSERHEAP()) ConstValue(*$4);
+                 ExeUtilLobUpdate *llu =  
+                   new (PARSERHEAP ()) ExeUtilLobUpdate
+		   (handle, 
+		    ExeUtilLobUpdate::FROM_BUFFER_,
+		    0, 0, ExeUtilLobUpdate::TRUNCATE_EXISTING_,0);
+
+		 $$ = llu;
+               }
+          | TOK_UPDATE_LOB '(' TOK_LOB QUOTED_STRING ',' TOK_EMPTY_CLOB '(' ')' ')' 
+               {
+                 /* Truncate and insert empty_blob */
+                 
+		 
+		 ConstValue * handle = new(PARSERHEAP()) ConstValue(*$4);
+                 ExeUtilLobUpdate *llu =  
+                   new (PARSERHEAP ()) ExeUtilLobUpdate
+		   (handle, 
+		    ExeUtilLobUpdate::FROM_BUFFER_,
+		    0, 0, ExeUtilLobUpdate::TRUNCATE_EXISTING_,0);
+
+		 $$ = llu;
+               }
+             
 
 /* type pSchema */
 optional_from_schema : /* empty */
@@ -20141,6 +20236,7 @@ set_clause : identifier '=' value_expression
 					   rc);
 				  delete $1;
 				}
+                         
 
 /* type relx */
 delete_start_tokens : TOK_DELETE no_check_log TOK_FROM table_name 
@@ -33612,6 +33708,7 @@ nonreserved_word :      TOK_ABORT
                       | TOK_UPD
                       | TOK_UPGRADE
 		      | TOK_UPDATE_STATS
+                      | TOK_UPDATE_LOB
                       | TOK_UPPERCASE
                       | TOK_USA				
 		      | TOK_USE				// MV REFRESH
@@ -33876,6 +33973,9 @@ nonreserved_func_word:  TOK_ABS
 		      | TOK_LOBTOFILE
 		      | TOK_LOBTOSTRING
                       | TOK_EXTERNALTOSTRING
+                      | TOK_EMPTY_CLOB
+                      | TOK_EMPTY_BLOB
+                      
 
 nonreserved_datatype  : TOK_ANSIVARCHAR
                       | TOK_BIGINT

http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/7baf325f/core/sql/parser/ulexer.cpp
----------------------------------------------------------------------
diff --git a/core/sql/parser/ulexer.cpp b/core/sql/parser/ulexer.cpp
index e6a21c6..4843e6f 100644
--- a/core/sql/parser/ulexer.cpp
+++ b/core/sql/parser/ulexer.cpp
@@ -3170,6 +3170,13 @@ Int32 yyULexer::yylex(YYSTYPE *lvalp)
                          keyWordEntry1->getTokenCode(),
                          end1, holdChar1, lvalp);
                       break;
+                    case TOK_UPDATE:
+                      return eitherCompoundOrSimpleKeyword(
+							   keyWordEntry2->getTokenCode() == TOK_LOB,
+							   TOK_UPDATE_LOB,
+							   keyWordEntry1->getTokenCode(),
+							   end1, holdChar1, lvalp);
+                      break;
                     default:
                       Int32 BadCompoundKeywordPrefix=0;
                       assert(BadCompoundKeywordPrefix);