@@ -863,8 +863,7 @@ ItemExpr *literalOfNumericPassingScale(NAString *strptr, char sign,
   } else if (strSize <= 19) {
     datatype = (createSignedDatatype ? REC_BIN64_SIGNED : REC_BIN64_UNSIGNED);
     length = sizeof(Int64);
-  } else if (strSize == 20) {
-    createSignedDatatype = FALSE;
+  } else if ((strSize == 20) && (!createSignedDatatype)) {
     datatype = REC_BIN64_UNSIGNED;
     length = sizeof(Int64);
   }    
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
/* -*++-*- 
******************************************************************************
*
* File:         SqlParserAux.cpp
* Description:  SQL Parser auxiliary methods: a logical progression from
*		Sql Parser Gnu  to  Sql Parser Yacc  to  Sql Parser Aux.
*
*		Extracted from sqlparser.y to
*               work around a c89 (v2.1) internal limit that shows up as
                  ugen: internal: Assertion failure
                  in source file 'W:\parser\SqlParser.cpp', at source line NNN
		  detected in back end file 'eval.c', at line 4653
*               when cross-compiling SQLMX for NSK
*
* Created:      4/28/94
* Language:     C++
*
*
*
******************************************************************************
*/

#define   SQLPARSERGLOBALS_CONTEXT_AND_DIAGS
#define   SQLPARSERGLOBALS_HOSTVARS
#define   SQLPARSERGLOBALS_LEX_AND_PARSE
#define   SQLPARSERGLOBALS_NADEFAULTS
#define   SQLPARSERGLOBALS_NAMES_AND_TOKENS
#define   SQLPARSERGLOBALS_FLAGS
#include "SqlParserGlobals.h"
#include "SqlParserAux.h"

#include <errno.h>
#include "AllItemExpr.h"
#include "MiscType.h"
#include "NumericType.h"
#include "ParserMsg.h"
#include "SqlciError.h"
#include "wstr.h"
#include "nawstring.h"


// Forward references and includes for Y.tab.h (SqlParser.h)
class ExprNodePtrList;
class ForUpdateSpec;
class IntervalQualifier;
class PairOfUnsigned;
#include "CharType.h"
#include "ComSmallDefs.h"
#include "ComTransInfo.h"
#include "ComUnits.h"
#include "HvTypes.h"
#include "ElemDDLConstraintRI.h"
#include "ElemDDLPartition.h"
#include "ElemDDLParamName.h"
#include "AllElemDDL.h"
#include "AllStmtDDL.h"
#include "RelScan.h"
#include "RelUpdate.h"
#include "RelSequence.h"
#include "StmtDMLSetTransaction.h"
#include "exp_clause_derived.h"
#include <sqlparser.h> // Angled-brackets are intentional here

const UInt32 SHORT_MAX =  32767;

char    *SQLTEXT()  {return SqlParser_CurrentParser->inputStr();}
charBuf *SQLTEXTCHARBUF()  {return SqlParser_CurrentParser->getInputcharBuf();}
Lng32    SQLTEXTCHARSET() {return SqlParser_CurrentParser->inputStrCharSet();}
NAWchar *SQLTEXTW() {return SqlParser_CurrentParser->wInputStr();}
NAWcharBuf *SQLTEXTNAWCHARBUF()  {return SqlParser_CurrentParser->getInputNAWcharBuf();}


CharInfo::CharSet getStringCharSet(NAString **p)
{ return ToStringvalWithCharSet(p)->charSet_; }

CharInfo::CharSet getStringCharSet(NAWString **p)
{ return ToStringvalWithCharSet(p)->charSet_; }

NABoolean charsetMismatchError(NAString **d1, NAString **d2)
{
  CharInfo::CharSet cs1 = getStringCharSet(d1);
  CharInfo::CharSet cs2 = getStringCharSet(d2);
  if (cs1 == cs2)
    return FALSE;

  NAString ns1("CHAR(n) CHARACTER SET ");
  NAString ns2(ns1);
  ns1 += CharInfo::getCharSetName(cs1);
  ns2 += CharInfo::getCharSetName(cs2);

  // 4034 The operation ($String0 $String1 $String2) is not allowed
  *SqlParser_Diags << DgSqlCode(-4034)
    << DgString0(ns1)
    << DgString1("||")				// string concatenation operator
    << DgString2(ns2);
  return TRUE;
}

// This function prints to the user the place in the input where an
// error occurred.  This error message is based on the contents of
// SqlParser_InputStr, which is what the parser scans, and the variable
// SqlParser_InputPos, which is an index that iterates over characters in that
// buffer as the Lexer tokenizes for the parser.
// However, if, on input, SqlParser_InputStr equals NULL, then the old
// behavior of printing the argument errtext is all that happens.
//
// NB: sqlcomp/parser.h's parser class keeps two versions of the SQL input stmt.
// Parser::inputStr() is the ascii/multibyte version and wInputStr() is
// the wide (unicode) version. Input/output requires multibyte strings (at
// least in NT 4.0) The wide (Unicode) versions of the C++ stream I/O
// functions do not work on Japanese or Chinese NT! Apparently, this is an
// accepted fact of life. All I/O must be multibyte. In-memory string handling
// can be in Unicode. So, you will see this duality in this parser. Strings
// destined for internal processing (eg, by the lexer) are in Unicode. But
// strings destined for I/O are first converted to multibyte. (tcr)

void yyerror(const char *errtext)
{
  NAWchar *inputStr = SQLTEXTW();
#ifndef NDEBUG		//## tmp code...
  if (inputStr && !getenv("YYERROR_QUIET"))
    {
      cerr << "yyerror: ";
      for (Int32 i = 0; i >= -2; i--)
        {
	  const ParScannedTokenQueue::scannedTokenInfo &tok
	    = ParScannedTokens->getScannedTokenInfo(i);
	  if (tok.tokenStrLen) 
	    {
	      NAString *ti = unicodeToChar
#pragma nowarn(1506)   // warning elimination 
		(&inputStr[tok.tokenStrPos], tok.tokenStrLen,
		 CharInfo::UTF8
		 , 
		 PARSERHEAP(), TRUE);
#pragma warn(1506)  // warning elimination 
	      cerr << "<" << (ti ? ti->data() : "") << "> ";
	      delete ti;
	    }
	  else 
	    {
	      cerr << "<" << "" << "> ";
	    }
	}
      NAString *stmt = unicodeToChar
#pragma nowarn(1506)   // warning elimination 
	(inputStr, NAWstrlen(inputStr), 
	 CharInfo::UTF8
	 , 
	 PARSERHEAP(), TRUE);
#pragma warn(1506)  // warning elimination 
      cerr << " " << (stmt ? stmt->data() : "") << endl;
      delete stmt;
    }
#endif
  
  if (inputStr || strstr(errtext, "syntax") == errtext)
    {
      if ((strcmp(errtext, "")) && 
          (strstr(errtext, "syntax") != errtext))
        *SqlParser_Diags << DgSqlCode(-SQLCI_PARSER_ERROR) << DgString0(errtext);
      else
      {
	*SqlParser_Diags << DgSqlCode(-SQLCI_SYNTAX_ERROR);
	// Point to the end of offending token,
	// knowing that the Lexer has looked ahead by 2 characters
 Int32 pos = SqlParser_CurrentParser->getLexer()->getInputPos();
	StoreSyntaxError(inputStr,pos,*SqlParser_Diags,0,
			CharInfo::UTF8
			);
      }
    }
  else
    {
      // Internal parser error -- we hope never to see this one
      *SqlParser_Diags << DgSqlCode(-SQLCI_PARSER_ERROR) << DgString0(errtext);
    }

  WeAreInACreateMVStatement = FALSE;
  WeAreInAnEmbeddedInsert = FALSE;
}


// THREAD_P LimitedStack *inJoinSpec = NULL;	// can handle <STACK_LIMIT> nested Joins

// First emit syntax error 15001.
// Then if we're not in a parenthesized join-spec, also emit error 4101,
// 	"If $0~String0 is intended to be a further table reference in the
//	FROM clause, the preceding join search condition must be enclosed
//	in parentheses."
void checkError4101(NAString *badItemStr, ItemExpr *badPrevExpr)
{
  yyerror("");

  if (!((*inJoinSpec)())) return;
  if (SqlParser_ParenDepth - (*inJoinSpec)() + STACKDELTA_ENSURES_NONZERO) return;

  if (badPrevExpr && badPrevExpr->getOperatorType() == ITM_REFERENCE) {
    const ColRefName &crn = ((ColReference *)badPrevExpr)->getColRefNameObj();

    // Is it a 3-part name at most (really a tablename intended here)?
    if (crn.getCorrNameObj().getQualifiedNameObj().fullyExpanded()) return;

    // Prepend 1, 2, or 3-part tablename to correlation name
    badItemStr->prepend(crn.getColRefAsAnsiString() + " ");
  }

  *SqlParser_Diags << DgSqlCode(-4101) << DgString0(*badItemStr);
}

// Emit warning 3169 if unknown collation,
// but emit it only once per stmt for each new unknown collation name.
NABoolean maybeEmitWarning3169(CharInfo::Collation co, const NAString &nam)
{
  if (co != CharInfo::UNKNOWN_COLLATION) return FALSE;	    // no warning
  for (Lng32 i = SqlParser_Diags->getNumber(); i; i--) {
    const ComCondition &cond = (*SqlParser_Diags)[i];
    if (cond.getSQLCODE() == +3169 &&
        strcmp(cond.getOptionalString(0), nam) == 0)
      return TRUE;					    // already emitted
  }
  *SqlParser_Diags << DgSqlCode(+3169) << DgString0(nam);
  return TRUE;
}

NABoolean checkError3179(const NAType *na)
{
  if (na->getTypeQualifier() != NA_CHARACTER_TYPE) return FALSE;  // no problem
  const CharType *ct = (const CharType *)na;
  if (ct->isCharSetAndCollationComboOK()) return FALSE;		  // no problem
  // 3179 Collation $0 is not defined on character set $1.
  *SqlParser_Diags << DgSqlCode(-3179)
    << DgString0(CharInfo::getCollationName(ct->getCollation()))
    << DgString1(CharInfo::getCharSetName(ct->getCharSet()));
  return TRUE;
}

void emitError3435( int tok_type, int cs, ParAuxCharLenSpec::ECharLenUnit parCLU )
{
  char *tok_type_name = (char *)"CHAR";
  if ( tok_type == TOK_BYTE )
       tok_type_name  = (char *)"BYTE";
  if ( tok_type == TOK_VARCHAR )
       tok_type_name  = (char *)"VARCHAR";
  if ( tok_type == TOK_LONG )
       tok_type_name  = (char *)"LONG VARCHAR";

  const char* cs_name = CharInfo::getCharSetName( (CharInfo::CharSet) cs );

  char *lenUnitName = (char *)"UNSPECIFIED";
  if ( parCLU EQU ParAuxCharLenSpec::eBYTES )
        lenUnitName = (char *)"BYTES";
  if ( parCLU EQU ParAuxCharLenSpec::eCHARACTERS )
        lenUnitName = (char *)"CHARS";

  *SqlParser_Diags << DgSqlCode(-3435) << DgString0(tok_type_name)
                                       << DgString1(cs_name)
                                       << DgString2(lenUnitName);
}
  
// LIST(ItemExpr *) AllHostVars;
// LIST(ItemExpr *) AssignmentHostVars;
THREAD_P AllHostVarsT    *AllHostVars = NULL;
THREAD_P AssignmentHostVarsT *AssignmentHostVars = NULL;
THREAD_P HVArgTypeLookup *TheProcArgTypes = NULL;
THREAD_P NABoolean        intoClause = FALSE;
THREAD_P NABoolean        InAssignmentSt = FALSE;
THREAD_P NABoolean        ThereAreAssignments;

void resetHostVars()
{
  if (AllHostVars == NULL)
    AllHostVars = new AllHostVarsT(NULL);
  AllHostVars->clear();
  TheHostVarRoles->clear();		// SqlParserGlobals.h

  // No need to "delete TheProcArgTypes;", as PARSERHEAP heap mgmt does cleanup
  TheProcArgTypes = NULL;
  InAssignmentSt =  FALSE;
  if (AssignmentHostVars == NULL)
    AssignmentHostVars = new AssignmentHostVarsT(NULL);
  AssignmentHostVars->clear();  

  intoClause = FALSE;

  ThereAreAssignments = FALSE;
}

void MarkInteriorNodesAsInCompoundStmt(RelExpr *node)
{
  node->setBlockStmt( TRUE );
  for (Int32 i=0; i < node->getArity(); i++) {
    if (node->child(i))
      MarkInteriorNodesAsInCompoundStmt(node->child(i));
  }
}

NAWString* localeMBStringToUnicode(NAString* localeString, Lng32 charset, CollHeap *heap)
{
#pragma nowarn(1506)   // warning elimination 
   charBuf cbuf((unsigned char*)(localeString->data()), localeString->length());
#pragma warn(1506)  // warning elimination 
   NAWcharBuf* wcbuf = 0;
   Int32 errorcode = 0;
   switch (charset) {
      case SQLCHARSETCODE_ISO88591:
        wcbuf = ISO88591ToUnicode(cbuf, 0, wcbuf);
        break;
      case SQLCHARSETCODE_SJIS:
	  case SQLCHARSETCODE_EUCJP:
	  case SQLCHARSETCODE_GB18030:
	  case SQLCHARSETCODE_GB2312:
	  case SQLCHARSETCODE_GBK:
	  case SQLCHARSETCODE_MB_KSC5601:
	  case SQLCHARSETCODE_BIG5:
	  case SQLCHARSETCODE_UTF8:
        wcbuf = csetToUnicode(cbuf, 0, wcbuf, charset, errorcode);
        break;
      default:
        wcbuf = ISO88591ToUnicode(cbuf, 0, wcbuf);
   }

   if ( wcbuf ) {
      NAWString* wstr = new(heap) NAWString(wcbuf->data(), wcbuf->getStrLen(), heap);
      delete wcbuf;
      return wstr;
   } else
      return new(heap) NAWString();
}

THREAD_P Int32 in3GL_ = 0;

static Lng32 findNameInList(ItemExprList &iel, const NAString &name)
{
  for (CollIndex i = 0; i < iel.entries(); i++)
    {
      if ((iel[i]->getOperatorType() == ITM_REFERENCE) &&
	  (((ColReference*)iel[i])->getColRefNameObj().getColName() 
	   == name))
	{
	  return i;
	}
    }
  return -1;
}

RelRoot *finalize(RelExpr *top, NABoolean outputVarCntValid)
{
  RelRoot *return_top;

  if ( top == NULL )
     return NULL;

  // if the top node isn't already a root node (e.g. for unions, insert,
  // update, delete), make a new root node to hold the hostvar information
  if (top->getOperatorType() == REL_ROOT)
    return_top = (RelRoot *)top;
  else
    return_top = new (PARSERHEAP()) RelRoot(top);

  return_top->setSubRoot(TRUE);

  // If called from inside a 3GL block statement, do not set the RootFlag
  if (in3GL_ <= 0) {
    return_top->setRootFlag(TRUE);
  }
  else {
    // We only take care of input/output host variables when we have exited all
	// 3GL blocks
	return return_top;
  }
  // code in BindRelExpr and NormRelExpr rely on this isTrueRoot flag

  // Rowset::bindNode relies (indirectly) on InputVarList, so update it.

  // ---------------------------------------------------------------------
  // Add all the input host vars/parameters encountered
  // to the topmost RelRoot node's input variable list.
  // Also keep a count of the output vars/params.
  //
  // NOTE:    The hostvars are of course used somewhere else in
  //          the query. This leads to the unpleasant effect that
  //          we have parse tree nodes that are shared. If we don't
  //          want this we should consider using a LIST(ItemExpr *)
  //          in the RelRoot node instead of the ItemExpr *. Currently,
  //          the Binder does the right thing for shared ItemExprs in
  //          that it uses the already assigned ValueId.
  //
  // We iterate over the enum values in TheHostVarRoles in parallel with
  // iterating over AllHostVars.  We do this so as to extract *only* the
  // input host variables and insert only those into the RelRoot.
  // ---------------------------------------------------------------------

  return_top->outputVarCnt() = 0;
  HVArgType *argInfo;

  CollIndex i = 0;
  CollIndex j = 0;
  for (i = 0; i < AllHostVars->entries(); i++)
    {
      HostVarRole role = (*TheHostVarRoles)[(size_t)j];
      ComASSERT(role != HV_IS_INDICATOR);

      if (role == HV_IS_INPUT || role == HV_IS_DYNPARAM)
        {
          return_top->addInputVarTree((*AllHostVars)[i]);
        }
      else if (role == HV_IS_OUTPUT || role == HV_IS_INPUT_OUTPUT)
        {
	 if (role == HV_IS_INPUT_OUTPUT) {
	    NAString hvName = ((HostVar *)((*AllHostVars)[i]))->getName();
	    HostVar *hv = NULL;
	    if ( inCallStmt && ( 0 != hvName.compareTo ("")))
	    {
	      const NAString &str = ((HostVar *) ((*AllHostVars)[i]))->getIndName ();
	      if ( 0 != str.compareTo (""))
	      {
	        NAString *hvn = new (PARSERHEAP())NAString(str, PARSERHEAP ());
	        hv = makeHostVar(&hvName, hvn);
	      }
	      else
		hv = makeHostVar (&hvName, NULL);
	    }
	    else
	      hv = makeHostVar(&hvName, NULL);
	    hv->setHVInputAssignment();
            return_top->addInputVarTree(hv);
	 }
         return_top->addOutputVarTree((*AllHostVars)[i]);

         return_top->outputVarCnt()++;
         argInfo = TheProcArgTypes ?
           TheProcArgTypes->get(&((HostVar *)((*AllHostVars)[i]))->getName()) :
           NULL;
         if (argInfo) argInfo->intoCount()++;
        }

      //delete (*AllHostVars)[i];  // an orphan after this, so delete it
      //(*AllHostVars)[i] = NULL;

      // Skip past at most one following indicator
      // but not beyond the end of the array please
      if (++j < TheHostVarRoles->entries() &&
          (*TheHostVarRoles)[(size_t)j] == HV_IS_INDICATOR)
        {
          j++;
          if (role == HV_IS_OUTPUT)
            {
              if (TheProcArgTypes)
                {
                  NAString *ivName = (NAString *)&
                    ((HostVar *)((*AllHostVars)[i]))->getIndName();
                  if (!ivName->isNull())
                    {
                      argInfo = TheProcArgTypes->get(ivName);
                      if (!argInfo)
                        argInfo = new (PARSERHEAP()) HVArgType
                          (ivName, new (PARSERHEAP()) SQLUnknown);
                      argInfo->useCount()++;
                      argInfo->intoCount()++;
                    }
                }
            } // INTO :hv :iv  -- lookup :iv, add if necessary, incr counts
        }
    } // for-AllHostVars-loop
  assert(j >= TheHostVarRoles->entries());    // j should reach end when i does

  // The RelRoot::outputVarCnt_ returns as
  // a nonnegative count of output host variables (e.g. SELECT cols INTO :hv...)
  // or of output dynamic parameters (no syntax for this currently (ever?)),
  // or -1 for roots that don't get called here (non-topmost or non-true roots)
  // or are called as part of a DECLARE CURSOR (as in the line following).
  // Binder checks this count.
  //
  if (!outputVarCntValid) return_top->outputVarCnt() = -1;

  if (TheProcArgTypes)
    {
      LIST(HVArgType *) argdump(PARSERHEAP());
      TheProcArgTypes->dump(argdump);
      for (i = 0; i < argdump.entries(); i++)
        {

          // Warnings: if procedure parameter is unused,
          //   or if used more than once as an INTO target.
          if (!argdump[i]->useCount())
            *SqlParser_Diags << DgSqlCode(+3162)
                             << DgString0(*argdump[i]->getName());

          // We can have an output variable appear more than once
          // if we have assignment statements
          if (!ThereAreAssignments) {
            if (argdump[i]->intoCount() > 1)
              *SqlParser_Diags << DgSqlCode(+3163)
                               << DgString0(*argdump[i]->getName());
          }

#ifndef NDEBUG
          // Ansi 4.2.3 says that by default, hostvars are COERCIBLE,
          // unless they have a COLLATE clause in which case they're EXPLICIT.
          // But only column refs can be IMPLICIT.
          //
          const CharType *ct = (const CharType *)argdump[i]->getType();
          if (ct->getTypeQualifier() == NA_CHARACTER_TYPE)
            { ComASSERT(ct->getCoercibility() != CharInfo::IMPLICIT); }
#endif
        }
    }

  return return_top;
}


void ForUpdateSpec::finalizeUpdatability(RelExpr *top)
{
  ComASSERT(top->getOperatorType() == REL_ROOT);
  RelRoot *treeTop = (RelRoot *)top;

  // Ansi 13.1 SR 5a -- no updatability clause specified, but ORDER BY was.
  // See also RelRoot::isUpdatableCursor() in NormRelExpr.cpp.
  // Genesis 10-990215-7815.
  //
  if (!explicitSpec_) {
    if (treeTop->hasOrderBy())
      forUpdate_ = FALSE;
    else {
      // Tandem extension, defaulting rule --
      // if user has set this default attr to TRUE,
      // they get FOR READ ONLY (itself a Tdm-ext syntax),
      // resulting in better runtime performance.
      forUpdate_ = (CmpCommon::getDefault(READONLY_CURSOR) == DF_FALSE);
    }
  }
  treeTop->updatableSelect() = forUpdate_;
  if (updateCol_) {
    ComASSERT(explicitSpec_ && forUpdate_);
    treeTop->addUpdateColTree(updateCol_);
  }
}


NABoolean finalizeAccessOptions(RelExpr *top,
                                AccessType at,
                                LockMode   lm)
{
  if (top->getOperatorType() == REL_TUPLE ||
      top->getOperatorType() == REL_TUPLE_LIST) {
    return (at == ACCESS_TYPE_NOT_SPECIFIED_ && lm == LOCK_MODE_NOT_SPECIFIED_);
  }

  // In case of an INSERT VALUES statement, this is a Tuple node.
  if (top->getOperatorType() != REL_ROOT)
    return TRUE;


  RelRoot *treeTop = (RelRoot *)top;

  if (at != ACCESS_TYPE_NOT_SPECIFIED_) {
    if (treeTop->accessOptions().accessType() != ACCESS_TYPE_NOT_SPECIFIED_) {
      *SqlParser_Diags << DgSqlCode(-3196);
      // Access type cannot be specified more than once.
      return FALSE;	// error
    }
    treeTop->accessOptions().accessType() = at;
  }

  if (lm != LOCK_MODE_NOT_SPECIFIED_) {
    if (treeTop->accessOptions().lockMode() != LOCK_MODE_NOT_SPECIFIED_) {
      *SqlParser_Diags << DgSqlCode(-3197);
      // Lock mode cannot be specified more than once.
      return FALSE;	// error
    }
    treeTop->accessOptions().lockMode() = lm;
  }

  return TRUE;		// no error
}

NAString * getSqlStmtStr(CharInfo::CharSet & refparam_targetCharSet, CollHeap * heap)
{
  NAWchar *inputStr = SQLTEXTW();
  Int32 start_pos = 0;
  if (NAWstrlen(inputStr) >= 7)
    {
      NAWchar temp[10];
      Int32 i = 0;
      while (i < 7)
	{
	  temp[i] = na_towupper(inputStr[i]);
	  i++;
	}
      if (NAWstrncmp(temp, WIDE_("DISPLAY"), 7) == 0) 
	start_pos = 7;
    }
#pragma nowarn(1506)   // warning elimination 
  
  // SqlParser_CurrentParser->charset_ is the encoding charset of the
  // sql stmt under parsing now. Target is the charset that the stmt
  // will be encoded before it is sent to catman.
  // Assume the target charset is the source charset for now.
  refparam_targetCharSet = SqlParser_CurrentParser->charset_;
  
  refparam_targetCharSet = CharInfo::UTF8;
  NAString *stmt = unicodeToChar ( &inputStr[start_pos] // in - const NAWchar *
                                 , SQLTEXTNAWCHARBUF()->getStrLen() - start_pos
                                 , CharInfo::UTF8
                                 , heap
                                 );
  ParScannedInputCharset = CharInfo::UTF8;
#pragma warn(1506)  // warning elimination

  return stmt;
}

// The purpose of this function is to return a pointer to a HostVar object.
// This new HostVar should have a name from the given name in the arg,
// and its type should either be SQLUnknown (if no type info is available),
// or it should be obtained from TheProcArgTypes.  This depends on whether
// that list was init'd which depends on the syntax that came before the
// occurrence of the host variable for which we are making this data.
//
// If hvName is NULL, that causes an assertion failure.
// If indName is NULL, that means this host variable has no indicator
// and is not a programming error.
//
// To set the NAType of the HostVar which we return, we must
// set its own nullability flag according to whether or not there
// is an indicator in this host variable.  Is this redundant since
// that info is already in the HostVar itself?

HostVar *makeHostVar(NAString *hvName, NAString *indName, NABoolean isDynamic)
{
  ComASSERT(hvName && !hvName->isNull() && ((isDynamic) || (*hvName)[(StringPos)0] == ':'));
  ComASSERT(!indName || (!indName->isNull() && (*indName)[(StringPos)0] == ':'));

  HVArgType *argInfo = TheProcArgTypes ?
		       TheProcArgTypes->get(hvName) : NULL;
  NAType    *naType  = argInfo ?
		       argInfo->getType() : new (PARSERHEAP()) SQLUnknown;
  ComASSERT(naType);
  naType->setNullable(!!indName);

  HostVar   *result  = indName ?
    new (PARSERHEAP()) HostVar(*hvName, *indName, naType) :
    new (PARSERHEAP()) HostVar(*hvName, naType);
  ComASSERT(result);

  if (
  #ifndef NDEBUG
      !getenv("HV_DEBUG") &&
  #endif
      (CmpCommon::context()->GetMode() == STMT_DYNAMIC) &&
      (NOT isDynamic))
    {
      // 3049 Host variables ($string0) are not allowed in dynamic compilation.
      *SqlParser_Diags << DgSqlCode(-3049) << DgString0(*hvName);
    }
  else if (!argInfo)
    {
      if (TheProcArgTypes)
        {
          // ANSI 12.3 SR 3
          // 3161 $string0 was not declared in the procedure parameter list.
          *SqlParser_Diags << DgSqlCode(-3161) << DgString0(*hvName);

          // So we won't display this errmsg again for this hv in this stmt:
          argInfo = new (PARSERHEAP()) HVArgType(hvName, naType);
          TheProcArgTypes->insert(argInfo);
          // And so we won't display warning 3162 in finalize() either:
          argInfo->useCount()++;
        }
      else
        {
          // Not in a PROCEDURE, it's okay, let the Generator coerce the
          // SQLUnknown type to some default flavor of signed int
          // (the way it does for INDICATOR variables, which you notice
          // we do *not* currently pass in the proc arg list).
        }
    }
  else
    {
      argInfo->useCount()++;
    }

  setHVorDPvarIndex ( result, hvName );
  
  return result;

  // Do **NOT** do this (remove info from our hashtable)!
  //	if (argInfo)
  //	  {
  //	    argInfo->type_ = NULL;
  //	    delete argInfo;
  //	  }
}

static
NABoolean literalToNumber(NAString *strptr, char sign, NAString *cvtstr, 
                          short &shortVal, Lng32 &longVal, Int64& i64Val, 
                          char **bigNum, Lng32& bigNumSize, size_t &strSize)
{
  NABoolean returnValue = TRUE; // assume success until proven otherwise
  //
  // Get the size of the absolute value first,
  // *then* it's safe to modify the text --
  // both the one we will store in strptr
  // and the descaled one to be converted by atoxxx (cvtstr).
  //
  strSize = cvtstr->length();
  if (sign == '-') {
    strptr->prepend(sign);
    if (strptr != cvtstr)
      cvtstr->prepend(sign);
  }

  if ((! (Get_SqlParser_Flags(ALLOW_ARB_PRECISION_LITERALS))) &&
      (CmpCommon::getDefaultNumeric(MAX_NUMERIC_PRECISION_ALLOWED)
       > MAX_HARDWARE_SUPPORTED_SIGNED_NUMERIC_PRECISION) &&
      (strSize > (ULng32)CmpCommon::getDefaultNumeric(MAX_NUMERIC_PRECISION_ALLOWED)))
    {
      *SqlParser_Diags << DgSqlCode(-3014) << DgInt0(strSize)
		       << DgInt1((Lng32)CmpCommon::getDefaultNumeric(MAX_NUMERIC_PRECISION_ALLOWED)); 
      returnValue = FALSE; // 
      return returnValue;
    }

  if (strSize < 5) {
#pragma nowarn(1506)   // warning elimination 
    shortVal = atoi(*cvtstr);
#pragma warn(1506)  // warning elimination 
  } else if (strSize < 10) {
    longVal = atol(*cvtstr);
  } else if (strSize < 19) {
    i64Val = atoInt64(*cvtstr);
  } else { // precision >= 19
    if ((CmpCommon::getDefaultNumeric(MAX_NUMERIC_PRECISION_ALLOWED) >
	 MAX_HARDWARE_SUPPORTED_SIGNED_NUMERIC_PRECISION) ||
	(Get_SqlParser_Flags(ALLOW_ARB_PRECISION_LITERALS)) 
	// callers know what they're doing, leave them alone.
	|| strSize < FLT_MAX_10_EXP) { 
      // LLONG_MAX & LLONG_MIN have 19 digits and must be allowed here.
      // There are other places in mxcmp like GenExpGenerator.cpp's
      // ExpGenerator::scaleBy10x() that do 
      //   rettree = createExprTree(str, 0, 1, retTree);
      // where str is "1000000000000000000000", a 22-digit "literal" that
      // must be allowed here also.
      // Also, just in case you ever want to use SQLNumeric here, be 
      // aware that atoInt64(LLONG_MAX) even with overflow checking can 
      // kill mxcmp with a signal 31!
      // Prepare BCD representation of number
#pragma nowarn(1506)   // warning elimination 
      Lng32 largestrSize = strSize + 1; // extra byte for sign
#pragma warn(1506)  // warning elimination 
      char *largestr = new (PARSERHEAP()) char[largestrSize];
      largestr[0] = sign;
      size_t j = (sign == '+') ? 0 : 1;
      for (size_t i = 0; i < strSize; i++)	  // strSize, not largestrSize
#pragma nowarn(1506)   // warning elimination 
        largestr[i+1] = (*cvtstr)[i+j] - '0';
#pragma warn(1506)  // warning elimination 

      // Convert BCD to Big Num representation
#pragma nowarn(1506)   // warning elimination 
      bigNumSize = BigNumHelper::ConvPrecisionToStorageLengthHelper(strSize);
#pragma warn(1506)  // warning elimination 
      *bigNum = new (PARSERHEAP()) char[bigNumSize];
      BigNumHelper::ConvBcdToBigNumWithSignHelper(largestrSize,
                                                  bigNumSize, 
                                                  largestr,
                                                  *bigNum);
      NADELETEBASIC(largestr, (PARSERHEAP()));	
    } else { // precision >= FLT_MAX_10_EXP in a user-specified literal
      // genesis 10-030220-1214 documents a cpu halt can happen here when we
      // try to support digit precisions >= 77. The R2 version of this code
      // has Gautam Das' BigNum code. It does not seem to cause a cpu halt
      // but can quietly experience an overflow and give a wrong answer!
      *SqlParser_Diags << DgSqlCode(-3165) << DgString0(*strptr);
      returnValue = FALSE; // 
    }
  }
  return returnValue;
}


// In the next several procedures, we set up ConstValue's, in whose text
// we want negative numbers to end up with minus signs but positive numbers
// without plus signs.  That is,
//	"1",'+'	-> "1"
//	"2",'-'	-> "-2"
// (Only digits, no signs, are passed in the strptr and cvtstr arguments.)
// (Note that we delete the strptr before returning:  thus we may freely
// modify the text therein.)

ItemExpr *literalOfNumericPassingScale(NAString *strptr, char sign,
                                       NAString *cvtstr, size_t scale)
{
  short rc = 0;

  ItemExpr *returnValue = NULL;
  //
  // Get the size of the absolute value first,
  // *then* it's safe to modify the text --
  // both the one we will store in ConstValue's text (strptr)
  // and the descaled one to be converted by atoxxx (cvtstr).
  //
  size_t strSize = cvtstr->length();
  NABoolean createSignedDatatype = 
    ((CmpCommon::getDefault(TRAF_CREATE_SIGNED_NUMERIC_LITERAL)) == DF_ON);
  if (sign == '-') {
    createSignedDatatype = TRUE;
    strptr->prepend(sign);
    if (strptr != cvtstr)
      cvtstr->prepend(sign);
  }

  if ((! (Get_SqlParser_Flags(ALLOW_ARB_PRECISION_LITERALS))) &&
      (CmpCommon::getDefaultNumeric(MAX_NUMERIC_PRECISION_ALLOWED)
       > MAX_HARDWARE_SUPPORTED_SIGNED_NUMERIC_PRECISION) &&
      (strSize > (ULng32)CmpCommon::getDefaultNumeric(MAX_NUMERIC_PRECISION_ALLOWED)))
    {
      *SqlParser_Diags << DgSqlCode(-3014) << DgInt0(strSize)
		       << DgInt1((Lng32)CmpCommon::getDefaultNumeric(MAX_NUMERIC_PRECISION_ALLOWED)); 
      return NULL;
    }

  NABoolean createTinyLiteral = 
    ((CmpCommon::getDefault(TRAF_CREATE_TINYINT_LITERAL)) == DF_ON);
  
  char numericVal[8];
  short datatype = -1;
  Lng32 length = -1;
  if ((createTinyLiteral) && (strSize < 3)) {
    datatype = (createSignedDatatype ? REC_BIN8_SIGNED : REC_BIN8_UNSIGNED);
    length = sizeof(Int8);
  } else if (strSize < 5) {
    datatype = (createSignedDatatype ? REC_BIN16_SIGNED : REC_BIN16_UNSIGNED);
    length = sizeof(short);
  } else if (strSize < 10) {
    datatype = (createSignedDatatype ? REC_BIN32_SIGNED : REC_BIN32_UNSIGNED);
    length = sizeof(Lng32);
  } else if (strSize <= 19) {
    datatype = (createSignedDatatype ? REC_BIN64_SIGNED : REC_BIN64_UNSIGNED);
    length = sizeof(Int64);
  } else if (strSize == 20) {
    createSignedDatatype = FALSE;
    datatype = REC_BIN64_UNSIGNED;
    length = sizeof(Int64);
  }    
    
  if (datatype != -1) {
    rc = convDoIt((char*)cvtstr->data(),
		  (Lng32)cvtstr->length(),
		  REC_BYTE_F_ASCII,
		  0, 0,
		  numericVal,
		  length,
		  datatype,
		  0, 0,
		  NULL, 0, 
		  PARSERHEAP(), 
		  NULL,
		  CONV_UNKNOWN);
    if (rc == 0) {
      if ((CmpCommon::getDefault(LIMIT_MAX_NUMERIC_PRECISION) == DF_ON) &&
	  (strSize == 19))
	returnValue = 
	  new (PARSERHEAP()) ConstValue
	  (new (PARSERHEAP()) SQLLargeInt
	    ((Lng32)scale, 
             (UInt16) 0, // 64-bit
	     TRUE,
	     FALSE),
	   (void *)numericVal,
	   (UInt32) length,
	   strptr);
      else
	returnValue = 
	  new (PARSERHEAP()) ConstValue
	  (new (PARSERHEAP()) SQLNumeric
	   (length,
	    (Lng32)strSize, // precision
	    (Lng32)scale, 
	    createSignedDatatype,
	    FALSE),
	   (void *)numericVal,
	   (UInt32) length,
	   strptr);
    }
    else if (strSize < 19) {
      *SqlParser_Diags << DgSqlCode(-8411);
      return NULL;
    }
    else
      datatype = -1;
  } // datatype != -1

  if (datatype == -1) {
    if ((CmpCommon::getDefaultNumeric(MAX_NUMERIC_PRECISION_ALLOWED) >
	 MAX_HARDWARE_SUPPORTED_SIGNED_NUMERIC_PRECISION) ||
	(Get_SqlParser_Flags(ALLOW_ARB_PRECISION_LITERALS)) 
        // callers know what they're doing, leave them alone.
        || strSize < FLT_MAX_10_EXP) { 
      // LLONG_MAX & LLONG_MIN have 19 digits and must be allowed here.
      // There are other places in mxcmp like GenExpGenerator.cpp's
      // ExpGenerator::scaleBy10x() that do 
      //   rettree = createExprTree(str, 0, 1, retTree);
      // where str is "1000000000000000000000", a 22-digit "literal" that
      // must be allowed here also.
      // Also, just in case you ever want to use SQLNumeric here, be 
      // aware that atoInt64(LLONG_MAX) even with overflow checking can 
      // kill mxcmp with a signal 31!
      // Prepare BCD representation of number
#pragma nowarn(1506)   // warning elimination 
      Lng32 largestrSize = strSize + 1; // extra byte for sign
#pragma warn(1506)  // warning elimination 
      char *largestr = new (PARSERHEAP()) char[largestrSize];
      largestr[0] = sign;
      size_t j = (sign == '+') ? 0 : 1;
      for (size_t i = 0; i < strSize; i++)	  // strSize, not largestrSize
#pragma nowarn(1506)   // warning elimination 
        largestr[i+1] = (*cvtstr)[i+j] - '0';
#pragma warn(1506)  // warning elimination 

      // Convert BCD to Big Num representation
#pragma nowarn(1506)   // warning elimination 
      Lng32 bigNumSize = BigNumHelper::ConvPrecisionToStorageLengthHelper(strSize);
#pragma warn(1506)  // warning elimination 
      char *bigNumData = new (PARSERHEAP()) char[bigNumSize];
      BigNumHelper::ConvBcdToBigNumWithSignHelper(largestrSize,
                                                  bigNumSize, 
                                                  largestr,
                                                  bigNumData);
    
      returnValue = new (PARSERHEAP()) ConstValue
#pragma nowarn(1506)   // warning elimination 
        (new (PARSERHEAP()) SQLBigNum(strSize, 
                                      scale,
                                      TRUE,
                                      TRUE,
                                      FALSE,
				      NULL),
         (void *) bigNumData,
         bigNumSize,
         strptr);
#pragma warn(1506)  // warning elimination 
      NADELETEBASIC(largestr, (PARSERHEAP()));	
      NADELETEBASIC(bigNumData, (PARSERHEAP()));
    } else { // precision >= FLT_MAX_10_EXP in a user-specified literal
      // genesis 10-030220-1214 documents a cpu halt can happen here when we
      // try to support digit precisions >= 77. The R2 version of this code
      // has Gautam Das' BigNum code. It does not seem to cause a cpu halt
      // but can quietly experience an overflow and give a wrong answer!
      *SqlParser_Diags << DgSqlCode(-3165) << DgString0(*strptr);
    }
  }
  //
  // Delete the original string (strptr),
  // but leave cvtstr alone (either a temporary, or identical to strptr)!
  delete strptr;
  return returnValue;
}


static Int32
removeDecimalPointReturnScale(NAString *strptr, NAString& tmpstr)
{
  // remove the decimal point, if any, from tmpstr
  size_t i, j, dot=0, strSize = strptr->length();
  for (i=j=dot; i < strSize; i++)
    if ((*strptr)[i] != '.')
      tmpstr[j++] = (*strptr)[i];
    else
      dot = j;			// Remember the position of the decimal point
  tmpstr.resize(j);             // adjust the size
  // return number's scale
  return Int32(strSize - dot -1); 
}


NABoolean literalToNumeric(NAString *strptr, double &val, char sign)
{
  // Create a new string after removing the decimal point, if any.
  NAString tmpstr(*strptr, strptr->length());
  size_t strSize;
  Int32 scale = removeDecimalPointReturnScale(strptr, tmpstr);

  // convert number into a double
  short shortVal; Lng32 longVal = 0; Int64 i64Val;
  char *bigNum = NULL; Lng32 bigNumSize;
  NABoolean result = literalToNumber
    (strptr, sign, &tmpstr, shortVal, longVal, i64Val, &bigNum,
     bigNumSize, strSize);
  if (result) {
    if (strSize < 5)
      val = shortVal * pow(10, -scale);
    else if (strSize < 10) 
      val = longVal * pow(10, -scale);
    else if (strSize < 19) 
      val = convertInt64ToDouble(i64Val) * pow(10, -scale);
    else {
      ComASSERT(BigNumHelper::ConvBigNumWithSignToInt64Helper
                (bigNumSize, bigNum, (void*)&i64Val,FALSE) == 0);
      val = convertInt64ToDouble(i64Val) * pow(10, -scale);
      NADELETEBASIC(bigNum, (PARSERHEAP()));
    }
  }
  delete strptr;
  return result;
}


ItemExpr *literalOfNumericWithScale(NAString *strptr, char sign)
{
  //
  // Create a new string after removing the decimal point, if any.
  //
  size_t strSize = strptr->length();
  NAString tmpstr(*strptr, strSize);
  size_t i, j, dot;
  for (i=j=dot=0; i < strSize; i++)
    if ((*strptr)[i] != '.')
      tmpstr[j++] = (*strptr)[i];
    else
      dot = j;			// Remember the position of the decimal point
  tmpstr.resize(j);             // adjust the size
  return literalOfNumericPassingScale(strptr, sign, &tmpstr, strSize - dot - 1);
}

NABoolean literalToDouble(NAString *strptr, double& val, 
                          NABoolean& floatP, char sign)
{
  NABoolean returnValue = FALSE; // assume failure until proven otherwise
  //
  // Compute the precision of the mantissa.  In other words, count the number
  // of significant digits in the mantissa.  Leading zeroes are not
  // significant.
  //
  UInt32 mantissaPrecision = 0;
  const char* s = *strptr;
  while ((*s != '\0') && (*s == '0'))
    s++;
  while ((*s != '\0') && (*s != 'e') && (*s != 'E')) {
    if (isdigit(*s++))
      mantissaPrecision++;
  }

  // Now get the size of the exponent
  Lng32 expValue = 0;
  if ((*s == 'e') || (*s == 'E')) {
    s++;
    expValue = atol(s);
  }

  // Having done that scanning, *now* it is safe to modify the text.
  //
  if (sign == '-') strptr->prepend(sign);

  floatP = FALSE;

  // check mantissa digits and exponent values to decide which type to build
  // and ensure some basic values are correct.
  // Overflow's and undflow's are caught at runtime in convDoIt()
  // under (case CONV_FLOAT64_FLOAT32:)
  if (mantissaPrecision < 8 &&             // real ?
      expValue < FLT_MAX_10_EXP &&
      expValue > -FLT_MAX_10_EXP)
  {
    floatP = TRUE;
  }
  else if (mantissaPrecision >= 20 ||
           expValue > DBL_MAX_10_EXP ||
           expValue < -DBL_MAX_10_EXP)
  {
    *SqlParser_Diags << DgSqlCode(-3165) << DgString0(*strptr);
    return returnValue;
  }

  // now try converting the string and see if there were problems
  char *endPtr;
  errno=0;
  val = strtod(*strptr, &endPtr);

  Int32 numErr=0;

  numErr = errno;

  // There are some anomalies with floating point operations on
  // NSK.  For instance strtod can produce double values that are
  // out-of-range with respect to the defines (DBL_MAX and
  // DBL_MIN).  Make range checking consistent with the executor
  // (see exp_conv.cpp convDoit, CONV_FLOAT64_FLOAT64).
  //
  if((val < -DBL_MAX) ||
     (val > DBL_MAX) ||
     (val != 0 && val < DBL_MIN && val > -DBL_MIN)) {
    numErr = ERANGE;
    val = 0;
  }
          

  // check for underflow and overflow
  if ( ((val == 0) &&
        ((numErr == ERANGE) ||                // underflo
         (strptr->data() == endPtr))) ||      // not a number
       (val == -HUGE_VAL) ||           // overflow
       (val ==  HUGE_VAL) )            // overflow
    *SqlParser_Diags << DgSqlCode(-3166) << DgString0(*strptr);
  else
    returnValue = TRUE; // success

  return returnValue;
}

ItemExpr *literalOfApproxNumeric(NAString *strptr, char sign)
{
  short rc = 0;
  ItemExpr *returnValue = NULL;

  if (sign == '-') 
    strptr->prepend(sign);

  double doubleVal;
  rc = convDoIt((char*)strptr->data(),
		(Lng32)strptr->length(),
		REC_BYTE_F_ASCII,
		0, 0,
		(char*)&doubleVal,
		sizeof(double),
		REC_FLOAT64,
		0, 0,
		NULL, 0, 
		PARSERHEAP(), 
		NULL,
		CONV_UNKNOWN);
  if (rc != 0)
    {
      *SqlParser_Diags << DgSqlCode(-3166) << DgString0(*strptr);;     
      return NULL;
    }

  returnValue = new (PARSERHEAP()) ConstValue (new (PARSERHEAP())
					       SQLDoublePrecision(FALSE),
					       (void *)&doubleVal,
					       sizeof(double),
					       strptr);
  if (returnValue == NULL)
    *SqlParser_Diags << DgSqlCode(-2006);     // out of memory error
  
  return returnValue;
}

ItemExpr *literalOfInterval(NAString *strptr,
                            IntervalQualifier *qualifier,
                            char sign)
{
  ItemExpr *returnValue = NULL;
  IntervalValue intervalValue(*strptr,
                              qualifier->getStartField(),
                              qualifier->getLeadingPrecision(),
                              qualifier->getEndField(),
                              qualifier->getFractionPrecision(),
                              sign);
  IntervalType *intervalType = new (PARSERHEAP())
		  SQLInterval(FALSE,
			      qualifier->getStartField(),
			      qualifier->getLeadingPrecision(),
			      qualifier->getEndField(),
			      qualifier->getFractionPrecision(),
                              PARSERHEAP());
  strptr->prepend("'");
  strptr->append ("' ");
  strptr->append (intervalType->getIntervalQualifierAsString());
  if (! intervalValue.isValid())
    *SqlParser_Diags << DgSqlCode(-3044) << DgString0(*strptr);
  else 
    {
     if (!intervalType->isSupportedType())  // issue a warning
     {
      *SqlParser_Diags << DgSqlCode(3044) << DgString0(*strptr);
     }
     if (sign == '-') 
     {
      strptr->prepend("-");
     }
     strptr->prepend("INTERVAL ");
     returnValue = new (PARSERHEAP()) ConstValue(
                        intervalType,
                        (void *) intervalValue.getValue(),
                       intervalValue.getValueLen(),
                        strptr);
    }
  delete strptr;
  //assert (returnValue);	//don't assert; caller checks value for NULL
  return returnValue;
}


ItemExpr *literalOfDate(NAString *strptr, NABoolean noDealloc)
{
  ItemExpr *returnValue = NULL;
  UInt32 fractionPrec;
  DatetimeValue dtValue(*strptr, REC_DATE_YEAR, REC_DATE_DAY, fractionPrec,
                        (CmpCommon::getDefault(USE_OLD_DT_CONSTRUCTOR) == DF_ON));
  if ((! dtValue.isValid()) &&
      (CmpCommon::getDefault(MARIAQUEST_PROCESS) == DF_OFF))
     *SqlParser_Diags << DgSqlCode(-3045) << DgString0(*strptr);
  else
    returnValue = new (PARSERHEAP()) ConstValue (new (PARSERHEAP())
		    SQLDate(FALSE, PARSERHEAP()),
		    (void *) dtValue.getValue(),
		    dtValue.getValueLen(),
		    strptr);
  if (NOT noDealloc)
    delete strptr;
  //assert (returnValue);	//don't assert; caller checks value for NULL
  return returnValue;
}


ItemExpr *literalOfTime(NAString *strptr)
{
  ItemExpr *returnValue = NULL;
  UInt32 fractionPrec = 0;
  DatetimeValue dtValue(*strptr, REC_DATE_HOUR, REC_DATE_SECOND, fractionPrec,
                        (CmpCommon::getDefault(USE_OLD_DT_CONSTRUCTOR) == DF_ON));
  if ((! dtValue.isValid()) &&
      (CmpCommon::getDefault(MARIAQUEST_PROCESS) == DF_OFF))
      *SqlParser_Diags << DgSqlCode(-3046) << DgString0(*strptr);
  else
    returnValue = new (PARSERHEAP()) ConstValue (new (PARSERHEAP())
		    SQLTime(FALSE, fractionPrec,PARSERHEAP()),
		    (void *) dtValue.getValue(),
		    dtValue.getValueLen(),
		    strptr);
  delete strptr;
  //assert (returnValue);	//don't assert; caller checks value for NULL
  return returnValue;
}
//
// This routine handles MP-style datetime literals; some of these literals map to ANSI
// DATE, TIME or TIMESTAMP, in which case the corresponding NAType is generated.
//
ItemExpr *literalOfDateTime(NAString *strptr, DatetimeQualifier *qualifier)
{
  ItemExpr *returnValue = NULL;
  UInt32 fractionPrec = qualifier->getFractionPrecision();
  DatetimeValue    dtValue(*strptr,
                           qualifier->getStartField(),
                           qualifier->getEndField(),
                           fractionPrec,                   // returned value
                           (CmpCommon::getDefault(USE_OLD_DT_CONSTRUCTOR) == DF_ON));

  DatetimeType  *dtType = DatetimeType::constructSubtype(       // This call is necessary to insure that we return
                               FALSE,                           // a standard DateTime, if possible.
                               qualifier->getStartField(),
                               qualifier->getEndField(),
                               fractionPrec,
                               PARSERHEAP()
                               );
  if (!dtType)
  {
   *SqlParser_Diags << DgSqlCode(-3158) << DgString0(""); // Error - invalid datetime
  }
  else
  {
   strptr->prepend("'");
   strptr->append ("'");
   strptr->append (dtType->getDatetimeQualifierAsString(TRUE));
   if (dtType->checkValid(SqlParser_Diags))
   {
    if (!dtValue.isValid())
    {
    *SqlParser_Diags << DgSqlCode(-3158) << DgString0(*strptr); // Error - invalid datetime
    }
    else
    {
    if (!dtType->isSupportedType())
    { 
    *SqlParser_Diags << DgSqlCode(3158) << DgString0(*strptr); // Warning - invalid datetime
    }
    strptr->prepend("DATETIME");
    returnValue = new (PARSERHEAP()) ConstValue(
                    dtType,
                    (void *) dtValue.getValue(),
                    dtValue.getValueLen(),
                    strptr);
    }
   }
  }
  delete strptr;
  //assert (returnValue);       //don't assert; caller checks value for NULL
  return returnValue;
  }




ItemExpr *literalOfTimestamp(NAString *strptr)
{
  ItemExpr *returnValue = NULL;
  UInt32 fractionPrec = 0;
  DatetimeValue dtValue(*strptr, REC_DATE_YEAR, REC_DATE_SECOND, fractionPrec,
                        (CmpCommon::getDefault(USE_OLD_DT_CONSTRUCTOR) == DF_ON));
  if ((! dtValue.isValid()) &&
      (CmpCommon::getDefault(MARIAQUEST_PROCESS) == DF_OFF))
     *SqlParser_Diags << DgSqlCode(-3047) << DgString0(*strptr);
  else
    returnValue = new (PARSERHEAP())
      ConstValue (new (PARSERHEAP())
                  SQLTimestamp (FALSE, fractionPrec, PARSERHEAP()),
                  (void *) dtValue.getValue(),
                  dtValue.getValueLen(),
                  strptr);
  delete strptr;
  //assert (returnValue);	//don't assert; caller checks value for NULL
  return returnValue;
}


void parseCasedIdentifier(ParCaseIdentifierClauseType clauseType,
                          NAString *pClauseBuffer,
                          NAString &casedIdentifier)
{
  assert(pClauseBuffer);
  NAString workBuf(*pClauseBuffer);
  StringPos invalidCharPos;

  switch (clauseType)
  {
   case ParCALL_CASED_IDENTIFIER_CLAUSE :
     {
     //  remove leading reserved word CALL from workBuf
     StringPos firstBlankPos = 0, startPos = 0;
     firstBlankPos = IndexOfFirstWhiteSpace(workBuf, startPos);
     ComASSERT(firstBlankPos != NA_NPOS);
     NAString firstTok(workBuf(startPos, firstBlankPos-startPos/*length*/));
     casedIdentifier = workBuf;
     TrimNAStringSpace(casedIdentifier,TRUE,FALSE);

     break;
     }
   case ParGOTO_CASED_IDENTIFIER_CLAUSE :
     {
     //  remove leading reserved word GOTO or GO TO from workBuf
     StringPos firstBlankPos, startPos = 0;
     firstBlankPos = IndexOfFirstWhiteSpace(workBuf, startPos);
     ComASSERT(firstBlankPos != NA_NPOS);
     NAString firstTok(workBuf(startPos, firstBlankPos-startPos/*length*/));
     startPos = IndexOfFirstNonWhiteSpace(workBuf, firstBlankPos);  // skips blank(s)
     if ( firstTok == "GO" ) // either "GO TO" or "GOTO" 
       { // skips GO
       StringPos secondBlankPos = IndexOfFirstWhiteSpace(workBuf, startPos);
       assert(secondBlankPos != NA_NPOS);
	   // skips TO
       startPos = IndexOfFirstNonWhiteSpace(workBuf, secondBlankPos);  // skips blank(s)
       }

     // gets cased identifier
     casedIdentifier = workBuf(startPos,workBuf.length()-startPos/*length*/);

     break;
     }
   case ParPERFORM_CASED_IDENTIFIER_CLAUSE :
     {
     //  remove leading reserved word PERFORM from workBuf
     //  please note that PERFORM is not a reserved word.
     StringPos firstBlankPos, startPos = 0;
     firstBlankPos = IndexOfFirstWhiteSpace(workBuf, startPos);
     ComASSERT(firstBlankPos != NA_NPOS);
     NAString firstTok(workBuf(startPos, firstBlankPos-startPos/*length*/));
     startPos = IndexOfFirstNonWhiteSpace(workBuf, firstBlankPos);  // skips blank(s)

     // gets cased identifier
     casedIdentifier = workBuf(startPos,workBuf.length()-startPos/*length*/);

     if (IdentifyMyself::GetMyName() != I_AM_COBOL_PREPROCESSOR) 
       {
	 *SqlParser_Diags << DgSqlCode(-3133); // PERFORM is valid only in COBOL
	 return;
       }

     break;
     }

   default :
     {
	 *SqlParser_Diags << DgSqlCode(-4000); // internal error
	 return;
	 }
   } // end of switch (clauseType)

  // If the running process is the C preprocessor, checks to make sure that 
  // workBuf contains a valid C identifier; otherwise, issues an error message. 
  // Please note that workBuf may contain a delimited identifier.

  // If the running process is the COBOL preprocessor, checks to make sure that
  // workBuf contains a valid COBOL work; otherwise, issues an error message.

  // If workBuf contains a regular identifier, makes sure that it is not a 
  // reserverd word.

  switch (IdentifyMyself::GetMyName())  
  {
    case I_AM_C_PREPROCESSOR:
	  {
          if (!IsCIdentifier(casedIdentifier.data()))
            {
	      //Illegal character in identifier $0~string0.
              *SqlParser_Diags << DgSqlCode(-3127)
		               << DgString0("C identifier " + casedIdentifier);
	      return;
            } 
	  break;
	  }
    case I_AM_COBOL_PREPROCESSOR:
	  {
          *SqlParser_Diags << DgSqlCode(-4222)
                           << DgString0("COBOL embedded SQL");
          return;
	  }
    default:
          {
          // error, should not have come here
	  *SqlParser_Diags << DgSqlCode(-4000); // internal error
	  break;
          }
  } // end of switch

} // end of parseCasedIdentifier


// deletes all members of seq[]  (recall in C++ delete NULL does nothing)
ShortStringSequence::~ShortStringSequence()
{
   for (UInt32 i=0; i!=MAX_NUM_PARTS; i++)
     delete seq[i];
} // destructor

// Sets up numParts_ to 0.  seq[] is all NULLs.
// Cannot determine seqPos_ and seqEndPos_.  Sets them to 0.
ShortStringSequence::ShortStringSequence()
  : numParts_(0),
    toInternalIdentifierFlags_(NASTRING_ALLOW_NSK_GUARDIAN_NAME_FORMAT),
    seqPos_(0),
    seqPosStartOffset_(0),
    seqEndPos_(0)
{
  for (UInt32 i=0; i!=MAX_NUM_PARTS; i++)
    seq[i] = NULL;
} // default constructor

// numParts_ gets 1.  seq[] is { arg, NULL, NULL, ... }.
ShortStringSequence::ShortStringSequence(NAString *arg,
                                         unsigned short toInternalIdenfifierFlags)
{
  toInternalIdentifierFlags_ = toInternalIdenfifierFlags;
  numParts_ = 1;
  seq[0] = arg;
  for (UInt32 i=numParts_; i!=MAX_NUM_PARTS; i++)
    seq[i] = NULL;

  // initialize seqPos_, seqEndPos_ with the info from the ParScannedTokenQueue.
  //
  const ParScannedTokenQueue::scannedTokenInfo &tokInfo = getTokInfo(arg);
  if (isValid())
  {
    seqPos_    = tokInfo.tokenStrPos;
    seqEndPos_ = tokInfo.tokenStrPos + tokInfo.tokenStrLen - 1;
    seqPosStartOffset_ = tokInfo.tokenStrOffset ;
  }

} // ShortStringSequence ctor

// Increments numParts_.  If numParts_ < MAX_NUM_PARTS, then sets seq[numParts_]
// to be a copy of arg.  If numParts_ >= MAX_NUM_PARTS, just the
// incrementing is all we need do (if this behavior seems odd, note the
// term "Short" in the name of this class).
void ShortStringSequence::append(NAString* arg)
{
  if (++numParts_ > MAX_NUM_PARTS)
  {
    invalidate();
    delete arg;
    return;
  }
  seq[numParts_-1] = arg;

  // update seqEndPos_ with the information from the ParScannedTokenQueue.
  //
  const ParScannedTokenQueue::scannedTokenInfo &tokInfo = getTokInfo(arg);
  if (isValid())
  {
    seqEndPos_ = tokInfo.tokenStrPos + tokInfo.tokenStrLen - 1;
    //
    // If this ShortStringSequence had a previous multi-byte component,
    // then tokInfo.tokenStrPos has extra bytes added to it which should NOT
    // be counted ar part of the length (in UCS2 chars) of the string, so
    // we must subtract off any such extra bytes that were added.
    //
    seqEndPos_ -= tokInfo.tokenStrOffset - seqPosStartOffset_ ;
  }

} // ShortStringSequence::append

// For i>=MAX_NUM_PARTS assertion fail.
// Otherwise return the pointer, seq[i], and set seq[i] to NULL.
NAString* ShortStringSequence::extract(UInt32 i)
{
  assert(i<MAX_NUM_PARTS);
  NAString  *resultValue = seq[i];
  seq[i] = NULL;
  return resultValue;
} // ShortStringSequence::extract

void ShortStringSequence::invalidate()
{
  // mark it as invalid:
  numParts_ = MAX_NUM_PARTS + 1;
  yyerror("Invalid SQL identifier");

  /*
    All callers of ShortStringSequence methods (ctor and append)
    must follow with a call to isValid, and if it isn't, then a YYABORT.
    This is because the following (commented out) does not work!
	// emulate YYABORT here, with
	// assert (*not* COMassert!)
	// to break out of parser
	assert(FALSE);
  */
}

const ParScannedTokenQueue::scannedTokenInfo&
ShortStringSequence::getTokInfo(NAString *arg)
{
  // The parser may look ahead one or more tokens.
  // So the most recently scanned token (with 0th index)
  // may not relate to the string pointed to by 'arg';
  // if not, then -1th indexed token (the previously scanned token) should.

  const ParScannedTokenQueue::scannedTokenInfo *tokInfoPtr = NULL;
  NAWchar *inputStr = SQLTEXTW();
  Int32 downTo = -1;
  for (Int32 i = 0; i >= downTo; i--)
    {
      const ParScannedTokenQueue::scannedTokenInfo &tokInfo
	= ParScannedTokens->getScannedTokenInfo(i);

      // is the i'th tok a valid SQL identifier?
      // offset is subtracted off because in THIS case it is the Wide copy

      size_t idx = tokInfo.tokenStrPos - tokInfo.tokenStrOffset;
      NAString *iTok = unicodeToChar(&inputStr[idx],
                                     tokInfo.tokenStrLen,
                                     (Lng32) ComGetNameInterfaceCharSet(), // SQLCHARSETCODE_UTF8
                                     PARSERHEAP());

      // This identifier string needs to be converted back to
      // ISO88591 because it may be passed to catman code to
      // determine if the named object exists. When catman 
      // becomes Unicode-enabled, this ISO88591 conversion
      // can go away. This comment also applies to other 
      // unicodeToChar() call sites here & elsewhere.
      if (!iTok)
        break;

      TrimNAStringSpace(*iTok);
      if (iTok->isNull() || tokInfo.tokenIsComment)
      {
        downTo--;
        delete iTok;
        continue;
      }
      
      if (!ToInternalIdentifier ( *iTok
                                , TRUE // upCase - default is TRUE
                                , TRUE // ^ ok?  - default is FLASE
                                , toInternalIdentifierFlags_
                                )
          && *arg == *iTok)
      {
        delete iTok;
        return tokInfo;
      }

      delete iTok;
      tokInfoPtr = &tokInfo;
    }

  invalidate();		// one or both tokens is an invalid SQL identifier
  return *tokInfoPtr;
  
} // ShortStringSequence::getTokInfo

// For error messages
NAWString badNameFromStrings(ShortStringSequence *names)
{
  assert(names);
  NAWString result(SQLTEXTW());
  result.remove(names->getEndPosition()+1);
  result.remove(0, names->getPosition());   // pos BEFORE the name began
  delete names;
  return result;
}

// This function is used in xxxNameFromStrings() functions below. 
void getNamePart(NAString &xxxName, ShortStringSequence *names,
                 UInt32&index)
{
  if (index>0) {
    NAString namePtr (*(names->extract(--index)));
    xxxName = namePtr;
  }
}

static NABoolean CharHereIsaDoubleQuote(StringPos p) {
  return SqlParser_CurrentParser && 
    SqlParser_CurrentParser->CharHereIsDoubleQuote(p);
}

// This function knows that if there is only one
// name it is the table name, two names, table and schema, all three
// then table, schema, and catalog.  And this is what it returns:
// a CorrName object whose corrName_ string is empty and whose
// QualifiedName fields are filled in with table, schema, and catalog.
//
// The input argument must not be NULL.  It must also have at least
// one, and not more than three (> 3 is an assertion error), name parts.
// Each of the names is extracted and then placed into a CorrName object
// that is returned.  A NULL return value implies that there was an error.

QualifiedName * qualifiedNameFromStrings(ShortStringSequence *names)
{
  assert(names);
  UInt32 index = names->numParts();
  assert(index>0);

  NAString  tblName;
  NAString  schName;
  NAString  catName;

  getNamePart(tblName,names,index);
  getNamePart(schName,names,index);
  getNamePart(catName,names,index);

  if (index) {
    // ~String0 is an invalid qualified name 
    *SqlParser_Diags << DgSqlCode(-3011)
      << DgWString0(badNameFromStrings(names));
    return NULL;
  }

  StringPos startPos = names->getPosition();
  delete names;
  QualifiedName *result = new (PARSERHEAP()) 
    QualifiedName(tblName, schName, catName, PARSERHEAP());
  ComASSERT(result);
  result->setNamePosition(startPos, CharHereIsaDoubleQuote(startPos));
  return result;
}

// if the schemaName part inName contains volatile schema prefix, then
// return an error. Don't do this if volatile schema prefix is allowed
// for internal queries.
// If validateVolatileName is set, then validate that:
//      -- volatile schema exists
//      -- name is a one or 2 part name
//      -- if 2-part name, then the schPart is the currentUserName.
// If updateVolatileName is set and the name is validate to be a volatile
// name, then change the schema name to be the current volatile schema
// name.
const NABoolean validateVolatileSchemaName(NAString &schName)
{
  return CmpCommon::context()->sqlSession()->
    validateVolatileSchemaName(schName);
}

SchemaName * processVolatileSchemaName(SchemaName *schName,
				       NABoolean validateVolatileName,
				       NABoolean updateVolatileName)
{
  SchemaName *result = schName;
  
  if (validateVolatileName)
    {
      //if ((!schName) ||
      //  (! validateVolatileSchemaName(*schName)))
      //return NULL;
    }

  if (updateVolatileName)
    {
      result = CmpCommon::context()->sqlSession()->updateVolatileSchemaName();
    }

  return result;
}

QualifiedName * processVolatileDDLName(QualifiedName * inName,
				       NABoolean validateVolatileName,
				       NABoolean updateVolatileName)
{
  QualifiedName *result = inName;

  if (NOT inName->getSchemaName().isNull())
    {
      if (! CmpCommon::context()->sqlSession()->
	  validateVolatileQualifiedSchemaName(*inName))
	return NULL;
    }

  if (validateVolatileName)
    {
      if (! CmpCommon::context()->sqlSession()->validateVolatileQualifiedName(*inName))
	return NULL;
    }

  if (updateVolatileName)
    {
      result = CmpCommon::context()->sqlSession()->updateVolatileQualifiedName(*inName);
    }

  return result;
}

CorrName * corrNameFromStrings(ShortStringSequence *names)
{
  QualifiedName *qn = qualifiedNameFromStrings(names);
  if (!qn) return NULL;

  CorrName *result;

  // ##SQLMP-SYNTAX-KLUDGE##
  //
  // ## Temporarily ##??, till we get ANSI name mapping working for
  // SQL/MP tables, this code stuffs the tablename into the corr name.
  //
  // MP-style queries may look like this:
  //   "SELECT T1.A, Y.B, T3.C FROM \Q.$R.S.T1, \N.$O.P.T2 Y, \K.$L.M.T3"
  // which uses non-ANSI defaulting rules for correlation names.
  //
  // If in NSK nametype mode, here we supply implicit corr names AS IF
  // the user had input
  //   "SELECT T1.A, Y.B, T3.C FROM \Q.$R.S.T1 T1, \N.$O.P.T2 Y, \K.$L.M.T3 T3"
  //
  // These implicit corr names are overridden if the user supplies
  // an explicit corr name -- by setCorrName() in rule "table_name as_clause" --
  // as in the "T2 Y" in the example here.
  //
  // ## See GenericUpdate::bindNode(), which UNDOES this temporary corr.

  const NAString &tblName = qn->getObjectName();

  if ((qn->getCatalogName() == "") && (SqlParser_NAMETYPE == DF_NSK))
    result = new (PARSERHEAP()) CorrName(*qn, PARSERHEAP(), tblName);
  else
    result = new (PARSERHEAP()) CorrName(*qn, PARSERHEAP());

  ComASSERT(result);

  result->setNamePosition(qn->getNamePosition(),
                          CharHereIsaDoubleQuote(qn->getNamePosition()));
  return result;
}


ColRefName *colRefNameFromStrings(ShortStringSequence *names)
{
  assert(names);
  UInt32 index = names->numParts();
  assert(index>0);

  NAString  colName;
  NAString  tblName;
  NAString  schName;
  NAString  catName;

  getNamePart(colName,names,index);
  getNamePart(tblName,names,index);
  getNamePart(schName,names,index);
  getNamePart(catName,names,index);

  if (index) {
    // ~String0 is an invalid colref name 
    *SqlParser_Diags << DgSqlCode(-3002)
      << DgWString0(badNameFromStrings(names));
    return NULL;
  }

  StringPos startPos = names->getPosition();
  delete names;
  ColRefName *result = new (PARSERHEAP())
    ColRefName(colName, CorrName(tblName, PARSERHEAP(), schName, catName), PARSERHEAP());
  ComASSERT(result);
  result->setNamePosition(startPos, CharHereIsaDoubleQuote(startPos));
  return result;
}


// The purpose of this function is to convert NAStrings that contain
// delimited identifiers as detected by SqlLexer
// to a format we can use internally.
//
// If a string begins with a double quote, then
// this function takes an NAString and:
//    - there are supposed to be double quotes surrounding the string
//      and they are removed
//    - any embedded double quotes (i.e., two consecutive dquotes)
//	are turned into just one dquote
//
// If the string does not begin with a double quote, then the
// only transformation is to make all the contents upper case.
//
// Efficiency: this function saves on space at the cost of some time.
// The calls to NAString.remove() probably take linear time as a function
// of string length on each call.  A faster version of this function
// would establish a transformed string in a separate buffer and then
// copy it back into the original.

NABoolean transformIdentifier(NAString& delimIdent, 
                              Int32 upCase,
                              NABoolean acceptCircumflex    // VO: Fix genesis solution 10-040204-2957
                             ,UInt16 toInternalIdentifierFlags
                             )
{
  NAString origIdent(delimIdent);
  Lng32 sqlcode = ToInternalIdentifier(delimIdent, upCase, acceptCircumflex, toInternalIdentifierFlags);

  if (sqlcode) {
    // 3004 A delimited identifier must contain at least one character.
    // 3118 Identifier too long.
    // 3127 Illegal character in identifier $0~string0.
    // 3128 $1~string1 is a reserved word.
    *SqlParser_Diags << DgSqlCode(sqlcode) 
                     << DgString0(origIdent)
                     << DgString1(delimIdent);

    if (sqlcode > 0) sqlcode = -sqlcode;
    if (sqlcode != -3118) {
      if (sqlcode == -3127) {
        Int32 i = -delimIdent[(size_t)0];	// count of scanned chars
        if (i > 0) i = -i;
        i += ((Int32)origIdent.length()) - 1;
        if (i > 0) {
          SqlParser_CurrentParser->getLexer()->setInputPos(i);
          // point to the illegal character
        }
      }
      yyerror("");			// emit syntax error 15001
    }

    return TRUE;
  }

  return FALSE;		// no error
}


void PicStream::skipPicture()
{
   NAString   theIdentifier;
#pragma nowarn(1506)   // warning elimination 
   while (isalpha(sgetc())) theIdentifier.append(toupper(sbumpc()));
#pragma warn(1506)  // warning elimination 
   skipWhite();
   NAString string1 = "PIC";
   NAString string2 = "PICTURE";
   assert(theIdentifier == string1 || theIdentifier == string2);
}

// The skipCount function is basically a loop that on each pass
// either gets a single character, or gets a single
// character followed by some parens with an enclosed integer, and optionally
// followed by a character length unit identifier ('CHARACTERS' for R2.0).
// We assertion fail on a syntax error --- this should be okay since
// the SqlLexer.l is guaranteed (read: is supposed to) give us only
// valid strings to parse in the first place and not doing so is a
// programming error.

NABoolean PicStream::skipCount (UInt32*result, const char pattern, NABoolean isCharType)
{
   assert(toupper(sgetc()) == pattern);
   UInt32   total = 0;
   do {
      stossc();
      if (sgetc() == '(') {
         // Next we advance over the characters in a pattern
         // of `( <unsigned-int> )' where there may be white space after
         // the left parens and white space before the right parens.  It is
         // an assertion fail (and ostensibly a SqlLexer.l error) if this
         // pattern is not encountered.  The unsigned int is parsed
         // and its value added to total.
         stossc();
         skipWhite();
         assert(isdigit(sgetc()));
         UInt32 val = 0;
         do {
            val = (val*10) + sbumpc() - '0';
	    if(val > SHORT_MAX)
	      return FALSE;
	    
         } while (isdigit(sgetc()));
         skipWhite();
#pragma nowarn(1506)   // warning elimination 
         char ch = sbumpc();
#pragma warn(1506)  // warning elimination 

         if ( isCharType == TRUE && ( ch=='C' || ch=='c' ) ) {

            char len_unit_array[11]; // len("CHARACTERS") = 10
            len_unit_array[0] = ch;  // store 'c'
            Int32 n = sgetn(len_unit_array+1, 9); // get the rest of "haracters"
            len_unit_array[10] = NULL;
            assert(n == 9 && strcasecmp(len_unit_array, "CHARACTERS") == 0);

            skipWhite();
#pragma nowarn(1506)   // warning elimination 
            ch = sbumpc();
#pragma warn(1506)  // warning elimination 
         }

         assert(ch==')');
         total += val;
      }
      else
         total++;
      if(total > SHORT_MAX)
	return FALSE;
   } while ( toupper(sgetc()) == pattern);
   *result = total;
   return TRUE;
}


// parsePicClause() accepts a char* and either
// assertion fails (fundamentally due to a SqlLexer.l error), or,
// yields the following data about a PIC clause:  string or not string,
// precision (length), scale,  signed or not signed.  Of course,
// scale and signedness only apply to the case of `not string.'
//
// The basic formats which this function parses are:
// PX, P9, PV9, P9V9, PS9, PSV9, PS9V9
// where P is the `PICTURE' part, X is a cobol-x's clause, 9 is a cobol-9's
// clause, and S and V are the letter S and V (upper or lower case),
// respectively.

// return TRUE if successful, FALSE if overflow
NABoolean parsePicClause(NAString *picClauseBuffer, NABoolean  *isStringPtr,
			 UInt32*precisionPtr, UInt32*scalePtr,
			 NABoolean *hasSignPtr)
{
   assert(picClauseBuffer);
   assert(precisionPtr);
   assert(isStringPtr);

   UInt32   frontPart=0;  // if a format is 99V999 then front=2, back=3
   UInt32   backPart=0;

   // We intentionally "cast away" const in the next line.
   // We need the char* pointer but the NAString::data() is defined as const.
   // Don't worry, we don't modify the string, and it wouldn't matter anyway.
   PicStream   s( (char *) picClauseBuffer->data());
   s.skipPicture();

   if (toupper(s.sgetc()) == 'X') {

      if(s.skipCount(precisionPtr, 'X', TRUE) == FALSE)
	return FALSE;

      *isStringPtr  = TRUE;
   }
   else {
      assert(hasSignPtr);
      assert(scalePtr);

      // Syntax of just 'S' or 'V' or 'SV' with no 9's are caught
      // by the picNAType() function.

      if (toupper(s.sgetc()) == 'S') {
         *hasSignPtr = TRUE;
         s.stossc();
      }
      else
         *hasSignPtr = FALSE;

      if (s.sgetc() == '9')
	if( s.skipCount(&frontPart, '9') == FALSE)
	  return FALSE;

      if (toupper(s.sgetc()) == 'V') {
         s.stossc();
         if (s.sgetc() == '9')
            if( s.skipCount(&backPart, '9') == FALSE)
	      return FALSE;
      }

      // We know this is the numeric case.
      // Also, frontPart + backPart = precision and backPart = scale.
      *precisionPtr   = frontPart + backPart;
      *scalePtr       = backPart;
      *isStringPtr    = FALSE;
   }
   assert(s.sgetc() == EOF);
   return TRUE;
}


// This function is used in the productions that handle the COBOL style
// PIC type declarations.  It accepts some parameters gleaned from the
// PIC syntax and either issues an error message, returning NULL,
// or returns a pointer to a newly allocated NAType appropriate
// to the given parameters.

NAType *picNAType(const NABoolean      isString, 
                  const DISPLAY_STYLE  style,
                  const UInt32       precision,
                  const UInt32       scale,
                  const NABoolean      hasSign,
                  const CharInfo::CharSet charset,
                  const CharInfo::Collation collation,
                  const CharInfo::Coercibility coerc,
                  const NAString &     picClauseBuffer,
		  const NABoolean      isCaseinsensitive)
{
   NAType    *returnValue=NULL;

   if (isString) {
      assert(precision > 0);
      switch (style) {
        case STYLE_DISPLAY:
          {
            CharInfo::CharSet eEncodingCharSet = charset;
            Int32 maxLenInBytes = precision;
            Int32 characterLimit = precision;
            Int32 maxBytesPerChar = CharInfo::maxBytesPerChar(charset);
            returnValue = new (PARSERHEAP())
              //            SQLChar(precision,TRUE,FALSE,isCaseinsensitive,FALSE,charset,collation,coerc);
              SQLChar(CharLenInfo(characterLimit, maxLenInBytes),
                      TRUE,FALSE,isCaseinsensitive,FALSE,
                      charset,collation,coerc,eEncodingCharSet);
            assert(returnValue);
          }
          break;
        case STYLE_UPSHIFT:
	    returnValue = new (PARSERHEAP())
#pragma nowarn(1506)   // warning elimination 
  		SQLChar(precision,TRUE,TRUE,isCaseinsensitive,FALSE,charset,collation,coerc);
#pragma warn(1506)  // warning elimination 
            assert(returnValue);
            break;
        case STYLE_LEADING_SIGN:
	    // PIC X types cannot have leading signs, or any signs.
            *SqlParser_Diags << DgSqlCode(-3038);   
            break;  
        case STYLE_COMP:
	    // PIC X types do not have any COMP representation.
            *SqlParser_Diags << DgSqlCode(-3039);
            break;  
        default:  assert(FALSE);
      }
   }
   else if (precision == 0)
     //  You can't have a precision of zero.  Add a '9' to
     //  the PICTURE clause.
         *SqlParser_Diags << DgSqlCode(-3040);
   else
      switch (style) {
        case STYLE_DISPLAY:
        case STYLE_LEADING_SIGN:
           if (scale >= 10  && !hasSign) {
	     // If scale is greater than or equal to 10, UNSIGNED
             // is invalid for a numeric or decimal type specification.
                *SqlParser_Diags << DgSqlCode(-3041);
              break;
           }
           else if (precision > 18)
           {
              // Precision of PIC 9 types, $0~string0, cannot exceed 18.
              *SqlParser_Diags << DgSqlCode(-3037)
                               << DgString0(picClauseBuffer.data());
              break;
           }
           else
              returnValue = new (PARSERHEAP())
#pragma nowarn(1506)   // warning elimination 
		SQLDecimal(precision,scale,hasSign);
#pragma warn(1506)  // warning elimination 
           assert(returnValue);
           break;
        case STYLE_UPSHIFT:
	  // Upshift for a numeric type is invalid.
             *SqlParser_Diags << DgSqlCode(-3042);
           break;  
        case STYLE_COMP:
           if (scale >= 10  && !hasSign) {
	      // If scale is greater than or equal to 10, UNSIGNED
              // is invalid for a numeric or decimal type specification.
              *SqlParser_Diags << DgSqlCode(-3041);
              break;
           }
           else if (precision > 18)
	      // Precision greater than eighteen invalid for a COMP
	      // numeric type.
              *SqlParser_Diags << DgSqlCode(-3043);
           else {
              const Int16 DisAmbiguate = 0; // added for 64bit project
              returnValue = new (PARSERHEAP())
#pragma nowarn(1506)   // warning elimination 
		SQLNumeric(hasSign, precision, scale, DisAmbiguate);
#pragma warn(1506)  // warning elimination 
              assert(returnValue);
           }
           break;
        default:  assert(FALSE);
      }
   return returnValue;
}


// : value_expression_list TOK_IN '(' value_expression_list ')'
// Convert "v IN (v1, v2 ...)" to "v=v1 OR v=v2 ...".
//
// This transformation is somewhat arbitrary (it creates a left-deep
// tree, instead of a right-deep or bushy or ...), and could easily be
// improved -- i.e., removing duplicates.
//
// NB: The left-deep nature of the resulting OR-tree is expected by
// histogram-manipulation code in /optimizer/ColStatDesc.cpp,
// CSDL::estimateCardinality().  If you change this transformation, then
// please change the code there, too.  (Or at least talk to the owner of
// the histogram code.)
ItemExpr *convertINvaluesToOR(ItemExpr *lhs, ItemExpr *rhs)
{
  NABoolean err = FALSE;
  if (lhs->getOperatorType() == ITM_ITEM_LIST)
    err = TRUE;
  else if (lhs->getOperatorType() == ITM_ROW_SUBQUERY)
    {
      RelExpr *subq = ((RowSubquery *)lhs)->getSubquery();
      CMPASSERT( subq->getOperatorType() == REL_ROOT );

      RelRoot *sq = (RelRoot *)subq;
      RelExpr *theChild;
      theChild = sq->child(0);
  
      if (sq->getCompExprTree() &&	// what if no compExprTree()?
          sq->getCompExprTree()->getOperatorType() == ITM_ITEM_LIST)
        err = TRUE;
      else if (theChild->getOperatorType() == REL_TUPLE &&
               ((Tuple *)theChild)->tupleExprTree()->getOperatorType() == 
                                       ITM_ITEM_LIST)
        err = TRUE;
    }
  if (err)
    {
      // 3147 The left operand of an IN predicate whose right operand is
      //      a value list must be scalar (degree of one).
      *SqlParser_Diags << DgSqlCode(-3147);
      return NULL;
    }

  ExprValueId rightListId = rhs;

  ItemExprTreeAsList *enl = new (PARSERHEAP())
    ItemExprTreeAsList(&rightListId, ITM_ITEM_LIST);

  ItemExpr *result = NULL;
  CollIndex nEnlEntries = (CollIndex) enl->entries();
  for (Lng32 i = 0; i < nEnlEntries ; i++)
    {
      BiRelat *eqpred = new (PARSERHEAP()) BiRelat(ITM_EQUAL, lhs, (*enl)[i]);
      eqpred->setCreatedFromINlist(TRUE);
      if (!result)
	result = eqpred;
      else
	result = new (PARSERHEAP()) BiLogic(ITM_OR, result, eqpred);
    }

  if (result && result->getOperatorType() == ITM_OR)
    ((BiLogic*)result)->setCreatedFromINlist(TRUE);
  return result;
}


// quantified_predicate : value_expression_list '=' quantifier rel_subquery
ItemExpr *makeQuantifiedComp(ItemExpr *lhs,
                             OperatorTypeEnum compOpType,
                             Int32 quantifierTok,
                             RelExpr *subquery)
{
  assert(quantifierTok == TOK_ALL || quantifierTok == TOK_ANY);
  NABoolean all = (quantifierTok == TOK_ALL);

  OperatorTypeEnum resultOpType = NO_OPERATOR_TYPE;
  switch (compOpType)
    {
    case ITM_EQUAL:
         resultOpType 	= all ? ITM_EQUAL_ALL      : ITM_EQUAL_ANY;      break;
    case ITM_LESS:
         resultOpType 	= all ? ITM_LESS_ALL       : ITM_LESS_ANY;       break;
    case ITM_GREATER:
         resultOpType 	= all ? ITM_GREATER_ALL    : ITM_GREATER_ANY;    break;
    case ITM_NOT_EQUAL:
	 resultOpType 	= all ? ITM_NOT_EQUAL_ALL  : ITM_NOT_EQUAL_ANY;  break;
    case ITM_LESS_EQ:
	 resultOpType 	= all ? ITM_LESS_EQ_ALL    : ITM_LESS_EQ_ANY;    break;
    case ITM_GREATER_EQ:
	 resultOpType	= all ? ITM_GREATER_EQ_ALL : ITM_GREATER_EQ_ANY; break;
    default:
	 assert(FALSE);
    }
  return new (PARSERHEAP()) QuantifiedComp(resultOpType, lhs, subquery, FALSE);
}

///////////////////////////////////////////////////////////////////////////
// this method converts an IN list to a VALUES subquery or
// converts it to an OR predicate.
// Conversion to VALUES SQ is done
// if all IN list elements are constants or parameters and
// the number of elements are greater than 100. For less than
// 100, it might be better to use the IN predicate so mdam could
// be chosen. The number 100 is experimental and may change.
//   <value> IN (<val1>, ...., <valN>)  gets converted to
//   <value> IN (VALUES(<val1>), ..., (<valN))
// Otherwise, IN list is converted to ORs.
//
// IN list is also converted to ORs if all consts do not have compatible
// types. (like, all numerics, or all characters...). This is done since
// we don't (yet) support incompatible types within a TupleList.
//
// processINlist should be moved to Binder. Will do that later.
//
///////////////////////////////////////////////////////////////////////////
ItemExpr *processINlist(ItemExpr *lhs, ItemExpr *rhs)
{
  ItemExpr * retItemExpr = NULL;
  Lng32 defaultsLimit = ActiveSchemaDB()->getDefaults().getAsLong(COMP_INT_22);
  if (rhs->castToItemExpr()->getOperatorType() == ITM_ITEM_LIST)
    {
      ItemList * il = (ItemList*)rhs;
      if ((defaultsLimit > 0) && // if defaultsLimit == 0 the the feature is turned OFF.
          (il->doesExprEvaluateToConstant(FALSE, FALSE)) &&
	  (il->numOfItems() > defaultsLimit)
         )
	{
	  // insert a convert node on top of each child item expr
	  ItemExpr * currIL = il;
	  NABoolean incompatibleTypes = FALSE;
	  NABoolean negate;
          ConstValue* prevCVExpr = currIL->child(0)->castToConstValue(negate);

	  NABuiltInTypeEnum prevEnum = ( prevCVExpr == NULL ) ? 
             NA_UNKNOWN_TYPE : prevCVExpr->getType()->getTypeQualifier()  ;

          ConstValue* currCVExpr = NULL;
          CollIndex index = 0;

	  while (1)
	    {
	      currCVExpr = currIL->child(index)->castToConstValue(negate);

	      if ( currCVExpr ) {
                NABuiltInTypeEnum currEnum = 
                       currCVExpr->getType()->getTypeQualifier();
	        if ( prevEnum == NA_UNKNOWN_TYPE ) {
                  prevEnum = currEnum;
                } else {
	          if (currEnum != prevEnum) {
		    incompatibleTypes = TRUE;
                    break;
                  }
                }
              } else {
                if (currIL->child(index)->castToItemExpr()->getOperatorType()
                  != ITM_DYN_PARAM) 
                {
                  incompatibleTypes = TRUE;
                  break;
                }
              }

	      Convert * cnv = new(PARSERHEAP()) Convert(currIL->child(index));
	      currIL->setChild(index, cnv);

              if ( index == 1 ) break;

	      if (currIL->child(1)->castToItemExpr()->getOperatorType() 
		  == ITM_ITEM_LIST)
		currIL = currIL->child(1);
	      else
                index = 1; 
            }

	  if (NOT incompatibleTypes)
	    {
	      // convert to VALUES subq.
	      TupleList * tl = new(PARSERHEAP()) TupleList(il);
          tl->setCreatedForInList(TRUE);
	      RelRoot * rr = new (PARSERHEAP()) RelRoot(tl);
	      retItemExpr = 
		makeQuantifiedComp(lhs, ITM_EQUAL, TOK_ANY, rr); 
	      if (retItemExpr)
		((QuantifiedComp*)retItemExpr)->setCreatedFromINlist(TRUE);
	    }
	}
    }
  
  if (! retItemExpr)
    retItemExpr = convertINvaluesToOR(lhs, rhs);

  return retItemExpr;
}

ItemExpr *makeBetween(ItemExpr *x, ItemExpr *y, ItemExpr *z, Int32 tok)
{
  ItemExpr *result = new (PARSERHEAP()) Between(x, y, z);
  if (tok == TOK_NOT_BETWEEN)
    result = new (PARSERHEAP()) UnLogic(ITM_NOT, result);
  return result;
}

// Change the <sqltext> arg of a CQD from
//	SET SCHEMA X.Y;		-- unquoted: Tandem syntax extension
//	SET MPLOC $V.SV;	-- MPLOC:    Tandem syntax extension
//	SET MPLOC '$V.SV';	-- MPLOC:    Tandem syntax extension
// into
//	SET SCHEMA 'X.Y';	-- string literal: Ansi syntax, MX canonical fmt
//	SET MP_SUBVOLUME '$V.SV';  -- string lit:  Tdm ext, MX canonical format
//	SET MP_SUBVOLUME '$V.SV';  -- string lit:  Tdm ext, MX canonical format
//
// This needs to be called ONLY for:
// - SET cqd's (not DECLARE cqd's), and
//   - the SET cqd's unquoted (non-string-literal) variants, or
//   - or if we are otherwise rewriting the user input text
//     (e.g. the syntactic sugar of "SET MPLOC" --
//	there is no NADefaults attribute of MPLOC --
//	NADefaults parses a multi-part MP_SUBVOLUME instead).
//
ControlQueryDefault *normalizeDynamicCQD(const char *attrName,
                                         const NAString &attrValue)
{
  size_t len = attrValue.length() + 2;		// assume only two quotes
  NAString quotedValue(len);
  ToQuotedString(quotedValue, attrValue);

  len += 4 + strlen(attrName) + 2;
  NAString tmpSQLTEXT(len);
  tmpSQLTEXT  = "SET ";
  tmpSQLTEXT += attrName;
  tmpSQLTEXT += quotedValue + ";";
  return new (PARSERHEAP())
    ControlQueryDefault(
      tmpSQLTEXT,
      CharInfo::UTF8
      , attrName, attrValue, TRUE/*dynamic*/);
}

// return the relexpr tree that evaluates an empty compound statement
RelExpr* getEmptyCSRelTree()
{
     ItemExpr *tupleExpr = new (PARSERHEAP()) ConstValue();
     RelExpr *tuple = new (PARSERHEAP()) Tuple(tupleExpr);
     ItemExpr *predicate = new (PARSERHEAP()) BoolVal(ITM_RETURN_FALSE);
     tuple->addSelPredTree(predicate);
     return tuple;
}

RelExpr* 
getIfRelExpr(ItemExpr* condition, RelExpr* thenBranch, RelExpr* elseBranch)
{
   if ( thenBranch == NULL && elseBranch == NULL ) {
    delete condition;
    return NULL;
   }
  NABoolean thenBranchAloneIsNull = FALSE ;
  NABoolean elseBranchAloneIsNull = FALSE ;

   if ( thenBranch == NULL ) {
      thenBranch = getEmptyCSRelTree();
      thenBranchAloneIsNull = TRUE ;
   }

   if (elseBranch == NULL) {
     elseBranch = getEmptyCSRelTree();
     elseBranchAloneIsNull = TRUE ;
   }
      

   Union *u = new (PARSERHEAP())
          Union(thenBranch, elseBranch, NULL, condition);
   u->setUnionForIF();


   if ( thenBranchAloneIsNull ) {
      u->setCondEmptyIfThen();
   }

   if (elseBranchAloneIsNull) {
     u->setCondEmptyIfElse();
   }
   
   return u;
}

// EJF L4J - dynamic CQD not allowed inside Compound Statements
NABoolean beginsWith(char *sqltext, const char *kwd)
{
  // Assumes Prettify has been called, so only one space (at most) btw tokens.
  // If this is called more than once, the second time in the text might begin
  // with a delimiting space.
  NAString sqlText(sqltext);
  size_t i = 0;
  size_t flen = sqlText.length();

  if (!sqlText.isNull())  {
    while (i < flen)  {
      if (isspace((unsigned char)sqlText[size_t(0)]))  // For VS2003
        sqlText.remove(0, 1);
      else
        i = flen;
      }
    }

  size_t len = strlen(kwd);
  if (sqlText.length() > len) {
    NAString tmp(sqlText);
    tmp.remove(len);
    if (tmp == kwd)
      return TRUE;
    }

  return FALSE;
}

void setHVorDPvarIndex(ItemExpr * expr, NAString *name)
{
  // This method sets the var index value to HV or DP
  // in sequential order. The duplicate HV or DP will be eliminated
  // during 'bind' phase.
  OperatorTypeEnum opType = expr->getOperatorType();

  if (inCallStmt)
  {
    if (ITM_HOSTVAR == opType)
      ((HostVar *)expr)->setPMOrdPosAndIndex(COM_INPUT_COLUMN,
                                             1,
                                             currVarIndex++);
    else
      ((DynamicParam *)expr)->setPMOrdPosAndIndex(COM_INPUT_COLUMN,
                                                  1,
                                                  currVarIndex++);
  }
}

//ct-bug-10-030102-3803 Begin
void  conditionalDelimit(NAString &tmpName, const NAString &tmp)
{
   if(tmp.contains(".",NAString::exact) || tmp.contains("*",NAString::exact))
   {
       tmpName.append("\"",1);
       tmpName.append(tmp.data(),tmp.length());
       tmpName.append("\"",1);
   }
   else
   {
       tmpName.append(tmp.data(),tmp.length());
   }
}
//ct-bug-10-030102-3803 End
Lng32 getDefaultMaxLengthForLongVarChar(CharInfo::CharSet cs)
{
  if (IdentifyMyself::IsPreprocessor() == TRUE )
     return INT_MAX;

  switch(cs) {
  case CharInfo::UNICODE:
    return (Lng32)CmpCommon::getDefaultNumeric(MAX_LONG_WVARCHAR_DEFAULT_SIZE);
    break;

  default:
    return (Lng32)CmpCommon::getDefaultNumeric(MAX_LONG_VARCHAR_DEFAULT_SIZE);
    break;
  }
}

Lng32 getDefaultMinLengthForLongVarChar(CharInfo::CharSet cs)
{
  if (IdentifyMyself::IsPreprocessor() == TRUE )
     return 0;

  switch(cs) {
  case CharInfo::UNICODE:
    return (Lng32)CmpCommon::getDefaultNumeric(MIN_LONG_WVARCHAR_DEFAULT_SIZE);
    break;

  default:
    return (Lng32)CmpCommon::getDefaultNumeric(MIN_LONG_VARCHAR_DEFAULT_SIZE);
    break;
  }
}

NABoolean getCharSetInferenceSetting(NAString& defVal)
{
  if (IdentifyMyself::IsPreprocessor() == TRUE )
    return FALSE;

  return (CmpCommon::getDefault(INFER_CHARSET, defVal) == DF_ON);
}

NABoolean allowRandFunction()
{
  if (IdentifyMyself::IsPreprocessor() == TRUE 
     )
    return TRUE;
  else
    return CmpCommon::getDefault(ALLOW_RAND_FUNCTION) == DF_ON;
}
    
RelExpr * getTableExpressionRelExpr(
     RelExpr *fromClause,
     ItemExpr *whereClause,
     RelExpr *sampleClause,
     RelExpr *transClause,
     ItemExpr *seqByClause,
     ItemExpr *groupByClause,
     ItemExpr *havingClause,
     ItemExpr *qualifyClause,
     NABoolean hasTDFunctions,
     NABoolean hasOlapFunctions)
{
  if (qualifyClause && seqByClause)
  {
    *SqlParser_Diags << DgSqlCode(-4360); 
    return NULL;
  }

  if(hasOlapFunctions && seqByClause)
  {
    *SqlParser_Diags << DgSqlCode(-4345);
    return NULL;
  }
  // childPtr is the current child node
  // as the tree is built.  At the end
  // it is the root of the table expression tree.
  //
  RelExpr *childPtr = fromClause;
  NABoolean groupByClauseProcessed = FALSE;

  
  // add where clause as a selection pred
  //
  if (whereClause)
    childPtr->addSelPredTree(whereClause);

   if(groupByClause || havingClause)
   { 
    // we are making this change so that for the following query the groupby is 
    // associlated with the last select statement and not the entire unioned result.
    //  select a from t union select a from t order by 1 group by 1;
    if ((CmpCommon::getDefault(MODE_SPECIAL_1) == DF_ON) &&
      ((childPtr->getOperatorType() == REL_GROUPBY) && // group by for union distinct
	childPtr->child(0) && (childPtr->child(0)->getOperatorType() == REL_ROOT) &&
	childPtr->child(0)->child(0) &&
	  (childPtr->child(0)->child(0)->getOperatorType() == REL_UNION) &&
	 childPtr->child(0)->child(0)->child(1) &&
	 (childPtr->child(0)->child(0)->child(1)->getOperatorType() == REL_ROOT) &&
	 childPtr->child(0)->child(0)->child(1)->child(0)) 
	 ||   // union all case is below
	  ((childPtr->getOperatorType() == REL_UNION) && 
	    childPtr->child(1) && (childPtr->child(1)->getOperatorType() == REL_ROOT) &&
	    childPtr->child(1)->child(0)))
    {
      RelExpr * unionGroupByChild ;
      RelExpr * unionChild;
      if (childPtr->getOperatorType() == REL_GROUPBY)
      {
	unionGroupByChild = childPtr->child(0)->child(0)->child(1)->child(0);
	unionChild = childPtr->child(0)->child(0)->child(1);
      }
      else
      {
	unionGroupByChild = childPtr->child(1)->child(0);
	unionChild = childPtr->child(1);
      }

      RelExpr * unionGrby ;
	if(unionGroupByChild->getOperatorType() != REL_GROUPBY)
	{
	  unionGrby = new (PARSERHEAP())
	  GroupByAgg(unionGroupByChild,
		    REL_GROUPBY,
		    groupByClause);
	// add having clause as a selection pred
	unionGrby->addSelPredTree(havingClause);
	if (childPtr->getOperatorType() == REL_GROUPBY)
	  childPtr->child(0)->child(0)->child(1)->child(0) = unionGrby;
	else
	  childPtr->child(1)->child(0) = unionGrby;
	}
	else
	{
	  yyerror("");
	}
      groupByClauseProcessed = TRUE;
    }
  }
  
  // Add the optional sample clause.
  //
  if(sampleClause) {
    sampleClause->setChild(0, childPtr);
    childPtr = sampleClause;
  }
  
  // Add chain of transpose clauses
  //
  if(transClause) {
    RelExpr *chain = transClause;
    while(chain->child(0))
      chain = chain->child(0);
    chain->setChild(0,childPtr);
    childPtr = transClause;
  }
  
  // Add the optional sequence by clause.
  // Used with sequence functions.
  //
  if(seqByClause) {
    childPtr = new (PARSERHEAP())
      RelSequence(childPtr, seqByClause);
  }
  else if( hasTDFunctions ) {  
    RelSequence *seqNode = new (PARSERHEAP()) RelSequence(childPtr,NULL);    
    seqNode->setHasTDFunctions(hasTDFunctions);
    childPtr = seqNode;
  }
  
  if (!hasTDFunctions)
  {
    if (qualifyClause)
    { //Using Qualify clause without using rank function in the query is not allowed.
      *SqlParser_Diags << DgSqlCode(-4363);
      return NULL;
    }
    if((groupByClause || havingClause) && (NOT groupByClauseProcessed))
    { 
      childPtr = new (PARSERHEAP())
	GroupByAgg(childPtr,
		   REL_GROUPBY,
		   groupByClause);
      // add having clause as a selection pred
      childPtr->addSelPredTree(havingClause);

      if (groupByClause)
        ((GroupByAgg*)childPtr)->setIsRollup(groupByClause->isGroupByRollup());
    }

    // sequence node goes right below rel root
    if( !seqByClause && hasOlapFunctions )
    {
      RelSequence *seqNode = new (PARSERHEAP()) RelSequence(childPtr,NULL);
      seqNode->setHasOlapFunctions(hasOlapFunctions);
      childPtr = seqNode;
    }
  } // !hasTDFunctions
  else
  {
    if (!seqByClause)
    { 
      // for TD rank, the group by becomes the partition by
      if (groupByClause)
      {
	((RelSequence *)childPtr)->
          setPartitionBy(groupByClause->copyTree(CmpCommon::statementHeap()));
      }
      if (qualifyClause)
      {
	childPtr->addSelPredTree(qualifyClause);
      }
    }
  }

  return childPtr;
}
RelExpr * processReturningClause(RelExpr * re, UInt32 returningType)
{
  // disable returning clause if in a compound statement.
  if (in3GL_)
    return NULL;

  Insert * insert = (Insert *)re;

  NAString nas("SYSKEY");
  ColRefName * newColRefName = new(PARSERHEAP())
    ColRefName(nas, PARSERHEAP());
  if (newColRefName == NULL) 
    return NULL;
  ColReference * cr = new (PARSERHEAP()) ColReference(newColRefName);

  // this flag sets up the insert operator to return rows.
  // Maybe it should be renamed to indicate that inserted rows are
  // being returned.
  insert->setMtsStatement(TRUE);
  
  RelRoot * root = new (PARSERHEAP())
    RelRoot(insert, 
	    ACCESS_TYPE_NOT_SPECIFIED_, 
	    LOCK_MODE_NOT_SPECIFIED_, 
	    REL_ROOT, cr);
  
  if ((insert->child(0)) &&
      (insert->child(0)->getOperatorType() != REL_TUPLE))
    {
      // indicate that [last 1] is needed. LAST 1 is indicated by -3.
      if (root)
	root->setFirstNRows(-3);
    }

  return root;
}

// Process the sequence generator options.
// Ensure that the number is not negative and not larger than
// the maximum allowed for an Int64
NABoolean validateSGOption(NABoolean positive,
			   NABoolean negAllowed,
			   char * numStr,
			   const char * optionName,
			   const char * objectType)
{
  Lng32 strLen = (Lng32)(strlen(numStr));
  Int64  theValue;
  Lng32 convErrFlag = ex_conv_clause::CONV_RESULT_OK;

  // if the option is a negative number and negative numbers are not allowed,
  // prepare a diagnostic and return.
  // In the future, negatives may be allowed.
  if (!positive && !negAllowed)
      {
       *SqlParser_Diags << DgSqlCode(-1572)
        << DgString0(optionName)
        << DgString1(objectType);
        return FALSE;
      }

  // Mark the diagnostics.
  // Any possible diagnostics added by convDoIt
  // will be removed.
  Lng32 markValue = SqlParser_Diags->mark();

  /* for char(n), we limit the value of n to be no more than
     2^63-1, so convert it to 64bit signed first, then check 
     to make sure the converted value is not negative. */

  ex_expr::exp_return_type result = 
         convDoIt(numStr,               /*source*/
	          strLen,               /*sourceLen*/
		  REC_BYTE_F_ASCII,     /*sourceType*/
		  0,                    /*sourcePrecision*/
		  0,                    /*sourceScale*/
	          (char *)&theValue,    /*target*/
	          sizeof(theValue),     /*targetLen*/
	          REC_BIN64_SIGNED,     /*targetType*/
	          0,                    /*targetPrecision*/
	          0,                    /*targetScale*/
                  NULL,                 /*varCharLen*/
                  0,                    /*varCharLenSize*/
	          PARSERHEAP(),         /*heap*/
	          &SqlParser_Diags,     /*diagsArea*/
		  CONV_ASCII_BIN64S,    /*index*/
                  &convErrFlag,         /*dataConversionErrorFlag*/
	          0                     /*flags*/);

      switch(convErrFlag){
      case ex_conv_clause::CONV_RESULT_ROUNDED_DOWN:
      case ex_conv_clause::CONV_RESULT_ROUNDED_DOWN_TO_MAX:
      case ex_conv_clause::CONV_RESULT_ROUNDED_UP:
      case ex_conv_clause::CONV_RESULT_ROUNDED_UP_TO_MIN:
      case ex_conv_clause::CONV_RESULT_ROUNDED:
      case ex_conv_clause::CONV_RESULT_FAILED:
        result = ex_expr::EXPR_ERROR;
	break;
      default:
        break;
      }
      
      if (result == ex_expr::EXPR_ERROR)
      {
	// Rewind any errors added by convDoIt
       SqlParser_Diags->rewind(markValue);

       // Set the correct error
       *SqlParser_Diags << DgSqlCode(-1576)
        << DgString0(optionName)
        << DgString1(objectType);
	return FALSE;
      }

      return TRUE;
}


/*
//  INSERT2000 COLUMN FIX STARTS HERE
//  Please refer to SqlParserAux.h for class details and comments.

RearrangeValueExprList * RearrangeValueExprList::tail = NULL;

RearrangeValueExprList::RearrangeValueExprList() 
{
	next = NULL;
	prev = NULL;
	value = NULL;
}

// start to return the value_expression_list in reverse order.
ItemExpr* RearrangeValueExprList::Return_ValueExprList()
{
	RearrangeValueExprList *tmp;
	tmp = new (PARSERHEAP()) RearrangeValueExprList();
	if(tmp->tail->prev != NULL) { // redundant check
		tmp->value = new (PARSERHEAP()) ItemList(tmp->tail->prev->value, tmp->tail->value);
		(tmp->tail->prev->prev != NULL) ? 
			(tmp->tail = tmp->tail->prev->prev) : (tmp->tail = NULL);
	}

    while (tmp->tail != NULL) {
		tmp->value = new (PARSERHEAP()) ItemList(tmp->tail->value, tmp->value);
		(tmp->tail->prev != NULL) ? 
			(tmp->tail = tmp->tail->prev) : (tmp->tail = NULL);
	}
      
	tmp->tail = NULL;
	return tmp->value;

}

// ( ItemExpr -2, ItemExpr 0 )
ItemExpr* RearrangeValueExprList::Store_ValueExprList(ItemExpr *j, ItemExpr *i)   
{
	if (j != NULL) 	{
		RearrangeValueExprList *newNode;
		newNode = new (PARSERHEAP()) RearrangeValueExprList();
		if (newNode->tail != NULL) {
			// this condition will be TRUE only for the statement like follow:
			// insert into table_name values (1,2,3),(4,5,6),(7,8,9);
			// call the code to store call the Return_ValueExprList
			// Store the final tmp->value in a list.
			MultiValueExprList *tmp;
			tmp = new (PARSERHEAP()) MultiValueExprList();
			tmp->value = newNode->Return_ValueExprList();
			tmp->Store_MultiValueExprList(tmp->value);

			// this would be the next new row
			newNode->value = j;
			newNode->tail = newNode;			
		}
		else {  // the first node. 		
			newNode->value = j;
			newNode->tail = newNode;
		}
	}

	if (i != NULL) 	{
		RearrangeValueExprList *newNode2;
		newNode2 = new (PARSERHEAP()) RearrangeValueExprList();
		if (newNode2->tail != NULL)	{
			newNode2->tail->next = newNode2;
			newNode2->prev = newNode2->tail;
			newNode2->value = i;
			newNode2->tail = newNode2;
		}
		else {
			// this code should not be executed since
			// "i" will never be the first node.. failsafe.
			newNode2->value = i;
			newNode2->tail = newNode2;
		}
	}
	
	// Expecting some value.
	// Correct value assigned later.
	return i;
}

RearrangeValueExprList::~RearrangeValueExprList()
{
  // setting free resources gives fragmentation error. remove this?
}


MultiValueExprList * MultiValueExprList::tail = NULL;

MultiValueExprList::MultiValueExprList() 
{
	next = NULL;
	prev = NULL;
	value = NULL;
}

void MultiValueExprList::Store_MultiValueExprList(ItemExpr *i)
{
	if (i != NULL) 	{
		MultiValueExprList *newNode;
		newNode = new (PARSERHEAP()) MultiValueExprList();
		if (newNode->tail != NULL) {
			newNode->tail->next = newNode;
			newNode->prev = newNode->tail;
			newNode->value = i;
			newNode->tail = newNode;
		}
		else {
			newNode->value = i;
			newNode->tail = newNode;
		}
	}
}

ItemExpr* MultiValueExprList::Return_MultiValueExprList()
{
	MultiValueExprList *tmpNode;
	tmpNode = new (PARSERHEAP()) MultiValueExprList();
	if (tmpNode->tail != NULL)	{
		tmpNode = tmpNode->tail;
		(tmpNode->tail->prev != NULL) ?
			(tmpNode->tail = tmpNode->tail->prev) : (tmpNode->tail = NULL) ;
	}
	return tmpNode->value;
}

MultiValueExprList::~MultiValueExprList()
{
  // setting free resources gives fragmentation error. 
}
*/

// INSERT2000 COLUMN FIX ENDS HERE

ItemExpr *buildUdfExpr(NAString *udfName,
                       NAString *fixedInput,
                       ItemExpr *valueList)
{
  NAString udfNameUpper = *udfName;
  udfNameUpper.toUpper();

  // Construct a 3-part UDF name
  QualifiedName *qualifiedName = new (PARSERHEAP())
    QualifiedName(udfNameUpper,
                  "", // schema name
                  "", // catalog name
                  PARSERHEAP());
  
  // Create a RelExpr
  IsolatedScalarUDF *udfFunc = new (PARSERHEAP())
    IsolatedScalarUDF(*qualifiedName, PARSERHEAP());
  
  // Give the RelExpr a pointer to the input and output
  // parameters. The output datatype is not known yet but
  // still a dummy ItemExpr is required.
  ConstValue *dummyOutVal = new (PARSERHEAP()) ConstValue(0);
  if (valueList)
  {
    ItemList *inputsAndReturn = new (PARSERHEAP())
      ItemList(valueList, dummyOutVal);
    udfFunc->setProcAllParamsTree(inputsAndReturn);
  }
  else
  {
    udfFunc->setProcAllParamsTree(dummyOutVal);
  }
  
  // Give the RelExpr a pointer to the fixed input string
  //if (fixedInput)
    // XXX Ignoring this for now
    //udfFunc->setFixedInput(*fixedInput);
  
  // Package the RelExpr as a scalar subquery
  RelRoot *root = new (PARSERHEAP()) RelRoot(udfFunc);
  ItemExpr *result = new (PARSERHEAP()) RowSubquery(root);

  return result;
}

// -----------------------------------------------------------------------
// SqlParserAux_buildUdfOptimizationHint
// -----------------------------------------------------------------------

ElemDDLNode *
SqlParserAux_buildUdfOptimizationHint ( Int32       tokvalStage     // in
                                      , Int32       tokvalResource  // in
                                      , ComSInt32 cost            // in
                                      )
{
  ElemDDLUdfOptimizationHint * pNode = NULL;
  ComUdfOptimizationHintKind kind = COM_UDF_INITIAL_CPU_COST;
  if (tokvalStage EQU TOK_INITIAL)
  {
    switch (tokvalResource)
    {
    case TOK_CPU:     kind = COM_UDF_INITIAL_CPU_COST;     break;
    case TOK_IO:      kind = COM_UDF_INITIAL_IO_COST;      break;
    case TOK_MESSAGE: kind = COM_UDF_INITIAL_MESSAGE_COST; break;
    default:          return pNode;                        break;
    }
  }
  else if (tokvalStage EQU TOK_NORMAL)
  {
    switch (tokvalResource)
    {
    case TOK_CPU:     kind = COM_UDF_NORMAL_CPU_COST;     break;
    case TOK_IO:      kind = COM_UDF_NORMAL_IO_COST;      break;
    case TOK_MESSAGE: kind = COM_UDF_NORMAL_MESSAGE_COST; break;
    default:          return pNode;                       break;
    }
  }
  else
    return pNode;
  pNode = new (PARSERHEAP()) ElemDDLUdfOptimizationHint(kind);
  pNode->setCost(cost);
  return pNode;
}

// -----------------------------------------------------------------------
// SqlParserAux_buildAlterFunction
// -----------------------------------------------------------------------

StmtDDLNode *
SqlParserAux_buildAlterFunction ( QualifiedName * ddl_qualified_name_of_udf                // in - deep copy
                                , ElemDDLNode   * optional_alter_passthrough_inputs_clause // in
                                , ElemDDLNode   * optional_add_passthrough_inputs_clause   // in
                                , ElemDDLNode   * optional_function_attribute_list         // in
                                )
{
  QualifiedName noRoutineActionName(PARSERHEAP());
  StmtDDLAlterRoutine *pNode66 = new (PARSERHEAP())
    StmtDDLAlterRoutine
    ( COM_UDF_NAME                             // in - function name space
    , *ddl_qualified_name_of_udf               // in - deep copy
    , noRoutineActionName                      // in - deep copy
    , COM_UNKNOWN_ROUTINE_TYPE                 // in - either scalar or universal function
    , optional_alter_passthrough_inputs_clause // in - shallow copy
    , optional_add_passthrough_inputs_clause   // in - shallow copy
    , optional_function_attribute_list         // in - shallow copy
    , PARSERHEAP()
    );
  pNode66->synthesize();
  return pNode66;
}

// -----------------------------------------------------------------------
// SqlParserAux_buildAlterAction
// -----------------------------------------------------------------------

StmtDDLNode *
SqlParserAux_buildAlterAction ( QualifiedName * ddl_qualified_name_of_uudf               // in - deep copy
                              , QualifiedName * ddl_qualified_name_of_action             // in - deep copy
                              , ElemDDLNode   * optional_alter_passthrough_inputs_clause // in
                              , ElemDDLNode   * optional_add_passthrough_inputs_clause   // in
                              , ElemDDLNode   * optional_function_attribute_list         // in
                              )
{
  StmtDDLAlterRoutine *pNode77 = new (PARSERHEAP()) StmtDDLAlterRoutine
    ( COM_UUDF_ACTION_NAME                     // in - routine action name space
    , *ddl_qualified_name_of_uudf              // in - deep copy
    , *ddl_qualified_name_of_action            // in - deep copy
    , COM_ACTION_UDF_TYPE                      // in - routine action type
    , optional_alter_passthrough_inputs_clause // in - shallow copy
    , optional_add_passthrough_inputs_clause   // in - shallow copy
    , optional_function_attribute_list         // in - shallow copy
    , PARSERHEAP()
    );
  pNode77->synthesize();
  return pNode77;
}

// -----------------------------------------------------------------------
// SqlParserAux_buildAlterTableMappingFunction
// -----------------------------------------------------------------------

StmtDDLNode *
SqlParserAux_buildAlterTableMappingFunction
  ( QualifiedName * ddl_qualified_name_of_table_mapping_udf  // in - deep copy
  , ElemDDLNode   * optional_alter_passthrough_inputs_clause // in
  , ElemDDLNode   * optional_add_passthrough_inputs_clause   // in
  , ElemDDLNode   * optional_function_attribute_list         // in
  )
{
  QualifiedName noRoutineActionName(PARSERHEAP());
  StmtDDLAlterRoutine *pNode88 = new (PARSERHEAP()) StmtDDLAlterRoutine
    ( COM_TABLE_NAME // table mapping function name belongs to table name space
    , *ddl_qualified_name_of_table_mapping_udf // in - deep copy
    , noRoutineActionName                      // in - deep copy
    , COM_TABLE_UDF_TYPE                       // in - ComRoutineType
    , optional_alter_passthrough_inputs_clause // in - shallow copy
    , optional_add_passthrough_inputs_clause   // in - shallow copy
    , optional_function_attribute_list         // in - shallow copy
    , PARSERHEAP()
    );
  pNode88->synthesize();
  return pNode88;
}

// -----------------------------------------------------------------------
// SqlParserAux_buildDropAction
// -----------------------------------------------------------------------

StmtDDLNode *
SqlParserAux_buildDropAction ( QualifiedName * ddl_qualified_name_of_uudf   // in - deep copy
                             , QualifiedName * ddl_qualified_name_of_action // in - deep copy
                             , NABoolean       optional_cleanup             // in
                             , ComDropBehavior optional_drop_behavior       // in
                             , NABoolean       optional_validate            // in
                             , NAString      * optional_logfile             // in - deep copy
                             )
{
  // If CLEANUP, VALIDATE, or LOG option specified,
  // ALLOW_SPECIALTABLETYPE must also be specified
  if ( (optional_cleanup  OR  optional_validate  OR  optional_logfile)  AND
       NOT Get_SqlParser_Flags(ALLOW_SPECIALTABLETYPE) )
  {
    return NULL; // Error: internal syntax only!
  }

  NAString *pLogFile = NULL;
  if (optional_logfile NEQ NULL) // logfile specified
  {
    pLogFile = new (PARSERHEAP()) NAString ( optional_logfile->data()
                                           , PARSERHEAP()
                                           );
  }
  ddl_qualified_name_of_uudf->setObjectNameSpace(COM_UDF_NAME);
  ddl_qualified_name_of_action->setObjectNameSpace(COM_UUDF_ACTION_NAME);
  return new (PARSERHEAP()) StmtDDLDropRoutine
    ( COM_ACTION_UDF_TYPE            // in - ComRoutineType
    , *ddl_qualified_name_of_uudf    // in - QualifiedName * - deep copy
    , *ddl_qualified_name_of_action  // in - QualifiedName * - deep copy
    , optional_drop_behavior         // in - ComDropBehavior
    , optional_cleanup               // in - NABoolean       - for CLEANUP  mode set to TRUE
    , optional_validate              // in - NABoolean       - for VALIDATE mode set to FALSE (?)
    , pLogFile                       // in - NAString *      - shallow copy
    , PARSERHEAP()
    );
  // Do not delete pLogFile because we did a shallow copy
}

// -----------------------------------------------------------------------
// SqlParserAux_buildDropRoutine
// -----------------------------------------------------------------------

StmtDDLNode *
SqlParserAux_buildDropRoutine ( ComRoutineType  drop_routine_type_tokens  // in
                              , QualifiedName * ddl_qualified_name_of_udf // in - deep copy
                              , NABoolean       optional_cleanup          // in
                              , ComDropBehavior optional_drop_behavior    // in
                              , NABoolean       optional_validate         // in
                              , NAString      * optional_logfile          // in - deep copy
                              , NABoolean       optional_if_exists        // in
                              )
{
  // If CLEANUP, VALIDATE, or LOG option specified,
  // ALLOW_SPECIALTABLETYPE must also be specified
  if ( (optional_cleanup  OR  optional_validate  OR  optional_logfile)  AND
       NOT Get_SqlParser_Flags(ALLOW_SPECIALTABLETYPE) )
  {
    return NULL; // Error: internal syntax only!
  }

  if (drop_routine_type_tokens EQU COM_ACTION_UDF_TYPE)
  {
    return NULL; // Error: illegal syntax!
  }

  QualifiedName noRoutineActionName(PARSERHEAP());

  NAString *pLogFile = NULL;
  if (optional_logfile NEQ NULL) // logfile specified
  {
    pLogFile = new (PARSERHEAP()) NAString ( optional_logfile->data()
                                           , PARSERHEAP()
                                           );
  }

  switch (drop_routine_type_tokens)
  {
  case COM_PROCEDURE_TYPE:
  case COM_TABLE_UDF_TYPE:
    ddl_qualified_name_of_udf->setObjectNameSpace(COM_TABLE_NAME);
    break;
  case COM_ACTION_UDF_TYPE:
    ComASSERT(FALSE);
    break;
  case COM_UNKNOWN_ROUTINE_TYPE: // either scalar or universal
  default:
    ddl_qualified_name_of_udf->setObjectNameSpace(COM_UDF_NAME);
    break;
  } // switch

  StmtDDLNode *pNode99 = new (PARSERHEAP()) StmtDDLDropRoutine
    ( drop_routine_type_tokens       // in - ComRoutineType
    , *ddl_qualified_name_of_udf     // in - QualifiedName & - deep copy
    , noRoutineActionName            // in - QualifiedName & - deep copy
    , optional_drop_behavior         // in - ComDropBehavior
    , optional_cleanup               // in - NABoolean       - for CLEANUP  mode set to TRUE
    , optional_validate              // in - NABoolean       - for VALIDATE mode set to FALSE (?)
    , pLogFile                       // in - NAString *      - shallow copy
    , PARSERHEAP()
    );

  pNode99->castToStmtDDLDropRoutine()->setDropIfExists(optional_if_exists);

  // Do not delete pLogFile because we did a shallow copy
  return pNode99;
}

// -----------------------------------------------------------------------
// SqlParserAux_buildAlterPassThroughParamDef
// -----------------------------------------------------------------------

ElemDDLNode *
SqlParserAux_buildAlterPassThroughParamDef
  ( UInt32                   passthrough_param_position      // in
  , ElemDDLNode *                  passthrough_input_value         // in - shallow copy
  , ComRoutinePassThroughInputType optional_passthrough_input_type // in
  )
{
  ElemDDLPassThroughParamDef *pNode3 =
    passthrough_input_value->castToElemDDLPassThroughParamDef();
  pNode3->setParamPosition(passthrough_param_position);
  pNode3->setPassThroughInputType(optional_passthrough_input_type);
  pNode3->setPassThroughParamDefKind(ElemDDLPassThroughParamDef::eALTER_PASS_THROUGH_INPUT);
  return pNode3;
}

// -----------------------------------------------------------------------
// SqlParserAux_buildDescribeForFunctionAndAction
// -----------------------------------------------------------------------

RelExpr *
SqlParserAux_buildDescribeForFunctionAndAction
  ( CorrName * actual_routine_name_of_udf_or_uudf  // in - deep copy
  , CorrName * optional_showddl_action_name_clause // in - deep copy
  , Lng32 optional_showddlroutine_options           // in
  )
{
  actual_routine_name_of_udf_or_uudf->getQualifiedNameObj().setObjectNameSpace(COM_UDF_NAME);
  Describe * pDescribe = NULL;
  if (optional_showddl_action_name_clause NEQ NULL) // routine action name
  {
    optional_showddl_action_name_clause->getQualifiedNameObj().setObjectNameSpace(COM_UUDF_ACTION_NAME);
    pDescribe = new (PARSERHEAP())
      Describe ( SQLTEXT()
               , *optional_showddl_action_name_clause // in - const CorrName & - deep copy
               , Describe::LONG_
               , COM_UUDF_ACTION_NAME                 // in - ComAnsiNameSpace labelAnsiNameSpace_
               , optional_showddlroutine_options      // in - long optional_showddlroutine_options
               );
    pDescribe->setUudfQualName(actual_routine_name_of_udf_or_uudf->getQualifiedNameObj()); // deep copy
  }
  else // function name
  {
    pDescribe = new (PARSERHEAP())
      Describe ( SQLTEXT()
               , *actual_routine_name_of_udf_or_uudf // in - const CorrName & - deep copy
               , Describe::LONG_
               , COM_UDF_NAME                        // in - ComAnsiNameSpace labelAnsiNameSpace_
               , optional_showddlroutine_options     // in - long optional_showddlroutine_options
               );
  }
  return new (PARSERHEAP()) RelRoot ( pDescribe
                                    , REL_ROOT
                                    , new (PARSERHEAP()) ColReference ( new (PARSERHEAP())
                                                                        ColRefName ( TRUE
                                                                                   , PARSERHEAP()
                                                                                   )
                                                                      )
                                    );
}

// ----------------------------------------------------------------------------
// method:: TableTokens::setTableTokens
//
// Method that sets appropriate values in the createTableNode parser tree
// based on options described in this class.
//
// in:  StmtDDLCreateTable *pNode - pointer to the create table parse tress
//
// ----------------------------------------------------------------------------
void
TableTokens::setTableTokens(StmtDDLCreateTable *pNode)
{
  pNode->setCreateIfNotExists(ifNotExistsSet());

  switch (type_)
  {
    case TableTokens::TYPE_REGULAR_TABLE:
    case TableTokens::TYPE_GHOST_TABLE:
      break;

    case TableTokens::TYPE_EXTERNAL_TABLE:
      pNode->setIsExternal(TRUE);
      break;

    case TableTokens::TYPE_SET_TABLE:
      pNode->setInsertMode(COM_SET_TABLE_INSERT_MODE);
      break;

    case TableTokens::TYPE_MULTISET_TABLE:
      pNode->setInsertMode(COM_MULTISET_TABLE_INSERT_MODE);
      break;

    case TableTokens::TYPE_VOLATILE_TABLE:
      pNode->setIsVolatile(TRUE);
      pNode->setProcessAsExeUtil(TRUE);
      break;

    case TableTokens::TYPE_VOLATILE_TABLE_MODE_SPECIAL1:
    case TableTokens::TYPE_VOLATILE_SET_TABLE:
      pNode->setIsVolatile(TRUE);
      pNode->setProcessAsExeUtil(TRUE);
      pNode->setInsertMode(COM_SET_TABLE_INSERT_MODE);
      break;

    case TableTokens::TYPE_VOLATILE_MULTISET_TABLE:
      pNode->setProcessAsExeUtil(TRUE);
      pNode->setInsertMode(COM_MULTISET_TABLE_INSERT_MODE);
      break;

    default:
      NAAbort("TableTokens - TypeAttr", __LINE__, "internal logic error");
      break;
  }

  switch (options_)
  {
    case TableTokens::OPT_NONE:
      break;

    case TableTokens::OPT_LOAD:
      pNode->setLoadIfExists(TRUE);
      break;

    case TableTokens::OPT_NO_LOAD:
      pNode->setNoLoad(TRUE);
      break;

    case TableTokens::OPT_IN_MEM:
      pNode->setNoLoad(TRUE);
      pNode->setInMemoryObjectDefn(TRUE);
      break;

    case TableTokens::OPT_LOAD_WITH_DELETE:
      pNode->setLoadIfExists(TRUE);
      pNode->setDeleteData(TRUE);
      break;

    default:
      NAAbort("TableTokens - LoadAttr", __LINE__, "internal logic error");
      break;
  }
}

//
// End of File
//

This is in the surround, but I wonder whether we shouldn't also look at the TRAF_LARGEINT_UNSIGNED_IO CQD and only generate unsigned largeint literals if that CQD is set to ON.