/**********************************************************************
// @@@ 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 @@@
**********************************************************************/
/* -*-C++-*-
******************************************************************************
*
* File:		BindRelExpr.C
* Description:  Relational expressions (both physical and logical operators)
*               Methods related to the SQL binder
*
* Created:      5/17/94
* Language:     C++
*
*
*
*	It is the secret sympathy,
*	The silver link, the silken tie,
*	Which heart to heart, and mind to mind,
*	In body and in soul can bind.
*		-- Sir Walter Scott,
*		   "The Lay of the Last Minstrel"
*
******************************************************************************
*/


#define   SQLPARSERGLOBALS_FLAGS   // must precede all #include's
#define   SQLPARSERGLOBALS_NADEFAULTS

#include "Platform.h"
#include "NAWinNT.h"


#include "Sqlcomp.h"
#include "AllItemExpr.h"
#include "AllRelExpr.h"
#include "BindWA.h"
#include "ComOperators.h"
#include "ComTransInfo.h"
#include "ComLocationNames.h"
#include "ControlDB.h"
#include "Debug.h"
#include "ex_error.h"
#include "GroupAttr.h"
#include "ParNameLocList.h"
#include "parser.h"
#include "Rel3GL.h"
#include "RelDCL.h"
#include "RelPackedRows.h"
#include "RelSequence.h"
#include "ShowSchema.h"           // GetControlDefaults class
#include "StmtDDLAddConstraintCheck.h"
#include "StmtDDLCreateView.h"
#include "ElemDDLColRefArray.h"
#include "ElemDDLSaltOptions.h"
#include "TrafDDLdesc.h"
#include "UdrErrors.h"
#include "SequenceGeneratorAttributes.h"

#include "wstr.h"
#include "Inlining.h"
#include "Triggers.h"
#include "TriggerDB.h"
#include "MVInfo.h"
#include "Refresh.h"
#include "ChangesTable.h"
#include "MvRefreshBuilder.h"
#include "OptHints.h"
#include "CmpStatement.h"
#include "OptimizerSimulator.h"
#include "charinfo.h"
#include "UdfDllInteraction.h"
#include "SqlParserGlobals.h"      // must be last #include
#include "ItmFlowControlFunction.h"
#include "ComSchemaName.h" // for ComSchemaName
#include "ItemSample.h"
#include "NAExecTrans.h"
#include "HDFSHook.h"
#include "CmpSeabaseDDL.h"
#include "ComUser.h"
#include "ComSqlId.h"
#include "PrivMgrCommands.h"
#include "PrivMgrComponentPrivileges.h"
#include "PrivMgrDefs.h"
#include "PrivMgrMD.h"

  #define SLASH_C '/'

NAWchar *SQLTEXTW();

// -----------------------------------------------------------------------
// external declarations
// -----------------------------------------------------------------------

// 



// -----------------------------------------------------------------------
// static functions
// -----------------------------------------------------------------------
#ifdef NDEBUG
  THREAD_P NABoolean GU_DEBUG = FALSE;
#else
  THREAD_P NABoolean GU_DEBUG;
#endif

static void GU_DEBUG_Display(BindWA *bindWA, GenericUpdate *gu,
                             const char *text,
                             RelExpr *reDown = NULL,
                             NABoolean preEndl = FALSE,
                             NABoolean postEndl = FALSE)
{
#ifndef NDEBUG
  if (!GU_DEBUG)
    return;

  if (preEndl) cerr << endl;
  cerr << "---" << endl;

  if (gu->getTableDesc()) {
    NAString tmp;
    ValueIdList vtmp(gu->getTableDesc()->getColumnList());
    vtmp.unparse(tmp);
    cerr << gu->getUpdTableNameText() << " this>td(" << text << ") "
      << gu->getTableDesc()->getCorrNameObj().getExposedNameAsAnsiString()
      << " " << tmp << endl;
  }

  RETDesc *rd = gu->getRETDesc();
  if (rd) {
    cerr << gu->getUpdTableNameText() << " this>grd(" << text << ") " << flush;
    rd->display();
  }
  if (reDown) RETDesc::displayDown(reDown);

  if (bindWA->getCurrentScope()->getRETDesc() &&
      bindWA->getCurrentScope()->getRETDesc() != rd) {
    cerr << gu->getUpdTableNameText() << " bwa>cs>grd(" << text << ") " <<flush;
    bindWA->getCurrentScope()->getRETDesc()->display();
  }

  if (postEndl) cerr << endl;
#endif
} // GU_DEBUG_Display()

static RETDesc *bindRowValues(BindWA *bindWA,
                              ItemExpr *exprTree,
                              ValueIdList &vidList,
                              RelExpr *parent,
                              NABoolean inTrueRoot)
{
  // Before we convert the row value expressions into a ValueIdList, save the
  // original value expression root nodes in an ItemExprList.
  //
  ItemExprList exprList(exprTree, bindWA->wHeap());
  //
  // Bind the row value expressions and create a ValueIdList.
  //
  exprTree->convertToValueIdList(vidList, bindWA, ITM_ITEM_LIST, parent);
  if (bindWA->errStatus()) return NULL;

  // Set up context flags.
  // We are in a subquery if the previous scope's flag is set, note.
  //
  BindScope *currScope   = bindWA->getCurrentScope();
  BindScope *prevScope   = bindWA->getPreviousScope(currScope);
  NABoolean inSelectList = currScope->context()->inSelectList();
  NABoolean inInsert     = currScope->context()->inInsert();
  NABoolean inSubquery   = FALSE;
  if (prevScope)
    inSubquery = prevScope->context()->inSubquery();

  // See if UDF_SUBQ_IN_AGGS_AND_GBYS is enabled. It is enabled if the
  // default is ON, or if the default is SYSTEM and ALLOW_UDF is ON.
  NABoolean udfSubqInAggGrby_Enabled = FALSE;
  DefaultToken udfSubqTok = CmpCommon::getDefault(UDF_SUBQ_IN_AGGS_AND_GBYS);
  if ((udfSubqTok == DF_ON) ||
      (udfSubqTok == DF_SYSTEM))
    udfSubqInAggGrby_Enabled = TRUE;
  
  // See if ALLOW_MULTIDEGREE_SUBQ_IN_SELECTLIST is enabled. It is
  // enabled if the default is ON, or if the default is SYSTEM and
  // ALLOW_UDF is ON.
  NABoolean allowMultiDegSubqInSelect_Enabled = FALSE;
  DefaultToken allowMultiDegreeTok =
    CmpCommon::getDefault(ALLOW_MULTIDEGREE_SUBQ_IN_SELECTLIST);
  if ((allowMultiDegreeTok == DF_ON) ||
      (allowMultiDegreeTok == DF_SYSTEM))
    allowMultiDegSubqInSelect_Enabled = TRUE;
  
  //
  // Create the result table.
  // If a row value expression is not a column reference and does not have
  // a rename AS clause, the column is an unnamed expression.
  //
  RETDesc *resultTable = new (bindWA->wHeap()) RETDesc(bindWA);
  CollIndex j = 0;
  for (CollIndex i = 0; i < exprList.entries(); i++, j++) 
  {
    ItemExpr *itemExpr = (ItemExpr *) exprList[i];
    ValueId valId = itemExpr->getValueId();
    ValueId boundValId = vidList[j];
    CMPASSERT(boundValId != NULL_VALUE_ID);

    if (inSelectList && inTrueRoot &&
        (boundValId.getType().getTypeQualifier() == NA_UNKNOWN_TYPE)&&
        (boundValId.getItemExpr()->getOperatorType() == ITM_CONSTANT))
    {
      ConstValue * constItemExpr = (ConstValue*) boundValId.getItemExpr();
      if (constItemExpr->isNull())
        boundValId.coerceType(NA_NUMERIC_TYPE) ;
    }

    switch (itemExpr->getOperatorType()) 
    {
      case ITM_REFERENCE: {
        ColReference *colRef = (ColReference *) itemExpr;
        const ColRefName &colRefName = colRef->getColRefNameObj();
        CMPASSERT(valId != NULL_VALUE_ID || colRefName.isStar());

        if (colRefName.isStar()) {
          const ColumnDescList *star = colRef->getStarExpansion();
          CMPASSERT(star != NULL);
          const ColumnDescList &starExpansion = *star;
          CMPASSERT(starExpansion.entries() > 0);   // ColRef::bind chked this alrdy
          CMPASSERT(inSelectList);

          resultTable->addColumns(bindWA, starExpansion);

          j += starExpansion.entries() - 1;
        }               // isStar
        else {
          // Do another xcnm lookup so the column we add to our resultTable
          // will have its CorrName object correct
          // (e.g., in "SELECT TL.B,* FROM TA TL,TA TR ORDER BY B;"
          // colref TL.B will resolve to TL.B, not CAT.SCH.TL.B)
          // and its heading (Genesis 10-980126-5495).
          BindScope *bindScope;
          ColumnNameMap *xcnmEntry = bindWA->findColumn(colRefName, bindScope);

          if (NOT xcnmEntry)   // ## I don't recall when this case occurs...
            resultTable->addColumn(bindWA,
                                   colRefName,
                                   boundValId,
                                   colRef->getTargetColumnClass());
          else
            resultTable->addColumn(bindWA,
                                   xcnmEntry->getColRefNameObj(),
                                   boundValId,
                                   colRef->getTargetColumnClass(), // MV --
                                   xcnmEntry->getColumnDesc()->getHeading());
        }
        break;
      }
      case ITM_RENAME_COL: 
      {
        RenameCol *renameCol = (RenameCol *) itemExpr;
        const ColRefName &colRefName = *renameCol->getNewColRefName();
        CMPASSERT(NOT colRefName.isStar());

        const char * heading = NULL;

        // if this rename was for a BLOB/CLOB column from JDBC, return
        // the heading of the child base column. This is needed for JDBC
        // as it uses the heading to figure out if the column is a LOB
        // column.
        if (CmpCommon::getDefault(JDBC_PROCESS) == DF_ON)
          {
            ItemExpr * childExpr = itemExpr->child(0)->castToItemExpr();
            if (childExpr->getOperatorType() == ITM_BASECOLUMN)
              {
                heading = ((BaseColumn *)childExpr)->getNAColumn()->getHeading();

                if (heading)
                  {
                    if ((strcmp(heading, "JDBC_BLOB_COLUMN -") != 0) &&
                        (strcmp(heading, "JDBC_CLOB_COLUMN -") != 0))
                      heading = NULL;
                  }
              }
          }

        // No heading is passed here (whole point of SQL derived-column is rename)
        // unless it is a jdbc blob/clob heading.
        resultTable->addColumn(bindWA,
                               colRefName,
                               boundValId,
                               renameCol->getTargetColumnClass(),
                               heading);
        break;
      }
      case ITM_ROW_SUBQUERY: 
      case ITM_USER_DEF_FUNCTION: {

        // Deal with multi Valued User Defined Functions or Subqueries with
        // degree > 1.
        //
        // In order to have the correct degree during the bind phase,
        // since we don't have all the information until after the transform
        // phase, we need to put entries into the RETDesc early.
        //
        // Say you have a query like this:
        //    select mvf(a,b) from t1;
        // and assume mvf outputs 2 values.
        //
        // at bind time, the select list will only have 1 entry in it, namely
        // the ITM_USER_DEF_FUNCTION.
        // Since we do degree checking at bind time, we need to know now that
        // mvf() actually produces 2 values.
        //
        // So what we do here, is that we substitute the original 
        // ITM_USER_DEF_FUNCTION with ValueIdProxies. One for each output of
        // the original function. The selectList of the RelRoot as well as the
        // retDESC are updated with the additional elements.
        //
        // Similarly if we have a subquery like this:
        //
        //    select (select max(a),max(b) from t2), a from t1;
        //
        // we will wrap the subquery in a ValeIdProxy representing the 
        // subquery from a transformation point of view, but representing
        // max(a) from an output point of view. A second ValueIdProxy will be
        // added for max(b), so the select list of the outer query would look 
        // like this:
        // 
        //     [ ValueIdProxy(Subq:max(a)), ValueIdProxy(Subq:max(b)), a ]
        //
        // instead of just 
        //    
        //     [ Subq, a ]
        //
        // like we are used to.
        //
        // At transform time the valueIdProxies, will disappear and we will
        // transform the UDF/Subquery carried inside the valueIdProxy
        // marked to be transformed. Some might hang around until Normalization.
        // Only the ValueIdProxy representing the first output will be marked
        // to be transformed, so we only transform the UDF/Subquery once.
        //
        // Similarly, we update the outer query's retDESC.


        NABoolean isSubquery = 
                           (itemExpr->getOperatorType() == ITM_ROW_SUBQUERY) ? 
                           TRUE  : FALSE;

        NAColumnArray outCols;
        ValueIdList outColVids;
        CollIndex currIndex = j;

        if (isSubquery)
        {
           Subquery * subq = (Subquery *) itemExpr;
   
           const RETDesc *retDesc = subq->getSubquery()->getRETDesc();

           if( retDesc )
           {
              retDesc->getColumnList()->getValueIdList(outColVids);
           }
        }
        else
        {
           UDFunction * udf = (UDFunction *) itemExpr;
           CMPASSERT(udf->getRoutineDesc());
           const RoutineDesc *rDesc = udf->getRoutineDesc();

          
           // Get the outputs of this UDF, these are as defined in metadata
           // including names etc.
           outCols = rDesc->getEffectiveNARoutine()->getOutParams();
           outColVids = rDesc->getOutputColumnList();
        }
  
        if ( (outColVids.entries() == 1) || 
             ( isSubquery  &&
               (!allowMultiDegSubqInSelect_Enabled)
             ))
        {
           // Do exactly what we used to do if the degree is 1.
           // or we have disallowed subqueries of degree > 1.

           if (isSubquery)
           {
              // ## Here we ought to manufacture a unique name per Ansi 7.9 SR 9c.
              ColRefName colRefName;
              resultTable->addColumn(bindWA, colRefName, boundValId);
           }
           else
           {
              NAColumn *col = outCols[0];
              const char *  heading = col->getHeading();
              ColRefName colRefName( col->getColName());
              ColumnClass colClass( col->getColumnClass());

              resultTable->addColumn(bindWA, 
                                     colRefName, 
                                     boundValId,
                                     colClass,
                                     heading);
           }
           break;
        }

        // Wrap all the outputs with a ValueIdProxy
        // so that we can deal with multiple outputs
        // If we didn't have a RETDesc or a RoutineDesc, outColVids
        // will be empty and we don't do anything.

        // Also we do not need to worry about recursing through the 
        // RETDesc entries as the call to convertToValueIdList() above
        // did that already.
        for (CollIndex idx = 0; idx < outColVids.entries(); idx++)
        {

           NAColumn *col;

           NABoolean isRealOrRenameColumn = 
                 (outColVids[idx].getItemExpr()->getOperatorType() == 
                  ITM_BASECOLUMN) || 
                 (outColVids[idx].getItemExpr()->getOperatorType() == 
                  ITM_RENAME_COL) ||
                  !isSubquery     ? TRUE : FALSE;

           if (isSubquery)
           {
              col = ((NAColumn *) outColVids[idx].getItemExpr());
           }
           else
           {
              col = ((NAColumn *) outCols[idx]);
           }

           const char *  heading  = isRealOrRenameColumn ?  
                                                col->getHeading() : "";
           ColRefName colRefName( isRealOrRenameColumn ? 
                                                col->getColName() : "");
           ColumnClass colClass( isRealOrRenameColumn ? 
                                           col->getColumnClass() : USER_COLUMN);


           // We are wrapping the MVF/Subquery and its additional outputs
           // with a ValueIdProxy. This way we don't end up flattening or
           // expanding the outputs of the MVF multiple times.

           // The valueId of the RoutineParam corresponding to the 
           // metadata column is used for the output valueId.

           // So if you had a query like this:
           //
           // select swap2(a,b) from t1;
           //
           // and swap2() returns 2 outputs (basically the inputs swapped)
           //
           // The new select list for the query would be:
           //
           // 1: ValueIdProxy with the derivedNode being swap2, and output
           //    valueId containing the first output parameter of swap2.
           //    Also the transformDerivedFrom flag would be set
           // 2: ValueIdProxy with the derivedNode being swap2, and output
           //    valueId containing the second output parameter of swap2.
           //
           // These ValueIdProxy nodes will go away at transform time..

           ValueIdProxy *proxyOutput = new (CmpCommon::statementHeap())
                               ValueIdProxy( boundValId, 
                                             outColVids[idx],
                                             idx);


           // The type of the proxy is the same as the output valueId associated
           // with it.
           proxyOutput = (ValueIdProxy *) proxyOutput->bindNode(bindWA);

           if (bindWA->errStatus()) return NULL;

           // Make sure we transform the MVF
           if (idx == 0) proxyOutput->setTransformChild(TRUE);


           if (!isSubquery || isRealOrRenameColumn) 
           {
              resultTable->addColumn(bindWA, 
                                     colRefName, 
                                     proxyOutput->getValueId(), 
                                     colClass,
                                     heading);
   
           }
           else
           {
              resultTable->addColumn(bindWA, colRefName, 
                                     proxyOutput->getValueId());
           }

           if (idx == 0) 
           {
             vidList.removeAt(currIndex); // we need to delete the old valueId
           }
           else
             j++; // The first entry simply replaces the original
           
           // Update the list with the new value.
           // insertAt has the nice feature that it will push 
           // the residual elements to the right, so we do not need to 
           // manage the valueIds we haven't processed yet as long as we
           // update the index (j++ above) correctly.
           vidList.insertAt(currIndex++,proxyOutput->getValueId());
        }

        break;
      }

      default: 
      {
        // ## Here we ought to manufacture a unique name per Ansi 7.9 SR 9c.
        ColRefName colRefName;
        resultTable->addColumn(bindWA, colRefName, boundValId);
        break;
      }
    } // switch
  } // for

  // need this for static cursor declaration
  cmpCurrentContext->saveRetrievedCols_ = resultTable->getDegree();

  // Before we can return the result table, we need to check for the possible
  // syntax error below, in which we can't use the definition of "inSubquery"
  // that we calculate above.  Our example case is, if we're directly below
  // a GroupByAgg, then we need to look at the scope *before* the GroupByAgg
  // to determine if we satisfy the error condition below.  This is a problem
  // with how our plan trees don't sync completely with SQL syntax.
  // Here's the error case (Genesis 10-980518-0765):
  //
  //   >> select (select distinct 1,2 from T1 t) from T1;
  //
  // First of all, yes, it's a really stupid query.  Oh well!  :-)
  //
  // It's pretty clear that the "1,2" is part of a "select list inside the
  // subquery of a select list."  However, the parser creates a GroupByAgg
  // for the distinct keyword (sigh), which means that we have an
  // additional scope between the scope of the SQLRecord (1,2) and the
  // scope of the "TRUE" parent, the inner-select.  This additional scope
  // is for the GroupByAgg.  So in the case of a GroupByAgg (and possibly
  // another case will arise later ...?), we need to look at the
  // GroupByAgg's parent to determine if we satisfy this error condition.
  //
  // To recap: To handle this one (stupid) case we've added a ton of
  // comments and code here and in GroupByAgg::bindNode(), plus created
  // the new functions/members BindWA::getSubqueryScope(), and
  // BindContext::lookAboveToDecideSubquery_/().  Wonderful!
  //
  if (prevScope) {

    BindScope *subQScope = bindWA->getSubqueryScope(currScope);
    //
    // subQScope should be non-NULL when prevScope is non-NULL
    //
    CMPASSERT(subQScope);

    NABoolean inSubqueryInSelectList = subQScope->context()->inSubquery() &&
                                       subQScope->context()->inSelectList();

    NABoolean inSubqueryInGroupByClause = subQScope->context()->inSubquery() &&
                   subQScope->context()->inGroupByClause() && 
                   (CmpCommon::getDefault(UDF_SUBQ_IN_AGGS_AND_GBYS) == DF_ON);

    //10-060602-6930 Begin
    //Added a check to not enter this condition when we are in bindView scope
    if (inSelectList && 
        (inSubqueryInSelectList || 
        inSubqueryInGroupByClause) && 
        !bindWA->inViewExpansion()) {
      //10-060602-6930 End
      // We now can check for the syntax error that we've done so much work
      // above (and in GroupByAgg::bindNode(), BindWA.h & BindWA.cpp)
      // to detect:

      if ((j > 1) && 
          (!allowMultiDegSubqInSelect_Enabled) ) {
        // 4019 The select list of a subquery in a select list must be scalar
        *CmpCommon::diags() << DgSqlCode(-4019);
        bindWA->setErrStatus();
        return NULL;
      }
    }
  } // prevScope

  return resultTable;
} // bindRowValues()

// Bind a constraint (MP Check Constraint).
// Returns NULL if error in constraint *OR* we can safely ignore the constraint
// (e.g., a NOT NULL NONDROPPABLE constraint); caller must check bindWA errsts.
//
static ItemExpr* bindCheckConstraint(
  BindWA *bindWA,
  CheckConstraint *constraint,
  const NATable *naTable,
  NABoolean catmanCollectUsages = FALSE,
  ItemExpr *viewCheckPred = NULL)
{
  ItemExpr *constraintPred = NULL;
  if (viewCheckPred) {
    // view WITH CHECK OPTION: the view's where-clause was already parsed
    // in bindView
    CMPASSERT(constraint->getConstraintText().isNull());   // sanity check
    constraintPred = viewCheckPred;
  }
  else {

    Parser parser(bindWA->currentCmpContext());
    constraintPred = parser.getItemExprTree(constraint->getConstraintText().data(),
                                            constraint->getConstraintText().length(),
                                            CharInfo::UTF8 // ComGetNameInterfaceCharSet()
                                            );

  }
  if (constraintPred) {
    ParNameLocList *saveNameLocList = bindWA->getNameLocListPtr();
    if (!catmanCollectUsages ||
        !bindWA->getUsageParseNodePtr() ||
        bindWA->getUsageParseNodePtr()->getOperatorType() == DDL_CREATE_VIEW)
      bindWA->setNameLocListPtr(NULL);

    CMPASSERT(!bindWA->getCurrentScope()->context()->inCheckConstraint());
    bindWA->getCurrentScope()->context()->inCheckConstraint() = constraint;

    constraintPred->bindNode(bindWA);
    bindWA->setNameLocListPtr(saveNameLocList);
    bindWA->getCurrentScope()->context()->inCheckConstraint() = NULL;

    if (bindWA->errStatus()) {
      delete constraintPred;
      constraintPred = NULL;
    }
  }
  // A NOT NULL constraint on a single column which never allows nulls
  // (has no null indicator bytes)
  // -- i.e., the common case of a column declared NOT NULL NONDROPPABLE --
  // does not need to be separately enforced as a constraint, because
  // Executor will raise a numeric-overflow error if someone tries to
  // put a NULL into such a column.
  //
  // So we don't need to put this constraint into the list, but we do need
  // to save its name, for run-time error diags.
  //
  // ##To be done:
  // ## GenRelUpdate DP2Insert/Update: for each col in newRecExpr(),
  // ##   if getNotNullViolationCode(), then
  // ##     save the SqlCode and the getNotNullConstraintName()...asAnsiString()
  // ##     and some column identifier (pos or offset) in some per-query struct
  // ## Executor: if error 8411, if truly a NULL violation, look up that column
  // ##   in the nnconstraint struct and populate diags with the info there.
  //
  if (constraintPred) {
    ItemExprList nncols(bindWA->wHeap());
    constraintPred->getColumnsIfThisIsISNOTNULL(nncols);
    for (CollIndex i = 0; i < nncols.entries(); i++) {
      NAColumn *nacol = nncols[i]->getValueId().getNAColumn();
      if (!nacol->getType()->supportsSQLnullPhysical()) {
        nacol->setNotNullNondroppable(constraint);
          //
          // DO *NOT* do:   delete constraintPred;
          // -- it deletes a whole tree of stuff referenced elsewhere!
          //
        constraintPred = NULL;
      } else {
        // Leaving the column's type's supportsSQLnullPhysical() as is (TRUE),
        // set its supportsSQLnullLogical() to FALSE,
        // for the Transform phase.
        nacol->mutateType()->setNullable(TRUE/*supports physical nulls*/,
                                         FALSE/*but not logical nulls */);
      }
    }
  }
  else {
    *CmpCommon::diags() << DgSqlCode(-4025)
      << DgConstraintName(ToAnsiIdentifier(constraint->getConstraintName().getObjectName()))
      << DgTableName(naTable->getTableName().getQualifiedNameAsAnsiString());
    bindWA->setErrStatus();
  }
  return constraintPred;
} // bindCheckConstraint()

static ItemExpr *intersectColumns(const RETDesc &leftTable,
                                  const RETDesc &rightTable,
                                  BindWA* bindWA)
{
  ItemExpr *predicate = NULL;
  for (CollIndex i = 0; i < leftTable.getDegree(); i++) {
    ItemExpr *leftExpr  = leftTable.getValueId(i).getItemExpr();
    ItemExpr *rightExpr = rightTable.getValueId(i).getItemExpr();
    BiRelat *compare = new (bindWA->wHeap())
      BiRelat(ITM_EQUAL, leftExpr, rightExpr, TRUE);
    if (predicate)
      predicate = new (bindWA->wHeap()) BiLogic(ITM_AND, predicate, compare);
    else
      predicate = compare;
  }
  // Binding this predicate must be done in caller's context/scope, not here...
  return predicate;
} // intersectColumns()

static ItemExpr *joinCommonColumns(const RelExpr *const leftRelExpr,
                                   const RelExpr *const rightRelExpr,
                                   BindWA* bindWA)
{
  const RETDesc &leftTable = *leftRelExpr->getRETDesc();
  const RETDesc &rightTable = *rightRelExpr->getRETDesc();
  //
  // Find the common column names between two tables and create a predicate
  // that joins the columns.  For example, if tables T1 and T2 have common
  // column names A and B, return the predicate T1.A = T2.A AND T1.B = T2.B.
  // The checking for ambiguous common columns will be done when they are
  // are coalesced for the output list.
  //
  ItemExpr *predicate = NULL;
  for (CollIndex i = 0; i < leftTable.getDegree(); i++) {
    ColRefName simpleColRefName(leftTable.getColRefNameObj(i).getColName()); //
    if (NOT simpleColRefName.isEmpty()) {                                    //
      ColumnNameMap *commonCol = rightTable.findColumn(simpleColRefName);    //
      if (commonCol) {                                                       //
        ItemExpr *leftExpr  = leftTable.getValueId(i).getItemExpr();
        ItemExpr *rightExpr = commonCol->getValueId().getItemExpr();         //

        bindWA->markAsReferencedColumn(leftExpr);

        bindWA->markAsReferencedColumn(rightExpr);

        BiRelat *compare = new (bindWA->wHeap())
        BiRelat(ITM_EQUAL, leftExpr, rightExpr);
        if (predicate)
          predicate = new(bindWA->wHeap()) BiLogic(ITM_AND, predicate, compare);
        else
          predicate = compare;
      }
    }
  }
  // Binding this predicate is being done in caller, Join::bindNode()
  return predicate;
} // joinCommonColumns()

// Functions findNonCommonColumns() and coalesceCommonColumns()
//
// These create the column descriptors for the result of a natural join.
// A natural join is equivalent to
//
// SELECT SLCC, SLT1, SLT2 FROM T1, T2
//
// where SLCC represents the list of coalesced common columns of T1 and T2,
//       SLT1 represents the list of non-common columns of T1, and
//       SLT2 represents the list of non-common columns of T2.
//
// A coalesced common column C is equivalent to
//
// COALESCE (T1.C, T2.C) AS C  -- i.e. there is no table name; CorrName is ""
//
// where COALESCE (T1.C, T2.C) is equivalent to
//
// CASE WHEN T1.C IS NOT NULL THEN T1.C ELSE T2.C END
//
// Function findNonCommonColumns(), on the first call, coalesces common
// columns into the resultTable, and collects non-common columns.
// On the second call it continues to collect non-common columns.
//
// Function coalesceCommonColumns() adds SLCC, SLT1, SLT2 to the
// resultTable in the proper order.
//
static void findNonCommonColumns(BindWA *bindWA,
                                 OperatorTypeEnum joinType,
                                 const RETDesc &sourceTable,
                                 const RETDesc &targetTable,
                                 RETDesc &resultTable,
                                 ColumnDescList &nonCommonCols)
{
  // Used for ANSI 6.4 SR 3aii below.
  CorrName implemDependCorr(bindWA->fabricateUniqueName(), TRUE);
  //
  for (CollIndex i = 0; i < sourceTable.getDegree(); i++) {
    const ColRefName &sourceColRefName = sourceTable.getColRefNameObj(i);
    ValueId sourceId = sourceTable.getValueId(i);
    ColRefName simpleColRefName(sourceColRefName.getColName());
    //
    // If a column is an unnamed expression, it is a non-common column.
    //
    if (simpleColRefName.isEmpty())
      nonCommonCols.insert(new (bindWA->wHeap())
               ColumnDesc(sourceColRefName, sourceId, NULL, bindWA->wHeap()));
    else {
      ColumnNameMap *commonCol = targetTable.findColumn(simpleColRefName);
      //
      // If the named column does not have a corresponding column in the
      // target table, it is a non-common column.
      //
      if (NOT commonCol)
        nonCommonCols.insert(new (bindWA->wHeap())
                ColumnDesc(sourceColRefName, sourceId, NULL, bindWA->wHeap()));
      //
      // If the target table has more than one corresponding column, error.
      //
      else if (commonCol->isDuplicate()) {
        NAString fmtdList(bindWA->wHeap());
        LIST(TableNameMap*) xtnmList(bindWA->wHeap());
        targetTable.getTableList(xtnmList, &fmtdList);   // Tables in the RETDesc

        *CmpCommon::diags() << DgSqlCode(-4004)
          << DgColumnName(simpleColRefName.getColName())
          << DgTableName(commonCol->getColRefNameObj().getCorrNameObj().
                                    getExposedNameAsAnsiString())
          << DgString0(fmtdList)
          << DgString1(bindWA->getDefaultSchema().getSchemaNameAsAnsiString());

        bindWA->setErrStatus();
        return;
      }
      else if (joinType != ITM_NO_OP) {
        //
        // Coalesce the common columns and add them to the result table.
        //
        ValueId resultId;
        switch(joinType) {
        case REL_JOIN:
        case REL_LEFT_JOIN:
          resultId = sourceId;
          break;
        case REL_RIGHT_JOIN:
          resultId = commonCol->getValueId();
          break;
        default: {
          ItemExpr *sourceExpr = sourceId.getItemExpr();
          ItemExpr *targetExpr = commonCol->getValueId().getItemExpr();
          UnLogic *test = new (bindWA->wHeap())
          UnLogic(ITM_IS_NULL, sourceExpr);
          ItemExpr *coalesce = new (bindWA->wHeap())
                                 Case(NULL, new (bindWA->wHeap())
                                   IfThenElse(test,
                                              targetExpr,
                                              sourceExpr));
          coalesce = coalesce->bindNode(bindWA)->castToItemExpr();
          if (bindWA->errStatus()) {
            delete test;
            delete coalesce;
            return;
          }
          resultId = coalesce->getValueId();
          break;
        } // default case (braces required since vars are initialized here)
        } // switch
        //
        // ANSI 6.4 SR 3aii:
        // We've fabricated a unique implementation-dependent CorrName
        // outside the loop; the common columns have this basically
        // invisible CorrName, the point of which seems to be that
        //   select * from
        //       ta natural join tb
        //     join			-- not natural!
        //      (ta tx natural join tb ty)
        //     on 1=1;
        // should not generate an ambiguous column reference error
        // from the star-expansion.  So according to ANSI,
        // the two natural joins produce, respectively,
        //   fab1.slcc, ta.slt1, tb.slt2
        //   fab2.slcc, tx.slt1, ty.slt2
        // so the join produces
        //   fab1.slcc, ta.slt1, tb.slt2, fab2.slcc, tx.slt1, ty.slt2
        // i.e. the two SLCC's are unambiguous.
        //
        ColRefName implemDepend(simpleColRefName.getColName(),implemDependCorr);
        resultTable.addColumn(bindWA, implemDepend, resultId);
      } // coalesce SLCC into resultTable
    } // named column
  } // for
} // findNonCommonColumns()

// Comments for this function can be found above the preceding function.
static void coalesceCommonColumns(BindWA *bindWA,
                                  OperatorTypeEnum joinType,
                                  const RETDesc &leftTable,
                                  const RETDesc &rightTable,
                                  RETDesc &resultTable)
{
  ColumnDescList nonCommonCols(bindWA->wHeap());
  // non-common columns of the left table
  //
  // Coalesce the common column names of the left and right tables and add
  // them to the result table.
  // Collect the non-common column names from the left.
  //
  findNonCommonColumns(bindWA,
    joinType,
    leftTable,
    rightTable,
    resultTable,
    nonCommonCols);
  if (bindWA->errStatus()) return;
  //
  // Collect the non-common column names from the right.
  //
  RETDesc irrelevantOnThisCall;
  findNonCommonColumns(bindWA,
    ITM_NO_OP,      // do not add SLCC to resultTable
    rightTable,
    leftTable,
    irrelevantOnThisCall,
    nonCommonCols);
  if (bindWA->errStatus()) return;
  //
  // Add the non-common columns from the left and right to the result table.
  //
  resultTable.addColumns(bindWA, nonCommonCols);
  nonCommonCols.clearAndDestroy();
  //
  // Add the system columns from the left and right to the result table.
  //
  resultTable.addColumns(bindWA, *leftTable.getSystemColumnList(), SYSTEM_COLUMN);
  resultTable.addColumns(bindWA, *rightTable.getSystemColumnList(), SYSTEM_COLUMN);
} // coalesceCommonColumns()

// For Catalog Manager, this function:
// 1) Fixes up the name location list to help with computing of the view text,
//    check constraint search condition text, etc.
// 2) Collects the table (base table, view, etc.) usages information for
//    view definitions, check constraint definitions, etc.
//
// ** Some of this could be implemented, perhaps more simply,
// ** using BindWA::viewCount() and BindWA::tableViewUsageList().
//
static void BindUtil_CollectTableUsageInfo(BindWA *bindWA,
                                           const CorrName& corrName)
{
  // Task (1)
  //
  ParNameLocList *pNameLocList = bindWA->getNameLocListPtr();
  if (pNameLocList)
  {
    ParNameLoc * pNameLoc
      = pNameLocList->getNameLocPtr(corrName.getNamePosition());
    if (pNameLoc)
    {
      if (NOT pNameLoc->getExpandedName(FALSE).isNull())
        CMPASSERT(pNameLoc->getExpandedName() ==
          corrName.getQualifiedNameObj().getQualifiedNameAsAnsiString());
      pNameLoc->setExpandedName(
                corrName.getQualifiedNameObj().getQualifiedNameAsAnsiString());
    }
    //
    // Task (2)
    //
    ExprNode *pUsageParseNode = bindWA->getUsageParseNodePtr();
    if (pUsageParseNode)
    {
      if (pUsageParseNode->getOperatorType() == DDL_CREATE_VIEW)
      {
        StmtDDLCreateView &cvpn = *pUsageParseNode->castToElemDDLNode()
          ->castToStmtDDLCreateView();
        ParTableUsageList &vtul = cvpn.getViewUsages().getViewTableUsageList();
        vtul.insert(corrName.getExtendedQualNameObj());
      }
      else if (pUsageParseNode->getOperatorType()
               == DDL_ALTER_TABLE_ADD_CONSTRAINT_CHECK)
      {
        StmtDDLAddConstraintCheck &node = *pUsageParseNode->castToElemDDLNode()
           ->castToStmtDDLAddConstraintCheck();
        ParTableUsageList &tul = node.getTableUsageList();
        tul.insert(corrName.getQualifiedNameObj());
      }
    }
  } // if (pNameLocList)

} // BindUtil_CollectTableUsageInfo()

void castComputedColumnsToAnsiTypes(BindWA *bindWA,
                                    RETDesc *rd,
                                    ValueIdList &compExpr)
{
  if (! rd)
    return;

  const ColumnDescList &cols = *rd->getColumnList();
  CollIndex i = cols.entries();
  CMPASSERT(i == compExpr.entries());

  while (i--) {
    ColumnDesc *col = cols[i];

    if (col->getValueId().getType().getTypeQualifier() == NA_ROWSET_TYPE) {
      return;
    }
    NAType *naType = &(NAType&)col->getValueId().getType();
    //
    // Note: the unsupported and DATETIME cases are mutually exclusive with the LARGEDEC case below.
    //
    if (!naType->isSupportedType()) {
      // Unsupported types are displayed as strings of '#' to their display length
      ItemExpr *theRepeat =
        new (bindWA->wHeap()) Repeat(new (bindWA->wHeap()) SystemLiteral("#"),
                                       new (bindWA->wHeap()) SystemLiteral(
                                            naType->getDisplayLength(
                                                 naType->getFSDatatype(),
                                                 0,
                                                 naType->getPrecision(),
                                                 naType->getScale(),
                                                 0)));
      theRepeat = theRepeat->bindNode(bindWA);
      col->setValueId(theRepeat->getValueId());
      compExpr[i] = theRepeat->getValueId();
    }
    else if ((CmpCommon::getDefault(MODE_SPECIAL_1) == DF_ON) &&
             (NOT bindWA->inViewDefinition()) &&
             (NOT bindWA->inMVDefinition()) &&
             (NOT bindWA->inCTAS()) &&
             (naType->getTypeQualifier()== NA_DATETIME_TYPE &&
              ((const DatetimeType *)naType)->getSubtype() == 
              DatetimeType::SUBTYPE_SQLDate) &&
             (! CmpCommon::context()->getSqlmxRegress()) &&
             (strcmp(ActiveSchemaDB()->getDefaults().getValue(OUTPUT_DATE_FORMAT),
               "ANSI") != 0))
      { // Special1 DATE, return as YY/MM/DD
        ItemExpr * newChild =
          new (bindWA->wHeap())
          Format(col->getValueId().getItemExpr(), "YY/MM/DD", FALSE);
        newChild = newChild->bindNode(bindWA);
        col->setValueId(newChild->getValueId());
        compExpr[i] = newChild->getValueId();
      }

    if ((naType->getFSDatatype() == REC_BIN64_UNSIGNED) &&
        (CmpCommon::getDefault(TRAF_LARGEINT_UNSIGNED_IO) == DF_OFF) &&
        (NOT bindWA->inCTAS()) &&
        (NOT bindWA->inViewDefinition()))
      {
        NumericType *nTyp = (NumericType *)naType;
        
        ItemExpr * cast = new (bindWA->wHeap())
          Cast(col->getValueId().getItemExpr(),
               new (bindWA->wHeap())
               SQLBigNum(bindWA->wHeap(), MAX_HARDWARE_SUPPORTED_UNSIGNED_NUMERIC_PRECISION,
                         nTyp->getScale(),
                         FALSE,
                         FALSE,
                         naType->supportsSQLnull()
                         ));
        
        cast = cast->bindNode(bindWA);
        if (bindWA->errStatus()) 
          return;
        col->setValueId(cast->getValueId());
        compExpr[i] = cast->getValueId();

        naType = (NAType*)&cast->getValueId().getType();
      }

    if ((naType->getFSDatatype() == REC_BOOLEAN) &&
        (CmpCommon::getDefault(TRAF_BOOLEAN_IO) == DF_OFF) &&
        (NOT bindWA->inCTAS()) &&
        (NOT bindWA->inViewDefinition()))
      {
        NumericType *nTyp = (NumericType *)naType;
        
        ItemExpr * cast = new (bindWA->wHeap())
          Cast(col->getValueId().getItemExpr(),
               new (bindWA->wHeap())
               SQLChar(bindWA->wHeap(), SQL_BOOLEAN_DISPLAY_SIZE, naType->supportsSQLnull()));
        
        cast = cast->bindNode(bindWA);
        if (bindWA->errStatus()) 
          return;
        col->setValueId(cast->getValueId());
        compExpr[i] = cast->getValueId();
        
        naType = (NAType*)&cast->getValueId().getType();
      }
    
    // if OFF, return tinyint as smallint.
    // This is needed until all callers/drivers have full support to
    // handle IO of tinyint datatypes.
    if (((naType->getFSDatatype() == REC_BIN8_SIGNED) ||
         (naType->getFSDatatype() == REC_BIN8_UNSIGNED)) &&
        (NOT bindWA->inCTAS()) &&
        (NOT bindWA->inViewDefinition()) &&
        ((CmpCommon::getDefault(TRAF_TINYINT_SUPPORT) == DF_OFF) ||
         (CmpCommon::getDefault(TRAF_TINYINT_RETURN_VALUES) == DF_OFF)))
      {
        NumericType *srcNum = (NumericType*)naType; 
        NumericType * newType;
        if (srcNum->getScale() == 0)
          newType = new (bindWA->wHeap())
            SQLSmall(bindWA->wHeap(), NOT srcNum->isUnsigned(),
                     naType->supportsSQLnull());
        else
          newType = new (bindWA->wHeap())
            SQLNumeric(bindWA->wHeap(), sizeof(short), srcNum->getPrecision(), 
                       srcNum->getScale(),
                       NOT srcNum->isUnsigned(), 
                       naType->supportsSQLnull());

        ItemExpr * cast = new (bindWA->wHeap())
          Cast(col->getValueId().getItemExpr(), newType);

        cast = cast->bindNode(bindWA);
        if (bindWA->errStatus()) 
          return;
        col->setValueId(cast->getValueId());
        compExpr[i] = cast->getValueId();
      }
    else if (naType->getTypeQualifier() == NA_NUMERIC_TYPE && 
             !((NumericType &)col->getValueId().getType()).binaryPrecision()) {
      NumericType *nTyp = (NumericType *)naType;
      
      ItemExpr * ie = col->getValueId().getItemExpr();
      NAType *newTyp = NULL;
      Lng32 newPrec;
      Lng32 newScale;
      Lng32 oflow = -1;
      Lng32 bignumOflow = -1;
      NABoolean bignumIO = FALSE;
      if (CmpCommon::getDefault(BIGNUM_IO) == DF_ON)
        bignumIO = TRUE; // explicitely set to ON
      else if (CmpCommon::getDefault(BIGNUM_IO) == DF_OFF)
        bignumIO = FALSE; // explicitely set to OFF
      else if (CmpCommon::getDefault(BIGNUM_IO) == DF_SYSTEM)
        {
          if ((nTyp->isBigNum()) &&
              (((SQLBigNum*)nTyp)->isARealBigNum()))
            bignumIO = TRUE;
        }

      if (CmpCommon::getDefaultNumeric(MAX_NUMERIC_PRECISION_ALLOWED) ==
          MAX_HARDWARE_SUPPORTED_SIGNED_NUMERIC_PRECISION)
        bignumIO = FALSE;

      if (bignumIO)
        bignumOflow = nTyp->getPrecision() - 
          (Lng32)CmpCommon::getDefaultNumeric(MAX_NUMERIC_PRECISION_ALLOWED);
      else
        {
          if (nTyp->isSigned())
            oflow = nTyp->getPrecision() - MAX_HARDWARE_SUPPORTED_SIGNED_NUMERIC_PRECISION;
          else
            oflow = nTyp->getPrecision() - MAX_HARDWARE_SUPPORTED_UNSIGNED_NUMERIC_PRECISION;
        }

      if ((bignumOflow > 0) || (oflow > 0))
        {
          if (bignumOflow > 0) {
            newPrec = 
              (Lng32)CmpCommon::getDefaultNumeric(MAX_NUMERIC_PRECISION_ALLOWED);
            Lng32 orgMagnitude = nTyp->getPrecision() - nTyp->getScale();
        
            // set the newScale
            // IF there is overflow in magnitude set the scale to 0.
            // ELSE set the accomodate the magnitude part and truncate the scale
            newScale = (orgMagnitude >= newPrec) ? 0 : newPrec - orgMagnitude ;

            if (newScale > newPrec)
              {
                *CmpCommon::diags() << DgSqlCode(-3015) 
                                    << DgInt0(newScale) << DgInt1(newPrec);

                bindWA->setErrStatus();
                return;
              }

            newTyp = new (bindWA->wHeap())
              SQLBigNum(bindWA->wHeap(), newPrec,
                        newScale,
                        ((SQLBigNum &)col->getValueId().getType()).isARealBigNum(),
                        nTyp->isSigned(),
                        nTyp->supportsSQLnull());
          }
          else if (oflow > 0) {
            // If it's not a computed expr, but a column w/ a legal type, re-loop
            if (col->getValueId().getNAColumn(TRUE/*don't assert*/)) {
              //CMPASSERT(!nTyp->isInternalType());
              //continue;
            }
            
            OperatorTypeEnum op = ie->origOpType();
            CMPASSERT(op != NO_OPERATOR_TYPE &&      // Init'd correctly?
                      op != ITM_RENAME_COL &&      // Expect these to have
                      op != ITM_REFERENCE);      // been bound, vanished.
            
            ItemExpr *ie2 = ie;
	    
            while (op == ITM_INSTANTIATE_NULL)
            {
              ie2 = ie2->child(0).getPtr();
              op = ie2->origOpType();
            }

            // ANSI 6.5 SR 7 - 9:  aggregates must be exact if column is exact.
            newPrec  = MAX_NUMERIC_PRECISION;
            Lng32 orgMagnitude = (nTyp->getMagnitude() + 9) / 10;
            // set the newScale
            // IF there is overflow in magnitude set the scale to 0.
            // ELSE set the accomodate the magnitude part and truncate the scale
            newScale = (orgMagnitude >= newPrec) ? 0 : newPrec - orgMagnitude ;
            
            // Based on the CQD set the scale to MIN value.
            // CQD specifies the MIN scale that has to be preserved in case
            // of overflow.
            NADefaults &defs = ActiveSchemaDB()->getDefaults();
            Lng32 minScale = defs.getAsLong(PRESERVE_MIN_SCALE);
            newScale = MAXOF(minScale, newScale);
            
            if (op == ITM_SUM || op == ITM_AVG) {
              // AVG = DIVIDE( SUM(), COUNT() )
              ItemExpr *tmp = (op == ITM_SUM) ?
                ie2 : ie2->child(0).getPtr();

              //
              // Now that we support OLAP functions, this may be
              // a pointer to an ITM_NOTCOVERED node.  If so, we
              // need to check its child(0) node rather than 
              // the ITM_NOTCOVERED node.
              //
              if (tmp->getOperatorType() == ITM_NOTCOVERED )
                  tmp = (Aggregate *)(ItemExpr *)tmp->child(0);

              CMPASSERT(tmp->isAnAggregate());
              Aggregate *sum = (Aggregate *)tmp;
              ItemExpr *arg = (sum->getOriginalChild()) ?
                sum->getOriginalChild()  : sum->child(0).getPtr();
              if (arg->getValueId() == NULL_VALUE_ID)
                arg = sum->child(0).getPtr();
              CMPASSERT(arg->getValueId() != NULL_VALUE_ID);
              Lng32 needScale = arg->getValueId().getType().getScale();
              if (needScale > newPrec)
                needScale = newPrec;
              if (newScale < needScale || op == ITM_SUM) // ANSI 6.5 SR 9 b + c
                newScale = needScale;
            }
            
            if (newScale == 0)
              newTyp = new (bindWA->wHeap())
                         SQLLargeInt(bindWA->wHeap(), TRUE, // hardware only supports signed
                                     nTyp->supportsSQLnull());
            else
              newTyp = new (bindWA->wHeap())
                         SQLNumeric(bindWA->wHeap(), sizeof(Int64),
                                    newPrec,
                                    newScale,
                                    nTyp->isSigned(),
                                    nTyp->supportsSQLnull());
            
          } // overflow
          
          ItemExpr *cast = new (bindWA->wHeap())
                             Cast(ie, newTyp, ITM_CAST, TRUE/*checkForTrunc*/);
          cast = cast->bindNode(bindWA);
          if (bindWA->errStatus()) return;
          
          if (!col->getColRefNameObj().getColName().isNull()) {
            // We get here via CREATE VIEW v AS SELECT (expr op expr) AS nam ...;
            
            // ColumnDesc::setValueId() makes the RETDesc's XCNM inconsistent --
            // but this is ok because name lookup over this XCNM doesn't happen
            // after the point we've gotten to here --
            // a) if caller is StmtDDLCreateView::bindNode via RelRoot::bindNode,
            //    there's no further lookup at all;
            // b) if caller is bindView(), then thanks to the way RenameTable
            //    and RETDesc work, the inconsistent XCNM is not consulted
            //    so we don't have to worry about this issue ... (for now anyhow!)
          }
          col->setValueId(cast->getValueId());
          compExpr[i] = cast->getValueId();
        } // overflow (bignum or regular)
    }   // numeric
  }   // loop over cols in RETDesc
}   // castComputedColumnsToAnsiTypes()

TrafDesc *generateSpecialDesc(const CorrName& corrName)
{
  TrafDesc * desc = NULL;

  if (corrName.getSpecialType() == ExtendedQualName::VIRTUAL_TABLE)
    {
      if (corrName.getQualifiedNameObj().getObjectName() == ExplainFunc::getVirtualTableNameStr())
        {
          ExplainFunc ef;
          desc = ef.createVirtualTableDesc();
        }
      else if (corrName.getQualifiedNameObj().getObjectName() == StatisticsFunc::getVirtualTableNameStr())
        {
          StatisticsFunc sf;
          desc = sf.createVirtualTableDesc();
        }
      else if (corrName.getQualifiedNameObj().getObjectName() == ExeUtilRegionStats::getVirtualTableNameStr())
        {
          ExeUtilRegionStats eudss;
          desc = eudss.createVirtualTableDesc();
        }
      else if (corrName.getQualifiedNameObj().getObjectName() == ExeUtilRegionStats::getVirtualTableClusterViewNameStr())
        {
          ExeUtilRegionStats eudss(TRUE);
          desc = eudss.createVirtualTableDesc();
        }
      else if (HiveMDaccessFunc::isHiveMD(corrName.getQualifiedNameObj().getObjectName()))
        {
          NAString mdType = 
            HiveMDaccessFunc::getMDType(corrName.getQualifiedNameObj().getObjectName());

          HiveMDaccessFunc hivemd(&mdType);
          desc = hivemd.createVirtualTableDesc();
        }
    }

  return desc;
} // generateSpecialDesc()


// -----------------------------------------------------------------------
// member functions for class BindWA
// -----------------------------------------------------------------------
NARoutine *BindWA::getNARoutine ( const QualifiedName &name )
{
  NARoutineDBKey key(name, wHeap());
  NARoutine * naRoutine = getSchemaDB()->getNARoutineDB()->get(this, &key);
  if (!naRoutine)
  {
     TrafDesc *udfMetadata = NULL;
     CmpSeabaseDDL cmpSBD(STMTHEAP);
     udfMetadata =  cmpSBD.getSeabaseRoutineDesc(
				       name.getCatalogName(),
				       name.getSchemaName(),
				       name.getObjectName());
     if (!udfMetadata)
       return NULL;

     NAHeap *routineHeap;
     if (getSchemaDB()->getNARoutineDB()->cachingMetaData()) 
     {
       const Lng32 size = 16 * 1024;  // The initial size
       routineHeap = new CTXTHEAP NAHeap("NARoutine Heap", (NAHeap *)CTXTHEAP, 
                                         size);
     }
     else 
       routineHeap=CmpCommon::statementHeap(); 

     Int32 errors=0;
     naRoutine = new (routineHeap)
       NARoutine(name,
                 udfMetadata, 
                 this,
                 errors,
                 routineHeap);
     if ( NULL == naRoutine || errors != 0)
     {
       setErrStatus();
       return NULL;
     }
     
     // Add NARoutine to the NARoutineDB cache.
     if (getSchemaDB()->getNARoutineDB()->cachingMetaData()) 
       getSchemaDB()->getNARoutineDB()->put(naRoutine);
  }
  return naRoutine;
}

NATable *BindWA::getNATable(CorrName& corrName,
                            NABoolean catmanCollectTableUsages, // default TRUE
                            TrafDesc *inTableDescStruct)     // default NULL
{
  BindWA *bindWA = this;   // for coding convenience

  NATable * table = NULL;
  // Search in volatile schema first. If not found, search in regular cat/sch.
  NABoolean volatileTableFound = FALSE;
  NAString userName;
  if ((CmpCommon::context()->sqlSession()->volatileSchemaInUse()) &&
      (! inTableDescStruct) &&
      (corrName.getSpecialType() != ExtendedQualName::VIRTUAL_TABLE) &&
      (corrName.getSpecialType() != ExtendedQualName::HBMAP_TABLE))
    {
      CorrName newCorrName = 
        CmpCommon::context()->sqlSession()->getVolatileCorrName
          (corrName);
      if (bindWA->errStatus())
        return NULL;

      //get NATable from cache
      table = bindWA->getSchemaDB()->getNATableDB()->
        get(newCorrName, bindWA, inTableDescStruct);
      if (!table)
        {
          // now search in regular cat/sch.
          // clear diags area.
          CmpCommon::diags()->clear();
          bindWA->resetErrStatus();
        }
      else
        {
          NABoolean isValid = 
            CmpCommon::context()->sqlSession()->validateVolatileCorrName
            (corrName);

          // if this table is found in volatile schema, then
          // make sure it is a volatile table.
          if ((isValid) &&
              (NOT table->isVolatileTable()))
            {
              *CmpCommon::diags() << DgSqlCode(-4190) <<
                                     DgTableName(table->getTableName().
                                       getQualifiedNameAsAnsiString(TRUE));
              
              bindWA->setErrStatus();
              return NULL;
            }

          if (isValid)
            {
              newCorrName.setIsVolatile(TRUE);
              corrName = newCorrName;
            }
          else
            {
              // table was found in the volatile schema but it is
              // not a valid volatile name.
              // Look for it in regular schema.
              table = NULL;

              CmpCommon::diags()->clear();
              bindWA->resetErrStatus();

              // remember that volatile table was found so we
              // can generate a better error message later.
              volatileTableFound = TRUE;
            }
        }
    }

  if (! table)
    {
      // Expand the table (base table, view, etc.) name with
      // the default catalog and schema parts if the specified
      // table name does not include these parts.
      // This method will also first apply any prototype value (from a host var)
      // into the corrName's qualifiedName.
      //

      NABoolean catNameSpecified =
              (NOT corrName.getQualifiedNameObj().getCatalogName().isNull());
      NABoolean schNameSpecified =
              (NOT corrName.getQualifiedNameObj().getSchemaName().isNull());

     // try PUBLIC SCHEMA only when no schema was specified
      // and CQD PUBLIC_SCHEMA_NAME is specified
      NAString publicSchema = "";
      CmpCommon::getDefault(PUBLIC_SCHEMA_NAME, publicSchema, FALSE);
      ComSchemaName pubSchema(publicSchema);
      NAString pubSchemaIntName = "";
      if ( !schNameSpecified && !pubSchema.getSchemaNamePart().isEmpty() )
      {
        pubSchemaIntName = pubSchema.getSchemaNamePart().getInternalName();
      }

      corrName.applyDefaults(bindWA, bindWA->getDefaultSchema());
      if (bindWA->errStatus())
        return NULL;      // prototype value parse error

      // cannot use hbase map schema as table name
      if ((corrName.getQualifiedNameObj().getSchemaName() == HBASE_EXT_MAP_SCHEMA) &&
          (! Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL)) &&
          (! Get_SqlParser_Flags(ALLOW_SPECIALTABLETYPE)))
         {
          *CmpCommon::diags() << DgSqlCode(-4261)
                              << DgSchemaName(corrName.getQualifiedNameObj().getSchemaName());
          
          bindWA->setErrStatus();
          return NULL;
        }

      // if this is an HBase mapped table and schema name is not specified, 
      // then set schema to hbase map schema.
      if ((corrName.getSpecialType() == ExtendedQualName::HBMAP_TABLE) &&
          (NOT schNameSpecified))
        {
          corrName.getQualifiedNameObj().setSchemaName(HBASE_EXT_MAP_SCHEMA);
        }
 
      // override schema
      if ( ( overrideSchemaEnabled() )
           // not volatile table
        && ( ! volatileTableFound ) 
        )
      {
        doOverrideSchema(corrName);
      }

      // if DEFAULT_SCHEMA_ACCESS_ONLY, can only access default and public schemas
      if (corrName.getSpecialType()==ExtendedQualName::NORMAL_TABLE) 
                                    // NORMAL_TABLE also covers synonym, view and MV
      {
        if (violateAccessDefaultSchemaOnly(corrName.getQualifiedNameObj()))
          return NULL;
      }

      // make sure that schema name is not a VOLATILE SCHEMA
      if ((! bindWA->inDDL()) ||
          ((bindWA->inViewDefinition()) ||
           (bindWA->inMVDefinition())))
      {
        // for Histogram, support to use VOLATILE SCHEMA
        // or else, don't support
        if (!corrName.getQualifiedNameObj().isHistogramTable() && 
            !CmpCommon::context()->sqlSession()->validateVolatileQualifiedSchemaName
            (corrName.getQualifiedNameObj()))
        {
          bindWA->setErrStatus();
          return NULL;
        }
      }

      // if specified name is an HBASE name, see if a mapped table exists
      if ((corrName.getQualifiedNameObj().getCatalogName() == HBASE_SYSTEM_CATALOG) &&
          ((corrName.getQualifiedNameObj().getSchemaName() == HBASE_MAP_SCHEMA) ||
           (corrName.getQualifiedNameObj().getSchemaName() == HBASE_SYSTEM_SCHEMA)))
        {
          corrName.getQualifiedNameObj().setCatalogName(TRAFODION_SYSCAT_LIT);
          corrName.getQualifiedNameObj().setSchemaName(HBASE_EXT_MAP_SCHEMA);
        }
      
      //get NATable (from cache or from metadata)
      table = bindWA->getSchemaDB()->getNATableDB()->
                                     get(corrName, bindWA, inTableDescStruct);

      //try the public schema if not found
      if ( !table && !pubSchemaIntName.isNull() )
      {
        CorrName pCorrName(corrName);
        pCorrName.getQualifiedNameObj().setSchemaName(pubSchemaIntName);
        if ( !pubSchema.getCatalogNamePart().isEmpty() )
        {
          pCorrName.getQualifiedNameObj().setCatalogName(
            pubSchema.getCatalogNamePart().getInternalName());
        }

        bindWA->resetErrStatus();
        table = bindWA->getSchemaDB()->getNATableDB()->
                                       get(pCorrName, bindWA, inTableDescStruct);
        if ( !bindWA->errStatus() && table )
        { // if found in public schema, do not show previous error
          // and replace corrName
          CmpCommon::diags()->clear();
          corrName.getQualifiedNameObj().setCatalogName(
            pCorrName.getQualifiedNameObj().getCatalogName());
          corrName.getQualifiedNameObj().setSchemaName(
            pCorrName.getQualifiedNameObj().getSchemaName());
        }
      }

      // if sch name was not specified and table is not found in default schema, then
      // look for it in HBase mapped schema.
      if ( !table && ! schNameSpecified)
        {
          CorrName pCorrName(corrName);
          pCorrName.getQualifiedNameObj().setSchemaName(HBASE_EXT_MAP_SCHEMA);
          
          bindWA->resetErrStatus();
          Lng32 diagsMark = CmpCommon::diags()->mark();
          table = bindWA->getSchemaDB()->getNATableDB()->
            get(pCorrName, bindWA, inTableDescStruct);
          if ( !bindWA->errStatus() && table )
            { // if found in mapped schema, do not show previous error
              // and replace corrName
              CmpCommon::diags()->clear();
              corrName.getQualifiedNameObj().setCatalogName(
                   pCorrName.getQualifiedNameObj().getCatalogName());
              corrName.getQualifiedNameObj().setSchemaName(
                   pCorrName.getQualifiedNameObj().getSchemaName());
            }
          else
            {
              // discard the errors from failed map table name lookup and only return
              // the previous error.
              CmpCommon::diags()->rewind(diagsMark);
            }
         }

      // move to here, after public schema try because BindUtil_CollectTableUsageInfo
      // saves table info for mv definition, etc.
      // Conditionally (usually) do stuff for Catalog Manager (static func above).

      if (catmanCollectTableUsages)
        if (corrName.getSpecialType() != ExtendedQualName::TRIGTEMP_TABLE)
          {
            if ((bindWA->inViewDefinition()) &&
                (corrName.isHbaseMap()))
              {
                // this is an internal hbase mapped name.
                // Use the original name to store in view definition.
                CorrName origName(corrName);
                origName.getQualifiedNameObj().setCatalogName(HBASE_SYSTEM_CATALOG);
                origName.getQualifiedNameObj().setSchemaName(HBASE_MAP_SCHEMA);
                BindUtil_CollectTableUsageInfo(bindWA, origName); 
              }
            else
              BindUtil_CollectTableUsageInfo(bindWA, corrName); 
          }

      if (!table)
        {
          if (volatileTableFound) 
            {
              if ((CmpCommon::diags()->mainSQLCODE() == -1003) &&
                  (NOT catNameSpecified))
                {
                  // the name is in true USER_NAME.VOL_TAB_NAME form
                  // where the USER_NAME doesn't match current name.
                  // Clear errors and return an appropriate message.
                  CmpCommon::diags()->clear();
                  CmpCommon::context()->sqlSession()->validateVolatileCorrName
                    (corrName);
                  bindWA->setErrStatus();
                }
            }
          
          return NULL;
        }
    }

  // if a volatile table is found, make sure that volatile schema is in
  // use and volatile tables are allowed.
  if ((table) && (table->isVolatileTable()))
    {
      // set volatile table indication in table's tablename
      ((QualifiedName&)(table->getTableName())).setIsVolatile(TRUE);
    }
      
  // For now, don't allow access through the Trafodion external name created for
  // native HIVE or HBASE objects unless the allowExternalTables flag is set.  
  // allowExternalTables is set for drop table and SHOWDDL statements.  
  // TDB - may want to merge the Trafodion version with the native version.
  if ((table) && 
      (table->isTrafExternalTable() && 
       (NOT table->getTableName().isHbaseMappedName()) &&
       (! bindWA->allowExternalTables())))    
    {
      *CmpCommon::diags() << DgSqlCode(-4258)
			  << DgTableName(table->getTableName().getQualifiedNameAsAnsiString());
      
      bindWA->setErrStatus();
      return NULL;
    }
  
  // If the table is an external table and has an associated native table, 
  // check to see if the external table structure still matches the native table.
  // If not, return an error
  if ((table) && table->isTrafExternalTable() &&
      (NOT table->getTableName().isHbaseMappedName()))
    {
      NAString adjustedName =ComConvertTrafNameToNativeName 
           (table->getTableName().getCatalogName(),
            table->getTableName().getUnqualifiedSchemaNameAsAnsiString(),
            table->getTableName().getUnqualifiedObjectNameAsAnsiString()); 
        
      // Get a description of the associated Trafodion table
      Int32 numNameParts = 3;
      QualifiedName adjustedQualName(adjustedName,numNameParts,STMTHEAP, bindWA);
      CorrName externalCorrName(adjustedQualName, STMTHEAP);
      NATable *nativeNATable = bindWA->getSchemaDB()->getNATableDB()->
                                  get(externalCorrName, bindWA, inTableDescStruct);
      if ((bindWA->externalTableDrop()) &&
          (bindWA->errStatus()))
        {
          return NULL;
        }
      
      // Compare native and external table definitions.
      // -- If this call is to drop external table, skip comparison.
      // -- Otherwise compare that number of columns is the same.
      // -- Compare type for corresponding columns. But if external table 
      //    was created with explicit col attrs, then skip type check for cols.
      // 
      // TBD - return what mismatches
      NABoolean compError = FALSE;
      if (nativeNATable &&
          (NOT bindWA->externalTableDrop()))
        { 
          if (table->getNAColumnArray().entries() != 
              nativeNATable->getNAColumnArray().entries())
            compError = TRUE;
          if ((NOT compError) &&
              (NOT table->hiveExtColAttrs()) &&
              (NOT table->hiveExtKeyAttrs()))
            {
              if (NOT (table->getNAColumnArray() == nativeNATable->getNAColumnArray()))
                compError = TRUE;
            }
          if (compError)
            {
              *CmpCommon::diags() << DgSqlCode(-3078)
                                  << DgString0(adjustedName)
                                  << DgTableName(table->getTableName().getQualifiedNameAsAnsiString());
              bindWA->setErrStatus();
              nativeNATable->setRemoveFromCacheBNC(TRUE);
              return NULL;
            }
        }
    }
  
  HostVar *proto = corrName.getPrototype();
  if (proto && proto->isPrototypeValid())
    corrName.getPrototype()->bindNode(bindWA);

  // This test is not "inAnyConstraint()" because we DO want to increment
  // the count for View With Check Option constraints.
  if (!getCurrentScope()->context()->inTableCheckConstraint() &&
      !getCurrentScope()->context()->inRIConstraint())
    table->incrReferenceCount();

  if (table)
    OSIM_captureTableOrView(table);

  return table;
} // BindWA::getNATable()

NATable *BindWA::getNATableInternal(
     CorrName& corrName,
     NABoolean catmanCollectTableUsages, // default TRUE
     TrafDesc *inTableDescStruct,     // default NULL
     NABoolean extTableDrop)
{
  ULng32 savedParserFlags = Get_SqlParser_Flags (0xFFFFFFFF);
  Set_SqlParser_Flags(ALLOW_VOLATILE_SCHEMA_IN_TABLE_NAME);
  Set_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL);
  
  setAllowExternalTables(TRUE);
  if (extTableDrop)
    setExternalTableDrop(TRUE);

  NATable * nat = 
    getNATable(corrName, catmanCollectTableUsages, inTableDescStruct);

  // Restore parser flags settings to what they originally were
  Assign_SqlParser_Flags (savedParserFlags);
  setAllowExternalTables(FALSE);
  setExternalTableDrop(FALSE);

  return nat;
}

static TableDesc *createTableDesc2(BindWA *bindWA,
                                   const NATable *naTable,
                                   CorrName &corrName, Hint *hint)
{
  // Allocate a base table descriptor.
  //
  TableDesc *tdesc = new (bindWA->wHeap()) TableDesc(bindWA, naTable, corrName);

  // Insert the table name into the XTNM.
  //
  bindWA->getCurrentScope()->getXTNM()->insertNames(bindWA, corrName);
  if (bindWA->errStatus()) return NULL;

  // For each NAColumn, allocate a BaseColumn, bind the BaseColumn, and
  // add the ValueId to the TableDesc.
  //
  CollIndex i = 0;
  for (i = 0; i < naTable->getColumnCount(); i++) {
    BaseColumn *baseCol = new (bindWA->wHeap()) BaseColumn(tdesc, i);
    baseCol->bindNode(bindWA);
    if (bindWA->errStatus()) 
      return NULL;
    ValueId valId = baseCol->getValueId();
    tdesc->addToColumnList(valId);
  }

  // set primary key for this table
  tdesc->setPrimaryKeyColumns();

  // For each index, create an IndexDesc.
  //

  NAString indexChoice;
  NADefaults &defs = ActiveSchemaDB()->getDefaults();
  defs.getValue(HIDE_INDEXES,indexChoice);

  for (i = 0; i < naTable->getIndexList().entries(); i++)
  {
      NAFileSet *nfs=naTable->getIndexList()[i];
      
      IndexDesc *idesc = new (bindWA->wHeap())
        IndexDesc(tdesc, nfs, bindWA->currentCmpContext());

      if (naTable->getClusteringIndex()->getFileSetName() ==
          idesc->getIndexName()) {
        tdesc->setClusteringIndex(idesc);
        idesc->markAsClusteringIndex();
      }
      
      if(indexChoice.compareTo("NONE") ==0
         OR indexChoice.compareTo("VERTICAL") ==0
         OR (indexChoice.compareTo("KEYINDEXES") ==0 AND
         tdesc->isKeyIndex(idesc))
         OR naTable->getClusteringIndex()->getFileSetName() ==
            nfs->getFileSetName())
      {
          tdesc->addIndex(idesc);
          // implementation of optimizer hints
          if (hint AND hint->hasIndexHint
              (idesc->getNAFileSet()->getExtFileSetName()))
          {
            tdesc->addHintIndex(idesc);
          }
      if (idesc->isUniqueIndex() )
        tdesc->addUniqueIndex(idesc);
      }
      else
      {
        delete idesc;
      }

  }

  if (hint AND hint->indexCnt() > tdesc->getHintIndexes().entries() AND
      CmpCommon::getDefault(INDEX_HINT_WARNINGS) != DF_OFF)
    {
      // emit a warning that we didn't process all the index hints,
      // there is probably a spelling mistake
      *CmpCommon::diags() << DgSqlCode(4371)
                          << DgInt0(tdesc->getHintIndexes().entries())
                          << DgInt1(hint->indexCnt())
                          << DgTableName(naTable->getTableName().
                                         getQualifiedNameAsAnsiString());
    }

  // For each vertical partition, create an IndexDesc.
  // Add this VP to the list of VPs for the TableDesc.
 for (i = 0; i < naTable->getVerticalPartitionList().entries(); i++) {
    if(indexChoice.compareTo("NONE") ==0
       OR indexChoice.compareTo("INDEXES")==0
       OR indexChoice.compareTo("KEYINDEXES")==0)
      {
        IndexDesc *idesc = new (bindWA->wHeap())
            IndexDesc(tdesc, naTable->getVerticalPartitionList()[i],
                     bindWA->currentCmpContext());
        tdesc->addVerticalPartition(idesc);
      }
  }

  // Allocate a RETDesc, attach it to the BindScope.
  //
  bindWA->getCurrentScope()->setRETDesc(new (bindWA->wHeap())
    RETDesc(bindWA, tdesc));

  // Do not include tables-referenced-in-a-constraint (when/if we allow them)
  // in the view-contains-table list; if we did include them, then
  // TableViewUsageList::getViewsOnTable() would give wrong results
  // for where it's used to prevent the Halloween problem.
  //
  // If we end up needing this extra info, I advise either a separate list,
  // or a new field in TableViewUsage indicating usage type (containment
  // versus reference), enhancing method getViewsOnTable() accordingly.
  //
  if (!bindWA->getCurrentScope()->context()->inAnyConstraint())
    bindWA->tableViewUsageList().insert(new (bindWA->wHeap())
      TableViewUsage(
           tdesc->getCorrNameObj().getQualifiedNameObj(),
           tdesc->getCorrNameObj().getSpecialType(),
           naTable->getViewText() != NULL,
           bindWA->viewCount()));

  return tdesc;

} // static createTableDesc2()

TableDesc *BindWA::createTableDesc(const NATable *naTable,
                                   CorrName &corrName,
                                   NABoolean catmanCollectUsages, Hint *hint)
{
  BindWA *bindWA = this;  // for coding convenience

  TableDesc *tdesc = createTableDesc2(bindWA, naTable, corrName, hint);
  if (bindWA->errStatus()) return NULL;

  // Now bind any table check constraints and attach them to our new tdesc.
  // These constraints must be processed for UPDATE and INSERT.
  // DELETEs must clear them; see Delete::bindNode.
  //
  // For SELECTs, NOT NULL constraints are marked on the NAColumn::allowsNulls
  // allowing more elaborate Transformations.  For SELECTs, other types of
  // constraints are not currently used, but could be in future,
  // to optimize by providing additional predicate/selectivity info.
  //
  // ## We ought to write some regression test cases like
  //	INSERT INTO T (SELECT * FROM S)	-- T's constraints yes, S irrelevant
  //	INSERT INTO T VALUES ((SELECT A FROM S WHERE..),..)
  //	INSERT INTO V3 ...	-- underlying basetbl's constrts yes
  //				-- V3 atop VA atop T: let the views be
  //				-- WITH CHECK OPTION, then viewpred-constrt yes
  //
  const CheckConstraintList &ccl = naTable->getCheckConstraints();
  if (ccl.entries()) {

    // Table check constraint text is stored in the metadata tables
    // with the underlying table/view name (e.g. "CHECK (C.S.T.COL > 0)"),
    // whereas any correlation name in a query
    // (e.g. "SELECT * FROM C.S.T FOO WHERE COL < 10")
    // is irrelevant to the persistent constraint text --
    // when binding the check constraint, we want to find column C.S.T.COL,
    // while the TableDesc/RETDesc just built only exposes the column
    // under names COL and FOO.COL.
    //
    // So, if we have a correlation name, we must:
    // - rename our TableDesc (rename FOO to C.S.T)
    // - create a temporary table name scope for C.S.T that will hide FOO
    // - construct a temporary RETDesc with names COL, T.COL, S.T.COL, C.S.T.COL
    //   but the same ValueId's they had before
    //
    // Then we bind the constraints using that RETDesc for name lookups.
    //
    // Then for the non-empty correlation, reset/undo the temporary stuff.

    RETDesc *savedRETDesc = NULL;
    NABoolean corrNameIsNonEmpty = !corrName.getCorrNameAsString().isNull();
    CorrName synonymReferenceCorrName; 

    if(naTable->getIsSynonymTranslationDone()){
      QualifiedName baseQualifiedName(naTable->getSynonymReferenceName(),3);
      synonymReferenceCorrName=baseQualifiedName; 
    }
   
    if ((corrNameIsNonEmpty) || (naTable->getIsSynonymTranslationDone())) {
      
      CorrName baseCorrName;
      baseCorrName = (naTable->getIsSynonymTranslationDone()) ? synonymReferenceCorrName : naTable->getTableName();

      tdesc->setCorrName(baseCorrName);

      bindWA->getCurrentScope()->xtnmStack()->createXTNM();
      bindWA->getCurrentScope()->getXTNM()->insertNames(bindWA, baseCorrName);
      if (bindWA->errStatus()) return NULL;

      savedRETDesc = bindWA->getCurrentScope()->getRETDesc();
      bindWA->getCurrentScope()->setRETDesc(new (bindWA->wHeap())
      RETDesc(bindWA, tdesc));
      if (bindWA->errStatus()) return NULL;
    }

    for (CollIndex i = 0; i < ccl.entries(); i++) {
      ItemExpr *constraintPred =
        bindCheckConstraint(bindWA, ccl[i], naTable, catmanCollectUsages);
      if (constraintPred)
        tdesc->addCheckConstraint(bindWA, naTable, ccl[i], constraintPred);
      else if (bindWA->errStatus())
        break;
    }

    if ((corrNameIsNonEmpty) || (naTable->getIsSynonymTranslationDone())){  // reset temporaries
      tdesc->setCorrName(corrName);
      delete bindWA->getCurrentScope()->getRETDesc();
      bindWA->getCurrentScope()->setRETDesc(savedRETDesc);
      bindWA->getCurrentScope()->xtnmStack()->removeXTNM();
    }
  } // check constraint processing required

  // if the table contains computed columns, bind the expressions to compute the columns
  for (CollIndex c = 0; c < naTable->getColumnCount(); c++) {
    NAColumn *nac = tdesc->getNATable()->getNAColumnArray()[c];

    if (nac->isComputedColumn()) {
        ItemExpr *computedColumnExpr = NULL;
        Parser parser(bindWA->currentCmpContext());

        // parse the text stored in the NAColumn
        computedColumnExpr = parser.getItemExprTree(
             nac->getComputedColumnExprString(),
             str_len(nac->getComputedColumnExprString()),
             CharInfo::UTF8);

        if (computedColumnExpr) {
          ParNameLocList *saveNameLocList = bindWA->getNameLocListPtr();
          bindWA->setNameLocListPtr(NULL);
          bindWA->getCurrentScope()->context()->inComputedColumnExpr() = TRUE;
          
          computedColumnExpr = computedColumnExpr->bindNode(bindWA);

          bindWA->setNameLocListPtr(saveNameLocList);
          bindWA->getCurrentScope()->context()->inComputedColumnExpr() = FALSE;
         
          if (bindWA->errStatus()) {
            delete computedColumnExpr;
            computedColumnExpr = NULL;
            return NULL;
          }
          else {
            // Store the expression tree in the base column
            ((BaseColumn *) tdesc->getColumnList()[c].getItemExpr())->
              setComputedColumnExpr(computedColumnExpr->getValueId());
          }
        }
    }
  }

  return tdesc;

} // BindWA::createTableDesc()


// QSTUFF - helper for BindWA::bindView.
static void propagateDeleteAndStream(RelExpr *re, GroupAttributes *ga)
{
  if (ga->isEmbeddedUpdateOrDelete())
    re->getGroupAttr()->setEmbeddedIUD(
      ga->getEmbeddedIUD());

  if (ga->isStream())
    re->getGroupAttr()->setStream(TRUE);

  if (ga->isSkipInitialScan())
    re->getGroupAttr()->setSkipInitialScan(TRUE);

  Int32 arity = re->getArity();
  for (Int32 i = 0; i < arity; i++) {
    if (re->child(i))
      propagateDeleteAndStream(re->child(i), ga);
  }
}

RelExpr *BindWA::bindView(const CorrName &viewName,
                          const NATable *naTable,
                          const StmtLevelAccessOptions &accessOptions,
                          ItemExpr *predicate,
                          GroupAttributes *groupAttrs,
                          NABoolean catmanCollectUsages)
{
  BindWA *bindWA = this;   // for coding convenience

  CMPASSERT(viewName.getQualifiedNameObj() == naTable->getTableName());

  NABoolean inViewExpansion = bindWA->setInViewExpansion(TRUE);   // QSTUFF

  // If this is a native hive view, then temporarily change the default schema to
  // that of viewName. This will make sure that all unqualified objects in view
  // text are expanded in this schema. 
  NABoolean defSchWasChanged = FALSE;
  SchemaName savedSch(bindWA->getDefaultSchema());
  if (viewName.isHive())
    {
      SchemaName s(viewName.getQualifiedNameObj().getSchemaName(),
                   viewName.getQualifiedNameObj().getCatalogName());
      bindWA->setDefaultSchema(s);
      defSchWasChanged = TRUE;
    }

  // set a flag for overrride_schema
  //if (overrideSchemaEnabled())
    bindWA->getCurrentScope()->setInViewExpansion(TRUE);

  if (!bindWA->getCurrentScope()->context()->inAnyConstraint())
    bindWA->tableViewUsageList().insert(new (bindWA->wHeap())
      TableViewUsage(
        viewName.getQualifiedNameObj(),
        viewName.getSpecialType(),
        TRUE/*isView*/,
        bindWA->viewCount()));

  // save the current parserflags setting
  ULng32 savedParserFlags = Get_SqlParser_Flags (0xFFFFFFFF);

  // allow funny characters in the tablenames used in the select list.
  // This enables views to be created on 'internal' secret table
  // so they could be accessed.
  // At view creation time, the caller still need to set this
  // parserflag from the sql interface(mxci, etc) otherwise the view
  // creation will fail. Since parserflags can only be set by super
  // users, the view with special tablenames could only have been created
  // by a super user.
  Set_SqlParser_Flags(ALLOW_FUNNY_IDENTIFIER);

  // Parse the view text.
  //
  // isolation level and order by are allowed in create view, if
  // the corresponding cqds are set.
  // These cqds are only valid during 'create view' time. Once the views
  // are created, we don't need to look at them.
  // During view expansion when we reach this method, turn the cqds on if
  // they are not already on, so parser doesn't return an error.
  // Reset them back, if they were set here.
  NABoolean allowIsolationLevelWasSet = FALSE;
  NABoolean allowOrderByWasSet = FALSE;
  if (CmpCommon::getDefault(ALLOW_ISOLATION_LEVEL_IN_CREATE_VIEW) == DF_OFF)
    {
      allowIsolationLevelWasSet = TRUE;

      NAString op("ON");
      ActiveSchemaDB()->getDefaults().validateAndInsert
        ("ALLOW_ISOLATION_LEVEL_IN_CREATE_VIEW", op, FALSE);
    }
  if (CmpCommon::getDefault(ALLOW_ORDER_BY_IN_CREATE_VIEW) == DF_OFF)
    {
      allowOrderByWasSet = TRUE;

      NAString op("ON");
      ActiveSchemaDB()->getDefaults().validateAndInsert
        ("ALLOW_ORDER_BY_IN_CREATE_VIEW", op, FALSE);
    }

  Parser parser(bindWA->currentCmpContext());
  parser.hiveDDLInfo_->disableDDLcheck_ = TRUE;
  ExprNode *viewTree = parser.parseDML(naTable->getViewText(),
                                       naTable->getViewLen(),
                                       naTable->getViewTextCharSet());

  // Restore parser flags settings to what they originally were
  Set_SqlParser_Flags (savedParserFlags);

  if (allowIsolationLevelWasSet)
    {
      NAString op("OFF");
      ActiveSchemaDB()->getDefaults().validateAndInsert
        ("ALLOW_ISOLATION_LEVEL_IN_CREATE_VIEW", op, FALSE);
    }
  if (allowOrderByWasSet)
    {
      NAString op("OFF");
      ActiveSchemaDB()->getDefaults().validateAndInsert
        ("ALLOW_ORDER_BY_IN_CREATE_VIEW", op, FALSE);
    }

  if (NOT viewTree) {
    bindWA->setErrStatus();

    if (defSchWasChanged)
      bindWA->setDefaultSchema(savedSch);

    return NULL;
  }

  // Remove the StmtQuery node.
  // Clear the root flag in the RelRoot node since this not the topmost
  // RelRoot in the query tree.
  //
  CMPASSERT(viewTree->getOperatorType() == STM_QUERY);
  RelExpr *queryTree = viewTree->castToStatementExpr()->getQueryExpression();
  CMPASSERT(queryTree->getOperatorType() == REL_ROOT);
  ((RelRoot *)queryTree)->setRootFlag(FALSE);

  CMPASSERT(queryTree->getChild(0)->getOperatorType() == REL_DDL);
  StmtDDLCreateView *createViewTree = ((DDLExpr *)(queryTree->getChild(0)))->
    getDDLNode()->castToStmtDDLNode()->castToStmtDDLCreateView();
  CMPASSERT(createViewTree);
  queryTree = createViewTree->getQueryExpression();
  CMPASSERT(queryTree->getOperatorType() == REL_ROOT);
  ((RelRoot *)queryTree)->setRootFlag(FALSE);

  RelRoot *viewRoot = (RelRoot *)queryTree;  // save for add'l binding below
  ParNameLocList *saveNameLocList = bindWA->getNameLocListPtr();

  // This was put here for Genesis 10-980217-0467.
  // Now with the fix for 10-980408-5149, we even more strongly need to bypass
  // or ignore any accessOpts from the view, for a consistent access model.

  if ((CmpCommon::getDefault(ALLOW_ISOLATION_LEVEL_IN_CREATE_VIEW) == DF_OFF) ||
      (viewRoot->accessOptions().accessType() == TransMode::ACCESS_TYPE_NOT_SPECIFIED_))
    {
      // if cqd is set and view options were explicitely specified,
      // then do not overwrite it with accessOptions.
      viewRoot->accessOptions() = accessOptions;
    }

  // Set the WCO context (Genesis 10-971112-7028 + 10-990518-8420):
  //   If this view is WITH CHECK OPTION, then all views below it acquire
  //   check-option-ness, per Ansi 11.19 GR 9-11a
  //   (we implement only CASCADED -- see further notes later on in this func);
  //   if some view above this one is WCO, then this view effectively is too,
  //   regardless of its getViewCheck() value.
  // Genesis 10-990518-8420 fix in particular:
  //   with-check-option views of the form
  //     SELECT..FROM(SELECT..WHERE p1)REN WHERE p2
  //   were emitting a bind error on pred p1, and ignoring pred p2!
  //
  NABoolean topmostViewWithCheckOption = FALSE;
  if (naTable->getViewCheck() &&
      bindWA->getCurrentScope()->context()->inUpdateOrInsert() &&
      !bindWA->inViewWithCheckOption()) {
    topmostViewWithCheckOption = TRUE;
    bindWA->inViewWithCheckOption() = naTable;
  }

  // QSTUFF
  // Give the new query tree the pubsub group attrs before
  // binding, so that binder checks are applied to the new tree.
  if ((groupAttrs) &&
      (groupAttrs->isEmbeddedUpdateOrDelete() || groupAttrs->isStream()))
    propagateDeleteAndStream(queryTree,groupAttrs);

  // ************ THE FIRST OF TWO BINDNODE'S ************
  // Bind the basic queryTree first (before Rename), for stoi_ security stuff.
  // Cascade the WCO-ness down to RelExpr::bindSelf which captures predicates.
  // On this bind, unconditionally we never collect usages.
  //
  bindWA->viewCount()++;

  bindWA->setNameLocListPtr(NULL);      // do not collect usages for catman

  queryTree = queryTree->bindNode(bindWA);

  if (bindWA->errStatus())
    {
      if (defSchWasChanged)
        bindWA->setDefaultSchema(savedSch);
      
      return NULL;
    }

  bindWA->setNameLocListPtr(saveNameLocList);

  bindWA->viewCount()--;

  // if RelRoot has an order by, insert a Logical Sort node below it
  // and move the order by expr from view root to this sort node.
  // The view root node is eliminated during transformation/normalization
  // and the sortlogical node provides a place to 'hold' the order by expr.
  // During transformation, this sort key is moved from the sortlogical node
  // to the root node of the query, if there is no explicit order by 
  // specified as part of the query.
  // SortLogical node is a shortlived node and is eliminated during
  // the normalization phase.
  if (viewRoot->hasOrderBy())
    {
      RelExpr * sortNode = new (bindWA->wHeap())
                             SortLogical(queryTree->child(0)->castToRelExpr(),
                                         viewRoot->reqdOrder(),
                                         bindWA->wHeap());
      sortNode = sortNode->bindNode(bindWA);
      if (bindWA->errStatus())
        return NULL;

      viewRoot->removeOrderByTree();
      viewRoot->reqdOrder().clear();

      viewRoot->setChild(0, sortNode);
    }

  // Insert a RenameTable node above the view tree.
  //
  const NAColumnArray &columns = naTable->getNAColumnArray();
  ItemExpr *columnList = new (bindWA->wHeap())
    RenameCol(NULL, new (bindWA->wHeap())
      ColRefName(columns[0]->getColName(), bindWA->wHeap()));
  //
  CollIndex i = 1;
  for (i = 1; i < naTable->getColumnCount(); i++)
    columnList = new (bindWA->wHeap())
      ItemList(columnList, new (bindWA->wHeap())
        RenameCol(NULL, new (bindWA->wHeap())
          ColRefName(columns[i]->getColName(), bindWA->wHeap())));
  //

  queryTree = new (bindWA->wHeap())
    RenameTable(TRUE/*copy tableName as is*/,
                queryTree->castToRelExpr(),
                viewName,
                columnList,
                bindWA->wHeap(),
                TRUE/*isView*/);
  if (predicate) queryTree->addSelPredTree(predicate);
  ((RenameTable *) queryTree)->setViewNATable(naTable);

  // this query used this view
  appendViewName
    (viewName.getQualifiedNameObj().getQualifiedNameAsAnsiString().data());

  // set a flag for overrride_schema
  // with the call to bindNode below, only the Rename node will be bound.
  // Since the view has already been expanded we reset the viewExpansion flag here.
  //if (overrideSchemaEnabled())
    bindWA->getCurrentScope()->setInViewExpansion(inViewExpansion);

  // ************ THE SECOND OF TWO BINDNODE'S ************
  // Bind the view tree whose top is this new RenameTable.
  // If we are the topmost WCO, then do NOT cascade the incoming predicate!
  // Collect usages only if CatMan caller requested it.
  //
  if (topmostViewWithCheckOption) bindWA->inViewWithCheckOption() = NULL;
  if (!catmanCollectUsages) bindWA->setNameLocListPtr(NULL);
  queryTree = queryTree->bindNode(bindWA);
  bindWA->setNameLocListPtr(saveNameLocList);
  if (bindWA->errStatus()) return NULL;

  ((RenameTable *) queryTree)->setViewNATable(NULL);

  // Genesis 10-980126-5495:
  // Now that we have the RenameTable's RETDesc, set its view column headings.
  // We know that the NATable and the RenameTable column lists are in lockstep.
  //
  const ColumnDescList &columnsRET = *queryTree->getRETDesc()->getColumnList();
  CMPASSERT(columns.entries() == naTable->getColumnCount() &&
            columns.entries() == columnsRET.entries());
  for (i = 0; i < naTable->getColumnCount(); i++)
  {
    columnsRET[i]->setHeading(columns[i]->getHeading());
  }


  // If it's a view that is WITH CHECK OPTION, and this is an UPDATE/INSERT,
  // bind/transform/normalize the view predicate and place it as a constraint
  // on the base table's TableDesc.  This is equivalent to the default kind
  // of check clause, WITH CASCADED CHECK OPTION, which is all we need provide
  // up through Intermediate-Level SQL'92.
  //
  // (ANSI says that all CHECK OPTION views must be updatable (11.19 SR12)
  // which means it references exactly one updatable view or, at bottom,
  // exactly one base table (7.9 SR12).
  // MP guarantees that all CHECK OPTION views must be protection views, and
  // all pviews reference exactly one base table.)
  //
  // Notice that since (Genesis 10-990518-8420) we now bind and collect the
  // view preds in bindSelf -- i.e. pushed down below here --
  // only this topmost WCO can set up the constraint(s).
  // Thus we have lost the nice, but not mandated by Ansi, ability to specify
  // which cascaded-down-to view causes which exact pred violation --
  // i.e. error EXE_CHECK_OPTION_VIOLATION_CASCADED (8104)
  // no longer appears, only EXE_CHECK_OPTION_VIOLATION (8105).

  if (topmostViewWithCheckOption) {

    CheckConstraint *constraint = NULL;
    ItemExpr *viewCheckPred = NULL;

    if (bindWA->predsOfViewWithCheckOption().entries()) {
      constraint = new (bindWA->wHeap())
      CheckConstraint(viewName.getQualifiedNameObj(),       // this view name
                      naTable->getTableName(),       // no parsing needed
                      bindWA->wHeap());
      viewCheckPred = bindWA->predsOfViewWithCheckOption().rebuildExprTree();
    }

    // if at least one predicate exists in the view or what underlies it
    if (constraint) {

      RelExpr *underlyingTableOrView = viewRoot->child(0);
      RETDesc *saveRETDesc = bindWA->getCurrentScope()->getRETDesc();
      RETDesc *underlyingRETDesc = underlyingTableOrView->getRETDesc();
      bindWA->getCurrentScope()->setRETDesc(underlyingRETDesc);
      CMPASSERT(underlyingTableOrView);
      CMPASSERT(underlyingTableOrView->getOperatorType() == REL_RENAME_TABLE ||
                underlyingTableOrView->getOperatorType() == REL_SCAN);

      ItemExpr *constraintPred =
                 bindCheckConstraint(bindWA,
                                     constraint,
                                     naTable,
                                     catmanCollectUsages,
                                     viewCheckPred);
      if (constraintPred)
                 queryTree->getScanNode()->getTableDesc()->addCheckConstraint(
                                                             bindWA,
                                                             naTable,    // topmost WCO view
                                                             constraint,    // this view name
                                                             constraintPred);

      bindWA->getCurrentScope()->setRETDesc(saveRETDesc);

    }   // at least one predicate exists

    bindWA->inViewWithCheckOption() = NULL;
    bindWA->predsOfViewWithCheckOption().clear();

  }   // topmost WCO view

  // QSTUFF
  bindWA->setInViewExpansion(inViewExpansion);
  bindWA->getUpdateToScanValueIds().clear();
  // QSTUFF

  if (defSchWasChanged)
    bindWA->setDefaultSchema(savedSch);

  return queryTree;
} // BindWA::bindView()

// -----------------------------------------------------------------------
// member functions for class RelExpr
// -----------------------------------------------------------------------

void RelExpr::bindChildren(BindWA *bindWA)
{
  // Increment the trigger recursion counter.
  if (getInliningInfo().isTriggerRoot())
    getInliningInfo().getTriggerObject()->incRecursionCounter();

  // TSJ's flow their data from left child to right child;
  // some can also share binding scope column info from left to right.
  Int32 arity = getArity();
  for (Int32 i = 0; i < arity; i++) {
    if (child(i)) {

      // If doing a non-first child and the operator is
      // NOT one in which values/names can flow from one scope
      // the sibling scope, then we must clear the current RETDesc
      // (so as to disallow the illegal query in the Binder internals document,
      // section 1.5.3, also in TEST028).
      //
      if (i && !getOperator().match(REL_ANY_TSJ))
        bindWA->getCurrentScope()->setRETDesc(NULL);

      child(i) = child(i)->bindNode(bindWA);
      if (bindWA->errStatus()) return;
    }
  }

  synthPropForBindChecks();   // QSTUFF

  // Decrement the trigger recursion counter.
  if (getInliningInfo().isTriggerRoot())
    getInliningInfo().getTriggerObject()->decRecursionCounter();

} // RelExpr::bindChildren()

void RelExpr::synthPropForBindChecks()   // QSTUFF
{
  // synthesis of delete and stream properties to
  // allow for binder checks. We assume that all
  // operators are rejected when binding the respective node
  // -- except UNIONS -- in which more than one child has
  // has any of those attributes. If both attributes are
  // specified both must be specified for the same
  // result-set/base table.

  for (Int32 j = 0; j < getArity(); j++) {

     if (child(j)) {

        if (child(j)->getGroupAttr()->isStream())
        {
          getGroupAttr()->setStream(TRUE);

          if (child(j)->getGroupAttr()->isSkipInitialScan())
            getGroupAttr()->setSkipInitialScan(TRUE);
        }

        if (child(j)->getGroupAttr()->isEmbeddedUpdateOrDelete() ||
            child(j)->getGroupAttr()->isEmbeddedInsert())
          getGroupAttr()->setEmbeddedIUD(
               child(j)->getGroupAttr()->getEmbeddedIUD());
 
        if (child(j)->getGroupAttr()->reorderNeeded())
            getGroupAttr()->setReorderNeeded(TRUE);
     }
  }
}

RelExpr *RelExpr::bindSelf(BindWA *bindWA)
{
  // create the group attributes
  //
  if (NOT getGroupAttr())
    setGroupAttr(new (bindWA->wHeap()) GroupAttributes);

  //
  // Detach the item expression tree for the predicate, bind it, convert it to
  // a ValueIdSet, and attach it to the RelExpr node.
  //
  ItemExpr *predTree = removeSelPredTree();
  if (predTree) {
    bindWA->getCurrentScope()->context()->inWhereClause() = TRUE;
    predTree->convertToValueIdSet(selectionPred(), bindWA, ITM_AND);
    bindWA->getCurrentScope()->context()->inWhereClause() = FALSE;

    if (bindWA->errStatus()) return this;

    // If this is an embedded insert, then subquery predicates are not
    // allowed.  
    // For example:  To handle this query and issue an error stating
    //               subqueries are not allowed in embedded inserts
    // 
    //  select a from (insert into t901t01 values(22,22,222))t(a,b,c)
    //  where t.a IN (select m from t901t03 where t901t03.m = 77);

    if (getGroupAttr()->isEmbeddedInsert())
    {
       if (!selectionPred().isEmpty() && selectionPred().containsSubquery())
       {
         *CmpCommon::diags() << DgSqlCode(-4337);
         bindWA->setErrStatus();
         return this;
       }
    }  

    // Genesis 10-990518-8420.
    if (bindWA->inViewWithCheckOption())
      bindWA->predsOfViewWithCheckOption() += selectionPred();
  }

  // ++MV
  // Bind the uniqueColumnsTree expression.
  //
  ItemExpr *uniqueColumnsTree = removeUniqueColumnsTree();
  if (uniqueColumnsTree)
  {
    uniqueColumnsTree->
      convertToValueIdSet(getUniqueColumns(), bindWA, ITM_ITEM_LIST);
    if (bindWA->errStatus()) return this;
  }
  // --MV

  // set flag here if an Insert/Update/Delete operation is below this node   
  if( bindWA->isBindingIUD() )
  {
    setSeenIUD();
  }

  //
  // This mechanism is used to set InliningInfo flags on an entire subtree.
  getInliningInfo().setFlags(bindWA->getInliningInfoFlagsToSetRecursivly());

  //
  // Add the values in the Outer References Set as the input values
  // that must be supplied to this RelExpr.
  //
  getGroupAttr()->addCharacteristicInputs(bindWA->getCurrentScope()->getOuterRefs());
  markAsBound();
  return this;
} // RelExpr::bindSelf()

RelExpr *RelExpr::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  bindChildren(bindWA);
  if (bindWA->errStatus())
    return this;
  return bindSelf(bindWA);
}

RETDesc *RelExpr::getRETDesc() const
{
  if (RETDesc_)
    return RETDesc_;
  if ((getArity() == 1) && (child(0)))
    return child(0)->getRETDesc();
  else
    return NULL;
}

// When there is a view atop a view atop a ... atop a single base table,
// this will follow the chain of RenameTable-RelRoot-... down till it finds
// the bottom, the single base table's Scan node.
//
// This method does check to ensure exactly one single base table.
//
Scan *RelExpr::getScanNode(NABoolean assertExactlyOneScanNode) const
{
  RelExpr *result = (RelExpr *)this;   // cast away constness, big whoop

  while (result) {
    if ((result->getOperatorType() == REL_SCAN) ||
	(result->getOperatorType() == REL_HBASE_ACCESS))
      break;
    if (result->getArity() > 1) {
      if (assertExactlyOneScanNode)
      { 
        CMPASSERT(result->getArity() <= 1);
      }
      else return NULL;
    }
    result = result->child(0);
  }

  if (assertExactlyOneScanNode) { CMPASSERT(result); }
  return (Scan *)result;
}


Scan *RelExpr::getLeftmostScanNode() const
{
  RelExpr *result = (RelExpr *)this;   // cast away constness, big whoop

  while (result) {
    if (result->getOperatorType() == REL_SCAN) break;
    result = result->child(0);
  }

  return (Scan *)result;
}



Join * RelExpr::getLeftJoinChild() const
{
  RelExpr *result = (RelExpr *)this;
  
  while(result)
    {
      if (result->getOperatorType() == REL_LEFT_JOIN) 
        break;
      result = result->child(0);
    }
  return (Join *)result;
}

RelSequence* RelExpr::getOlapChild() const
{
  RelExpr *result = (RelExpr *)this;
  
  while(result)
    {
      if (result->getOperatorType() == REL_SEQUENCE) 
        break;
      result = result->child(0);
    }
  return (RelSequence *)result;
}

// QSTUFF
// We use this method for finding the scan node of an updatable view.
// This may either be a base table scan or a RenameTable node inserted
// by a previous index expansion.
RelExpr *RelExpr::getViewScanNode(NABoolean isTopLevelUpdateInView) const
{
  RelExpr *result = (RelExpr *)this;    // cast away constness, big whoop

  while (result) {
    if (result->getOperatorType() == REL_SCAN) break;

    if (result->getOperatorType() == REL_RENAME_TABLE &&
        ((RenameTable *)result)->isView()) break;

    result = result->child(0);
  }

  return result;
}

// -----------------------------------------------------------------------
// getFirstIUDNode
//
// Return the first node that is an insert, update, or delete.
// Only search down left side from the starting point (currentNode)
//
// If an IUD node is not found, return NULL
// -----------------------------------------------------------------------
GenericUpdate * Join::getFirstIUDNode(RelExpr *currentNode)
{
  while(currentNode)
  {
    if( currentNode->getOperator().match(REL_ANY_GEN_UPDATE))
    {      
      break;
    }        
    currentNode = currentNode->child(0);
  }
  return (GenericUpdate*)currentNode;
}

// -----------------------------------------------------------------------
// member functions for class Join
//
// When we implement "JOIN USING (column list)", we need to:		##
// - disallow both NATURAL and USING in the same query (syntax err in Parser?)
// - ensure that the named USING cols are indeed common cols
// - coalesce common cols for USING just as we do for NATURAL,
//   including ensuring that common cols are marked as referenced
//   (as done in joinCommonColumns)
// -----------------------------------------------------------------------

RelExpr *Join::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  // Do not support for general NEO users.
  if ( (getOperatorType() == REL_FULL_JOIN) &&
       (CmpCommon::getDefault(COMP_BOOL_192) == DF_ON) ) {
    
    RelExpr *leftJoin = this;
    leftJoin->setOperatorType(REL_LEFT_JOIN);
    
    Join *antiJoin = static_cast<Join *>(leftJoin->copyTree(bindWA->wHeap()));
    antiJoin->setOperatorType(REL_RIGHT_JOIN);

    NAString leftName("ALJ", bindWA->wHeap());

    // Make it unique.  
    //  
    leftName += bindWA->fabricateUniqueName();

    RelExpr *rename = new (bindWA->wHeap())
      RenameTable(antiJoin, leftName);

    RelExpr *unionAll = new (bindWA->wHeap()) Union(leftJoin, rename);

    unionAll->bindNode(bindWA);
    if (bindWA->errStatus()) return this;

    ItemExpr *nullCheck = antiJoin->addNullInstIndicatorVar(bindWA).getItemExpr();

    CMPASSERT(nullCheck);
    
    ItemExpr *filter = new (bindWA->wHeap())
      UnLogic(ITM_IS_NULL, nullCheck );
    
    filter->bindNode(bindWA);
    if (bindWA->errStatus()) return this;
    
    // Add filter to Join
    //
    antiJoin->selectionPred() += filter->getValueId();

    return unionAll;
  }

  Join *saveInJ = bindWA->getCurrentScope()->context()->inJoin();
  bindWA->getCurrentScope()->context()->inJoin() = this;
  NABoolean savedPrivSetting = FALSE;

  // Bind the child nodes.
  //
  bindChildren(bindWA);
  if (bindWA->errStatus()) return this;

  // MV logging push-down
  if( getInliningInfo().isDrivingMvLogInsert() )
  {
    GenericUpdate *rightSideIUD = getFirstIUDNode(this->child(1));

    if( NULL != rightSideIUD )
    {
      TableDesc *tdesc = rightSideIUD->getTableDesc();

      CMPASSERT(tdesc);

      const NATable *table = tdesc->getNATable();

      // only for MV logs
      if( ExtendedQualName::IUD_LOG_TABLE == table->getSpecialType() )
      {
        updateTableDesc_ = tdesc;
        updateSelectValueIdMap_ = new (bindWA->wHeap())
                             ValueIdMap(rightSideIUD->updateToSelectMap());
      }
    }
  }


  // Controlled availability of Full Outer Join support 
  // The COMP_BOOL_199 must be removed when full outer join
  // becomes general availability.
  
  // Full outer joins are not currently supported.
  // But can enabled by setting COMP_BOOL_199 to ON.

  if ((getOperatorType() == REL_FULL_JOIN &&
       (CmpCommon::getDefault(COMP_BOOL_199) == DF_OFF))
      ||  //OR
      (getOperatorType() == REL_UNION_JOIN )){
    // 3022 Feature not yet supported
    *CmpCommon::diags() << DgSqlCode(-3022)
                        << DgString0(
                                    (getOperatorType() == REL_FULL_JOIN) ?
                                    "FULL OUTER JOIN" : "UNION JOIN");
    bindWA->setErrStatus();
    return this;
  }
  
  //
  // Bind the ON clause of the join.
  //
  RelExpr *leftRelExpr  = child(0).getPtr();
  RelExpr *rightRelExpr = child(1).getPtr();
  RETDesc *leftTable    = child(0)->getRETDesc();
  RETDesc *rightTable   = child(1)->getRETDesc();

  ItemExpr *joinPredx;
  if (isNaturalJoin()) {
    // since the common column references need fetch histograms, the where
    // flag is set here so that when we call markAsReferencedColumn()
    // in the joinCommoncolumns() method it would set the common
    // columns as refenced by looking a the inWhereCaluse_ flag.
    NABoolean orig = bindWA->getCurrentScope()->context()->inWhereClause();
    bindWA->getCurrentScope()->context()->inWhereClause() = TRUE;
    joinPredx = joinCommonColumns(leftRelExpr, rightRelExpr, bindWA);
    bindWA->getCurrentScope()->context()->inWhereClause() = orig;
  }
  else
    joinPredx = removeJoinPredTree();

  if (joinPredx) {
    ItemExpr *saveInJP = bindWA->getCurrentScope()->context()->inJoinPred();
    bindWA->getCurrentScope()->context()->inJoinPred() = joinPredx;
    RETDesc preJoinResult;
    preJoinResult.addColumns(bindWA, *leftTable);
    preJoinResult.addColumns(bindWA, *rightTable);
    bindWA->getCurrentScope()->setRETDesc(&preJoinResult);
    joinPredx->convertToValueIdSet(joinPred(), bindWA, ITM_AND);
    bindWA->getCurrentScope()->context()->inJoinPred() = saveInJP;
    if (bindWA->errStatus()) return this;
  }
  //
  // Create the output list.
  // The TRUE's in the nullInstantiate() force a Cast expression to be set up,
  // as required by the Normalizer.
  //
  NABoolean newTables = TRUE;
  ValueIdList &nullOutputList = nullInstantiatedOutput();
  ValueIdList &nullOutputForRightJoinList = nullInstantiatedForRightJoinOutput();

  switch(getOperatorType()) {
  case REL_LEFT_JOIN:
    leftTable  = new (bindWA->wHeap()) RETDesc(bindWA, *leftTable);
    rightTable = rightTable->nullInstantiate(bindWA, TRUE, nullOutputList);
    break;
  case REL_RIGHT_JOIN:
    leftTable  = leftTable->nullInstantiate(bindWA,  TRUE, nullOutputList);
    rightTable = new (bindWA->wHeap()) RETDesc(bindWA, *rightTable);
    break;
  case REL_FULL_JOIN:
  case REL_UNION_JOIN:
    {
    leftTable  = leftTable->nullInstantiate(bindWA,  TRUE, nullOutputForRightJoinList);
    
    rightTable = rightTable->nullInstantiate(bindWA, TRUE, nullOutputList);

    
    // comp_bool_198 = 'on' enables FullOuter transformation
    // inner, left or right
    if (CmpCommon::getDefault(COMP_BOOL_198) == DF_OFF) //don't enable FOJ transformation
      {
      ItemExpr * instNull = NULL;
      CollIndex index = 0; 
      
      // disable the FOJ Transformation.
      for (index = 0; index < nullInstantiatedOutput().entries(); index++)
        {
          instNull = nullInstantiatedOutput()[index].getItemExpr();
          CMPASSERT(instNull->getOperatorType() == ITM_INSTANTIATE_NULL);
          ((InstantiateNull *)instNull)->NoCheckforLeftToInnerJoin = TRUE;
        } // endfor
      
      instNull = NULL;
      
      for (index = 0; 
        index < nullInstantiatedForRightJoinOutput().entries(); index++)
        {
          instNull = nullInstantiatedForRightJoinOutput()[index].getItemExpr();
          CMPASSERT(instNull->getOperatorType() == ITM_INSTANTIATE_NULL);
          ((InstantiateNull *)instNull)->NoCheckforLeftToInnerJoin = TRUE;
        } // endfor
      } // env "ENABLE_FOJ_TRANSFORMATION"
    break;
    }
  case REL_JOIN:
  default:
    newTables = FALSE;
    break;
  }
  RETDesc *resultTable = new (bindWA->wHeap()) RETDesc(bindWA);

  Int32 rowSet = (child(0)->getOperatorType() == REL_RENAME_TABLE) &&
               (child(0)->child(0)->getOperatorType() == REL_UNPACKROWS) &&
               (child(1)->getOperatorType() == REL_ROOT);

  if (NOT isNaturalJoin()) {
    if ((!rowSet) &&
        (getOperatorType() != REL_TSJ_FLOW)) {
      resultTable->addColumns(bindWA, *leftTable);
    }
    // ++MV  -- bug fixing for semi-joins
    if (!isSemiJoin())
    {
      resultTable->addColumns(bindWA, *rightTable);
    }
    // --MV  -- bug fixing for semi-joins
  } else {
    coalesceCommonColumns(bindWA,
                          getOperatorType(),
                          *leftTable,
                          *rightTable,
                          *resultTable);
    if (bindWA->errStatus()) return this;
  }
  setRETDesc(resultTable);
  bindWA->getCurrentScope()->setRETDesc(resultTable);

  // QSTUFF
  NAString fmtdList(bindWA->wHeap());
  LIST(TableNameMap*) xtnmList(bindWA->wHeap());

  bindWA->getTablesInScope(xtnmList, &fmtdList);

  if ((child(0)->getGroupAttr()->isStream()) &&
      (child(1)->getGroupAttr()->isStream())){
    bindWA->getTablesInScope(xtnmList, &fmtdList);
    *CmpCommon::diags() << DgSqlCode(-4158)
      << DgString0(fmtdList);
    bindWA->setErrStatus();
    return this;
  }

  // Disallowing joins for EMBEDDED...INSERT
  // 
  if (getGroupAttr()->isEmbeddedInsert() && 
      !isTSJForWrite()   // the tsjForWrite flag is set for
                         // those joins which are created by
                         // the Binder during inlining (eg. IndexMaintanence)
                         // Here we only want to disable user specified joins
                         // and not joins introduced as part of inlining.
      ){
      *CmpCommon::diags() << DgSqlCode(-4336)
        << DgString0(fmtdList)
        << DgString1(getGroupAttr()->getOperationWithinGroup());
      bindWA->setErrStatus();
      return this;
    }


  if ( ((child(0)->getGroupAttr()->isEmbeddedUpdateOrDelete()) &&
        (child(1)->getGroupAttr()->isEmbeddedUpdateOrDelete())) ||
       ((child(0)->getGroupAttr()->isEmbeddedInsert()) &&
        (child(1)->getGroupAttr()->isEmbeddedInsert())) ||
       (bindWA->isEmbeddedIUDStatement()) ) {
    NAString type0,type1;
    if (child(0)->getGroupAttr()->isEmbeddedUpdate())
      type0 = "UPDATE";
    else
    {
      if (child(0)->getGroupAttr()->isEmbeddedInsert())
        type0 = "INSERT";
      else
        type0 = "DELETE";
    }
    if (child(1)->getGroupAttr()->isEmbeddedUpdate())
      type1 = "UPDATE";
    else
    {
      if (child(1)->getGroupAttr()->isEmbeddedInsert())
        type1 = "INSERT";
      else
        type1 = "DELETE";
    }
    *CmpCommon::diags() << DgSqlCode(-4175)
      << DgString0(fmtdList)
      << DgString1(type0)
      << DgString2(type1);
    bindWA->setErrStatus();
    return this;
  }

  if ((child(0)->getGroupAttr()->isEmbeddedUpdateOrDelete() ||
       child(0)->getGroupAttr()->isStream()) &&
      (child(1)->getGroupAttr()->isEmbeddedUpdateOrDelete() ||
       child(1)->getGroupAttr()->isStream())){
    *CmpCommon::diags() << DgSqlCode(-4176)
      << DgString0(fmtdList)
      << (getGroupAttr()->isEmbeddedUpdate() ?
          DgString1("UPDATE"):DgString1("DELETE"));
    bindWA->setErrStatus();
    return this;
  }

  if (getOperatorType() == REL_LEFT_JOIN){
    if (child(1)->getGroupAttr()->isEmbeddedUpdateOrDelete()){
      *CmpCommon::diags() << DgSqlCode(-4156)
        << DgString0(fmtdList)
        << (child(1)->getGroupAttr()->isEmbeddedUpdate() ?
            DgString1("UPDATE"):DgString1("DELETE"));
      bindWA->setErrStatus();
      return this;
    }
    if (child(1)->getGroupAttr()->isStream()){
      *CmpCommon::diags() << DgSqlCode(-4157)
        << DgString0(fmtdList);
      bindWA->setErrStatus();
      return this;
    }
  }

  if (getOperatorType() == REL_RIGHT_JOIN){
    if (child(0)->getGroupAttr()->isEmbeddedUpdateOrDelete()){
      *CmpCommon::diags() << DgSqlCode(-4164)
        << DgString0(fmtdList)
        << (child(0)->getGroupAttr()->isEmbeddedUpdate() ?
            DgString1("UPDATE"):DgString1("DELETE"));
      bindWA->setErrStatus();
      return this;
    }
    if (child(0)->getGroupAttr()->isStream()){
      *CmpCommon::diags() << DgSqlCode(-4165)
        << DgString0(fmtdList);
      bindWA->setErrStatus();
      return this;
    }
  }

  // we need to move stream and nested updates to the
  // left to ensure correct execution. This causes the statement
  // to be rejected if the user specified join_order_by_user and
  // the query must be reordered

  if (child(1)->getGroupAttr()->isStream() ||
    child(1)->getGroupAttr()->isEmbeddedUpdateOrDelete()){
    getGroupAttr()->setReorderNeeded(TRUE);
  }
  // QSTUFF

  if (newTables) {
    delete leftTable;
    delete rightTable;
  }

  bindWA->getCurrentScope()->context()->inJoin() = saveInJ;

  if (getOperatorType() == REL_TSJ){
    //Using rowsets in a predicate with embedded update/delete results
    //in a NestedJoin subtree after Normalization.This NestedJoin subtree
    //has embedded update/delete as the right child, which is not allowed
    //during optimization. Here we try to disallow this usage at Binding
    //when a REL_TSJ subtree has rowsets as the left child and embedded
    //update/delete as the right child. An error message[4123] is signaled.
    if (rowSet && getGroupAttr()->isEmbeddedUpdateOrDelete()){
      *CmpCommon::diags() << DgSqlCode(-4213);
      bindWA->setErrStatus();
      return this;
    }
  }

  // transfer rowsetRowCountArraySize from HostArrayWA to this node.
  if (bindWA->getHostArraysArea() && isRowsetIterator())
    setRowsetRowCountArraySize(bindWA->getHostArraysArea()->getRowsetRowCountArraySize());

  // Bind the base class.
  //
  return bindSelf(bindWA);
} // Join::bindNode()

ValueId Join::addNullInstIndicatorVar(BindWA *bindWA,
                                      ItemExpr *indicatorVal)
{
  // Add an indicator variable that can tell us whether
  // a left join found a match in the right child table
  // or not. The returned ValueId will have the value 1
  // if a match was found, and NULL if no match was found.

  ItemExpr *cval = indicatorVal;

  if (!cval)
    cval = new (bindWA->wHeap()) SystemLiteral(1);
  cval = cval->bindNode(bindWA);
  if (bindWA->errStatus())
    return NULL_VALUE_ID;

  // Null instantiate the value.
  ValueId niCval = cval->getValueId().nullInstantiate(bindWA, TRUE);

  // Add it to the RETDesc of the Join.
  ColRefName cvalName("", bindWA->wHeap());
  getRETDesc()->addColumn(bindWA, cvalName , niCval, USER_COLUMN);

  // Add it to the list of null instantiated outputs.
  nullInstantiatedOutput().insert(niCval);

  return niCval;
}

//++MV
// This function builds the BalueIdMap that is used for translating the required
// sort key to the right child sort key and backwards
void Join::BuildRightChildMapForLeftJoin()
{
  ValueIdMap &map = rightChildMapForLeftJoin();

  for (CollIndex j = 0; j < nullInstantiatedOutput().entries(); j++)
  {
    ValueId instNullId, rightChildId;

    instNullId = nullInstantiatedOutput_[j];

    assert(instNullId.getItemExpr()->getOperatorType() == ITM_INSTANTIATE_NULL);

    // Access the operand of the InstantiateNull
    rightChildId = (((InstantiateNull *)(instNullId.getItemExpr()))->getExpr()->getValueId());

    map.addMapEntry(instNullId, rightChildId);
  }
}
//--MV

//++MV
// This function builds the ValueIdMap that is used for translating the 
// required
// sort key to the left  child sort key and backwards
void Join::BuildLeftChildMapForRightJoin()
{
  ValueIdMap &map = leftChildMapForRightJoin();

  for (CollIndex j = 0; j < nullInstantiatedForRightJoinOutput().entries(); j++)
  {
    ValueId instNullId, leftChildId;

    instNullId = nullInstantiatedForRightJoinOutput_[j];

    assert(instNullId.getItemExpr()->getOperatorType() == ITM_INSTANTIATE_NULL);

    // Access the operand of the InstantiateNull
    leftChildId = (((InstantiateNull *)(instNullId.getItemExpr()))->getExpr()->getValueId());

    map.addMapEntry(instNullId, leftChildId);
  }
}
//--MV

// -----------------------------------------------------------------------
// member functions for class Intersect
// -----------------------------------------------------------------------

RelExpr *Intersect::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  // Bind the child nodes.
  //
  bindChildren(bindWA);
  if (bindWA->errStatus()) return this;

  // Check that there are an equal number of select items on both sides.
  //
  const RETDesc &leftTable = *child(0)->getRETDesc();
  const RETDesc &rightTable = *child(1)->getRETDesc();
  if (leftTable.getDegree() != rightTable.getDegree()) {
    // 4014 The operands of an intersect must be of equal degree.
    *CmpCommon::diags() << DgSqlCode(-4014);
    bindWA->setErrStatus();
    return this;
  }

  // Join the columns of both sides. 
  //
  if(CmpCommon::getDefault(MODE_SPECIAL_4) != DF_ON)
  {
    *CmpCommon::diags() << DgSqlCode(-3022)    // ## INTERSECT not yet supported , not fully tested
        << DgString0("INTERSECT");             // ##
    bindWA->setErrStatus();                    // ##
    if (bindWA->errStatus()) return NULL;      // ##
  }
  //
  ItemExpr *predicate = intersectColumns(leftTable, rightTable, bindWA);
  RelExpr *join = new (bindWA->wHeap())
    Join(child(0)->castToRelExpr(),
         child(1)->castToRelExpr(),
         REL_JOIN,
         predicate);

  // Bind the join.
  //
  join = join->bindNode(bindWA)->castToRelExpr();
  if (bindWA->errStatus()) return join;

  // Change the output of the join to just the left side.
  //
  delete join->getRETDesc();
  join->setRETDesc(new (bindWA->wHeap()) RETDesc(bindWA, leftTable));
  bindWA->getCurrentScope()->setRETDesc(join->getRETDesc());

  // QSTUFF
  NAString fmtdList1(bindWA->wHeap());
  LIST(TableNameMap*) xtnmList1(bindWA->wHeap());
  NAString fmtdList2(bindWA->wHeap());
  LIST(TableNameMap*) xtnmList2(bindWA->wHeap());

  leftTable.getTableList(xtnmList1, &fmtdList1);
  rightTable.getTableList(xtnmList2, &fmtdList2);

  if (child(0)->getGroupAttr()->isStream() &&
      child(1)->getGroupAttr()->isStream()){
    *CmpCommon::diags() << DgSqlCode(-4159)
                << DgString0(fmtdList1) << DgString1(fmtdList2);
    bindWA->setErrStatus();
    return this;
  }

  // Needs to be removed when supporting get_next for INTERSECT
  if (getGroupAttr()->isEmbeddedUpdateOrDelete()) {
    *CmpCommon::diags() << DgSqlCode(-4160)
                << DgString0(fmtdList1)
                << DgString1(fmtdList2)
                << (child(0)->getGroupAttr()->isEmbeddedUpdate() ?
                             DgString2("UPDATE"):DgString2("DELETE"))
                << (child(1)->getGroupAttr()->isEmbeddedUpdate() ?
                             DgString3("UPDATE"):DgString3("DELETE"));
    bindWA->setErrStatus();
    return this;
  }
  // QSTUFF

  return join;
} // Intersect::bindNode()

// -----------------------------------------------------------------------
// member functions for class Except 
// -----------------------------------------------------------------------

RelExpr *Except::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  // Bind the child nodes.
  //
  bindChildren(bindWA);
  if (bindWA->errStatus()) return this;

  // Check that there are an equal number of select items on both sides.
  //
  const RETDesc &leftTable = *child(0)->getRETDesc();
  const RETDesc &rightTable = *child(1)->getRETDesc();
  if (leftTable.getDegree() != rightTable.getDegree()) {
    // 4014 The operands of an intersect must be of equal degree.
    *CmpCommon::diags() << DgSqlCode(-4014);
    bindWA->setErrStatus();
    return this;
  }

  // Join the columns of both sides. 
  //
  if(CmpCommon::getDefault(MODE_SPECIAL_4) != DF_ON)
  {
    *CmpCommon::diags() << DgSqlCode(-3022)    // ## EXCEPT not yet supported: not fully tested
        << DgString0("EXCEPT");             // ##
    bindWA->setErrStatus();                    // ##
    if (bindWA->errStatus()) return NULL;      // ##
  }
  //
  ItemExpr *predicate = intersectColumns(leftTable, rightTable, bindWA);
  RelExpr *join = new (bindWA->wHeap())
    Join(child(0)->castToRelExpr(),
         child(1)->castToRelExpr(),
         REL_ANTI_SEMIJOIN,
         predicate);

  // Bind the join.
  //
  join = join->bindNode(bindWA)->castToRelExpr();
  if (bindWA->errStatus()) return join;

  // Change the output of the join to just the left side.
  //
  delete join->getRETDesc();
  join->setRETDesc(new (bindWA->wHeap()) RETDesc(bindWA, leftTable));
  bindWA->getCurrentScope()->setRETDesc(join->getRETDesc());

  // QSTUFF
  NAString fmtdList1(bindWA->wHeap());
  LIST(TableNameMap*) xtnmList1(bindWA->wHeap());
  NAString fmtdList2(bindWA->wHeap());
  LIST(TableNameMap*) xtnmList2(bindWA->wHeap());

  leftTable.getTableList(xtnmList1, &fmtdList1);
  rightTable.getTableList(xtnmList2, &fmtdList2);

  if (child(0)->getGroupAttr()->isStream() &&
      child(1)->getGroupAttr()->isStream()){
    *CmpCommon::diags() << DgSqlCode(-4159)
                << DgString0(fmtdList1) << DgString1(fmtdList2);
    bindWA->setErrStatus();
    return this;
  }

  // Needs to be removed when supporting get_next for EXCEPT
  if (getGroupAttr()->isEmbeddedUpdateOrDelete()) {
    *CmpCommon::diags() << DgSqlCode(-4160)
                << DgString0(fmtdList1)
                << DgString1(fmtdList2)
                << (child(0)->getGroupAttr()->isEmbeddedUpdate() ?
                             DgString2("UPDATE"):DgString2("DELETE"))
                << (child(1)->getGroupAttr()->isEmbeddedUpdate() ?
                             DgString3("UPDATE"):DgString3("DELETE"));
    bindWA->setErrStatus();
    return this;
  }
  // QSTUFF

  return join;
} // Excpet::bindNode()

// -----------------------------------------------------------------------
// member functions for class Union
// -----------------------------------------------------------------------

RelExpr *Union::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  //
  // Bind the conditional expression.
  //
  ItemExpr *condExprTree = removeCondExprTree();
  if (condExprTree)
  {
    condExprTree->convertToValueIdList(condExpr(), bindWA, ITM_ITEM_LIST);
    if (bindWA->errStatus()) {
      return NULL;
    }
  }

  //
  // Bind the triggered action exception expression.
  //
  ItemExpr *trigExprTree = removeTrigExceptExprTree();
  if (trigExprTree)
  {
    // the assumption in the binder (in Union::addValueIdUnion) is that 
    // unionMap_ count is always less than or equal to one but triggers 
    // code might increment this number during binding because of 
    // recursive triggers or triggers that are used more than once 
    // in the statement. This check fixes the unionMap_ for triggers. 
    if ((unionMap_ != NULL) && (unionMap_->count_ > 1))
    {
       unionMap_->count_--;
       unionMap_ = new (CmpCommon::statementHeap()) UnionMap;
    }

    trigExprTree->convertToValueIdList(trigExceptExpr(), bindWA, ITM_ITEM_LIST);
    if (bindWA->errStatus()) {
      return NULL;
    }
  }

  AssignmentStArea *assignArea = NULL;
  // We store a pointer to this Union node in the assignment statements area.
  // This is needed for compound statements project, in particular when we have
  // assignment statements within an IF statement
  if (getUnionForIF()) {
    assignArea = bindWA->getAssignmentStArea();
    setPreviousIF(assignArea->getCurrentIF());
    assignArea->setCurrentIF(this);
  }

  //
  // Bind the child nodes.
  //
  bindWA->getCurrentScope()->context()->inUnion() = TRUE;

  currentChild() = 0;
  child(0) = child(0)->bindNode(bindWA);

  if (bindWA->errStatus()) return this;

  // If we have assignment statements of compound statements, we need to get rid
  // of the value ids generated while binding the first child. Also, we create a
  // list of the value ids of the variables that are on the left side of a SET
  // statement
  if (getUnionForIF() && leftList() && assignArea) {
    assignArea->removeLastValueIds(leftList(), this);
  }

  if (getCondUnary()) {
    CollIndex leftDegree = child(0)->getRETDesc()->getDegree();

    ItemExpr *tupleExpr = new (bindWA->wHeap()) ConstValue();

    for (CollIndex i=0; i+1<leftDegree; i++) {
      ItemExpr *con = new (bindWA->wHeap()) ConstValue();

      ItemList *list = new (bindWA->wHeap()) ItemList(con, tupleExpr);

      tupleExpr = list;
    }

    RelExpr *tuple = new (bindWA->wHeap()) Tuple(tupleExpr);

    // create the selection predicate (1=0) for the Tuple node
    ItemExpr *predicate = new (bindWA->wHeap())
                            BiRelat(ITM_EQUAL,
                                  new (bindWA->wHeap()) ConstValue(1),
                                  new (bindWA->wHeap()) ConstValue(0));
    tuple->addSelPredTree(predicate);

    RelExpr *tupleRoot = new (bindWA->wHeap()) RelRoot(tuple);

    setChild (1, tupleRoot);
  }

  if (child(1)) {
    if (!(child(1)->getOperator().match(REL_ANY_TSJ))) {
      bindWA->getCurrentScope()->setRETDesc(NULL);
    }

    currentChild() = 1;
    child(1) = child(1)->bindNode(bindWA);
    if (bindWA->errStatus()) return this;

    // If we have assignment statements of compound statements,
    // we need to get rid of the value ids generated while binding
    // the second child
    if (getUnionForIF() && rightList() && assignArea) {
      assignArea->removeLastValueIds(rightList(), this);
    }
  }

  // check for & warn against UNIONs that have inconsistent access/lock modes.
  // flag "select * from t1 union select * from t2 for <access> mode"
  // with a warning that t1 and t2 may have inconsistent access/lock modes.
  checkAccessLockModes();

  //Copies the leftlist and rightlist this conditional union to the appropriate list of the
  //conditional union node pointed to by the previousIF argument.
  Union * previousIF = getPreviousIF();
  if (previousIF && getUnionForIF()) {
     copyLeftRightListsToPreviousIF(previousIF, bindWA);
  }

  synthPropForBindChecks();
                                              // QSTUFF

  bindWA->getCurrentScope()->context()->inUnion() = FALSE;

  //
  // Check that there are an equal number of select items on both sides.
  //
  const RETDesc &leftTable = *child(0)->getRETDesc();
  const RETDesc &rightTable = *child(1)->getRETDesc();
  RETDesc *resultTable = NULL;

  RelRoot * root = bindWA->getTopRoot() ;
  if (root) {
     if (getGroupAttr()->isStream() && root->hasOrderBy()){
       NAString fmtdList1(bindWA->wHeap());
       LIST(TableNameMap*) xtnmList1(bindWA->wHeap());
       NAString fmtdList2(bindWA->wHeap());
       LIST(TableNameMap*) xtnmList2(bindWA->wHeap());
       leftTable.getTableList(xtnmList1, &fmtdList1);
       rightTable.getTableList(xtnmList2, &fmtdList2);
       *CmpCommon::diags() << DgSqlCode(-4166)
                           << DgString0(fmtdList1)
                           << DgString1(fmtdList2) ;
       bindWA->setErrStatus();
       return this;
     }
  }

  if (leftTable.getDegree() != rightTable.getDegree()) {

#ifndef NDEBUG
    dumpChildrensRETDescs(leftTable, rightTable);
#endif

    if ( (!getUnionForIF()) &&
         (!getCondUnary()) //for triggers
       ) {
      // 4126 The row-value-ctors of a VALUES must be of equal degree.
      // 4066 The operands of a union must be of equal degree.
      // This is not necessary if we are in an assignment stmt.
      Lng32 sqlcode = bindWA->getCurrentScope()->context()->inTupleList() ?
                                                            -4126 : -4066;
      *CmpCommon::diags() << DgSqlCode(sqlcode);
      bindWA->setErrStatus();
      return this;
    }
  }

  //
  // For each select item on both sides, create a ValueIdUnion and insert its
  // ValueId into the select list for the union.
  //

  // We check to see if there were assignments on either side
  if  ( !getUnionForIF() ) {
    resultTable = new (bindWA->wHeap()) RETDesc(bindWA);
    for (CollIndex i = 0; i < leftTable.getDegree(); i++) {
      ValueIdUnion *vidUnion = new (bindWA->wHeap())
      ValueIdUnion(leftTable.getValueId(i),
                   rightTable.getValueId(i),
                   NULL_VALUE_ID,
                   getUnionFlags());
      vidUnion->setIsTrueUnion(TRUE);
      vidUnion->bindNode(bindWA);
      if (bindWA->errStatus()) {
        delete vidUnion;
        delete resultTable;
        return this;
      }
      ValueId valId = vidUnion->getValueId();
      addValueIdUnion(valId, bindWA->wHeap());
      resultTable->addColumn(bindWA, leftTable.getColRefNameObj(i), valId);
    }
  }
  else {
    // Case in which we have asignment statements below this node.
    // We have to carefuly match the valueids in the IF and ELSE part.
    // For instance, if SET :a = ... occurs in both branches or only in one.
    if (getUnionForIF() && assignArea) {
      resultTable = createReturnTable(assignArea, bindWA);
    }
  }


  setRETDesc(resultTable);
  bindWA->getCurrentScope()->setRETDesc(resultTable);
  //
  // Bind the base class.
  //

  // We are done binding this node. The current IF node is now the closest
  // IF node that is also an ancestor of this node
  if (getUnionForIF() && assignArea) {
    assignArea->setCurrentIF(getPreviousIF());
  }

  // QSTUFF
  // this is not a hard restriction. Once the get_next protocol supports unions
  // similar to the split-top operator, this check can be removed.
  if (getGroupAttr()->isEmbeddedUpdateOrDelete() ||
      (getGroupAttr()->isEmbeddedInsert() && !isSystemGenerated_) ||
      (bindWA->isEmbeddedIUDStatement())) {
    if (getUnionForIF()) {
      *CmpCommon::diags() << DgSqlCode(-4210);
      bindWA->setErrStatus();
      return this;
    }

  NAString fmtdList1(bindWA->wHeap());
    LIST(TableNameMap*) xtnmList1(bindWA->wHeap());
  NAString fmtdList2(bindWA->wHeap());
    LIST(TableNameMap*) xtnmList2(bindWA->wHeap());

    leftTable.getTableList(xtnmList1, &fmtdList1);
    rightTable.getTableList(xtnmList2, &fmtdList2);

    // Fix for Solution 10-070117-1834. 
    // Error Message for -4161 - assumes that both sides
    // of the UNION is an embedded operation. For a
    // query such as, 
    // select * from (delete from t709t1)as x union all (select * from t709t1)
    // the right side of the UNION is not an embedded operation.
    // Hence, changing the text for 4161 to a more generic one so
    // that all cases are covered in this one text message.


    *CmpCommon::diags() << DgSqlCode(-4161)
      << DgString0(fmtdList1)
      << DgString1(fmtdList2);

    bindWA->setErrStatus();
    return this;
  }
  // QSTUFF


  // ++MV
  // Bind the alternateRightChildOrderExprTree expression.
  //
  ItemExpr *alternateRightChildOrderExprTree = removeAlternateRightChildOrderExprTree();
  if (alternateRightChildOrderExprTree)
  {
    alternateRightChildOrderExprTree->
      convertToValueIdList(alternateRightChildOrderExpr(), bindWA, ITM_ITEM_LIST);
    if (bindWA->errStatus()) {
      return NULL;
    }
  }
  // --MV

  // Bind the base class.
  //
  RelExpr *boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus()) {
    delete resultTable;
    return boundExpr;
  }
  return boundExpr;
} // Union::bindNode()

// check for & warn against UNIONs that have inconsistent access/lock modes
void Union::checkAccessLockModes()
{
  Scan *left = child(0)->getAnyScanNode();
  Scan *right = child(1)->getAnyScanNode(); 
  
  if (!left || !right) return; // no-op.

  // UNION is user-specified as opposed to system-generated (eg, by
  // triggers/RI in GenericUpdate::inlinePipelineActions, etc)
  if (isSystemGenerated_) {
    return;
  }
  
  Lng32 lockFlagSession = CmpCommon::transMode()->getDP2LockFlags().getValue();
  StmtLevelAccessOptions optionsLeft = left->accessOptions();
  StmtLevelAccessOptions optionsRight = right->accessOptions();

  Lng32 lockFlagLeft = lockFlagSession;
  Lng32 lockFlagRight = lockFlagSession;

  if (optionsLeft.userSpecified()) {
    lockFlagLeft = optionsLeft.getDP2LockFlags().getValue();
  }
  if (optionsRight.userSpecified()) {
    lockFlagRight = optionsRight.getDP2LockFlags().getValue();
  }
  if (lockFlagLeft != lockFlagRight) {
    *CmpCommon::diags()
      << DgSqlCode(3192)
      << DgString0(left->getTableName().getQualifiedNameAsString())
      << DgString1(right->getTableName().getQualifiedNameAsString());
  }
} // Union::checkAccessLockModes()

void Union::copyLeftRightListsToPreviousIF(Union * previousIF, BindWA * bindWA)
{
  AssignmentStHostVars *thisLeftList =  leftList();
  AssignmentStHostVars *thisRightList = rightList();

  // If the previous IF node does not have a left list, we copy the left and right
  // lists to that left list
  if (previousIF->currentChild() == 0 && !(previousIF->leftList())) {
      AssignmentStHostVars *leftListOfPreviousIF = previousIF->getCurrentList(bindWA);
      // Copy the leftList of this node to the left list of the previous IF
      leftListOfPreviousIF->addAllToListInIF(thisLeftList) ;
      // Copy the rightList of this node to the left list of the previous IF
      leftListOfPreviousIF->addAllToListInIF(thisRightList) ;
  }

  // If the previous IF node does not have a right list, we copy the left and right
  // lists to that left list
  if (previousIF->currentChild() == 1 && !(previousIF->rightList())) {
      AssignmentStHostVars *rightListOfPreviousIF = previousIF->getCurrentList(bindWA);
      // Copy the leftList of this node to the right list of the previous IF
      rightListOfPreviousIF->addAllToListInIF(thisLeftList) ;
      // Copy the rightList of this node to the right list of the previous IF
      rightListOfPreviousIF->addAllToListInIF(thisRightList) ;
  }
} // Union::copyLeftRightListsToPreviousIF

// -----------------------------------------------------------------------
// MV --
// A debugging method for dumping the columns in the RETDesc of both
// children when they do not match.
void Union::dumpChildrensRETDescs(const RETDesc& leftTable,
                                  const RETDesc& rightTable)
{
// turn this code on when you need it by changing the #if below
#if 0   
  // -- MVs. Debugging code !!!!! TBD
  fprintf(stdout, " #    Left                                Right\n");
  CollIndex maxIndex, minIndex;
  NABoolean leftIsBigger;
  if (leftTable.getDegree() > rightTable.getDegree())
  {
    maxIndex = leftTable.getDegree();
    minIndex = rightTable.getDegree();
    leftIsBigger = TRUE;
  }
  else
  {
    maxIndex = rightTable.getDegree();
    minIndex = leftTable.getDegree();
    leftIsBigger = FALSE;
  }

  for (CollIndex i=0; i<minIndex; i++)
  {
    ColumnDesc *leftColDesc  = leftTable.getColumnList()->at(i);
    ColumnDesc *rightColDesc = rightTable.getColumnList()->at(i);
    NAString leftCol (leftColDesc->getColRefNameObj().getColRefAsString());
    NAString rightCol(rightColDesc->getColRefNameObj().getColRefAsString());
    fprintf(stdout, " %3d  %-55s %-55s \n",
            i, leftCol.data(), rightCol.data());
  }

  if (leftIsBigger)
  {
    for (CollIndex j=minIndex; j<maxIndex; j++)
    {
      ColumnDesc *leftColDesc  = leftTable.getColumnList()->at(j);
      NAString leftCol(leftColDesc->getColRefNameObj().getColRefAsString());
      fprintf(stdout, " %3d  %-35s\n",
              j, leftCol.data());
    }
  }
  else
  {
    for (CollIndex k=minIndex; k<maxIndex; k++)
    {
      ColumnDesc *rightColDesc = rightTable.getColumnList()->at(k);
      NAString rightCol(rightColDesc->getColRefNameObj().getColRefAsString());
      fprintf(stdout, " %3d                                      %-35s \n",
              k, rightCol.data());
    }
  }
#endif
}


// ----------------------------------------------------------------------
// static helper functions for classes RelRoot and GroupByAgg
// ----------------------------------------------------------------------

static NABoolean containsGenericUpdate(const RelExpr *re)
{
  if (re->getOperator().match(REL_ANY_GEN_UPDATE)) return TRUE;
  for (Int32 i = 0; i < re->getArity(); ++i ) {
    if (re->child(i) && containsGenericUpdate(re->child(i))) return TRUE;
  }
  return FALSE;
}

static NABoolean containsUpdateOrDelete(const RelExpr *re)
{
  if (re->getOperator().match(REL_ANY_UPDATE_DELETE))
    return TRUE;
  for (Int32 i = 0; i < re->getArity(); ++i ) {
    if (re->child(i) && containsUpdateOrDelete(re->child(i)))
      return TRUE;
  }
  return FALSE;
}

// QSTUFF

static GenericUpdate *getGenericUpdate(RelExpr *re)
{
  if (re) {
    if (re->getOperatorType() == REL_UNARY_UPDATE ||
        re->getOperatorType() == REL_UNARY_DELETE)
      return (GenericUpdate *)re;

    for (Int32 i = 0; i < re->getArity(); ++i) {    // check all children (both sides)
      GenericUpdate *gu = getGenericUpdate(re->child(i));
      if (gu) return gu;
    }
  }
  return NULL;
}

static NABoolean checkUnresolvedAggregates(BindWA *bindWA)
{
  const ValueIdSet &aggs = bindWA->getCurrentScope()->getUnresolvedAggregates();
  if (aggs.isEmpty()) return FALSE;         // no error

  NAString unparsed(bindWA->wHeap());
  for (ValueId vid = aggs.init(); aggs.next(vid); aggs.advance(vid)) {

    const ItemExpr *ie = vid.getItemExpr();
    CMPASSERT(ie->isAnAggregate());
    Aggregate *agg = (Aggregate *)ie;

  // Don't display COUNT() part of SUM()/COUNTxxx(), our implementation of AVG()
  // Display only the COUNT_NONULL() our implementation of VARIANCE and STDDEV
  // This is to avoid printing the aggregate functions more than once.

    if((agg->origOpType() != ITM_AVG || agg->getOperatorType() == ITM_SUM) &&
       (!(agg->origOpType() == ITM_STDDEV || agg->origOpType() == ITM_VARIANCE)
       || agg->getOperatorType() == ITM_COUNT_NONULL)){

      unparsed += ", ";
      if (agg->origOpType() == ITM_COUNT_STAR__ORIGINALLY)
        unparsed += "COUNT(*)";
      else
        agg->unparse(unparsed, DEFAULT_PHASE, USER_FORMAT_DELUXE);
    }
  }
  unparsed.remove(0,2);              // remove initial ", "

  // 4015 Aggregate functions placed incorrectly.
  *CmpCommon::diags() << DgSqlCode(-4015) << DgString0(unparsed);
  bindWA->setErrStatus();
  return TRUE;
} // checkUnresolvedAggregates()

// ----------------------------------------------------------------------
// member functions for class RelRoot
// ----------------------------------------------------------------------


static NABoolean isRenamedColInSelList(BindWA * bindWA, ItemExpr * col, 
                                       ItemExprList &origSelectList,
                                       CollIndex &indx,
                                       RETDesc * childRETDesc)
{
  if (col->getOperatorType() != ITM_REFERENCE)
    return FALSE;

  ColReference * havingColReference = (ColReference*)col;
  
  CollIndex j = 0;

  NABoolean found = FALSE;
  while (j < origSelectList.entries())
    {
      ItemExpr * selectListEntry = origSelectList[j];
      
      if (selectListEntry->getOperatorType() == ITM_RENAME_COL)
        {
          const ColRefName &selectListColRefName = 
            *((RenameCol *)selectListEntry)->getNewColRefName();
          
          if (havingColReference->getColRefNameObj() == selectListColRefName)
            {
              if (found)
                {
                  // multiple entries with the same name. Error.
                  *CmpCommon::diags() << DgSqlCode(-4195) 
                                      << DgString0(selectListColRefName.getColName());
                  bindWA->setErrStatus();
                  return FALSE;
                }

              ColumnNameMap *baseColExpr = NULL;
              if (childRETDesc)
                baseColExpr = childRETDesc->findColumn(selectListColRefName);
              if ( NOT baseColExpr)
              { 
                found = TRUE;
                indx = j;
              }
            }
        } // rename col
      
      j++;
    } // while
  return found;
}

static short replaceRenamedColInHavingWithSelIndex(
                                     BindWA * bindWA,
                                     ItemExpr * expr, 
                                     ItemExprList &origSelectList,
                                     NABoolean &replaced,
                                     NABoolean &notAllowedWithSelIndexInHaving,
                                     RETDesc * childRETDesc)
{
  if (((expr->getOperatorType() >= ITM_ROW_SUBQUERY) &&
       (expr->getOperatorType() <= ITM_GREATER_EQ_ANY)) ||
      ((expr->getOperatorType() >= ITM_AVG) &&
       (expr->getOperatorType() <= ITM_VARIANCE)) ||
      ((expr->getOperatorType() >= ITM_DIFF1) &&
       (expr->getOperatorType() <= ITM_NOT_THIS)))
    {
      notAllowedWithSelIndexInHaving = TRUE;
      return 0;
    }

  for (Int32 i = 0; i < expr->getArity(); i++)
    {
      CollIndex j = 0;
      if (isRenamedColInSelList(bindWA, expr->child(i), origSelectList, 
                                j, childRETDesc))
        {
          SelIndex * selIndex = new(bindWA->wHeap()) SelIndex(j+1);
          expr->setChild(i, selIndex);
          replaced = TRUE;
        }
      else if (bindWA->errStatus())
        return -1;
      else if (replaceRenamedColInHavingWithSelIndex(
                              bindWA, expr->child(i), origSelectList, replaced,
                              notAllowedWithSelIndexInHaving, childRETDesc))
        return -1;
    }
  return 0;
}

static short setValueIdForRenamedColsInHaving(BindWA * bindWA,
                                              ItemExpr * expr, 
                                              ValueIdList &compExpr)
{
  if (((expr->getOperatorType() >= ITM_ROW_SUBQUERY) &&
       (expr->getOperatorType() <= ITM_GREATER_EQ_ANY)) ||
      ((expr->getOperatorType() >= ITM_AVG) &&
       (expr->getOperatorType() <= ITM_VARIANCE)) ||
      ((expr->getOperatorType() >= ITM_DIFF1) &&
       (expr->getOperatorType() <= ITM_NOT_THIS)))
    {
      return 0;
    }

  for (Int32 i = 0; i < expr->getArity(); i++)
    {
      if (expr->child(i)->getOperatorType() == ITM_SEL_INDEX)
        {
          SelIndex * si = (SelIndex*)expr->child(i)->castToItemExpr();
          si->setValueId(compExpr[si->getSelIndex()-1]);
        }
      else
        setValueIdForRenamedColsInHaving(bindWA, expr->child(i), compExpr);
    }
  return 0;
}

// Method to update the selIndecies after we have gone through a
// selectList expansion due to MVFs or Subqueries with degree > 1
// used to update the orderByTree
// 
// Returns a list of SelIndecies that were updated.
static void fixUpSelectIndecies(ItemExpr * expr, ValueIdSet &updatedIndecies,
                                CollIndex idx, CollIndex offset)
{

  if (expr == NULL ) return;

  for (Int32 i = 0; i < expr->getArity(); i++)
    {
      // Only update ones that we haven't already done.
      if ((expr->child(i)->getOperatorType() == ITM_SEL_INDEX) && 
           !updatedIndecies.contains(expr->child(i)->getValueId()))
        {
          SelIndex * si = (SelIndex*)expr->child(i)->castToItemExpr();
          if (si->getSelIndex() > idx)
          {
            si->setSelIndex(si->getSelIndex() + offset);
            updatedIndecies += si->getValueId();
          }
        }
      else
        fixUpSelectIndecies(expr->child(i), updatedIndecies, idx, offset);
    }

    // Now check myself..
    // Only update ones that we haven't already done.
    if ((expr->getOperatorType() == ITM_SEL_INDEX) && 
         !updatedIndecies.contains(expr->getValueId()))
      {
        SelIndex * si = (SelIndex*)expr->castToItemExpr();
        if (si->getSelIndex() > idx)
        {
          si->setSelIndex(si->getSelIndex() + offset);
          updatedIndecies += si->getValueId();
        }
      }
}

// Method to update the selIndecies after we have gone through a
// selectList expansion due to MVFs or Subqueries with degree > 1
// used to update the GroupByList
// 
// Returns a list of SelIndecies that were updated.
static void fixUpSelectIndeciesInSet(ValueIdSet & expr, 
                                ValueIdSet &updatedIndecies,
                                CollIndex idx, 
                                CollIndex offset)
{

  for (ValueId vid = expr.init(); expr.next(vid); expr.advance(vid))
    {
      // Only update ones that we haven't already done.
      if (((ItemExpr *)vid.getItemExpr())->getOperatorType() == ITM_SEL_INDEX &&
          !updatedIndecies.contains(vid))
        {
          SelIndex * si = (SelIndex*) vid.getItemExpr();
          if (si->getSelIndex() > idx)
          {
            si->setSelIndex(si->getSelIndex() + offset);
            updatedIndecies += si->getValueId();
          }
        }
    }
}

RelRoot * RelRoot::transformOrderByWithExpr(BindWA *bindWA)
{
  NABoolean specialMode = (CmpCommon::getDefault(GROUP_OR_ORDER_BY_EXPR) == DF_ON);
  if (NOT specialMode)
    return this;
  ItemExprList origSelectList(bindWA->wHeap());
  ItemExprList origOrderByList(bindWA->wHeap());
  
  CollIndex origSelectListCount ;
  if ((getCompExprTree() == NULL) &&
      (child(0)->getOperatorType() != REL_GROUPBY))
    {
      return this;
    }
  
  ItemExpr *orderByTree = getOrderByTree();
  if (!orderByTree) 
    return this;
  
  if (orderByTree)
    {
      origOrderByList.insertTree(orderByTree);
    }
  
  if (getCompExprTree())
    origSelectList.insertTree(getCompExprTree());
  else if (child(0)->getOperatorType() == REL_GROUPBY)
    {
      // this is the case:  select distinct <expr> from t order by <expr>
      GroupByAgg * grby = (GroupByAgg *)(child(0)->castToRelExpr());
      if (grby->child(0) && grby->child(0)->getOperatorType() == REL_ROOT)
        {
          RelRoot * selRoot = (RelRoot*)grby->child(0)->castToRelExpr();
          if (selRoot->getCompExprTree())
            origSelectList.insertTree(selRoot->getCompExprTree());
        }
    }
  
  Lng32 selListCount = origSelectList.entries();

  // if there is an expression in the order by list and this expression matches
  // a select list expression, then replace it with the index of that select list item.
  ItemExprList newOrderByList((Lng32)origOrderByList.entries(), bindWA->wHeap());
  NABoolean orderByExprFound = FALSE;
  for (Lng32 i = 0; i < origOrderByList.entries(); i++)
    {
      ItemExpr * currOrderByItemExpr = origOrderByList[i];

      NABoolean isDesc = FALSE;
      if (currOrderByItemExpr->getOperatorType() == ITM_INVERSE)
        {
          currOrderByItemExpr = currOrderByItemExpr->child(0)->castToItemExpr();
          isDesc = TRUE;
        }

      if (NOT ((currOrderByItemExpr->getOperatorType() == ITM_SEL_INDEX) ||
               (currOrderByItemExpr->getOperatorType() == ITM_REFERENCE) ||
               (currOrderByItemExpr->getOperatorType() == ITM_CONSTANT)))
        {
          NABoolean found = FALSE;
          Lng32 selListIndex = 0;
          ItemExpr * selItem = NULL;
          ItemExpr * renameColEntry = NULL;
          while ((NOT found) && (selListIndex < selListCount))
            {
              selItem = origSelectList[selListIndex];
              
              if (selItem->getOperatorType() == ITM_RENAME_COL)
                {
                  renameColEntry = selItem;
                  selItem = selItem->child(0);
                }
              
              found = currOrderByItemExpr->duplicateMatch(*selItem);
              if (NOT found)
                selListIndex++;
            }
          
          if (NOT found)
            {
              *CmpCommon::diags() << DgSqlCode(-4197) 
                                  << DgString0("ORDER BY");
              bindWA->setErrStatus();
              return NULL;
            }

          selItem->setInOrderByOrdinal(TRUE);
          currOrderByItemExpr = new(bindWA->wHeap()) SelIndex(selListIndex+1);
          if (isDesc)
            {
              currOrderByItemExpr = new(bindWA->wHeap()) InverseOrder(currOrderByItemExpr);
            }

          orderByExprFound = TRUE;
        } // if order by expr
      
      newOrderByList.insert(currOrderByItemExpr);
    }
  
  if ((orderByExprFound) &&
      (newOrderByList.entries() > 0))
    {
      removeOrderByTree();
      addOrderByTree(newOrderByList.convertToItemExpr());
    }

  return this;
}

//////////////////////////////////////////////////////////////////////
// GROUPING functions returns a 1 or 0 depending on whether a null
// value was moved as a rollup group or not.
//
// GROUPING_ID(a,b,c) returns a value corresponding to the bit vector 
// where each bit entry represents the GROUPING result for the argument
// of GROUPING_ID function.
//
// For ex: GROUPING_ID(a,b,c) will have 3 bit entries, 
// and is equivalent to:
//   GROUPING(a)*4 + GROUPING(b)*2 + GROUPING(c)*1
//////////////////////////////////////////////////////////////////////
ItemExpr * RelRoot::processGroupingID(ItemExpr * ie, BindWA *bindWA)
{
  if (ie->getOperatorType() != ITM_GROUPING_ID)
    return ie;

  ItemExpr * groupingIdExpr = NULL;

  ItemExprList childExprList(bindWA->wHeap());
  childExprList.insertTree(ie->child(0)->castToItemExpr());
  
  Int64 multiplier = (Int64)pow(2, (childExprList.entries()-1));
  SQLLargeInt * li = 
    new(bindWA->wHeap()) SQLLargeInt(bindWA->wHeap(), FALSE, FALSE); // +ve value, no nulls
  for (CollIndex i = 0; i < (CollIndex)childExprList.entries(); i++)
    {
      ItemExpr * currChildIE = 
        ((ItemExpr *) childExprList[i])->castToItemExpr();
      
      ItemExpr * groupingClause =
        new(bindWA->wHeap()) Aggregate(ITM_GROUPING, currChildIE, FALSE);
      
      ItemExpr * multiplierClause = new(bindWA->wHeap()) 
        ConstValue(li, (void*)&multiplier, sizeof(Int64));
      ItemExpr * groupingExpr = new(bindWA->wHeap()) 
        BiArith(ITM_TIMES, groupingClause, multiplierClause);
      
      if (i == 0)
        {
          groupingIdExpr = groupingExpr;
        }
      else
        {
          groupingIdExpr = new(bindWA->wHeap())
            BiArith(ITM_PLUS, groupingIdExpr, groupingExpr);
        }
      
      multiplier = multiplier / 2;
    }
  
  groupingIdExpr = new(bindWA->wHeap()) Cast(groupingIdExpr, li);

  return groupingIdExpr;
}

///////////////////////////////////////////////////////////////////////////
//
// This methods performs the following in this order:
//
// If groupby name refers to a renamed col name in the select list,
// replace group by entry with ordinal position of that sel list entry.
//
// If groupby ordinal exceeds the number of select list elements, 
// return error.
//
// If groupby ordinal referes to a '*', return error.
// 
// If groupby ordinal refers to a column(ITM_REFERENCE) or a renamed 
// col name(ITM_RENAME_COL) whose child is a column(ITM_REFERENCE),
// replace ordinal with actual col name.
//
// If there are ordinals in group by list, mark RelRoot indicating
// phase2 transformation is needed.
//
// Mark all select list item exprs which are referened as an ordinal to
// indicate that groupby check to validate grouping columns is not needed
// for the subtree rooted below that select list item.
//
///////////////////////////////////////////////////////////////////////////
RelRoot * RelRoot::transformGroupByWithOrdinalPhase1(BindWA *bindWA)
{
  NABoolean specialMode =
    (CmpCommon::getDefault(MODE_SPECIAL_1) == DF_ON);

  // make sure child of root is a groupby node.or a sequence node 
  // whose child is a group by node
  if (child(0)->getOperatorType() != REL_GROUPBY && 
      (child(0)->getOperatorType() != REL_SEQUENCE || 
       (child(0)->child(0) && child(0)->child(0)->getOperatorType()!=REL_GROUPBY)))
    return this;

  NABoolean compExprTreeIsNull = FALSE;
  CollIndex origSelectListCount ;
  if (getCompExprTree() == NULL)
  {
    compExprTreeIsNull = TRUE;
    origSelectListCount = 0;
   // return this;
  }

  GroupByAgg * grby;

  if (child(0)->getOperatorType() == REL_GROUPBY)
  {  
    grby = (GroupByAgg *)(child(0)->castToRelExpr());
  }
  else
  {// sequence node above group by
    grby = (GroupByAgg *)(child(0)->child(0)->castToRelExpr());
  }

  DCMPASSERT(grby != NULL);

  if ((NOT specialMode) &&
      (grby->getGroupExprTree() == NULL))
    return this;

  ItemExpr * groupExprTree  = grby->getGroupExprTree();
  ItemExprList origSelectList(bindWA->wHeap());
  ItemExprList origGrbyList(bindWA->wHeap());

  if (groupExprTree)
  {
    origGrbyList.insertTree(groupExprTree);
  }

  if (NOT compExprTreeIsNull)
  {
    // expand GROUPING_ID in terms of GROUPING aggregates
    if (grby->isRollup())
      {
        NABoolean groupingIDfound = FALSE;

        ItemExprList selList(getCompExprTree(), bindWA->wHeap());
        ItemExprList newSelList(bindWA->wHeap());
        for (CollIndex ii = 0; ii < selList.entries(); ii++)
          {
            ItemExpr * ie = selList[ii];
            if (ie->getOperatorType() == ITM_GROUPING_ID)
              {
                ItemExpr * newIE = processGroupingID(ie, bindWA);
                if (bindWA->errStatus())
                  return this;
                
                groupingIDfound = TRUE;
                newSelList.insert(newIE);
              }
            else
              newSelList.insert(ie);
          } // for

        if (groupingIDfound)
          {
            ItemExpr * newCompExprTree = newSelList.convertToItemExpr();
            removeCompExprTree();
            addCompExprTree(newCompExprTree);
          }
       }

    origSelectList.insertTree(getCompExprTree());
    origSelectListCount = origSelectList.entries();
  }

  ItemExprList newGroupByList((Lng32)origGrbyList.entries(), bindWA->wHeap());
  
  NABoolean foundSelIndex = FALSE;

  NABoolean lookForRenamedCols = TRUE;
  if ((CmpCommon::getDefault(GROUP_OR_ORDER_BY_EXPR) == DF_OFF) &&
      (NOT specialMode))
    lookForRenamedCols = FALSE;

  NABoolean lookForExprInGroupByClause = TRUE;
  if (CmpCommon::getDefault(COMP_BOOL_92) == DF_ON)
    lookForExprInGroupByClause = FALSE;

  // See if UDF_SUBQ_IN_AGGS_AND_GBYS is enabled. It is enabled if the
  // default is ON, or if the default is SYSTEM and ALLOW_UDF is ON.
  NABoolean udfSubqInAggGrby_Enabled = FALSE;
  DefaultToken udfSubqTok = CmpCommon::getDefault(UDF_SUBQ_IN_AGGS_AND_GBYS);
  if ((udfSubqTok == DF_ON) ||
      (udfSubqTok == DF_SYSTEM))
    udfSubqInAggGrby_Enabled = TRUE;

  // This list will store duplicate expression specified in  select list and 
  // GroupBy clause. It helps with specifying select Index  as well as 
  // mark InGroupByOrdinal flag correctly (Gen Sol:10-100129-7836)
  NAList<CollIndex> listOfExpressions(CmpCommon::statementHeap());

  for (CollIndex i = 0; (i < (CollIndex) origGrbyList.entries());i++)
    {
      ItemExpr * currGroupByItemExpr = 
        ((ItemExpr *) origGrbyList[i])->castToItemExpr();
      ItemExpr * newGroupByItemExpr = NULL;

      NABoolean selIndexError = FALSE;
      Int64 selIndex = -1;
      if (currGroupByItemExpr->getOperatorType() == ITM_CONSTANT)
        {
          ConstValue * cv = (ConstValue*)currGroupByItemExpr;
          if ((cv->canGetExactNumericValue()) &&
              (cv->getType()->getScale() == 0))
            {
              selIndex = cv->getExactNumericValue();
              if ((selIndex >= 0) && (selIndex < MAX_COMSINT32))
                {
                  if (selIndex == 0 || selIndex > origSelectListCount)
                    {
                      // remember that this select index is in error.
                      // Look for this constant in the select list.
                      // If it is not found, then this const will be
                      // treated as a select index and an error will 
                      // returned. If it is found in the select list,
                      // then it will be treated as a group by expression.
                      selIndexError = TRUE;
                    }
                  else
                    currGroupByItemExpr = 
                      new(bindWA->wHeap()) SelIndex((Lng32)selIndex);
                }
            }
        }

      NABoolean found = FALSE;
      if ((currGroupByItemExpr->getOperatorType() != ITM_REFERENCE) &&
          (currGroupByItemExpr->getOperatorType() != ITM_SEL_INDEX) &&
          (lookForExprInGroupByClause))
        {
           Int32 selListIndex = -1, lastMatch = -1;
          CollIndex j = 0;
          while ((NOT found) && (j < origSelectListCount))
            {
              ItemExpr * selectListEntry = origSelectList[j];
              
              if ((selectListEntry->getOperatorType() != ITM_REFERENCE) &&
                  ((selectListEntry->getOperatorType() != ITM_RENAME_COL) ||
                  ((selectListEntry->child(0)) && 
                  (selectListEntry->child(0)->getOperatorType() != ITM_REFERENCE))))
                {
                  ItemExpr * renameColEntry = NULL;
                  if (selectListEntry->getOperatorType() == ITM_RENAME_COL)
                    {
                      renameColEntry = selectListEntry;
                      selectListEntry = selectListEntry->child(0);
                    }
                  
                  found = 
                    currGroupByItemExpr->duplicateMatch(*selectListEntry);
                  if (found)
                    {
		      lastMatch = j;
		      if(!listOfExpressions.contains(j))
		      {
			selListIndex = j;
			listOfExpressions.insert(j);
			
                        selectListEntry->setInGroupByOrdinal(TRUE);
                        selectListEntry->setIsGroupByExpr(TRUE);

			if (renameColEntry)
			  renameColEntry->setInGroupByOrdinal(TRUE);
		      }
		      else
			found = FALSE;
                    }
                }
              j++;
            } // while

	    if(lastMatch != -1)
	    {
	      found = TRUE;

	      if(selListIndex == -1)
		selListIndex = lastMatch;

	      if (bindWA->inViewDefinition())
		currGroupByItemExpr = 
		  new(bindWA->wHeap()) SelIndex(selListIndex+1, 
						currGroupByItemExpr);
	      else
		currGroupByItemExpr = new(bindWA->wHeap()) SelIndex(selListIndex+1);
	    }
        } // expr in group by clause
      
      if ((NOT found) &&
          (selIndexError) &&
          (selIndex > 0))
        {
          // this const was not found in the select list and it was
          // not a valid select index.
          // Return an error.
          *CmpCommon::diags() << DgSqlCode(-4007) 
                              << DgInt0((Lng32)selIndex)
                              << DgInt1((Lng32)origSelectList.entries());
          bindWA->setErrStatus();
          return NULL;
        }
      if (compExprTreeIsNull)
        return this;

      if (currGroupByItemExpr->getOperatorType() == ITM_SEL_INDEX)
        {
          SelIndex * si = (SelIndex*)currGroupByItemExpr;
          if (si->getSelIndex() > origSelectList.entries())
            {
              *CmpCommon::diags() << DgSqlCode(-4007) 
                                  << DgInt0((Lng32)si->getSelIndex()) 
                                  << DgInt1((Lng32)origSelectList.entries());
              bindWA->setErrStatus();
              return NULL;
            }

          ItemExpr * selectListEntry = origSelectList[si->getSelIndex()-1];
          if ((selectListEntry->getOperatorType() == ITM_RENAME_COL) &&
              (selectListEntry->child(0)->getOperatorType() == ITM_REFERENCE))
            {
              // make a copy of this entry's child
              newGroupByItemExpr = 
                selectListEntry->child(0)->
                  castToItemExpr()->copyTopNode(NULL, bindWA->wHeap());
            }
          else if (selectListEntry->getOperatorType() == ITM_REFERENCE)
            {
              if (((ColReference*)selectListEntry)-> getColRefNameObj().isStar())
                {
                  *CmpCommon::diags() << DgSqlCode(-4185) ;
                  bindWA->setErrStatus();
                  return NULL;
                }

              // make a copy of this entry
              newGroupByItemExpr = 
                selectListEntry->copyTopNode(NULL, bindWA->wHeap());
            }
          else
            {
              selectListEntry->setInGroupByOrdinal(TRUE);
              newGroupByItemExpr = currGroupByItemExpr;
            }

          foundSelIndex = TRUE;
        } // group by ordinal
      else if (currGroupByItemExpr->getOperatorType() == ITM_REFERENCE)
        {
           ColReference * groupByColReference = 
                                 (ColReference*)currGroupByItemExpr;
           
          // find out if this ColReference name is a renamed col in the
          // select list.
          if (lookForRenamedCols && 
              groupByColReference->getCorrNameObj().getQualifiedNameObj().getObjectName().length() == 0)
            {

              NABoolean renamedColsInSelectList = FALSE;
              CollIndex j = 0;
              NABoolean found = FALSE;
              while (j < origSelectList.entries())
                {
                  ItemExpr * selectListEntry = origSelectList[j];

                  if (selectListEntry->getOperatorType() == ITM_RENAME_COL)
                    {
                      renamedColsInSelectList = TRUE;

                      const ColRefName &selectListColRefName = 
                        *((RenameCol *)selectListEntry)->getNewColRefName();
                      
                      if (groupByColReference->getColRefNameObj().getColName()
                          == selectListColRefName.getColName())
                        {
                          if (found)
                            {
                              // multiple entries with the same name. Error.
                              *CmpCommon::diags() << DgSqlCode(-4195) 
                                << DgString0(selectListColRefName.getColName());
                              bindWA->setErrStatus();
                              return NULL;
                            }

                          foundSelIndex = TRUE;

                          selectListEntry->setInGroupByOrdinal(TRUE);

                          newGroupByItemExpr = 
                            new(bindWA->wHeap()) SelIndex(j+1);
                          ((SelIndex *) newGroupByItemExpr)->
                            setRenamedColNameInGrbyClause(TRUE);


                          found = TRUE;
                        }
                    } // rename col

                  j++;
                } // while

              if ((NOT renamedColsInSelectList) &&
                  (j == origSelectList.entries()))
                lookForRenamedCols = FALSE;
            } // lookForRenamedCols

          if (! newGroupByItemExpr)
            newGroupByItemExpr = currGroupByItemExpr;
        } // else foundSelIndex
      else if ((currGroupByItemExpr->getOperatorType() == ITM_USER_DEF_FUNCTION) &&
               (udfSubqInAggGrby_Enabled))
            newGroupByItemExpr = currGroupByItemExpr;
      else if ((currGroupByItemExpr->getOperatorType() == ITM_ROW_SUBQUERY) &&
               (udfSubqInAggGrby_Enabled))
            newGroupByItemExpr = currGroupByItemExpr;
      else
        {
          *CmpCommon::diags() << DgSqlCode(-4197) 
                              << DgString0("GROUP BY");
          bindWA->setErrStatus();
          return NULL;
        }

      newGroupByList.insert(newGroupByItemExpr);

    } // for
  
  if ((foundSelIndex) &&
      (newGroupByList.entries() > 0))
    {
      grby->removeGroupExprTree();
      grby->addGroupExprTree(newGroupByList.convertToItemExpr());
    }

  grby->setParentRootSelectList(getCompExprTree());

  // if order by and group by are specified, check to see that
  // all columns specified in the order by clause are also present
  // in the group by clause.
  allOrderByRefsInGby_ = FALSE;
  if (
      (getOrderByTree()) &&
      (grby->getGroupExprTree() != NULL))
    {
      ItemExpr *orderByTree = getOrderByTree();

      ItemExprList orderByList(orderByTree, bindWA->wHeap());
      ItemExprList groupByList(grby->getGroupExprTree(), bindWA->wHeap());

      allOrderByRefsInGby_ = TRUE;
      for (CollIndex ii = 0; ii < orderByList.entries(); ii++)
        {
          ItemExpr * colRef = orderByList[ii];
          if (colRef->getOperatorType() == ITM_INVERSE)
            colRef = colRef->child(0)->castToItemExpr();
          if (colRef && colRef->getOperatorType() == ITM_REFERENCE)
            {
              ColReference * obyColRef = (ColReference*)colRef;
              
              NABoolean found = FALSE;
              for (CollIndex j = 0; j < groupByList.entries(); j++)
                {
                  ItemExpr * gbyExpr = groupByList[j];
                  if (gbyExpr->getOperatorType() == ITM_REFERENCE)
                    {
                      ColReference * gbyColRef = (ColReference*)gbyExpr;
                      if (obyColRef->getColRefNameObj().getColName() ==
                          gbyColRef->getColRefNameObj().getColName())
                        {
                          found = TRUE;
                          break;
                        }
                    } // if
                } // for

              if (NOT found)
                {
                  allOrderByRefsInGby_ = FALSE;
                  break;
                }
            } // if
        } // for
    } // if

  return this;
}

RelRoot * RelRoot::transformGroupByWithOrdinalPhase2(BindWA *bindWA)
{
  NABoolean specialMode =
    (CmpCommon::getDefault(MODE_SPECIAL_1) == DF_ON);

  // make sure child of root is a groupby node or a sequence node 
  // whose child is a group by node
  if (child(0)->getOperatorType() != REL_GROUPBY && 
       (child(0)->getOperatorType() != REL_SEQUENCE || 
         (child(0)->child(0) && child(0)->child(0)->getOperatorType()!=REL_GROUPBY)))
    return this;

  GroupByAgg * grby;
  RelSequence * seqNode=NULL;

  if (child(0)->getOperatorType() == REL_GROUPBY )
  {
    grby=(GroupByAgg *)(child(0)->castToRelExpr());
  }
  else
  {//sequence node above group by
    grby=(GroupByAgg *)(child(0)->child(0)->castToRelExpr());
    seqNode=(RelSequence *)(child(0)->castToRelExpr());
  }

  DCMPASSERT(grby != NULL);

  if (grby->isRollup())
    {
      if (grby->groupExpr().entries() != grby->rollupGroupExprList().entries())
        {
          *CmpCommon::diags() << DgSqlCode(-4384)
                              << DgString0("Cannot have duplicate entries.");
          
          bindWA->setErrStatus();
          return NULL;
        }

      for (ValueId valId = grby->aggregateExpr().init();
           grby->aggregateExpr().next(valId);
           grby->aggregateExpr().advance(valId))
        {
          ItemExpr * ae = valId.getItemExpr();

          // right now, only support groupby rollup on min/max/sum/avg/count
          if (NOT ((ae->getOperatorType() == ITM_MIN) ||
                   (ae->getOperatorType() == ITM_MAX) ||
                   (ae->getOperatorType() == ITM_SUM) ||
                   (ae->getOperatorType() == ITM_AVG) ||
                   (ae->getOperatorType() == ITM_COUNT) ||
                   (ae->getOperatorType() == ITM_COUNT_NONULL) ||
                   (ae->getOperatorType() == ITM_GROUPING)))
            {
              *CmpCommon::diags() << DgSqlCode(-4384)
                                  << DgString0("Unsupported rollup aggregate function.");
              
              bindWA->setErrStatus();
              return NULL;
            }
          
          // right now, only support groupby rollup on non-distinct aggrs
          Aggregate * ag = (Aggregate*)ae;
          if (ag->isDistinct())
            {
              *CmpCommon::diags() << DgSqlCode(-4384)
                                  << DgString0("Distinct rollup aggregates not supported.");
              
              bindWA->setErrStatus();
              return NULL;
            }

          // if grouping aggr, find the rollup group it corresponds to.
          if (ae->getOperatorType() == ITM_GROUPING)
            {
              NABoolean found = FALSE;
              ItemExpr * aggrChild = ae->child(0);
              int i = 0;
              while ((NOT found) and (i < grby->rollupGroupExprList().entries()))
                {
                  ValueId vid =  grby->rollupGroupExprList()[i];
                  if (vid.getItemExpr()->getOperatorType() == ITM_SEL_INDEX)
                    {
                      SelIndex * si = (SelIndex*)vid.getItemExpr();
                      vid = compExpr()[si->getSelIndex()-1];
                    }
                  found =  aggrChild->duplicateMatch(*vid.getItemExpr());
                  if (found)
                    ag->setRollupGroupIndex(i);
                  i++;
                } // while

              if (NOT found)
                {
                  // must find it.
                  *CmpCommon::diags() << DgSqlCode(-4384)
                                      << DgString0("GROUPING function can only be specified on a GROUP BY ROLLUP entry.");
                  
                  bindWA->setErrStatus();
                  return NULL;
                }
            }
        } // for
    }
  else
    {
      // not groupby rollup
      for (ValueId valId = grby->aggregateExpr().init();
           grby->aggregateExpr().next(valId);
           grby->aggregateExpr().advance(valId))
        {
          ItemExpr * ae = valId.getItemExpr();

          // grouping can only be specified with 'groupby rollup' clause
          if (ae->getOperatorType() == ITM_GROUPING)
            {
              *CmpCommon::diags() << DgSqlCode(-3242)
                                  << DgString0("GROUPING function can only be specified with GROUP BY ROLLUP clause.");
              
              bindWA->setErrStatus();
              return NULL;
            }
 
        } // for
    }

  ValueIdSet &groupExpr = grby->groupExpr();
  // copy of groupExpr used to identify the changed
  // value ids
  ValueIdSet groupExprCpy(grby->groupExpr());

  // When we encounter subqueries or MVFs in the select list 
  // these gets expanded at bind time, and so the select index have to
  // be offset with the expansion number since the sel_index number 
  // reflects the select list at parse time.
  for (ValueId vid = groupExpr.init(); 
       groupExpr.next(vid);
       groupExpr.advance(vid))
    {
      if (vid.getItemExpr()->getOperatorType() == ITM_SEL_INDEX)
        {
          CollIndex selIndexExpansionOffset = 0;
          SelIndex * si = (SelIndex*)(vid.getItemExpr());
          ValueId grpById = 
                      compExpr()[si->getSelIndex() -1];
          si->setValueId(grpById);
          if (child(0)->getOperatorType() != REL_SEQUENCE)
          {
            groupExprCpy.remove(vid);
            groupExprCpy.insert(grpById);
            if (grby->isRollup())
              {
                CollIndex idx = grby->rollupGroupExprList().index(vid);
                grby->rollupGroupExprList()[idx] = grpById;
              }
          }
          else
          {  //sequence
            CMPASSERT(seqNode);
            const ValueIdSet seqCols = ((const RelSequence*)seqNode)->sequencedColumns();

            ItemExpr * ie = grpById.getItemExpr();
            ItemExpr::removeNotCoveredFromExprTree(ie,seqCols);

            //ie = ie->copyTree(bindWA->wHeap());
            //ie = ie->bindNode(bindWA);
            if (bindWA->errStatus())
	      return NULL;

            groupExprCpy.remove(vid);
            groupExprCpy.insert(ie->getValueId());

            ie = new (bindWA->wHeap()) NotCovered(ie);
            ie->synthTypeAndValueId();

            compExpr()[si->getSelIndex()-1] = ie->getValueId();
            seqNode->addSequencedColumn(ie->getValueId());

          }

          switch (grpById.getItemExpr()->getOperatorType())
          {
            case ITM_VALUEID_PROXY:
            {
              ValueId derivedId = 
                    (( ValueIdProxy *)(grpById.getItemExpr()))->isDerivedFrom();

              // If this is not the ValueIdProxy that represents the MVF or Subq
              // skip the expansion.
              if ((( ValueIdProxy *)(grpById.getItemExpr()))->
                     needToTransformChild() != TRUE) break;

              ValueIdList outputs;

              switch (derivedId.getItemExpr()->getOperatorType())
              {
                case ITM_USER_DEF_FUNCTION:
                {
                  // When we reference a UDF in the groupBy clause,
                  // if the UDF is a MVF(has multiple outputs), we need to add 
                  // the other elements from the MVF's outputs.
                
                  // These elements have already been expanded into the 
                  // select list, so all we need to do is to add them to the
                  // groupby expression.
   
                  // By default, we associate the valueId of the MVF with 
                  // its first output, so we just need to copy the rest of the 
                  // outputs.
                  UDFunction *udf = (UDFunction *) derivedId.getItemExpr();
                  const RoutineDesc *rDesc = udf->getRoutineDesc();
                  outputs =  rDesc->getOutputColumnList();
                  break;
                }

                case ITM_ROW_SUBQUERY:
                {
                  // When we reference a subquery in the groupBy clause,
                  // if the subquery has a degree > 1, we need to add the other
                  // elements from the subquery's select list.
                  Subquery *subq = (Subquery *) derivedId.getItemExpr();
                  RelRoot *subqRoot = (RelRoot *) subq->getSubquery();
                  outputs =  subqRoot->compExpr();
                  break;
                }
                default:
                  CMPASSERT(0); // we don't support anything else
              }


              // Add in the other outputs from the MVF/Subquery
              for (CollIndex i=1; i < outputs.entries();  i++)
              {
                selIndexExpansionOffset ++;
                groupExprCpy.insert(outputs[i]);
              }

              // Need to check the groupBy and orderBy lists
              // for selIndexes with an index greater than this one, 
              // If we find one, bump its index into the select list by
              // the expansion.
     
              ValueIdSet fixedUpIndecies;

              fixUpSelectIndeciesInSet(grby->groupExpr(),fixedUpIndecies,
                                       si->getSelIndex(), 
                                       selIndexExpansionOffset);

              fixUpSelectIndecies(getOrderByTree(), fixedUpIndecies,
                                  si->getSelIndex(), 
                                  selIndexExpansionOffset);
            break;
            }
          }

          // Now that we have swapped the vid list from grouping
          // expression to the corresponding one from select list
          // go thru each expression, collect the base columns
          // and mark each column as referenced for histogram.
          // Since this is only for group by, we will get only single
          // interval histograms - 10-081015-6557
          ValueIdSet columns;
          grpById.getItemExpr()->findAll(ITM_BASECOLUMN, columns, TRUE, TRUE);
          for (ValueId id = columns.init(); 
                       columns.next(id); 
                       columns.advance(id))
          {
            NAColumn *nacol = id.getNAColumn();
            if (nacol->isReferencedForHistogram())
              continue;
            nacol->setReferencedForSingleIntHist();
          }
       } // found Sel Index
    }

  ValueId valId;
  if (grby->isRollup())
    {
      for (CollIndex i = 0; i < grby->rollupGroupExprList().entries(); i++)
        {
          valId = grby->rollupGroupExprList()[i];
          
          if (NOT valId.getType().supportsSQLnull())
            {
              *CmpCommon::diags() << DgSqlCode(-4384)
                                  << DgString0("Grouped columns must be nullable.");
              bindWA->setErrStatus();
              return NULL;
            }
        }
    }

  //looking for extra order requirement, currently, aggregate function PIVOT_GROUP will need extra order 
  //so loop through the aggregation expression and check if there is PIVOT_GROUP and it needs explicit order
  //if found, populate the extraOrderExpr for the GroupAggBy
  //so later optimizer can add correct sort key 
  ValueIdSet &groupAggExpr = grby->aggregateExpr();

  for (ValueId vid = groupAggExpr.init(); 
       groupAggExpr.next(vid);
       groupAggExpr.advance(vid))
    {
      if (vid.getItemExpr()->getOperatorType() == ITM_PIVOT_GROUP)
      {
        if( ((PivotGroup*)vid.getItemExpr())->orderBy() ) 
        {
          grby->setExtraGrpOrderby(((PivotGroup*)vid.getItemExpr())->getOrderbyItemExpr());
          ValueIdList tmpList;
          grby->getExtraGrpOrderby()->convertToValueIdList(tmpList, bindWA, ITM_ITEM_LIST);
          grby->setExtraOrderExpr(tmpList);
        }
      }
    }
  // recreate the groupExpr expression after updating the value ids
  grby->setGroupExpr (groupExprCpy);

  if ((grby->selPredTree()) &&
      (grby->selIndexInHaving()))
    {
      setValueIdForRenamedColsInHaving(bindWA, grby->selPredTree(),
                                       compExpr());

      BindScope *currScope = bindWA->getCurrentScope();
      
      ItemExpr *havingPred = grby->removeSelPredTree();
      currScope->context()->inHavingClause() = TRUE;
      havingPred->convertToValueIdSet(grby->selectionPred(), 
                                      bindWA, ITM_AND);
      currScope->context()->inHavingClause() = FALSE;
      if (bindWA->errStatus()) 
        return this;
    }

  if (orderByTree_ && seqNode && grby)
  {
    ItemExprList origOrderByList(bindWA->wHeap());

    origOrderByList.insertTree(orderByTree_);
    
    ItemExprList newOrderByList((Lng32)origOrderByList.entries(), bindWA->wHeap());

    for (CollIndex i = 0; (i < (CollIndex) origOrderByList.entries());i++)
    {
      ItemExpr * currOrderByItemExpr = 
                      ((ItemExpr *) origOrderByList[i])->castToItemExpr();
      ItemExpr * newOrderByItemExpr = currOrderByItemExpr;
      
      if (currOrderByItemExpr->getOperatorType() == ITM_SEL_INDEX)
      {
         SelIndex * si = (SelIndex*)(currOrderByItemExpr);
         if (compExpr()[si->getSelIndex()-1].getItemExpr()->getOperatorType() != ITM_BASECOLUMN)
         {
           newOrderByItemExpr = compExpr()[si->getSelIndex()-1].getItemExpr();
         }
      }
      newOrderByList.insert(newOrderByItemExpr);
    }
    orderByTree_ = newOrderByList.convertToItemExpr();
  }

  return this;
}

void RelRoot::transformTDPartitionOrdinals(BindWA *bindWA)
{
  if(!getHasTDFunctions()) 
    return ;

  if (getCompExprTree() == NULL)
    return ;

  BindScope *currScope = bindWA->getCurrentScope();

  RelExpr * realChildNode = NULL;
 
  if (child(0)->getOperatorType() == REL_FIRST_N)
  {
    realChildNode = child(0)->child(0);
  }
  else
  {
    realChildNode = child(0);
  }
  
  if(realChildNode->getOperatorType() != REL_SEQUENCE )
  {
    return;
  }

  RelSequence * seqNode = (RelSequence *)realChildNode;

  if (!seqNode->getPartitionBy())
  {
    return;
  }
  
  ItemExpr * partitionBy  = seqNode->getPartitionBy()->copyTree(bindWA->wHeap());

  ItemExprList origSelectList(getCompExprTree(), bindWA->wHeap());

  ItemExprList origPartitionByList(bindWA->wHeap());
  if (partitionBy)
  {
      origPartitionByList.insertTree(partitionBy);
  }

  for (CollIndex i = 0; (i < (CollIndex) origPartitionByList.entries());i++)
  {
    ItemExpr * currPartitionByItemExpr = 
      ((ItemExpr *) origPartitionByList[i])->castToItemExpr();    

    NABoolean selIndexError = FALSE;
    Int64 selIndex = -1;
    if (currPartitionByItemExpr->getOperatorType() == ITM_CONSTANT)
    {
      ConstValue * cv = (ConstValue*)currPartitionByItemExpr;
      if ((cv->canGetExactNumericValue()) &&
          (cv->getType()->getScale() == 0))
      {
        selIndex = cv->getExactNumericValue();

        if (selIndex <= 0 || selIndex > origSelectList.entries())
        { //index in error -- produce error message
          //in TD mode group by <constant> -- constant is purely positional  
          //selIndexError = TRUE;
          *CmpCommon::diags() << DgSqlCode(-4366);
          bindWA->setErrStatus();
          return;
        }
        else
        {
          origPartitionByList.usedEntry( i )= 
            origSelectList.usedEntry((CollIndex)selIndex-1)->copyTree(bindWA->wHeap());
        }
      }
    }
  }
  seqNode->setPartitionBy(origPartitionByList.convertToItemExpr());
}
// resolveAggregates - 
// If aggregate functions have been found in the select list, then
// either attach the aggregate functions to the existing GroupBy below
// this RelRoot, or if there is no GroupBy create a GroupBy with an
// empty groupby list (scalar) and attach the aggregate functions to
// this GroupBy.
//
void RelRoot::resolveAggregates(BindWA *bindWA) 
{
  BindScope *currScope = bindWA->getCurrentScope();

  if (NOT currScope->getUnresolvedAggregates().isEmpty()) {
    if (getHasTDFunctions())
    { //Using rank function and aggregate functions in the same scope is not supported. 
      *CmpCommon::diags() << DgSqlCode(-4365);
      bindWA->setErrStatus();
      return;    
    }

    RelExpr *sequence = currScope->getSequenceNode();

    // The aggregates were used without a GROUP BY or HAVING
    // clause, i.e. an implicit aggregation is performed
    // (with a NULL result for an empty input table).
    NABoolean implicitGrouping = (child(0)->getOperatorType() != REL_GROUPBY);
    
    if(getHasOlapFunctions()) {
      implicitGrouping = (sequence->child(0)->getOperatorType() != REL_GROUPBY);
    }
    GroupByAgg *groupByAgg = NULL;
    if (implicitGrouping) {
      RelExpr * realChildNode = NULL;

      // if my child is a FIRST_N node, then add the GroupByAgg below it.
      // Otherwise, add the GroupByAgg below me.
      if (child(0)->getOperatorType() == REL_FIRST_N)
      {
        realChildNode = child(0)->child(0);
      }
      else
        realChildNode = child(0);

      if(getHasOlapFunctions()) {

        realChildNode = sequence->child(0);
      }

      groupByAgg =
        new (bindWA->wHeap()) GroupByAgg(realChildNode,REL_GROUPBY);
      realChildNode->setBlockStmt(isinBlockStmt());

      if(getHasOlapFunctions())
        sequence->setChild(0, groupByAgg);
      else if (child(0)->getOperatorType() == REL_FIRST_N)
        child(0)->setChild(0, groupByAgg);
      else
        setChild(0, groupByAgg);

      groupByAgg->setBlockStmt(isinBlockStmt());
    }
    else {
      if(getHasOlapFunctions()) {
        groupByAgg = (GroupByAgg *)sequence->child(0).getPtr();
      } else {
        groupByAgg = (GroupByAgg *)child(0).getPtr();
      }
    }

    NAString colName(bindWA->wHeap());
    Lng32 sqlCode = 0;
    ValueId valId = NULL_VALUE_ID;

    if (currScope->context()->unaggColRefInSelectList()) {
      sqlCode = -4021;
      valId = currScope->context()->unaggColRefInSelectList()->getValueId();
    }
    else if (implicitGrouping) {
      // Genesis 10-000414-9410:  "SELECT SUM(A),* FROM T; --no GROUP BY"
      // cannot be flagged with err 4012 in ColReference::bindNode
      // because table not marked "grouped" yet.
      //
      const ColumnDescList &cols = *currScope->getRETDesc()->getColumnList();
      CollIndex i, n = cols.entries();
      for (i=0; i<n; i++) {
        const ColumnDesc *col = cols[i];
        if (!col->isGrouped())
          if (col->getColRefNameObj().isStar() ||
              col->getValueId().getNAColumn(TRUE/*okIfNotColumn*/)) {
            sqlCode = -4012;
            valId = col->getValueId();
            colName = col->getColRefNameObj().getColRefAsAnsiString();
            break;
          }
      }
    }

    // Table has no GROUP BY (so no grouping columns exist at all)
    // but is grouped by dint of a column reference within an aggregate,
    // making any unaggregated column references illegal, by ANSI 7.9 SR 7.
    if (sqlCode) {

      if (colName.isNull()) {
        const NAColumn *nacol = valId.getNAColumn(TRUE/*okIfNotColumn*/);
        if (nacol)
          colName = nacol->getFullColRefNameAsAnsiString();
        else
          colName = "_unnamed_column_";
      }

      // 4012 Col ref must be grouping or aggregated -- no star ref allowed!
      // 4021 The select list contains a non-grouping non-aggregated column.
      *CmpCommon::diags() << DgSqlCode(sqlCode) << DgColumnName(colName);
      bindWA->setErrStatus();
      return;
    }

    // Move the unresolved aggregates into the groupby node and bind
    // (simply returns if "groupByAgg" isn't new).
    groupByAgg->aggregateExpr() += currScope->getUnresolvedAggregates();
    currScope->getUnresolvedAggregates().clear();
    groupByAgg->bindNode(bindWA);
  }
}

// resolveSequenceFunctions -
// Add the unresolvedSequenceFunctions to the Sequence node for this
// scope.  If there are sequence functions, but no sequence node, it
// is an error.  Also if there is a sequence node, but no sequence
// functions, it is an error.
//
// 
void RelRoot::resolveSequenceFunctions(BindWA *bindWA)
{
  BindScope *currScope = bindWA->getCurrentScope();

  // If we have a Sequence Node associated with the RelRoot node,
  //
  RelSequence *sequenceNode = (RelSequence *)currScope->getSequenceNode();
  currScope->getSequenceNode() = NULL;

  if (sequenceNode) {
    if (getHasTDFunctions() && sequenceNode->child(0)->getOperatorType() == REL_GROUPBY) 
    { //Using rank function and group by clause in the same scope is not supported.
      *CmpCommon::diags() << DgSqlCode(-4366);
      bindWA->setErrStatus();
      return;
    }

    CMPASSERT(sequenceNode->getOperatorType() == REL_SEQUENCE);

    // Do not allow sequence functions or OLAP Window functions
    // with Embedded Updates.
    //
    if (getGroupAttr()->isEmbeddedUpdateOrDelete()){
      *CmpCommon::diags() << DgSqlCode(-4202)
        << (getGroupAttr()->isEmbeddedUpdate() ?
            DgString0("UPDATE"):DgString0("DELETE"));
      bindWA->setErrStatus();
      return;
      }

    // If there are some sequence functions that have not been attached
    // to the Sequence node, do so now.  These were found when binding
    // the select list.
    //
    sequenceNode->
      addUnResolvedSeqFunctions(currScope->getUnresolvedSequenceFunctions(),
                                bindWA);

    currScope->getUnresolvedSequenceFunctions().clear();
    currScope->getAllSequenceFunctions().clear();
    if (bindWA->errStatus()) return;

    // Make sure the sequence function has some work to do.
    // The cast is needed since the compiler will attempt to pick the
    // protected (writable) version of 'sequenceFunctions()'.  (Is this
    // a compiler bug)
    //
    if ((((const RelSequence *)sequenceNode)->sequenceFunctions().isEmpty() )
        && 
        ( !getHasOlapFunctions() &&
          ((const RelSequence *)sequenceNode)->requiredOrder().entries() != 0 )) {
      // Can't have a sequence by clause without
      // sequence functions.
      //
      *CmpCommon::diags() << DgSqlCode(-4111);
      bindWA->setErrStatus();
      return;
    }
  } else if (! currScope->getUnresolvedSequenceFunctions().isEmpty()) {

    // Can't have sequence functions without a
    // sequence by clause.
    // First, loop through the list of functions.
    //
    ValueIdSet &unresolved = currScope->getUnresolvedSequenceFunctions();
    NAString unparsed(bindWA->wHeap());
    for (ValueId vid = unresolved.init(); unresolved.next(vid); unresolved.advance(vid)) {
     ItemExpr *ie = vid.getItemExpr();
     CMPASSERT(ie->isASequenceFunction());
     unparsed += ", ";
     ie->unparse(unparsed, DEFAULT_PHASE, USER_FORMAT_DELUXE);
    }
    unparsed.remove(0,2);     // remove initial ", "

    *CmpCommon::diags() << DgSqlCode(-4110) << DgString0(unparsed);
    bindWA->setErrStatus();
    return;
  }
}

// if a where pred is specified on an immediate child scan or rename node,
// and it contains an 'and'ed rownum() predicate of the form:
//    rownum < val, or rownum <= val, or rownum = val
// then get the val and make it the firstN value.
// Also, remove this predicate from selPredTree.
void RelRoot::processRownum(BindWA * bindWA)
{
  NABoolean specialMode = (CmpCommon::getDefault(MODE_SPECIAL_4) == DF_ON);
  if (NOT specialMode)
    return;

  if (! child(0))
    return;

  if ((child(0)->getOperatorType() != REL_SCAN) &&
      (child(0)->getOperatorType() != REL_RENAME_TABLE))
    return;

  if (! child(0)->selPredTree())
    return;
  
  ItemExpr * wherePred = child(0)->selPredTree();
  ItemExprList iel(wherePred, bindWA->wHeap(), ITM_AND, FALSE, FALSE);

  NABoolean found = FALSE;
  for (Lng32 i = 0; ((NOT found) && (i < iel.entries())); i++)
    {
      ItemExpr * ie = iel[i];
      if (ie->getArity() != 2)
        continue; 

      if (NOT ((ie->getOperatorType() == ITM_LESS) ||
               (ie->getOperatorType() == ITM_EQUAL) ||
               (ie->getOperatorType() == ITM_LESS_EQ)))
        continue;
      
      ItemExpr * child0 = ie->child(0)->castToItemExpr();
      ItemExpr * child1 = ie->child(1)->castToItemExpr();

      if (NOT ((child0->getOperatorType() == ITM_REFERENCE) &&
               (child1->getOperatorType() == ITM_CONSTANT)))
        continue;
               
      ColReference * col = (ColReference*)child0;
      ColRefName &colRefName = col->getColRefNameObj();
      CorrName &cn = col->getCorrNameObj();
      
      const NAString &catName = cn.getQualifiedNameObj().getCatalogName();	       
      const NAString &schName = cn.getQualifiedNameObj().getSchemaName();		
      const NAString &objName = cn.getQualifiedNameObj().getObjectName();		
      const NAString &colName = colRefName.getColName();
      
      if (NOT ((catName.isNull()) &&
               (schName.isNull()) &&                
               (objName.isNull()) &&
               (colName == "ROWNUM")))
        continue;

      ConstValue * cv = (ConstValue*)child1;
      if (NOT cv->canGetExactNumericValue())
        continue;

      Int64 val = cv->getExactNumericValue();
      if (val < 0)
        continue;

      if ((ie->getOperatorType() == ITM_EQUAL) &&
          (val != 1))
        continue;

      if ((ie->getOperatorType() == ITM_LESS) &&
          (val > 0))
        val--;

      setFirstNRows(val);

      // remove this pred from the list
      iel.removeAt(i);

      found = TRUE;
    }

  if (found)
    {
      // convert the list back to selection pred.
      ItemExpr * ie = iel.convertToItemExpr();
      child(0)->removeSelPredTree();
      child(0)->addSelPredTree(ie);
    }

  return;
}

RelExpr *RelRoot::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  if (isTrueRoot()) 
    {
      // if this is simple scalar aggregate on a seabase table
      //  (of the form:  select count(*), sum(a) from t; )
      // then transform it so it could be evaluated using hbase co-processor.
      if ((CmpCommon::getDefault(HBASE_COPROCESSORS) == DF_ON) &&
	  (child(0) && child(0)->getOperatorType() == REL_SCAN))
	{
          Scan * scan = (Scan*)child(0)->castToRelExpr();

	  if ((getCompExprTree()) &&
              (NOT hasOrderBy()) &&
              (! getSelPredTree()) &&
              (! scan->getSelPredTree()) &&
	      (scan->selectionPred().isEmpty()) &&
              ((scan->getTableName().getSpecialType() == ExtendedQualName::NORMAL_TABLE) ||
	       (scan->getTableName().getSpecialType() == ExtendedQualName::INDEX_TABLE)) &&
              !scan->getTableName().isPartitionNameSpecified() &&
              !scan->getTableName().isPartitionRangeSpecified() &&
              (NOT bindWA->inViewDefinition()))
	    {
              ItemExprList selList(bindWA->wHeap());
              selList.insertTree(getCompExprTree());
	      // for now, only count(*) can be co-proc'd
              if ((selList.entries() == 1) &&
                  (selList[0]->getOperatorType() == ITM_COUNT) &&
		  (selList[0]->origOpType() == ITM_COUNT_STAR__ORIGINALLY))
                {
                  CorrName cn(scan->getTableName());
                  NATable *naTable = bindWA->getNATable(cn);
		  if (bindWA->errStatus()) 
		    return this;

		  if (((naTable->getObjectType() == COM_BASE_TABLE_OBJECT) ||
		       (naTable->getObjectType() == COM_INDEX_OBJECT)) &&
		      (((naTable->isSeabaseTable()) &&
                        (NOT naTable->isHbaseMapTable())) ||
                       ((naTable->isHiveTable()) &&
                        (NOT naTable->isView()) &&
                        (naTable->getClusteringIndex()) &&
                        (naTable->getClusteringIndex()->getHHDFSTableStats()->isOrcFile()))))
		    {
		      Aggregate * agg = 
			new(bindWA->wHeap()) Aggregate(ITM_COUNT,
						       new (bindWA->wHeap()) SystemLiteral(1),
						       FALSE /*i.e. not distinct*/,
						       ITM_COUNT_STAR__ORIGINALLY,
						       '!');
		      agg->bindNode(bindWA);
		      if (bindWA->errStatus())
			{	  
			  return this;
			}

		      ValueIdSet aggrSet;
		      aggrSet.insert(agg->getValueId());
		      ExeUtilExpr * eue = NULL;
                      
                      if (naTable->isSeabaseTable())
                        eue = 
                          new(CmpCommon::statementHeap())
                          ExeUtilHbaseCoProcAggr(cn,
                                                 aggrSet);
                      else
                        eue = 
                          new(CmpCommon::statementHeap())
                          ExeUtilOrcFastAggr(cn,
                                             aggrSet);
		      
		      eue->bindNode(bindWA);
		      if (bindWA->errStatus())
			{	  
			  return this;
			}
		      
		      setChild(0, eue);

                      removeCompExprTree();
                      addCompExprTree(agg);

		    } // if seabaseTable
		} // count aggr
	    }
	} // coproc on


      if (child(0) && 
	  ((child(0)->getOperatorType() == REL_INSERT) ||
	   (child(0)->getOperatorType() == REL_UNARY_INSERT) ||
	   (child(0)->getOperatorType() == REL_LEAF_INSERT)))
	{
	  Insert * ins = (Insert*)child(0)->castToRelExpr();
	  if (ins->isNoRollback())
          {
            if ((CmpCommon::getDefault(AQR_WNR) 
                 != DF_OFF) &&
                (CmpCommon::getDefault(AQR_WNR_INSERT_CLEANUP)
                 != DF_OFF))
              ins->enableAqrWnrEmpty() = TRUE;
          }
          if (CmpCommon::transMode()->anyNoRollback())
          {
            // tbd - may need to integrate these two.
            if ((CmpCommon::getDefault(AQR_WNR)
                != DF_OFF) &&
                (CmpCommon::getDefault(AQR_WNR_INSERT_CLEANUP)
                != DF_OFF))
              ins->enableAqrWnrEmpty() = TRUE;
          }
	}
      
      // if lob is being extracted as chunks of string, then only one
      // such expression could be specified in the select list.
      // If this is the case, then insert ExeUtilLobExtract operator.
      // This operator reads lob contents and returns them to caller as
      // multiple rows.
      // This lobextract function could only be used in the outermost select
      // list and must be converted at this point.
      // It is not evaluated on its own.
      if (getCompExprTree())
	{
	  ItemExprList selList(bindWA->wHeap());
	  selList.insertTree(getCompExprTree());
	  if ((selList.entries() == 1) &&
	      (selList[0]->getOperatorType() == ITM_LOBEXTRACT))
	    {
	      LOBextract * lef = (LOBextract*)selList[0];
	      
	      ExeUtilLobExtract * le =
		new (PARSERHEAP()) ExeUtilLobExtract
		(lef, ExeUtilLobExtract::TO_STRING_,
		 0, 0, lef->getTgtSize(), 0,
		 NULL, NULL, NULL, child(0), PARSERHEAP());
	      le->setHandleInStringFormat(FALSE);
	      setChild(0, le);
	    }
	}

      processRownum(bindWA);
      
    } // isTrueRoot

  if (getHasTDFunctions()) 
  {
    transformTDPartitionOrdinals(bindWA);
    if (bindWA->errStatus()) return NULL;
  }

  RelRoot * returnedRoot = 
    transformGroupByWithOrdinalPhase1(bindWA);
  if (! returnedRoot)
    return NULL;

  returnedRoot = 
    transformOrderByWithExpr(bindWA);
  if (! returnedRoot)
    return NULL;

  if (bindWA->getCurrentScope()->context()->inTableCheckConstraint()) {
    // See ANSI 11.9 Leveling Rule 1a (Intermediate Sql).
    // 4089 A check constraint cannot contain a subquery.
    *CmpCommon::diags() << DgSqlCode(-4089)
      << DgConstraintName(
            bindWA->getCurrentScope()->context()->inCheckConstraint()->
            getConstraintName().getQualifiedNameAsAnsiString());
    bindWA->setErrStatus();
  }

  if (isTrueRoot()) 
    bindWA->setTopRoot(this);

  bindWA->setBindTrueRoot(isTrueRoot());

  if (!bindWA->getAssignmentStArea()) {
    bindWA->getAssignmentStArea() =
      new (bindWA->wHeap()) AssignmentStArea(bindWA);
    bindWA->getAssignmentStArea()->getAssignmentStHostVars() =
      new (bindWA->wHeap()) AssignmentStHostVars(bindWA);
  }


  // If there are one or more output rowset variables, then we introduce
  // a RowsetInto node below this Root node. The RowsetInto node will
  // create a Pack node later on when it is binded, so that we can
  // insert values into the rowset output variables.
  // We don't do this transformation if we are inside a compound statement.
  //
  if (isTrueRoot() && assignmentStTree()) {
    ItemExpr *outputVar = getOutputVarTree();
    if (outputVar) {

      CMPASSERT(outputVar->getChild(0)->getOperatorType() == ITM_HOSTVAR);
      HostVar *hostVar = (HostVar *) outputVar->getChild(0);

      if (hostVar->getType()->getTypeQualifier() == NA_ROWSET_TYPE) {

        ItemExpr *outputVar = removeOutputVarTree();
        assignmentStTree() = NULL;

        // Get the output size expression. It may be a constant or a variable.
        ItemExpr * sizeExpr = getHostArraysArea()->outputSize();

        // set the SelectIntoRowsets flag
        getHostArraysArea()->setHasSelectIntoRowsets(TRUE);

        // Create INTO node. Its child is the current root
        RelExpr *intoNode =
          new (bindWA->wHeap()) RowsetInto(this, outputVar, sizeExpr);

        //If case of first N with ORDER BY generator introduces the FIRST N
        //operator.  For rowsets FIRST N node need to be introduced below the
        //PACK node and not below the top root. So set first N rows for INTO
        //node and not the top root.
        if (hasOrderBy()) {
          intoNode->setFirstNRows(getFirstNRows());
          setFirstNRows(-1);
        }

        // Create a new root node that will go above the RowsetInto node
        setRootFlag(FALSE);
        RelRoot *newRoot  = new (bindWA->wHeap()) RelRoot(intoNode);
        newRoot->setRootFlag(TRUE);
        // copy the display flag from this true Root to the new root.
        // newRoot->setDisplayTree(getDisplayTree());
        newRoot->setDisplayTree(TRUE);
        newRoot->addInputVarTree(removeInputVarTree());
        newRoot->outputVarCnt() = outputVarCnt();

        NABoolean defaultSortedRows = newRoot->needFirstSortedRows();
        //Int64 defaultFirstNRows = newRoot->getFirstNRows();
        newRoot->needFirstSortedRows() = needFirstSortedRows();
        //newRoot->setFirstNRows(getFirstNRows());
        needFirstSortedRows() = defaultSortedRows;
        //        setFirstNRows(defaultFirstNRows);

        newRoot->rollbackOnError() = rollbackOnError();

        // migrate hostArraysArea to newroot, and tell bindWA about it
        newRoot->setHostArraysArea(getHostArraysArea());
        bindWA->setHostArraysArea(getHostArraysArea());
        setSubRoot(FALSE);      // old root is no longer the root
        newRoot->setSubRoot(TRUE);   // newRoot becomes the root

        return newRoot->bindNode(bindWA);
      }
    }
  }

  if (assignmentStTree() && child(0)->getOperatorType() != REL_ROWSET_INTO) {
    AssignmentStHostVars *ptr =
      new (bindWA->wHeap()) AssignmentStHostVars(bindWA);

    if (ptr->containsRowsets(assignmentStTree())) {
      ItemExpr *outputSizeExpr = NULL;

      // The user may have used the ROWSET FOR OUTPUT SIZE construct
      // set the SelectIntoRowsets flag.
      if (getHostArraysArea()) {
        outputSizeExpr  = getHostArraysArea()->outputSize();
        getHostArraysArea()->setHasSelectIntoRowsets(TRUE);
      }

      // Create RowsetInto node. Its child is the current root
      RelExpr *intoNode = new (bindWA->wHeap())
                           RowsetInto(this, assignmentStTree(), outputSizeExpr);

      //If case of first N with ORDER BY generator introduces the FIRST N
      //operator.  For rowsets FIRST N node need to be introduced below the
      //PACK node and not below the top root. So set first N rows for INTO
      //node and not the top root.
      if (hasOrderBy()) {
        intoNode->setFirstNRows(getFirstNRows());
        setFirstNRows(-1);
      }

      RelRoot *newRoot  = new (bindWA->wHeap()) RelRoot(*this);

      newRoot->child(0) = intoNode;
      newRoot->removeCompExprTree();
      setRootFlag(FALSE);
      removeInputVarTree();
      assignmentStTree() = NULL;

      return newRoot->bindNode(bindWA);
    }
  }

  // Create a new scope.
  //
  if (!isDontOpenNewScope())  // -- Triggers.
  {
    bindWA->initNewScope();

    // MV --
    if(TRUE == hasMvBindContext())
    {
      // Copy the MvBindContext object from the RelRoot node to the
      // current BindContext.
      bindWA->markScopeWithMvBindContext(getMvBindContext());
    }

    if (getInliningInfo().isTriggerRoot())
    {
      CMPASSERT(getInliningInfo().getTriggerObject() != NULL);
      bindWA->getCurrentScope()->context()->triggerObj() =
        getInliningInfo().getTriggerObject()->getCreateTriggerNode();
    }

    if (getInliningInfo().isActionOfRI())
      bindWA->getCurrentScope()->context()->inRIConstraint() = TRUE;
  }

  // Save whether the user specified SQL/MP-style access options in the query
  // (this is always true for the LOCK stmt, which we must maximize).
  //
  if (child(0)->getOperatorType() == REL_LOCK) {
    accessOptions().updateAccessOptions(
      TransMode::ILtoAT(TransMode::READ_COMMITTED_),
      ((RelLock *)child(0).getPtr())->getLockMode());
    accessOptions().updateAccessOptions(
      TransMode::ILtoAT(CmpCommon::transMode()->getIsolationLevel()));
  }

  // QSTUFF:  the updateOrDelete flag is set to ensure that scans done as 
  // part of a generic update cause an exclusive lock to be set to ensure
  // a consistent completion of the following update or delete.
  if (containsUpdateOrDelete(this))
  {
    accessOptions().setUpdateOrDelete(TRUE);
  }
  else if (isTrueRoot())
  {
    // if the query does not contain any Generic Update nodes, mark it
    // as read only query. In that case, we have freedom not to include
    // some indexes in the indexes list.
    bindWA->setReadOnlyQuery();
  }


  // This block of code used to be in RelRoot::propagateAccessOptions() which
  // used to be called from here. We've since replaced this old 'push' call
  // with the 'pull' of BindWA->findUserSpecifiedAccessOption() calls from
  // RelRoot, Scan, and GenericUpdate.
  // QSTUFF
  // We decided to stick with READ COMMITTED as the default access
  //  (even for streams).  However, if we change our mind again, this is
  //  the place to do it.
  // if (getGroupAttr()->isStream() &&
  //   (accessOptions().accessType() == ACCESS_TYPE_NOT_SPECIFIED_))
  //	  accessOptions().accessType() = SKIP_CONFLICT_;

  // Set the flag to indicate to DP2 that this executes an
  //  embedded update or delete.
  if (getGroupAttr()->isEmbeddedUpdateOrDelete())
    accessOptions().setUpdateOrDelete(TRUE);
  // QSTUFF

  if (accessOptions().userSpecified())
    bindWA->getCurrentScope()->context()->setStmtLevelAccessOptions(accessOptions());

  if (isSubRoot() && getHostArraysArea())
    getHostArraysArea()->setRoot(this);

  if (isTrueRoot()) {

    // If this were false, then SynthType's ValueDesc::create()
    // would use a DIFFERENT SchemaDB than BindItemExpr's createValueDesc()
    // -- wrong!  Assert this only once per query.
    CMPASSERT(ActiveSchemaDB() == bindWA->getSchemaDB());

    // set the upDateCurrentOf_ attribute for the root if possible
    if (child(0)->getOperatorType() == REL_UNARY_UPDATE ||
      child(0)->getOperatorType() == REL_UNARY_DELETE) {
      GenericUpdate *gu = (GenericUpdate *)child(0)->castToRelExpr();
      if (gu->updateCurrentOf()) {
        updateCurrentOf()  = gu->updateCurrentOf();
        currOfCursorName() = gu->currOfCursorName();
      }
    }

    // If we are processing a rowset,
    // then the child operator is a REL_TSJ.
    // If this is the case, and the operation is
    // an update or delete, we need to search
    // further to deterine its correct child
    // operator type. 
    
    // Otherwise, the child operator type is correct.
 
    if (bindWA->getHostArraysArea() && 
        bindWA->getHostArraysArea()->hasHostArraysInWhereClause() && 
        bindWA->getHostArraysArea()->hasInputRowsetsInSelectPredicate() == HostArraysWA::NO_  &&
        NOT bindWA->getHostArraysArea()->hasHostArraysInTuple())
        // ensure that we don't flag rowset selects or insert selects with rowsets in the predicate
    {
      if (bindWA->getHostArraysArea()->hasHostArraysInSetClause())  // includes rowset merge statements too
        childOperType() = REL_UNARY_UPDATE;
      else
        childOperType() = REL_UNARY_DELETE;
    }
    else
      childOperType() = child(0)->getOperator();

    // see if we can potentially optimize the buffer sizes for
    // oltp queries. Done for update/delete/insert-values/select-unique.

    // if scan, olt opt is possible.
    if (childOperType() == REL_SCAN)
      oltOptInfo().setOltOpt(TRUE);

    /*
    // For Denali release 1, compound statements are restricted
    // to yield at most one row; so olt opt is possible for CS.
    // If a compound statement is not pushed down to DP2, then
    // OLT optimization will be turned off in generator.
    //
    //       Turn it off for Compound statement as insertion with tuple list
    //       is possible in a CS.
    */
    else if (childOperType() == REL_COMPOUND_STMT)
      oltOptInfo().setOltOpt(TRUE);

    // if INSERT...VALUES, olt opt is possible.
    else if ((childOperType() == REL_UNARY_INSERT) &&
             (NOT child(0)->child(0) ||
             child(0)->child(0)->getOperatorType() == REL_TUPLE))
      oltOptInfo().setOltOpt(TRUE);

  } // isTrueRoot

  else if (checkFirstNRowsNotAllowed(bindWA)) {
    *CmpCommon::diags() << DgSqlCode(-4102);
    bindWA->setErrStatus();
    return NULL;
  }

  BindScope *currScope = bindWA->getCurrentScope();

  // -- MVs
  // Check for the Refresh node before binding, because after binding it
  // will be gone.
  if (child(0)->getOperatorType() == REL_REFRESH)
    setRootOfInternalRefresh();

  // set the currect host area in bindWA for non-root stmt.
  // fix 10-031106-4430 (RG: mxcmp failed to compile INSERT
  //                         statement with rowsets within IF statement)
  HostArraysWA *tempWA = NULL;
  if ( NOT isTrueRoot() && getHostArraysArea() )
  {
     tempWA = bindWA->getHostArraysArea();
     bindWA->setHostArraysArea(getHostArraysArea());
  }

  bindWA->setBindTrueRoot(FALSE);

  // Bind the children here to determine if we need to rollback on error
  // for embedded update/delete's.
  //
  bindChildren(bindWA);

  if ( tempWA )
  {
    // Restore previous environment
    bindWA->setHostArraysArea(tempWA);
  }

  if (bindWA->errStatus()) 
    return NULL;

  // For SPJ, store the spOutParams_ from the bindWA in RelRoot,
  // We need it at codegen
  if ( bindWA->getSpOutParams ().entries ())
    spOutParams_ = &( bindWA->getSpOutParams ());

  if (isTrueRoot()) {

    if (child(0) && child(0)->getGroupAttr()->isEmbeddedUpdateOrDelete()) {
      // Olt optimization is now supported for embedded updates/deletes (pub/sub
      // thingy) for now.
      oltOptInfo().setOltOpt(TRUE);
      if (getFirstNRows() != -1) {
        // [FIRST/ANY n] syntax cannot be used with an embedded update or embedded delete.
      *CmpCommon::diags() << DgSqlCode(-4216);
      bindWA->setErrStatus();
      return NULL;
      }
    }

    // If updateCurrentOf_ not set yet
    // Check the tree for a GenericUpdate RelExpr (anywhere in the tree)
    // so we can set the root node accordingly.
    GenericUpdate *gu = getGenericUpdate(this);
    if (!updateCurrentOf() && gu && gu->updateCurrentOf()) {
      updateCurrentOf()  = gu->updateCurrentOf();
      currOfCursorName() = gu->currOfCursorName();
    }

    // if standalone update/delete(no update where current of),
    // olt opt is possible.
    if (((childOperType() == REL_UNARY_UPDATE) ||
        (childOperType() == REL_UNARY_DELETE)) &&
        (NOT updateCurrentOf()))
      oltOptInfo().setOltOpt(TRUE);

    // If transaction statement (begin/commit/rollback/set xn,
    // olt opt is possible.
    if (childOperType() == REL_TRANSACTION)
      oltOptInfo().setOltOpt(TRUE);

    // Set indication whether transaction need to be aborted on error
    // during an IUD query.
    // Rollback will be done for a query that contains
    // rowsets, or an insert which is
    // not an 'insert...values' with a single value.
    //
    // There are more cases when a transaction will be rolled back on
    // an IUD error. These are set in GenericUpdate::preCodeGen,
    // and DP2(IUD)::preCodeGen.
    // These include embedded update or delete, stream access, non-unique
    // update or delete... See ::preCodeGen methods for details.
    rollbackOnError() = FALSE;
    if (childOperType().match(REL_ANY_GEN_UPDATE))
      {
        if (bindWA->getHostArraysArea() &&
            bindWA->getHostArraysArea()->done()) // rowsets
          rollbackOnError() = TRUE;
        else if ((childOperType() == REL_UNARY_INSERT) &&
                 (child(0)->child(0) &&
                  child(0)->child(0)->getOperatorType() != REL_TUPLE))
          rollbackOnError() = TRUE;
      }
      if (bindWA->getHostArraysArea() &&
          bindWA->getHostArraysArea()->getTolerateNonFatalError())
      {
        setTolerateNonFatalError(RelExpr::NOT_ATOMIC_);
      }
  }

  CMPASSERT(currScope == bindWA->getCurrentScope());   // sanity check

  // do not do olt qry optimization, if rowsets are present.
  if (bindWA->getHostArraysArea() && bindWA->getHostArraysArea()->done())
    {
      oltOptInfo().setOltOpt(FALSE);

      if (bindWA->getHostArraysArea()->getTolerateNonFatalError()) {
        // we also cannot do  dp2 level olt optimization if this is a non-atomic rowset insert
        oltOptInfo().setOltEidOpt(FALSE);
      }
      else {
        // but can do dp2 level olt optimization if this is "regular" rowset insert
        oltOptInfo().setOltEidOpt(TRUE); 
      }
    }

  // If unresolved aggregate functions have been found in the children of the
  // root node, that would mean that we are referencing aggregates before
  // the groupby operation is performed

  if (checkUnresolvedAggregates(bindWA)) return this;

  // A RelRoot does not have a select list for SQL update, delete, insert
  // statements as well as when the query contains an SQL union. If a
  // select list is absent, assign the select list of its child to it.
  // This will propagate the selection lists of the children of the
  // union up to the root.
  //
  // Detach the item expression tree for the select list and bind it.
  //
  ItemExpr *compExprTree = removeCompExprTree();
  if (NOT compExprTree) {
        // -- for RI and Triggers
    if (isEmptySelectList())
      setRETDesc(new (bindWA->wHeap()) RETDesc(bindWA));
    else {
      if (child(0)) {
        setRETDesc(child(0)->getRETDesc());
        getRETDesc()->getValueIdList(compExpr());
      }
    }
  }
  else {
    CMPASSERT(!currScope->context()->inSelectList());
    currScope->context()->inSelectList() = TRUE;

    // QSTUFF
    // in case we are binding an embedded generic update within a view
    // we have to rename column references using OLD or NEW as
    // table names since we adopted the RETDesc/TableDesc of the
    // scan node or the view scan node, i.e. the RenameTable node
    // at the root of an expanded view.

    if (bindWA->renameToScanTable()){

      ColReference * cr = NULL;
      ItemExpr * itm = compExprTree;
      NABoolean done = FALSE;

      const CorrName corr =
        (getViewScanNode()->getOperatorType() == REL_RENAME_TABLE) ?
        ((RenameTable *)getViewScanNode())->getTableName() :
      ((Scan *)getViewScanNode())->getTableDesc()->getCorrNameObj();

      while (NOT done){

        if (itm->getOperatorType() == ITM_ITEM_LIST){
          cr = (ColReference *) itm->getChild(0);
          itm = itm->getChild(1)->castToItemExpr();
          }
        else {
          cr = (ColReference *) itm;
          done = TRUE;
          }

        cr->getCorrNameObj().getQualifiedNameObj().
          setObjectName(corr.getQualifiedNameObj().getObjectName());

        }
      }
    // QSTUFF

    RelRoot *viewQueryRoot = NULL;
    StmtDDLCreateView *pCreateView = NULL;
    if (bindWA->inViewDefinition()) {
      pCreateView = bindWA->getCreateViewParseNode();
      if (pCreateView->getQueryExpression() == this) {
        viewQueryRoot = this;
        CMPASSERT(isTrueRoot());
        pCreateView->setCurViewColNum((CollIndex)0);
      }
    }

    // charset inference
    compExprTree->setResolveIncompleteTypeStatus(TRUE);

    HostArraysWA * arrayWA = bindWA->getHostArraysArea() ;
    if (arrayWA && arrayWA->hasHostArraysInTuple()) {
      CollIndex counterRowVals = 0;
      CMPASSERT(!bindWA->getCurrentScope()->context()->counterForRowValues());
      bindWA->getCurrentScope()->context()->counterForRowValues() = &counterRowVals;
      
      // If this query (scope) contains OLAP Window functions, then add
      // a Sequence Operator just below the Root node.  Also, if aggregates
      // exist, resolve them now.
      //
      setRETDesc(bindRowValues(bindWA, compExprTree, compExpr(), this, isTrueRoot()));
      bindWA->getCurrentScope()->context()->counterForRowValues() = NULL;
    }
    else {
      setRETDesc(bindRowValues(bindWA, compExprTree, compExpr(), viewQueryRoot, isTrueRoot()));
    }
    if (bindWA->errStatus()) return NULL;

    if (viewQueryRoot) pCreateView->resetCurViewColNum();

    currScope->context()->inSelectList() = FALSE;
  }

  // MVs --
  if (bindWA->isPropagateOpAndSyskeyColumns()        &&
      child(0)->getOperatorType()!=REL_GROUPBY       &&
      child(0)->getOperatorType()!=REL_AGGREGATE     &&
      currScope->getUnresolvedAggregates().isEmpty() &&
      !isEmptySelectList()                           &&
      !isTrueRoot())
    getRETDesc()->propagateOpAndSyskeyColumns(bindWA, TRUE);

  CMPASSERT(currScope == bindWA->getCurrentScope());   // sanity check
  currScope->setRETDesc(getRETDesc());
  bindWA->setRenameToScanTable(FALSE);         // QSTUFF

  // Genesis 10-980106-2038 + 10-990202-1098.
  //
  if (isTrueRoot()) {
    castComputedColumnsToAnsiTypes(bindWA, getRETDesc(), compExpr());
    if (bindWA->errStatus()) return NULL;
  }

  // Genesis 10-970822-2581.  See finalize() in SqlParser.y.
  //
  // If we are in a compound statement (an IF's UNION), do not issue an error.
  //
  // Added condition for CALL StoredProcedures
  // If we invoke a CALL statement, the #out params do not match the
  // # columns, we make that check in the CallSP::bindNode, so ignore it
  // for now.
  if (isTrueRoot() &&
      (child(0)) &&
      (child(0)->getOperatorType() != REL_CALLSP &&
      (child(0)->getOperatorType() != REL_COMPOUND_STMT &&
      (child(0)->getOperatorType() != REL_TUPLE &&
       (Int32)getRETDesc()->getDegree() != 0))) &&
     (child(0)->getOperatorType() != REL_UNION ||
     (!((Union *) (RelExpr *) child(0))->getUnionForIF())) &&
      outputVarCntValid() &&
      outputVarCnt() != (Int32)getRETDesc()->getDegree() &&
     (outputVarCnt() ||
      CmpCommon::context()->GetMode() != STMT_DYNAMIC)) {
      // 4093 The number of output parameters ($0) must equal the number of cols
      // 4094 The number of output host vars  ($0) must equal the number of cols
      Lng32 sqlcode = (CmpCommon::context()->GetMode() == STMT_DYNAMIC) ?
      -4093 : -4094;
      *CmpCommon::diags() << DgSqlCode(sqlcode)
      << DgInt0(outputVarCnt()) << DgInt1(getRETDesc()->getDegree());
      bindWA->setErrStatus();
      return NULL;
    }

  ItemExpr *inputVarTree = removeInputVarTree();
  if (inputVarTree) {
    inputVarTree->convertToValueIdList(inputVars(), bindWA, ITM_ITEM_LIST);
    if (bindWA->errStatus()) return NULL;

    // If DYNAMIC SQL compilation, then
    // remove from the input var list (list of HostVars and DynamicParams)
    // any env vars that were found to have a equivalence value which is
    // valid (parseable) for the context it appears in
    // (i.e., we've already bound the env var name's dynamic value,
    // so we no longer need the env var name at all).
    // Right now, this means that in sqlci you can say
    //	 set envvar xyz cat.sch.tbl;
    //	 select * from $xyz;
    //
    if (CmpCommon::context()->GetMode() == STMT_DYNAMIC) {
      for (CollIndex i = inputVars().entries(); i--; ) {
        HostVar *hostVar = (HostVar *)inputVars()[i].getItemExpr();
        if (hostVar->getOperatorType() == ITM_HOSTVAR &&
            hostVar->isPrototypeValid() &&
            (hostVar->isEnvVar() ||
             hostVar->isDefine()))
          inputVars().removeAt(i);
      }
    } // STMT_DYNAMIC
  } // inputVarTree

  // add to the inputVars, any user functions that are to be treated
  // like input values, that is, evaluated once and used therafter.
  // Do not insert duplicate value ids.
  for (CollIndex i = 0; i < bindWA->inputFunction().entries(); i++ ) {
    if (NOT inputVars().contains(bindWA->inputFunction()[i]))
      inputVars().insert(bindWA->inputFunction()[i]);
  }

  // If aggregate functions have been found in the select list, then
  // create a groupby node with an empty groupby list, if the child is not
  // already a groupby node.
  //
  resolveAggregates(bindWA);
  if (bindWA->errStatus()) return NULL;

  // Add the unresolvedSequenceFunctions to the Sequence node for this
  // scope.  If there are sequence functions, but no sequence node, it
  // is an error.  Also if there is a sequence node, but no sequence
  // functions, it is an error.
  // If OLAP Window functions exist for this scope, they will have been
  // translated into sequence functions by this point and so will be added
  // to the Sequence node here.
  //
  resolveSequenceFunctions(bindWA);
  if (bindWA->errStatus()) return NULL;

  BindScope *prevScope   = bindWA->getPreviousScope(currScope);
  NABoolean inRowSubquery   = FALSE;
  if (prevScope)
    inRowSubquery = prevScope->context()->inRowSubquery();

  NABoolean groupByAggNodeAdded = FALSE;
  if (inRowSubquery && (CmpCommon::getDefault(COMP_BOOL_137) == DF_OFF))
    // force adding one row aggregates in the [last 0] case
    groupByAggNodeAdded = addOneRowAggregates(bindWA, 
                            getFirstNRows() == -2 /* [last 0] case */);

  returnedRoot = 
    transformGroupByWithOrdinalPhase2(bindWA);
  if (! returnedRoot)
    return NULL;

  ItemExpr *orderByTree = removeOrderByTree();
  if (orderByTree) {
    //
    // Tandem extension to ANSI (done only if source table is not grouped!):
    // Allow the ORDER BY clause to reference columns in the source table even
    // if the columns are not referenced in the select list.  Treat the extra
    // columns as *system* columns so that they can be referenced by name
    // (ORDER BY name) but not by position in select list (ORDER BY n).
    // Thus, select-list columns have precedence, as they should since ANSI
    // allows only them in ORDER BY to begin with!
    //
    // Add all source columns to system column list of temporary orderBy;
    // remove select-list columns from this system column list;
    // insert select-list columns into the *user* column list
    // (these must be in separate loops to set up the orderBy XCNM correctly!).
    // Then bind the temporary (convert to ValueId list), reset the RETDesc.
    //
    bindWA->getCurrentScope()->context()->inOrderBy() = TRUE;
    CollIndex i;
    RETDesc orderBy;
    const RETDesc &select = *getRETDesc();
    const RETDesc &source = *child(0)->getRETDesc();

    // if the source is grouped, then the ORDER BY columns must be in
    // the select list.  So, don't add any other columns that aren't
    // in the select list...
    if (source.isGrouped()) {
      orderBy.setGroupedFlag();
      //10-031125-1549 -begin
      //Since we are processing a groupby we should
      //certainly have some node below it. Futher if
      //that node is a REL_ROOT we will certainly have
      //a child. So this rather unusual call sequence
      //is safe. We are actually looking for a Pattern
      //like REL_GROUPBY(REL_ROOT(*)) introduced to handle
      //Distint qualifier.
      //for example if we have a query like
      //select distinct j as jcol from t1 order by j;
      //the tree will look like
      //REL_ROOT(REL_GROUPBY(REL_ROOT(REL_SCAN(t1))))
      //In this is a NON-ANSI query. To support queries like this
      //we need to expose "J" as a system column. To do that we need
      //to get hold of the RetDesc of the node below the REL_ROOT
      //(not the actual REL_ROOT).
      RETDesc *src = NULL;
      if(child(0)->child(0)&&
         child(0)->child(0)->getOperatorType() == REL_ROOT)
      {
         src = child(0)->child(0)->child(0)->getRETDesc();
      }
      else
      {
        src = child(0)->getRETDesc();
      }

      const ColumnDescList &sysColList = *src->getSystemColumnList();
      const ColumnDescList &usrColList = *src->getColumnList();
      ValueId vid;

      for(i = 0; i < select.getDegree(); i++) {
        vid = select.getValueId(i);
        for(CollIndex j = 0; j < sysColList.entries(); j++){
          if( vid == sysColList[j]->getValueId()){
               orderBy.addColumn(bindWA, sysColList[j]->getColRefNameObj()
                                 , sysColList[j]->getValueId()
                                 , SYSTEM_COLUMN);
          }
        }
        for(CollIndex k = 0; k < usrColList.entries(); k++){
          if(vid ==  usrColList[k]->getValueId()){
               orderBy.addColumn(bindWA, usrColList[k]->getColRefNameObj()
                                 , usrColList[k]->getValueId()
                                 , SYSTEM_COLUMN);
              }
        }
      }
      //10-031125-1549 -end

      NABoolean specialMode = TRUE;
      

      // In specialMode, we want to support order by on columns
      // which are not explicitely specified in the select list.
      // Ex: select a+1 from t group by a order by a;
      // Find all the column references in the orderByTree which are
      // also in the group by list but are not explicitely specified
      // in the select list.
      // This code path is for cases when both GROUP BY and ORDER BY are
      // specified.
      // If order by is specified without the group by, then that case
      // is already covered in the 'else' portion.
      if ((specialMode) &&
          (child(0)->getOperatorType() == REL_GROUPBY) &&
          (allOrderByRefsInGby_)) // already validated that all order by cols
                                  // are also in group by clause
        {
          ItemExprList orderByList(orderByTree, bindWA->wHeap());
          GroupByAgg * grby=(GroupByAgg *)(child(0)->castToRelExpr());
          for (CollIndex ii = 0; ii < orderByList.entries(); ii++)
            {
              ItemExpr * colRef = orderByList[ii];
              if (colRef->getOperatorType() == ITM_INVERSE)
                colRef = colRef->child(0)->castToItemExpr();
              if (colRef && colRef->getOperatorType() == ITM_REFERENCE)
                {
                  ColReference * obyColRef = (ColReference*)colRef;

                  for (CollIndex k = 0; k < usrColList.entries(); k++)
                    {
                      if (obyColRef->getColRefNameObj().getColName() ==
                          usrColList[k]->getColRefNameObj().getColName())
                        {
                          orderBy.delColumn(bindWA,
                                            usrColList[k]->getColRefNameObj(),
                                            SYSTEM_COLUMN);

                          orderBy.addColumn(bindWA, 
                                            usrColList[k]->getColRefNameObj(),
                                            usrColList[k]->getValueId(),
                                            SYSTEM_COLUMN);
                          break;
                        } // if
                    } // for
                  
                } // if
            } // for
        }
      
      for (i = 0; i < select.getDegree(); i++)
        orderBy.delColumn(bindWA, select.getColRefNameObj(i), SYSTEM_COLUMN);
    }
    else {
      // add the potential ORDER BY columns... omitting the ones that will
      // in the select list anyway.
      orderBy.addColumns(bindWA, *source.getColumnList(),       SYSTEM_COLUMN);
      orderBy.addColumns(bindWA, *source.getSystemColumnList(), SYSTEM_COLUMN);

      for (i = 0; i < select.getDegree(); i++)
        orderBy.delColumn(bindWA, select.getColRefNameObj(i),   SYSTEM_COLUMN);
    }

    for (i = 0; i < select.getDegree(); i++)
      orderBy.addColumn(bindWA, select.getColRefNameObj(i),
                                select.getValueId(i),           USER_COLUMN);

    bindWA->getCurrentScope()->setRETDesc(&orderBy);

    // fix for defect 10-010522-2978
    // If we need to move this OrderBy to the RelRoot above this one...
    //   move it to the rowsetReqdOrder_ of that RelRoot, otherwise keep
    //   it at this level... in the current RelRoot's reqdOrder_

    ValueIdList & pRRO = getParentForRowsetReqdOrder() ?
                         getParentForRowsetReqdOrder()->rowsetReqdOrder_ :
                         reqdOrder();

      // Replace any selIndexies in the orderByTree with what it refers to
      // before we expand it.
      // This is done so that we can deal with subqueries with degree > 1
      // and MVFs.

    ItemExpr *sPtr = orderByTree, *ePtr = orderByTree;
    
    Int32 childIdx = 0;
    NABoolean onlyOneEntry(TRUE);

    CollIndex selListCount = compExpr().entries();

    while (sPtr != NULL) 
    {
      
      if (sPtr->getOperatorType() == ITM_ITEM_LIST)
      {
        ePtr = sPtr;
        sPtr = ePtr->child(0);
        childIdx = 0;
        onlyOneEntry = FALSE;
      }
      if (sPtr->getOperatorType() == ITM_SEL_INDEX)
      {
        SelIndex * si = (SelIndex*)(sPtr);

        CollIndex selIndex = si->getSelIndex();
        if(selIndex == 0 || selIndex > selListCount)
        {
          *CmpCommon::diags() << DgSqlCode(-4007) 
                              << DgInt0((Lng32)si->getSelIndex()) 
                              << DgInt1(selListCount);
           bindWA->setErrStatus();
           return NULL;
        }

        ValueId orderById = compExpr()[si->getSelIndex()-1];
        if (ePtr->getOperatorType() == ITM_ITEM_LIST)
          ePtr->child(childIdx) = orderById.getItemExpr();
        else
          ePtr = orderById.getItemExpr();

        orderById.getItemExpr()->setInOrderByOrdinal(TRUE);
      }
      if ((ePtr->getArity() == 2) && ePtr->child(1) != NULL && 
          ePtr->child(1)->getOperatorType() != ITM_ITEM_LIST &&
          childIdx != 1)
        childIdx = 1;
      else
        childIdx = 0;
      sPtr = (childIdx == 1) ? ePtr->child(1) : NULL;
    }

    if (onlyOneEntry)
      orderByTree =  ePtr;

      // If we had any ordinal expressions expand them in case there
      // are any UDFs or subquery of degree > 1.
      // Also expand any directly referenced UDFs and subqueries of degree > 1.
    ItemExprList origOrderByList(orderByTree, bindWA->wHeap());

    origOrderByList.convertToItemExpr()->
      convertToValueIdList(pRRO, bindWA, ITM_ITEM_LIST);
    
    // end fix for defect 10-010522-2978

    if (bindWA->errStatus()) 
      return NULL;

    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    bindWA->getCurrentScope()->context()->inOrderBy() = FALSE;
  }

  // validate that select list doesn't contain any expressions that cannot be
  // grouped or ordered.
  for (Lng32 selIndex = 0; selIndex < compExpr().entries(); selIndex++)
    {
      ItemExpr * ie = compExpr()[selIndex].getItemExpr();
      if ((ie->inGroupByOrdinal()) || (ie->inOrderByOrdinal()))
        {
          if (NOT ie->canBeUsedInGBorOB(TRUE))
            {
              return NULL;
            }
        }
    }

  if (hasPartitionBy())
  {
    ItemExpr *partByTree = removePartitionByTree();
    partByTree->convertToValueIdSet(partArrangement_, bindWA, ITM_ITEM_LIST);
    if (bindWA->errStatus()) return NULL;
  }

  // fix for defect 10-010522-2978
  // If we're the upper level RelRoot, we must check to see if we have
  // any entries that need to be added to reqdOrder() and add them if
  // there are any...

  if ( rowsetReqdOrder_.entries() ) {
     // We never expect for reqdOrder to contain any entries.  But
     // if it ever does, we want to be able to take a look at this
     // code again to decide whether we should be appending to the
     // reqdOrder list.  Currently the code is written to append to
     // the end of the reqdOrder list, which is likely to be the correct
     // behavior even if there are entries in reqdOrder; we just think
     // that someone should have the chance to rethink this in the event
     // there are entries in reqdOrder and so we're making it fail here
     // to allow/force someone to make the decision.
     CMPASSERT(reqdOrder().entries() == 0);

     // note: NAList<ValueIdList>::insert(const NAList<ValueIdList> &)
     //       actually does an append to the END of the list (not an
     //       insert at the head or after the current position).
     reqdOrder().insert( rowsetReqdOrder_ );
  }

  // end fix for defect 10-010522-2978

  // Bind the update column specification of a cursor declaration.
  // Don't remove the tree: leave it for possible error 4118 in NormRelExpr.
  if (updateColTree_) {
    updateColTree_->convertToValueIdList(updateCol(), bindWA, ITM_ITEM_LIST);
    if (bindWA->errStatus()) {
      if (CmpCommon::diags()->contains(-4001))
        *CmpCommon::diags() << DgSqlCode(-4117);
      return NULL;
    }

    if (getGroupAttr()->isEmbeddedDelete()) {   // QSTUFF
      *CmpCommon::diags() << DgSqlCode(-4169);
      bindWA->setErrStatus() ;
      return NULL;
    }
  }


  // check whether a CONTROL QUERY SHAPE statement is in effect.
  // Do not do if this is a control query statement.
  if (ActiveControlDB()->getRequiredShape()) {
    OperatorTypeEnum op = child(0)->getOperatorType();
    if (!child(0)->isAControlStatement() &&
        op != REL_DESCRIBE &&
        op != REL_EXPLAIN &&
        op != REL_DDL &&
        op != REL_LOCK &&
        op != REL_UNLOCK &&
        op != REL_SET_TIMEOUT &&  
        op != REL_STATISTICS &&
        op != REL_TRANSACTION &&
        op != REL_EXE_UTIL)
      reqdShape_ = ActiveControlDB()->getRequiredShape()->getShape();
  }

  // If this is a parallel extract producer query:
  // * the number of requested streams must be greater than one and
  //   not more than the number of configured CPUs
  // * force a shape with an ESP exchange node immediately below
  //   the root
  ComUInt32 numExtractStreams = getNumExtractStreams();
  if (numExtractStreams_ > 0)
  {
    // Check the number of requested streams
    NADefaults &defs = bindWA->getSchemaDB()->getDefaults();

    NABoolean fakeEnv = FALSE;
    ComUInt32 numConfiguredESPs = defs.getTotalNumOfESPsInCluster(fakeEnv);
    
    if ((numExtractStreams == 1) || (numExtractStreams > numConfiguredESPs))
    {
      *CmpCommon::diags() << DgSqlCode(-4119)
                          << DgInt0((Lng32) numConfiguredESPs);
      bindWA->setErrStatus();
      return NULL;
    }

    // Force the shape. There are three cases to consider:
    // a. there is no required shape in the ControlDB
    // b. there is a required shape and it is acceptable for this
    //    parallel extract.
    // c. there is a required shape and it is not acceptable.

    if (reqdShape_ == NULL)
    {
      // Case a.
      // Manufacture an esp_exchange(cut,N) shape
      reqdShape_ = new (bindWA->wHeap())
        ExchangeForceWildCard(new (bindWA->wHeap()) CutOp(0),
                              ExchangeForceWildCard::FORCED_ESP_EXCHANGE,
                              ExchangeForceWildCard::ANY_LOGPART,
                              (Lng32) numExtractStreams_);
    }
    else
    {
      NABoolean reqdShapeIsOK = FALSE;
      if (reqdShape_->getOperatorType() == REL_FORCE_EXCHANGE)
      {
        ExchangeForceWildCard *exch = (ExchangeForceWildCard *) reqdShape_;
        ExchangeForceWildCard::forcedExchEnum whichType = exch->getWhich();
        Lng32 howMany = exch->getHowMany();
        if (whichType == ExchangeForceWildCard::FORCED_ESP_EXCHANGE &&
            howMany == (Lng32) numExtractStreams_)
        {
          reqdShapeIsOK = TRUE;
        }
      }

      if (reqdShapeIsOK)
      {
        // Case b.
        // Do nothing
      }
      else
      {
        // Case c.
        // Add an esp_exchange to the top of the required shape
        RelExpr *child = reqdShape_;
        reqdShape_ = new (bindWA->wHeap())
          ExchangeForceWildCard(child,
                                ExchangeForceWildCard::FORCED_ESP_EXCHANGE,
                                ExchangeForceWildCard::ANY_LOGPART,
                                (Lng32) numExtractStreams_);
      }

    } // if (reqdShape_ == NULL) else ...
  } // if (numExtractStreams_ > 0)

  // Bind the base class.
  //
  RelExpr *boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus()) return boundExpr;

  // If we have dynamic rowsets, we want to replace
  // dynamic parameters with available inputs.
  if (isTrueRoot() && bindWA->hasDynamicRowsetsInQuery()) {
    ValueIdSet inputs = getGroupAttr()->getCharacteristicInputs();
    UInt32 j = 0;
    // this for loop is over the list of available inputs. We are replacing array
    // parameters with hostvars introduced during HostArraysWA::processArrayHostVar
    // The hostvars introduced in that method are contained in the inputs() list.
    for (ValueId id = inputs.init(); inputs.next(id); inputs.advance(id)) {
      if (id.getItemExpr()->getOperatorType() == ITM_DYN_PARAM) {
        continue;
      }
      // We are assuming here that the hostvars introduced are in the same order as
      // the parameter arrays in inputVars(), i.e. (hv_A, hv_B) corresponds to
      // (?,?,?(as A), ?(as B))
      while (j < inputVars().entries()) {
        ItemExpr *ie = inputVars()[j].getItemExpr() ;
        OperatorTypeEnum ieType = ie->getOperatorType() ;
        if (( ieType != ITM_DYN_PARAM) ||
            (((DynamicParam *) ie)->getRowsetSize() == 0))
             {
          // if an ie is not a dynamicParam or it is a scalar dynamic Param do not remove
          // it from inputVars_. From embedded SQL it is possible to have scalar and array
          // dynamic params in the same statement. This is not possible from ODBC.
               j++;
             }
        else
          break ;
      }
      if (j < inputVars().entries()) {
        inputVars().removeAt(j);
        inputVars().insertAt(j, id);
        j++;
      }
    }
  }

  // RelRoot::codeGen() and Statement::execute() use TOPMOST root's accessOpts.
  //
  if (bindWA->getCurrentScope()->context()->stmtLevelAccessOptions())
    if (!accessOptions().userSpecified()) // seems redundant
      accessOptions() = *bindWA->getCurrentScope()->context()->stmtLevelAccessOptions();

  // Update operations currently require SERIALIZABLE (== MP REPEATABLE_)
  // locking level -- the QSTUFF-enabled DP2 now does this, supporting a true
  // READ_COMMITTED that is STABLE rather than merely CLEAN.
  if (!containsGenericUpdate(this)) {
    // Genesis 10-990114-6293:
    // This flag tells RelRoot::codeGen to set a flagbit in the root-tdb which
    // cli/Statement::execute + compareTransModes() will look at --
    //   if set, then this "read-write" stmt will be allowed to execute
    //   in a run-time transmode of read-only W/O HAVING TO BE RECOMPILED.
    readOnlyTransIsOK() = TRUE;
  }

  if (isTrueRoot()) {
    if (updateCurrentOf()) {
      // add child genericupdate's primary key hostvars to pkeyList.
      // The getLeftmostScanNode() method will return the leftmost Scan node
      // as the original scan node may have moved due to the IM tree.
      pkeyList().insert(child(0)->castToRelExpr()->getLeftmostScanNode()->pkeyHvarList());
    }

    for(Int32 st=0; st < (Int32)bindWA->getStoiList().entries(); st++)
    {
      if(bindWA->getStoiList()[st]->getStoi()->isView())
        viewStoiList_.insert(bindWA->getStoiList()[st]);
    }

    if(bindWA->inDDL())
      ddlStoiList_.insert(bindWA->getStoiList());

    // populate the list of all the routines open information of this query
    stoiUdrList_.insert(bindWA->getUdrStoiList());

    // populate the list of all the UDF information of this query
    udfList_.insert(bindWA->getUDFList());

    // check privileges
    if (!checkPrivileges(bindWA))
    {
      bindWA->setErrStatus();
      return NULL;
    }

    // store the trigger's list in the root
    if (bindWA->getTriggersList())
    {
      triggersList_ =
        new (bindWA->wHeap()) LIST(ComTimestamp)
                (bindWA->wHeap(), bindWA->getTriggersList()->entries());
      triggersList_->insert(*(bindWA->getTriggersList()));

      // Don't allow OLT optimization when triggers are involved.
      oltOptInfo().setOltOpt(FALSE);
    }


    // store the uninitialized mv list if there are any
    // entries    
    if( bindWA->getUninitializedMvList() )
    {    
        uninitializedMvList_ = new (bindWA->wHeap()) UninitializedMvNameList 
            (bindWA->wHeap(), bindWA->getUninitializedMvList()->entries());
        uninitializedMvList_->insert( *(bindWA->getUninitializedMvList()) );             
    } 
    
    
    DBG( if (getenv("TVUSG_DEBUG")) bindWA->tableViewUsageList().display(); )
  } // isTrueRoot

  // Don't allow OLT optimization when ON STATEMENT MV refresh is involved.
  if (bindWA->isBindingOnStatementMv())
    oltOptInfo().setOltOpt(FALSE);

  // disable esp parallelism for merge statements.
  // See class RelRoot for details about this.
  if ((isTrueRoot()) &&
      (bindWA->isMergeStatement()))
    {
      setDisableESPParallelism(TRUE);
    }

  // Remove the current scope.
  //
  if (!isDontOpenNewScope())  // -- Triggers
    bindWA->removeCurrentScope();

  // In case we have a query of the form
  //	SET <host var list> = <select statement>
  // we must update the value ids of the host variables in that list.
  // See Assignment Statement Internal Spec (a project of Compound Statements).
  if (assignmentStTree() &&
      bindWA->getAssignmentStArea() &&
      bindWA->getAssignmentStArea()->getAssignmentStHostVars() &&
     !bindWA->getAssignmentStArea()->getAssignmentStHostVars()->
                              updateValueIds(compExpr(), assignmentStTree())) {
    bindWA->setErrStatus();
    return NULL;
  }

  if (getPredExprTree())
    {
      CMPASSERT(isTrueRoot());

      ItemExpr * ie = removePredExprTree();
      ie = ie->bindNode(bindWA);
      if (bindWA->errStatus())
        return NULL;
      
      addPredExprTree(ie);
    }

  if (getFirstNRowsParam())
    {
      firstNRowsParam_ = firstNRowsParam_->bindNode(bindWA);
      if (bindWA->errStatus())
        return this;

      const SQLInt si(FALSE, FALSE);
      ValueId vid = firstNRowsParam_->castToItemExpr()->getValueId();
      vid.coerceType(si, NA_NUMERIC_TYPE);

      if (vid.getType().getTypeQualifier() != NA_NUMERIC_TYPE)
        {
          // 4045 must be numeric.
          *CmpCommon::diags() << DgSqlCode(-4045) << DgString0(getTextUpper());
          bindWA->setErrStatus();
          return this;
        }
    }

  if ((getFirstNRows() != -1) ||
       (getFirstNRowsParam()))
    {
      // [first/any/last N] processing

      RelExpr * nodeToInsertUnder = this;
      if (inRowSubquery)
        {
          // [first/any/last N] in a row subquery special case
          //
          // In this case, if N > 1 it is first/any N, and we can simply
          // ignore that as row subqueries already enforce an at-most-one
          // row semantic. For [first 1], [last 1], [last 0], we need to
          // add the node below any one-row aggregate group by node created
          // earlier in this method. (If it put it above that group by node,
          // that is too late; the one-row aggregate will raise an 8401 error
          // before our FirstN node has a chance to narrow the result down to
          // zero or one rows.) There is an interesting nuance with [last 0]:
          // We forced the addition of a one-row aggregate group by node
          // in that case, because [last 0] returns no rows. We might have
          // a scalar aggregate subquery which ordinarily would not require
          // a one-row aggregate group, but when [last 0] is present we want
          // to force the aggregates to become NULL. Adding a one-row 
          // aggregate group on top of the scalar aggregate, with the FirstN
          // node in between them does the trick.
          if (groupByAggNodeAdded &&
               ( (getFirstNRows() == 1) ||   // [first 1] or [any 1]
                 (getFirstNRows() == -2) ||  // [last 0]
                 (getFirstNRows() == -3) ) ) // [last 1]
            {
              nodeToInsertUnder = child(0);
              CMPASSERT(nodeToInsertUnder->getOperatorType() == REL_GROUPBY);             
            }
          else if (!groupByAggNodeAdded && (getFirstNRows() == -2))  // [last 0]
            {
              CMPASSERT(groupByAggNodeAdded);  // a GroupByAgg should have been forced
            }
          else  // a case where we can throw the [first/any/last N] away
            {
              nodeToInsertUnder = NULL;
            }
        }
          
      if (nodeToInsertUnder)
        {
          // create a firstN node to retrieve firstN rows.
          FirstN * firstn = new(bindWA->wHeap())
            FirstN(nodeToInsertUnder->child(0), getFirstNRows(), needFirstSortedRows(), getFirstNRowsParam());   

          firstn->bindNode(bindWA);
          if (bindWA->errStatus())
            return NULL;

          // Note: For ORDER BY + [first n], we want to sort the rows before 
          // picking just n of them. (We don't do this for [any n].) We might
          // be tempted to copy the orderByTree into the FirstN node at this
          // point, but this doesn't work. Instead, we copy the bound ValueIds
          // at normalize time. We have to do this in case there are expressions
          // involved in the ORDER BY and there is a DESC. The presence of the
          // Inverse node at the top of the expression tree seems to cause the
          // expressions underneath to be bound to different ValueIds, which 
          // causes coverage tests in FirstN::createContextForAChild requirements
          // generation to fail. An example of where this occurs is:
          //
          // prepare s1 from
          //   select [first 2] y, x from
          //    (select a,b + 26 from t1) as t(x,y)
          //   order by y desc;
          //
          // If we copy the ORDER BY ItemExpr tree and rebind, we get a different
          // ValueId for the expression b + 26 in the child characteristic outputs
          // than what we get for the child of Inverse in Inverse(B + 26). The
          // trick of copying the already-bound ORDER BY clause later avoids this.

          nodeToInsertUnder->setChild(0, firstn);
        }

      // reset firstN indication in the root node.
      setFirstNRows(-1);
      setFirstNRowsParam(NULL);
    }

  // if we have no user-specified access options then
  // get it from nearest enclosing scope that has one (if any)
  if (!accessOptions().userSpecified()) {
    StmtLevelAccessOptions *axOpts = bindWA->findUserSpecifiedAccessOption();
    if (axOpts) {
      accessOptions() = *axOpts;
    }
  }

  if (bindWA->getHoldableType() == SQLCLIDEV_ANSI_HOLDABLE)
  {
    if (accessOptions().accessType() != TransMode::ACCESS_TYPE_NOT_SPECIFIED_)
    {
      if (accessOptions().accessType() == TransMode::REPEATABLE_READ_ACCESS_)
      {
        *CmpCommon::diags() << DgSqlCode(-4381);
        bindWA->setErrStatus();
        return NULL;
      }
    }
    else
    {
      TransMode::IsolationLevel il=CmpCommon::transMode()->getIsolationLevel();
      if (CmpCommon::transMode()->ILtoAT(il) == TransMode::REPEATABLE_READ_ACCESS_)
      {
        *CmpCommon::diags() << DgSqlCode(-4381);
        bindWA->setErrStatus();
        return NULL;
      }
    }
  }

  // The above code is in Scan::bindNode also.
  // It would be nice to refactor this common code; someday.
             
  return boundExpr;
} // RelRoot::bindNode()

// Present the select list as a tree of Item Expressions
ItemExpr *RelRoot::selectList()
{
  return compExpr().rebuildExprTree(ITM_ITEM_LIST);
} // RelRoot::selectList()

// Returns current place that assignmentStTree_ points to and
// sets that pointer to NULL
ItemExpr * RelRoot::removeAssignmentStTree()
{
  ItemExpr* tempTree = assignmentStTree_;
  assignmentStTree_ = NULL;
  return tempTree;
}

bool OptSqlTableOpenInfo::checkColPriv(const PrivType privType,
                                       const PrivMgrUserPrivs *pPrivInfo)
{
  CMPASSERT (pPrivInfo);

  NATable* table = getTable();
  NAString columns = "";

  if (!isColumnPrivType(privType))
  {
    *CmpCommon::diags() << DgSqlCode(-4481)
                        << DgString0(PrivMgrUserPrivs::convertPrivTypeToLiteral(privType).c_str())
                        << DgString1(table->getTableName().getQualifiedNameAsAnsiString())
                        << DgString2(columns);
    return false;  
  }

  bool hasPriv = true;

  // initialize to something, gets set appropriately below
  LIST (Lng32) * colList = NULL ;
  switch (privType)
  {
    case INSERT_PRIV:
    {
      colList = (LIST (Lng32) *)&(getInsertColList());
      break;
    }
    case UPDATE_PRIV:
    {
      colList = (LIST (Lng32) *)&(getUpdateColList());
      break;
    }
    case SELECT_PRIV:
    {
      colList = (LIST (Lng32) *)&(getSelectColList());
      break;
    }
    default:
      CMPASSERT(FALSE); // delete has no column privileges.
  }

  bool collectColumnNames = false;
  if (pPrivInfo->hasAnyColPriv(privType))
  {
    collectColumnNames = true;
    columns += "(columns:" ; 
  }
  bool firstColumn = true;
  for(size_t i = 0; i < colList->entries(); i++)
  {
    size_t columnNumber = (*colList)[i];
    if (!(pPrivInfo->hasColPriv(privType,columnNumber)))
    {
      hasPriv = false;
      if (firstColumn && collectColumnNames)
      {
        columns += " ";
        firstColumn = false;
      }
      else 
        if (collectColumnNames)
          columns += ", ";

      if (collectColumnNames)
        columns += table->getNAColumnArray()[columnNumber]->getColName();
    }
  }

  if (collectColumnNames)
    columns += ")" ;

  // (colList->entries() == 0) ==> we have a select count(*) type query or a
  // select 1 from T type query. In other words the table needs to be accessed
  // but no column has been explicitly referenced.
  // For such queries if the user has privilege on any one column that is 
  // sufficient. collectColumnNames indicates whether the user has privilege
  // on at least one column. The following if statement applies only to selects
  // For update and insert we do not expect colList to be empty.

  if ((colList->entries() == 0)&& !collectColumnNames)
  {
    hasPriv = false;
    columns = "";
  }

  if (!hasPriv)
    *CmpCommon::diags() << DgSqlCode(-4481)
                        << DgString0(PrivMgrUserPrivs::convertPrivTypeToLiteral(privType).c_str())
                        << DgString1(table->getTableName().getQualifiedNameAsAnsiString())
                        << DgString2(columns);

  return hasPriv;
  
}


NABoolean RelRoot::checkFirstNRowsNotAllowed(BindWA *bindWA)
{
  // do not call this method on a true root.
  CMPASSERT(NOT isTrueRoot());
 
  //***************************************************************** 
  // FirstNRows >= 0 (for FirstN)
  //            == -2 For Last 0
  //            == -3 For Last 1
  // These values are set in parser; see the code SqlParser.y under
  // Non-Terminal querySpecification when fisrtN is specified
  //******************************************************************

  if ( (getFirstNRows() >= 0 || 
        getFirstNRows() == -2 ||
        getFirstNRows() == -3) &&  // this root has firstn
      (!((getInliningInfo().isEnableFirstNRows()) ||
      (getHostArraysArea() && getHostArraysArea()->getHasSelectIntoRowsets()) || //firstn is allowed with a rowset subroot
      (assignmentStTree()))))  // first n is allowed in a CS. Presence of assignmentStTree
                               // on a non true root implies presence of select into statement
                               // within a cs
        {
          // 4102 The [FIRST/ANY n] syntax can only be used in an outermost SELECT statement.
          if (CmpCommon::getDefault(ALLOW_FIRSTN_IN_SUBQUERIES) == DF_OFF)
            return TRUE;
        }
   return FALSE;
}

// ----------------------------------------------------------------------------
// Method:  checkPrivileges
//
// This method:
//   - Verifies that the user executing the query has the necessary privileges
//   - Adds security keys to RelRoot class  that need to be checked when priv
//     changes (revokes) are performed.  Security keys are part of the Query 
//     Invalidation feature.
//   - Also, removes any previously cached entries if the user has no priv
//
// Input: pointer to the binder work area
// Output:  result of the check
//   TRUE  - user has priv
//   FALSE - user does not have priv or unexpected error occurred
//
// The ComDiags area is populated with error details
// The BindWA flag setFailedForPrivileges is set to TRUE if priv check fails 
// ----------------------------------------------------------------------------
NABoolean RelRoot::checkPrivileges(BindWA* bindWA)
{
  // If internal caller and not part of explain, then return 
  if (Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL)) 
    return TRUE;

  // If qiPath (used for testing) is not 0, skip root user check
  NAString qiPath = "";
  CmpCommon::getDefault(QI_PATH, qiPath, FALSE);
  if (qiPath.length() == 0 && ComUser::isRootUserID())
    return TRUE;

  // See if there is anything to check
  //  StoiList contains any tables used in the query
  //  UdrStoiList contains any routines used in the query
  //  CoProcAggrList contains any queries using the aggregate co-processor
  //  SeqValList contains any sequences
  if (bindWA->getStoiList().entries() == 0 &&
      bindWA->getUdrStoiList().entries() == 0 &&
      bindWA->getCoProcAggrList().entries() == 0 &&
      bindWA->getSeqValList().entries() == 0)
    return TRUE;

  // If authorization is not enabled, then return TRUE
  if (!CmpCommon::context()->isAuthorizationEnabled())
    return TRUE;

  ComBoolean QI_enabled = (CmpCommon::getDefault(CAT_ENABLE_QUERY_INVALIDATION) == DF_ON);
  NABoolean RemoveNATableEntryFromCache = FALSE ;

  // Have the ComSecurityKey constructor compute the hash value for the the User's ID.
  // Note: The following code doesn't care about the object's hash value or the resulting 
  // ComSecurityKey's ActionType....we just need the hash value for the User's ID.
  int64_t objectUID = 12345;
  Int32 thisUserID = ComUser::getCurrentUser();
  ComSecurityKey userKey( thisUserID , objectUID
                         , SELECT_PRIV
                         , ComSecurityKey::OBJECT_IS_OBJECT
                        );
  uint32_t userHashValue = userKey.getSubjectHashValue();


  // Set up a PrivMgrCommands class in case we need to get privilege information
  NAString privMDLoc;
  CONCAT_CATSCH(privMDLoc,CmpSeabaseDDL::getSystemCatalogStatic(),SEABASE_PRIVMGR_SCHEMA);
  PrivMgrCommands privInterface(privMDLoc.data(), CmpCommon::diags(), PrivMgr::PRIV_INITIALIZED);
  PrivStatus retcode = STATUS_GOOD;

  // ==> Check privileges for tables used in the query.
  SqlTableOpenInfo * stoi = NULL ;
  OptSqlTableOpenInfo * optStoi = NULL;
  for(Int32 i=0; i<(Int32)bindWA->getStoiList().entries(); i++)
  {
    RemoveNATableEntryFromCache = FALSE ;  // Initialize each time through loop
    optStoi = (bindWA->getStoiList())[i];
    stoi = optStoi->getStoi();
    NATable* tab = optStoi->getTable();

    // System metadata tables do not, by default, have privileges stored in the
    // NATable structure.  Go ahead and retrieve them now. 
    PrivMgrUserPrivs *pPrivInfo = tab->getPrivInfo();
    PrivMgrUserPrivs privInfo;
    if (!pPrivInfo)
    {
      CmpSeabaseDDL cmpSBD(STMTHEAP);
      if (cmpSBD.switchCompiler(CmpContextInfo::CMPCONTEXT_TYPE_META))
      {
        if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
          *CmpCommon::diags() << DgSqlCode( -4400 );
        return FALSE;
      }
      retcode = privInterface.getPrivileges( tab, thisUserID, privInfo);
      cmpSBD.switchBackCompiler();

      if (retcode != STATUS_GOOD)
      {
        tab->setRemoveFromCacheBNC(TRUE);
        bindWA->setFailedForPrivileges(TRUE);
        *CmpCommon::diags() << DgSqlCode( -1034 );
        return FALSE;
      }
      pPrivInfo = &privInfo;
    }

    // Check each primary DML privilege to see if the query requires it. If 
    // so, verify that the user has the privilege
    bool insertQIKeys = (QI_enabled && tab->getSecKeySet().entries() > 0);
    for (int_32 i = FIRST_DML_PRIV; i <= LAST_PRIMARY_DML_PRIV; i++)
    {
      if (stoi->getPrivAccess((PrivType)i))
      {
        if (!pPrivInfo->hasPriv((PrivType)i) && !optStoi->checkColPriv((PrivType)i, pPrivInfo))
          RemoveNATableEntryFromCache = TRUE;
        else
          if (insertQIKeys)    
            findKeyAndInsertInOutputList(tab->getSecKeySet(),userHashValue,(PrivType)(i));
      }
    }

    // wait until all the primary DML privileges have been checked before
    // setting failure information
    if ( RemoveNATableEntryFromCache )
    {
       bindWA->setFailedForPrivileges( TRUE );
       tab->setRemoveFromCacheBNC(TRUE); // To be removed by CmpMain before Compilation retry
    }
  }  // for loop over tables in stoi list

  // ==> Check privileges for functions and procedures used in the query.
  NABoolean RemoveNARoutineEntryFromCache = FALSE ;
  if (bindWA->getUdrStoiList().entries())
  {
    for(Int32 i=0; i<(Int32)bindWA->getUdrStoiList().entries(); i++)
    {
      // Privilege info for the user/routine combination is stored in the 
      // NARoutine object.
      OptUdrOpenInfo *udrStoi = (bindWA->getUdrStoiList())[i];
      NARoutine* rtn = udrStoi->getNARoutine();
      PrivMgrUserPrivs *pPrivInfo = rtn->getPrivInfo();

      NABoolean insertQIKeys = FALSE;
      if (QI_enabled && (rtn->getSecKeySet().entries() > 0))
       insertQIKeys = TRUE;

      if (pPrivInfo == NULL) 
      {
        RemoveNARoutineEntryFromCache = TRUE ; 
        *CmpCommon::diags() << DgSqlCode( -1034 );
      }

      // Verify that the user has execute priv
      else
      {
        if (pPrivInfo->hasPriv(EXECUTE_PRIV))
        {
          // do this only if QI is enabled and object has security keys defined
          if ( insertQIKeys )
            findKeyAndInsertInOutputList(rtn->getSecKeySet(), userHashValue, EXECUTE_PRIV);
        }

        // plan requires privilege but user has none, report an error
        else
        {
          RemoveNARoutineEntryFromCache = TRUE ; 
          *CmpCommon::diags() 
            << DgSqlCode( -4482 )
            << DgString0( "EXECUTE" )
            << DgString1( udrStoi->getUdrName() );
        }
      }

      if ( RemoveNARoutineEntryFromCache )
      {
        bindWA->setFailedForPrivileges(TRUE);

        // If routine exists in cache, add it to the list to remove
        NARoutineDB *pRoutineDBCache  = bindWA->getSchemaDB()->getNARoutineDB();
        NARoutineDBKey key(rtn->getSqlName(), bindWA->wHeap());
        NARoutine *cachedNARoutine = pRoutineDBCache->get(bindWA, &key);
        if (cachedNARoutine != NULL)
          pRoutineDBCache->moveRoutineToDeleteList(cachedNARoutine, &key);
      }
    }  // for loop over UDRs
  }  // end if any UDRs.

  // ==> Check privs on any CoprocAggrs used in the query.
  for (Int32 i=0; i<(Int32)bindWA->getCoProcAggrList().entries(); i++)
  {
    RemoveNATableEntryFromCache = FALSE ;  // Initialize each time through loop
    ExeUtilHbaseCoProcAggr *coProcAggr = (bindWA->getCoProcAggrList())[i];
    NATable* tab = bindWA->getSchemaDB()->getNATableDB()->
                                   get(coProcAggr->getCorrName(), bindWA, NULL);

    Int32 numSecKeys = 0;

    // Privilege info for the user/table combination is stored in the NATable
    // object.
    PrivMgrUserPrivs* pPrivInfo = tab->getPrivInfo();
    PrivMgrUserPrivs privInfo;

    // System metadata tables do not, by default, have privileges stored in the
    // NATable structure.  Go ahead and retrieve them now. 
    if (!pPrivInfo)
    {
      CmpSeabaseDDL cmpSBD(STMTHEAP);
      if (cmpSBD.switchCompiler(CmpContextInfo::CMPCONTEXT_TYPE_META))
      {
        if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
          *CmpCommon::diags() << DgSqlCode( -4400 );
        return FALSE;
      }
      retcode = privInterface.getPrivileges( tab, thisUserID, privInfo);
      cmpSBD.switchBackCompiler();

      if (retcode != STATUS_GOOD)
      {
        bindWA->setFailedForPrivileges( TRUE );
        tab->setRemoveFromCacheBNC(TRUE); // To be removed by CmpMain before Compilation retry
        *CmpCommon::diags() << DgSqlCode( -1034 );
        return FALSE;
      }
      pPrivInfo = &privInfo;
    }

    // Verify that the user has select priv
    // Select priv is needed for EXPLAIN requests, so no special check is done
    NABoolean insertQIKeys = FALSE; 
    if (QI_enabled && (tab->getSecKeySet().entries()) > 0)
      insertQIKeys = TRUE;
    if (pPrivInfo->hasPriv(SELECT_PRIV))
    {
      // do this only if QI is enabled and object has security keys defined
      if ( insertQIKeys )
        findKeyAndInsertInOutputList(tab->getSecKeySet(), userHashValue, SELECT_PRIV );
    }

    // plan requires privilege but user has none, report an error
    else
    {
       bindWA->setFailedForPrivileges( TRUE );
       tab->setRemoveFromCacheBNC(TRUE); // To be removed by CmpMain before Compilation retry
       *CmpCommon::diags()
         << DgSqlCode( -4481 )
         << DgString0( "SELECT" )
         << DgString1( tab->getTableName().getQualifiedNameAsAnsiString() );
    }
  }  // for loop over coprocs

  // ==> Check privs on any sequence generators used in the query.
  for (Int32 i=0; i<(Int32)bindWA->getSeqValList().entries(); i++)
  {
    RemoveNATableEntryFromCache = FALSE ;  // Initialize each time through loop
    SequenceValue *seqVal = (bindWA->getSeqValList())[i];
    NATable* tab = const_cast<NATable*>(seqVal->getNATable());
    CMPASSERT(tab);

    // get privilege information from the NATable structure
    PrivMgrUserPrivs *pPrivInfo = tab->getPrivInfo();
    PrivMgrUserPrivs privInfo;
    if (!pPrivInfo)
    {
      CmpSeabaseDDL cmpSBD(STMTHEAP);
      if (cmpSBD.switchCompiler(CmpContextInfo::CMPCONTEXT_TYPE_META))
      {
        if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0)
          *CmpCommon::diags() << DgSqlCode( -4400 );
        return FALSE;
      }
      retcode = privInterface.getPrivileges(tab, thisUserID, privInfo);
      cmpSBD.switchBackCompiler();
      if (retcode != STATUS_GOOD)
      {
        bindWA->setFailedForPrivileges(TRUE);
        tab->setRemoveFromCacheBNC(TRUE); // Not used until sequences stored in table cache
        *CmpCommon::diags() << DgSqlCode( -1034 );
        return FALSE;
      }
      pPrivInfo = &privInfo;
    }

    // Verify that the user has usage priv
    NABoolean insertQIKeys = FALSE; 
    if (QI_enabled && (tab->getSecKeySet().entries()) > 0)
      insertQIKeys = TRUE;
    if (pPrivInfo->hasPriv(USAGE_PRIV))
    {
      // do this only if QI is enabled and object has security keys defined
      if ( insertQIKeys )
        findKeyAndInsertInOutputList(tab->getSecKeySet(), userHashValue, USAGE_PRIV );
    }

    // plan requires privilege but user has none, report an error
    else
    {
      bindWA->setFailedForPrivileges( TRUE );
      tab->setRemoveFromCacheBNC(TRUE); // To be removed by CmpMain before Compilation retry
      *CmpCommon::diags()
        << DgSqlCode( -4491 )
        << DgString0( "USAGE" )
        << DgString1( tab->getTableName().getQualifiedNameAsAnsiString());
    }
  }  // for loop over sequences

  return !bindWA->failedForPrivileges() ;
}

// ****************************************************************************
// method: findKeyAndInsertInOutputList
//
// This method searches through the list of security keys associated with the
// object to find the best candidate to save in the plan based on the
// privilege required.  If it finds a candidate, it inserts the best candidate 
// into securityKeySet_ member of the RelRoot class.
//
// Security key types currently include:
//   COM_QI_OBJECT_<priv>:   privileges granted directly to the user
//   COM_QI_USER_GRANT_ROLE: privileges granted to the user via a role 
//   COM_QI_USER_GRANT_SPECIAL_ROLE: privileges granted to PUBLIC
//
// Keys are added as follows:
//   if a privilege has been granted via a role, add a RoleUserKey
//      if this role is revoked from the user, then invalidation is forced
//   if a privilege has been granted to public, add a UserObjectPublicKey
//      if a privilege is revoked from public, then invalidation is forced
//   if a privilege has been granted directly to an object, add UserObjectKey
//      if the privilege is revoked from the user, then invalidation is forced
//   If a privilege has not been granted to an object, but is has been granted
//      to a role, add a RoleObjectKey
//
//   So if the same privilege has been granted directly to the user and via
//   a role granted to the user, we only add a UserObjectKey
// ****************************************************************************
void RelRoot::findKeyAndInsertInOutputList( ComSecurityKeySet KeysForTab
                                          , const uint32_t userHashValue
                                          , const PrivType which
                                          )
{
   // If no keys associated with object, just return
   if (KeysForTab.entries() == 0)
     return;

   ComSecurityKey * UserObjectKey = NULL;
   ComSecurityKey * RoleObjectKey = NULL;
   ComSecurityKey * UserObjectPublicKey = NULL;
   ComSecurityKey * RoleUserKey = NULL;
   
   // These may be implemented at a later time
   ComSecurityKey * UserSchemaKey = NULL; //privs granted at schema level to user
   ComSecurityKey * RoleSchemaKey = NULL; //privs granted at schema level to role

   // Get action type for UserObjectKey based on the privilege (which)
   // so if (which) is SELECT, then the objectActionType is COM_QI_OBJECT_SELECT
   ComSecurityKey  dummyKey;
   ComQIActionType objectActionType =
                   dummyKey.convertBitmapToQIActionType ( which, ComSecurityKey::OBJECT_IS_OBJECT );

   ComSecurityKey * thisKey = NULL;

   // NOTE: hashValueOfPublic will be the same for all keys, so we generate it only once.
   uint32_t hashValueOfPublic = ComSecurityKey::SPECIAL_OBJECT_HASH;

   // Traverse List looking for ANY appropriate ComSecurityKey 
   for ( Int32 ii = 0; ii < (Int32)(KeysForTab.entries()); ii++ )
   {
      thisKey = &(KeysForTab[ii]);
  
      // See if the key is object related
      if ( thisKey->getSecurityKeyType() == objectActionType )
      {
         if ( thisKey->getSubjectHashValue() == userHashValue )
         {
            // Found a security key for the objectActionType
            if ( ! UserObjectKey ) 
               UserObjectKey = thisKey;
         }
         // Found a security key for a role associated with the user
         else
         {
            if ( ! RoleObjectKey )
               RoleObjectKey = thisKey;
         }
      }
     
      // See if the security key is role related
      else if (thisKey->getSecurityKeyType() == COM_QI_USER_GRANT_ROLE) 
      {
         if ( thisKey->getSubjectHashValue() == userHashValue )
         {
            if (! RoleUserKey ) 
               RoleUserKey = thisKey;
         }
      }

      else if (thisKey->getSecurityKeyType() == COM_QI_USER_GRANT_SPECIAL_ROLE)
      {
         if (thisKey->getObjectHashValue() == hashValueOfPublic )
         {
            if (! UserObjectPublicKey )
               UserObjectPublicKey = thisKey;
         }
      }

      else {;} // Not right action type, just continue traversing.
   }

   // Determine best key, UserObjectKeys are better than RoleObjectKeys
   ComSecurityKey * BestKey = (UserObjectKey) ? UserObjectKey : RoleObjectKey;

   if ( BestKey != NULL)
      securityKeySet_.insert(*BestKey);

   // Add RoleUserKey if priv comes from role - handles revoke role from user
   if (BestKey == RoleObjectKey)
      if ( RoleUserKey )
         securityKeySet_.insert(*RoleUserKey );

   // Add public if it exists - handles revoke public from user
   if ( UserObjectPublicKey != NULL )
     securityKeySet_.insert(*UserObjectPublicKey); 
}


// -----------------------------------------------------------------------
// member functions for class GroupByAgg
// -----------------------------------------------------------------------

RelExpr *GroupByAgg::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  //
  // add any aggregate functions found in the parent node(s)
  //
  BindScope *currScope = bindWA->getCurrentScope();
  aggregateExpr_ += currScope->getUnresolvedAggregates();
  currScope->getUnresolvedAggregates().clear();
  //
  // Bind the child nodes.
  //
  currScope->context()->lookAboveToDecideSubquery() = TRUE;
  bindChildren(bindWA);
  currScope->context()->lookAboveToDecideSubquery() = FALSE;
  if (bindWA->errStatus()) return this;
  bindWA->getCurrentScope()->setRETDesc(getRETDesc());

  // QSTUFF
  NAString fmtdList(bindWA->wHeap());
  LIST(TableNameMap*) xtnmList(bindWA->wHeap());
  bindWA->getTablesInScope(xtnmList, &fmtdList);

  // can be removed when supporting aggregates on streams
  if (getGroupAttr()->isStream()){
    *CmpCommon::diags() << DgSqlCode(-4162) << DgString0(fmtdList);
    bindWA->setErrStatus();
    return this;
  }

  if ((getGroupAttr()->isEmbeddedUpdateOrDelete()) ||
      (bindWA->isEmbeddedIUDStatement())) {
    *CmpCommon::diags() << DgSqlCode(-4163) << DgString0(fmtdList)
      << (getGroupAttr()->isEmbeddedUpdate() ?
         DgString1("UPDATE"):DgString1("DELETE"));
    bindWA->setErrStatus();
    return this;
  }
  // QSTUFF

  // if unresolved aggregate functions have been found in the children of the
  // Groupby node, that would mean that we are referencing aggregates before
  // the groupby operation is performed
  //
  if (checkUnresolvedAggregates(bindWA))
    return this;
  //
  // Detach the item expression tree for the grouping column list, bind it,
  // convert it to a ValueIdSet, and attach it to the GroupByAgg node.
  //
  ItemExpr *groupExprTree = removeGroupExprTree();
  if (groupExprTree) {
    currScope->context()->inGroupByClause() = TRUE;
    groupExprTree->convertToValueIdSet(groupExpr(), bindWA, ITM_ITEM_LIST);

    if (isRollup())
      groupExprTree->convertToValueIdList(
           rollupGroupExprList(), bindWA, ITM_ITEM_LIST);

    currScope->context()->inGroupByClause() = FALSE;
    if (bindWA->errStatus()) return this;

    ValueIdList groupByList(groupExpr());
 
    for (CollIndex i = 0; i < groupByList.entries(); i++)
    {
      ValueId vid = groupByList[i];
      vid.getItemExpr()->setIsGroupByExpr(TRUE);
    }

    if ((groupExprTree != NULL) &&
        (getParentRootSelectList() != NULL))
      {
        RETDesc * childRETDesc = child(0)->getRETDesc();
        ItemExprList origSelectList(getParentRootSelectList(), bindWA->wHeap());
        
        for (CollIndex i = 0; i < groupByList.entries(); i++)
          {
            ValueId vid = groupByList[i];
            if((vid.getItemExpr()->getOperatorType() == ITM_SEL_INDEX)&&
               (((SelIndex*)(vid.getItemExpr()))->renamedColNameInGrbyClause()))
              {
                ULng32 indx = ((SelIndex*)(vid.getItemExpr()))->getSelIndex() - 1;
                if (origSelectList.entries() > indx && 
                    origSelectList[indx]->getOperatorType() == ITM_RENAME_COL) 
                  {
                    const ColRefName &selectListColRefName = 
                      *((RenameCol *)origSelectList[indx])->getNewColRefName();
                    ColumnNameMap *baseColExpr = 
                      childRETDesc->findColumn(selectListColRefName);
                    if (baseColExpr)
                      {
                        groupExpr().remove(vid);
                        groupExpr().insert(baseColExpr->getValueId());

                        if (isRollup())
                          {
                            CollIndex idx = rollupGroupExprList().index(vid);
                            rollupGroupExprList()[idx] = baseColExpr->getValueId();
                          }
 
                        baseColExpr->getColumnDesc()->setGroupedFlag();
                        origSelectList[indx]->setInGroupByOrdinal(FALSE);
                      }
                  }
              }
          }
        
        if (getSelPredTree()) 
          {
            ItemExpr * havingPred = (ItemExpr *) getSelPredTree();
            
            // see if having expr refers to any renamed col in the select list.
            // that is NOT a name exposed by child RETDesc. 
            // If it does, replace it with SelIndex.
            // For now, do this for special1 mode and only if the having
            // is a simple pred of the form:  col <op> value.
            // Later, we can extend this to all kind of having pred by 
            // traversing the having pred tree and replacing renamed cols.
            NABoolean replaced = FALSE;
            NABoolean notAllowedWithSelIndexInHaving = FALSE;
            replaceRenamedColInHavingWithSelIndex(
                 bindWA, havingPred, origSelectList, replaced,
                 notAllowedWithSelIndexInHaving,child(0)->getRETDesc());
            if (bindWA->errStatus())
              return this;
            if (replaced)
              {
                if (notAllowedWithSelIndexInHaving)
                  {
                    *CmpCommon::diags() << DgSqlCode(-4196) ;
                    bindWA->setErrStatus();
                    return this;
                  }
                
                setSelIndexInHaving(TRUE);
              }
          }
        setParentRootSelectList(NULL);
      }
    
    // Indicate that we are not in a scalar groupby.  Any aggregate
    // functions found in the select list or having clause cannot
    // evaluate to NULL unless their argument is null.
    currScope->context()->inScalarGroupBy() = FALSE;
  }
  //
  // bind the having predicates and attach the resulting value id set
  // to the node (as a selection predicate on the groupby node)
  //
  ItemExpr *havingPred = removeSelPredTree();
  if (havingPred && NOT selIndexInHaving()) 
  {
    currScope->context()->inHavingClause() = TRUE;
    havingPred->convertToValueIdSet(selectionPred(), bindWA, ITM_AND);
    currScope->context()->inHavingClause() = FALSE;
    if (bindWA->errStatus()) 
      return this;
  }

  //
  // Bind the base class.
  //
  RelExpr *boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus()) return boundExpr;

  if ((havingPred) &&
    (selIndexInHaving())) 
  {
    addSelPredTree(havingPred);
  }

  //
  // Get the aggregate expressions from the list that has accumulated
  // in the current bind scope and clear the list in the bind scope --
  //   but first, if Tuple::bindNode()/checkTupleElementsAreAllScalar()
  //   created this node, add the subquery aggregate expr
  //   (Genesis 10-000221-6676).
  //
  if (aggregateExprTree_) { // only Binder, not Parser, should put anything here
    //	CMPASSERT(bindWA->getCurrentScope()->context()->inTupleList());
    CMPASSERT(aggregateExprTree_->nodeIsBound() ||
              aggregateExprTree_->child(0)->nodeIsBound());
    aggregateExprTree_ = aggregateExprTree_->bindNode(bindWA);
    if (bindWA->errStatus()) return boundExpr;
    aggregateExpr_    += aggregateExprTree_->getValueId();
    aggregateExprTree_ = NULL;
  }
  aggregateExpr_ += currScope->getUnresolvedAggregates();
  currScope->getUnresolvedAggregates().clear();
  getRETDesc()->setGroupedFlag();

  return boundExpr;
} // GroupByAgg::bindNode()

// -----------------------------------------------------------------------
// member functions for class Scan
// -----------------------------------------------------------------------


////////////////////////////////////////////////////////////////////////
// A list of 'fabricated' hostvar representing the hostvars is generated
// that will contain the primary key values. These primary key
// values are retrieved at runtime from the cursor statement
// specified in the 'current of' clause. A predicate of the
// form 'where pkey1 = :pkey1 and pkey2 = :pkey2...' is attached
// to the selection pred of this node. The hostvar values are
// then passed in by the root node to its child and they reach
// this node at runtime where the 'where' predicate is evaluated.
////////////////////////////////////////////////////////////////////////
void Scan::bindUpdateCurrentOf(BindWA *bindWA, NABoolean updateQry)
{
  ValueIdList keyList = getTableDesc()->getClusteringIndex()->getIndexKey();
  ItemExpr * rootPtr = NULL;
  char hvName[30];
  CollIndex i = 0;
  for (i = 0; i < keyList.entries(); i++)
    {
      ValueId vid = keyList[i];

      // Fabricate a name for the i'th host variable,
      // make a hostvar,add it to pkeyHvarList.
      sprintf(hvName,"_upd_pkey_HostVar%d",i);

      HostVar *hv = new(bindWA->wHeap()) HostVar(hvName, &vid.getType(), TRUE);
      hv->bindNode(bindWA);

      pkeyHvarList().insert(hv->getValueId());

      // Build a 'pkey = pkey_hvar' predicate.
      ItemExpr * eqPred = new(bindWA->wHeap())
                            BiRelat(ITM_EQUAL, vid.getItemExpr(), hv);

      if (!rootPtr)
        rootPtr = eqPred;
      else
        rootPtr = new(bindWA->wHeap()) BiLogic(ITM_AND, rootPtr, eqPred);
    } // loop over all pkey columns

  if (updateQry)
    {
      ItemExpr * updCheckPtr = NULL;
      ValueIdList nonKeyColList;
      getTableDesc()->getClusteringIndex()->getNonKeyColumnList(nonKeyColList);
      for (i = 0; i < nonKeyColList.entries(); i++)
        {
          ValueId vid = nonKeyColList[i];

          // Fabricate a name for the i'th host variable,
          // make a hostvar,add it to pkeyHvarList.
          sprintf(hvName,"_upd_col_HostVar%d",i);

          HostVar *hv = new(bindWA->wHeap()) HostVar(hvName, &vid.getType(), TRUE);
          hv->bindNode(bindWA);

          pkeyHvarList().insert(hv->getValueId());

          // Build a 'col = col_hvar' predicate.
          ItemExpr * eqPred = new(bindWA->wHeap())
            BiRelat(ITM_EQUAL, vid.getItemExpr(), hv, TRUE);

          if (!updCheckPtr)
            updCheckPtr = eqPred;
          else
            updCheckPtr =
              new(bindWA->wHeap()) BiLogic(ITM_AND, updCheckPtr, eqPred);
        } // loop over all pkey columns

      if (updCheckPtr)
        {
          updCheckPtr = new (bindWA->wHeap())
            Case(NULL,
                 new (bindWA->wHeap())
                   IfThenElse(updCheckPtr,
                              new (bindWA->wHeap()) BoolVal(ITM_RETURN_TRUE),
                              new (bindWA->wHeap())
                                BoolVal(ITM_RETURN_TRUE,
                                        new (bindWA->wHeap())
                                          RaiseError(-(Lng32)EXE_CURSOR_UPDATE_CONFLICT))));

          rootPtr = new(bindWA->wHeap()) BiLogic(ITM_AND, rootPtr, updCheckPtr);
        }
    }

//  rootPtr->bindNode(bindWA);

  // add this new tree to the existing selection predicate
  addSelPredTree(rootPtr);

  bindSelf(bindWA);   // just in case

} // Scan::bindUpdateCurrentOf()

// Every Scan and every GenericUpdate has its own stoi,
// plus copies of some of these stoi's are copied to the BindWA
//
// The scan/gu stoi's will become ex_partn_access stoi's
//
// The stoiList copies in BindWA will have their security
// checked in the binder, in RelRoot::checkPrivileges
//
// Stoi's must exist for every table/view/MV/index.
// Stoi's that are not copied to the BindWA are those for which Ansi mandates
// that no security checking be done (e.g., indexes).
//
OptSqlTableOpenInfo *setupStoi(OptSqlTableOpenInfo *&optStoi_,
                               BindWA *bindWA,
                               const RelExpr *re,
                               const NATable *naTable,
                               const CorrName &corrName,
                               NABoolean noSecurityCheck)
{
  // Get the PHYSICAL (non-Ansi/non-delimited) filename of the table or view.
  CMPASSERT(!naTable->getViewText() || naTable->getViewFileName());
  NAString fileName( naTable->getViewText() ?
                      (NAString)naTable->getViewFileName() :
                       naTable->getClusteringIndex()->
                          getFileSetName().getQualifiedNameAsString(),
                     bindWA->wHeap());

  SqlTableOpenInfo * stoi_ = new (bindWA->wHeap()) SqlTableOpenInfo;

  optStoi_ = new(bindWA->wHeap()) OptSqlTableOpenInfo(stoi_,
                                                      corrName,
                                                      bindWA->wHeap());

  stoi_->setFileName(convertNAString(fileName, bindWA->wHeap()));

  if (naTable->getIsSynonymTranslationDone())
  {
     stoi_->setAnsiName(convertNAString(
                         naTable->getSynonymReferenceName(),
                         bindWA->wHeap())); 
  }
  else
  {
     stoi_->setAnsiName(convertNAString(
                         naTable->getTableName().getQualifiedNameAsAnsiString(),
                         bindWA->wHeap()));
  }

  if(naTable->isUMDTable() || naTable->isSMDTable()
    || naTable->isMVUMDTable() || naTable->isTrigTempTable())
  {
    stoi_->setIsMXMetadataTable(1);
  }

  if (NOT corrName.getCorrNameAsString().isNull())
    {
      NABoolean corrNameSpecified = TRUE;
      if (corrNameSpecified)
        {
          stoi_->setCorrName(convertNAString(
               corrName.getCorrNameAsString(),
               bindWA->wHeap()));
        }
    }

  // Materialized-View is considered as a regular table
  stoi_->setSpecialTable(naTable->getSpecialType() != ExtendedQualName::NORMAL_TABLE &&
    naTable->getSpecialType() != ExtendedQualName::MV_TABLE);
  stoi_->setIsView(naTable->getViewText() ? TRUE : FALSE);

  if (naTable->isHbaseTable())
    stoi_->setIsHbase(TRUE);

  stoi_->setLocationSpecified(corrName.isLocationNameSpecified() || 
    corrName.isPartitionNameSpecified() );

  stoi_->setUtilityOpen(corrName.isUtilityOpenIdSpecified());
  stoi_->setUtilityOpenId(corrName.getUtilityOpenId());

  stoi_->setIsNSAOperation(corrName.isNSAOperation());


  if (! naTable->getViewText())
    stoi_->setIsAudited(naTable->getClusteringIndex()->isAudited());

  switch (re->getOperatorType())
  {
    case REL_UNARY_INSERT:
    case REL_LEAF_INSERT:
      stoi_->setInsertAccess();
      break;
    case REL_UNARY_UPDATE:
      {
        stoi_->setUpdateAccess();
        if (((GenericUpdate*)re)->isMerge())
          stoi_->setInsertAccess();
      }
      break;
    case REL_UNARY_DELETE:
    case REL_LEAF_DELETE:
      {
        stoi_->setDeleteAccess();
        if (((GenericUpdate*)re)->isMerge())
          stoi_->setInsertAccess();
      }
      break;
    case REL_SCAN:
    case REL_LOCK:
    case REL_UNLOCK:
    case REL_HBASE_COPROC_AGGR:
      stoi_->setSelectAccess();
      break;
    case REL_EXE_UTIL:

      stoi_->setSelectAccess();
      stoi_->setInsertAccess();
      stoi_->setUpdateAccess();
      stoi_->setDeleteAccess();
      break;
    default:
      CMPASSERT(FALSE);
  }

  NABoolean validateTS = TRUE;

  if ((naTable->getClusteringIndex() &&
       naTable->getClusteringIndex()->isSystemTable()) ||
      (NOT validateTS))
    stoi_->setValidateTimestamp(FALSE);
  else
    stoi_->setValidateTimestamp(TRUE);


  // MV --
  // For INTERNAL REFRESH statements, leave only the insert on the MV itself.
  if (re->getInliningInfo().isAvoidSecurityCheck() ||
      (bindWA->isBindingMvRefresh() &&
       (!naTable->isAnMV() || !stoi_->getInsertAccess())))
  {
    return NULL;
  }

  
  // In a SCAN, only the topmost view is inserted into BindWA StoiList
  // (thus there will be no security check on underlying views/basetables,
  // as Ansi says there shouldn't).
  if (re->getOperatorType() == REL_SCAN && bindWA->viewCount())
  {
    return NULL;
  }

  // Genesis 10-980306-4309:
  // Ansi says not supposed to be any security check on referenced tables,
  // nor of course on indexes, RIs and temp tables which are not an Ansi
  // notion to begin with.
  if ((naTable->getSpecialType() == ExtendedQualName::TRIGTEMP_TABLE) ||
      (naTable->getSpecialType() == ExtendedQualName::IUD_LOG_TABLE) ||
      (naTable->getSpecialType() == ExtendedQualName::INDEX_TABLE))
  {
    return NULL;
  }

  if (noSecurityCheck)
  {
    return NULL;
  }

  if (re->getOperator().match(REL_ANY_GEN_UPDATE)&& 
      (((GenericUpdate*)re)->getUpdateCKorUniqueIndexKey()))
  {
    return NULL;
  }

  OptSqlTableOpenInfo *stoiInList = NULL;

  for (CollIndex i=0; i < bindWA->getStoiList().entries(); i++)
    if (strcmp(bindWA->getStoiList()[i]->getStoi()->fileName(), fileName) == 0) {
      stoiInList = bindWA->getStoiList()[i];
      break;
    }
  
  if (!stoiInList) {
    stoiInList =
      new(bindWA->wHeap()) OptSqlTableOpenInfo(
					       new (bindWA->wHeap()) SqlTableOpenInfo(*stoi_),
					       corrName,
					       bindWA->wHeap());
    
    stoiInList->setTable((NATable*)naTable);
    bindWA->getStoiList().insert(stoiInList);

    bindWA->hbaseColUsageInfo()->insert((QualifiedName*)&naTable->getTableName());

  } else {
    // This is conceptually equivalent to
    //	stoiInList->AccessFlags |= stoi_->AccessFlags :
    if (stoi_->getInsertAccess()) stoiInList->getStoi()->setInsertAccess();
    if (stoi_->getUpdateAccess()) stoiInList->getStoi()->setUpdateAccess();
    if (stoi_->getDeleteAccess()) stoiInList->getStoi()->setDeleteAccess();
    if (stoi_->getSelectAccess()) stoiInList->getStoi()->setSelectAccess();
  }
  
  return stoiInList;
  
} // setupStoi()

static void bindHint(Hint *hint, BindWA *bindWA)
{
  // bind the index names, make them fully qualified
  for (CollIndex x=0; hint && x<hint->indexCnt(); x++)
    {
      QualifiedName qualIxName((*hint)[x], 1, bindWA->wHeap(), bindWA);
      hint->replaceIndexHint(x, qualIxName.getQualifiedNameAsAnsiString());
    }
}

//----------------------------------------------------------------------------
RelExpr *Scan::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
      return this;
  }

  // -- Triggers
  // Is this a Scan on a temporary table inside the action of a statement trigger?
  if (getTableName().isATriggerTransitionName(bindWA))
    return buildTriggerTransitionTableView(bindWA); // Located in Inlining.cpp

  // -- MV
  // Is this a Scan on a log inside the select statement of a Materialized View?
  // If so - maybe we need to replace this Scan with some other RelExpr tree.
  // Ignore when inDDL() because the log may not exist yet.
  if (!bindWA->inDDL() &&
      getTableName().getSpecialType() == ExtendedQualName::NORMAL_TABLE)
  {
    const MvBindContext *pMvBindContext = bindWA->getClosestMvBindContext();
    if (NULL != pMvBindContext)
    {
      RelExpr *replacementTree =
        pMvBindContext->getReplacementFor(getTableName().getQualifiedNameObj());

      if (replacementTree != NULL)
      {
        // We need to replace the Scan on the base table by some other tree.
        // Make sure this tree has the same name as the Scan.
        const CorrName& baseCorrName = getTableName();
        replacementTree = new(bindWA->wHeap())
          RenameTable(TRUE, replacementTree, baseCorrName);

        // Move any selection predicates on the Scan to the tree.
        replacementTree->addSelPredTree(removeSelPredTree());

        // Bind the tree and return instead of the tree.
        return replacementTree->bindNode(bindWA);
      }
    }
  }

  bindChildren(bindWA);
  if (bindWA->errStatus()) return this;

  // Get the NATable for this object.
  //
  NATable *naTable = bindWA->getNATable(getTableName());
  if (bindWA->errStatus()) 
    return this;

  // Set up stoi.  bindWA->viewCount is altered during expanding the view.
  setupStoi(stoi_, bindWA, this, naTable, getTableName(), noSecurityCheck());

  // If the object is a view, expand the view.
  //
  if (naTable->getViewText()) {

    // Allow view on exception_table or any other special_table_name objects  
    ComBoolean specialTableFlagOn = Get_SqlParser_Flags(ALLOW_SPECIALTABLETYPE);
    if (specialTableFlagOn == FALSE)
    {
        Set_SqlParser_Flags(ALLOW_SPECIALTABLETYPE);
        SQL_EXEC_SetParserFlagsForExSqlComp_Internal(ALLOW_SPECIALTABLETYPE);
    }

    RelExpr * boundView = bindWA->bindView(getTableName(),
                            naTable,
                            accessOptions(),
                            removeSelPredTree(),
                            getGroupAttr(),
                            TRUE/*catmanCollectUsages*/);

    // QSTUFF
    // First we checked whether its a view and if so it must be updatable
    // when using it for stream access or an embedded update or delete
    if (!naTable->isUpdatable() && getGroupAttr()->isEmbeddedUpdateOrDelete()){
      *CmpCommon::diags() << DgSqlCode(-4206)
        << DgTableName(naTable->getTableName().getQualifiedNameAsAnsiString())
        << (getGroupAttr()->isEmbeddedUpdate() ?
        DgString0("UPDATE") : DgString0("DELETE"));
      bindWA->setErrStatus();

//    restore ALLOW_SPECIALTABLETYPE setting
      if (specialTableFlagOn == FALSE)
          Reset_SqlParser_Flags(ALLOW_SPECIALTABLETYPE);
      return NULL;
    }

    if (!naTable->isUpdatable() && getGroupAttr()->isStream()){
      *CmpCommon::diags() << DgSqlCode(-4151)
        << DgTableName(naTable->getTableName().getQualifiedNameAsAnsiString());
      bindWA->setErrStatus();
      if (specialTableFlagOn == FALSE) 
          Reset_SqlParser_Flags(ALLOW_SPECIALTABLETYPE);
      return NULL;
    }


    // Second we make sure the the underlying base table is key sequenced
    // in case of embedded d/u and streams
    if (boundView->getLeftmostScanNode()) {
      // this is not a "create view V(a) as values(3)" kind of a view
      const NATable * baseTable =
        boundView->getLeftmostScanNode()->getTableDesc()->getNATable();

      if (getGroupAttr()->isStream()) {
        if (!baseTable->getClusteringIndex()->isKeySequenced()) {
          *CmpCommon::diags() << DgSqlCode(-4204)
            << DgTableName(
                 baseTable->getTableName().getQualifiedNameAsAnsiString());
          bindWA->setErrStatus();
          if (specialTableFlagOn == FALSE)
            Reset_SqlParser_Flags(ALLOW_SPECIALTABLETYPE);

          return NULL;
        }
      }

      if (getGroupAttr()->isEmbeddedUpdateOrDelete()){
        if (!baseTable->getClusteringIndex()->isKeySequenced()){
          *CmpCommon::diags() << DgSqlCode(-4205)
            << DgTableName(
                 baseTable->getTableName().getQualifiedNameAsAnsiString())
            << (getGroupAttr()->isEmbeddedUpdate() ?
                DgString0("UPDATE") : DgString0("DELETE"));
          bindWA->setErrStatus();
          if (specialTableFlagOn == FALSE)
            Reset_SqlParser_Flags(ALLOW_SPECIALTABLETYPE);

          return NULL;
        }
      }
    }
    // QSTUFF

//    restore ALLOW_SPECIALTABLETYPE setting
    if (specialTableFlagOn == FALSE)
        Reset_SqlParser_Flags(ALLOW_SPECIALTABLETYPE);

    return boundView;
  }


  // -- MV
  // If this is the expanded tree pass during CREATE MV, expand the MV into
  // its SELECT tree, just like a regular view.
  // Do this only for incremental MVs, otherwise they may introduce unsupported
  // operators such as Union.
  if (naTable->isAnMV() && 
      bindWA->isExpandMvTree() &&
      naTable->getMVInfo(bindWA)->isIncremental())
  {
    CMPASSERT(bindWA->inDDL());
    return bindExpandedMaterializedView(bindWA, naTable);
  }

  // Do not allow to select from an un initialized MV
  if (naTable->isAnMV() && !bindWA->inDDL() && !bindWA->isBindingMvRefresh())
  {
    if (naTable->verifyMvIsInitializedAndAvailable(bindWA))
      return NULL;
  }

  // Allocate a TableDesc and attach it to the Scan node.
  // This call also allocates a RETDesc, attached to the BindScope,
  // which we want to attach also to the Scan.
  //
  // disable override schema for synonym
  NABoolean os = FALSE;
  if ( ( bindWA->overrideSchemaEnabled() ) 
    && ( ! naTable->getSynonymReferenceName().isNull() ) )
  { 
    os = bindWA->getToOverrideSchema();
    bindWA->setToOverrideSchema(FALSE);  
  }

  if (getHint())
    bindHint(getHint(), bindWA);

  TableDesc * tableDesc = NULL;

  if ((NOT isHbaseScan()) || (! getTableDesc()))
    {
      tableDesc = bindWA->createTableDesc(naTable, getTableName(), 
					  FALSE, getHint());
    }
  else
    tableDesc = getTableDesc();

  // restore override schema setting
  if ( ( bindWA->overrideSchemaEnabled() ) 
    && ( ! naTable->getSynonymReferenceName().isNull() ) )
    bindWA->setToOverrideSchema(os);  

  // before attaching set the selectivity hint defined by the user for this
  // table

  if (tableDesc && getHint() &&
      getTableName().getSpecialType() == ExtendedQualName::NORMAL_TABLE)
  {
    double s;
    s = getHint()->getSelectivity();
    if (0.0 <= s && s <= 1.0) {
      SelectivityHint *selHint = new (STMTHEAP) SelectivityHint();
      selHint->setScanSelectivityFactor(s);
      tableDesc->setSelectivityHint(selHint);
    }
    if (getHint()->getCardinality() >= 1.0) {
      s = getHint()->getCardinality();
      CostScalar scanCard(s);
      if((scanCard.getValue() - floor(scanCard.getValue())) > 0.00001)
        scanCard = ceil(scanCard.getValue());

      CardinalityHint *cardHint = new (STMTHEAP) CardinalityHint();
      cardHint->setScanCardinality(scanCard);
      tableDesc->setCardinalityHint(cardHint);
    }
  }

  setTableDesc(tableDesc);
  if (bindWA->errStatus()) return this;
  setRETDesc(bindWA->getCurrentScope()->getRETDesc());

  if ((CmpCommon::getDefault(ALLOW_DML_ON_NONAUDITED_TABLE) == DF_OFF) &&
      (naTable && naTable->getClusteringIndex() && !naTable->getClusteringIndex()->isAudited()))
  {
     *CmpCommon::diags() << DgSqlCode(-4211)
       << DgTableName(
           naTable->getTableName().getQualifiedNameAsAnsiString());
     bindWA->setErrStatus();
     return NULL;
  }
 
  // restricted partitions for HBase table
  if (naTable->isHbaseTable() &&
      (naTable->isPartitionNameSpecified() ||
       naTable->isPartitionRangeSpecified()))
    {
      PartitioningFunction * partFunc = naTable->getClusteringIndex()->getPartitioningFunction();

      // find the salt column and apply a predicate on the salt column.
      // For Hash2, since the partittion key columns are columns used to build
      // the _SALT_ column, we need to search all columns for the _SALT_ column.
      const NAColumnArray &ccCols = 
           (partFunc && partFunc->castToHash2PartitioningFunction())?
            naTable->getClusteringIndex()->getAllColumns()
              :
            naTable->getClusteringIndex()->getPartitioningKeyColumns();

      NABoolean saltColFound = FALSE;

      for (CollIndex i=0; i<ccCols.entries() && !saltColFound; i++)
        {
          if (ccCols[i]->isComputedColumn() &&
              ccCols[i]->getColName() == 
              ElemDDLSaltOptionsClause::getSaltSysColName())
            {
              saltColFound = TRUE;
              // create a predicate "_SALT_" = <num> or
              // "_SALT_" between <num> and <num>
              Int32 beginPartNum = partFunc->getRestrictedBeginPartNumber() - 1;
              Int32 endPartNum = partFunc->getRestrictedEndPartNumber() - 1;
              
              // fill in defaults, indicated by -1 (-2 after subtraction above)
              if (beginPartNum < 0)
                beginPartNum = 0;
              if (endPartNum < 0)
                endPartNum = partFunc->getCountOfPartitions() - 1;
              
              ItemExpr *partPred = NULL;
              ColReference *saltColRef = new(bindWA->wHeap()) ColReference(
                   new(bindWA->wHeap()) ColRefName(
                        ccCols[i]->getFullColRefName(), bindWA->wHeap()));
              
              if (beginPartNum == endPartNum)
                {
                  partPred = new(bindWA->wHeap()) BiRelat
                    (ITM_EQUAL,
                     saltColRef,
                     new(bindWA->wHeap()) ConstValue(beginPartNum,bindWA->wHeap()));
                }
              else
                {
                  partPred = new(bindWA->wHeap()) Between
                    (saltColRef,
                     new(bindWA->wHeap()) ConstValue(beginPartNum,bindWA->wHeap()),
                     new(bindWA->wHeap()) ConstValue(endPartNum,bindWA->wHeap()));
                }
              
              ItemExpr *newSelPred = removeSelPredTree();
              if (newSelPred)
                newSelPred = new(bindWA->wHeap()) BiLogic(ITM_AND,
                                                          newSelPred,
                                                          partPred);
              else
                newSelPred = partPred;
              
              // now add the partition predicates
              addSelPredTree(newSelPred->bindNode(bindWA));
            }
        }
      
      if (!saltColFound)
        {
          // not allowed to select individual partitions from HBase tables
          // unless they are salted
          char buf[20];
          snprintf(buf, 20, "%d", partFunc->getRestrictedBeginPartNumber());
          *CmpCommon::diags() << DgSqlCode(-1276)
                              << DgString0(buf)
                              << DgTableName(
                                   naTable->getTableName().getQualifiedNameAsAnsiString());
          bindWA->setErrStatus();
          return NULL;
        }
    }

   if (naTable->isHiveTable() && 
       !(naTable->getClusteringIndex()->getHHDFSTableStats()->isOrcFile() ||
	 naTable->getClusteringIndex()->getHHDFSTableStats()
	 ->isSequenceFile()) &&
       (CmpCommon::getDefaultNumeric(HDFS_IO_BUFFERSIZE_BYTES) == 0) && 
       (naTable->getRecordLength() >
	CmpCommon::getDefaultNumeric(HDFS_IO_BUFFERSIZE)*1024))
     {
       // do not raise error if buffersize is set though buffersize_bytes.
       // Typically this setting is used for testing alone.
       *CmpCommon::diags() << DgSqlCode(-4226)
			   << DgTableName(
					  naTable->getTableName().
					  getQualifiedNameAsAnsiString())
			   << DgInt0(naTable->getRecordLength());
       bindWA->setErrStatus();
       return NULL;
     }
  // Bind the base class.
  //
  RelExpr *boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus()) return this;
  //
  // Assign the set of columns that belong to the table to be scanned
  // as the output values that can be produced by this scan.
  //
  getGroupAttr()->addCharacteristicOutputs(getTableDesc()->getColumnList());
  getGroupAttr()->addCharacteristicOutputs(getTableDesc()->hbaseTSList());

   // MV --
  if (getInliningInfo().isMVLoggingInlined())
    projectCurrentEpoch(bindWA);

  // QSTUFF
  // Second we make sure the the underlying base table is key sequenced in case
  // of embedded d/u and streams
  if (getGroupAttr()->isStream()){

    if (!naTable->getClusteringIndex()->isKeySequenced() ||
        naTable->hasVerticalPartitions()){
      *CmpCommon::diags() << DgSqlCode(-4204)
        << DgTableName(naTable->getTableName().getQualifiedNameAsAnsiString());
      bindWA->setErrStatus();
      return NULL;
    }
    if (!getTableDesc()->getClusteringIndex()->getNAFileSet()->isAudited()) {
      // Stream access not allowed on a non-audited table
      *CmpCommon::diags() << DgSqlCode(-4215)
        << DgTableName(
            naTable->getTableName().getQualifiedNameAsAnsiString());
      bindWA->setErrStatus();
      return NULL;
    }
  }

  if (getGroupAttr()->isEmbeddedUpdateOrDelete()){
    if (!naTable->getClusteringIndex()->isKeySequenced()
      || naTable->hasVerticalPartitions()){
      *CmpCommon::diags() << DgSqlCode(-4205)
        << DgTableName(naTable->getTableName().getQualifiedNameAsAnsiString())
        << (getGroupAttr()->isEmbeddedUpdate() ?
            DgString0("UPDATE") : DgString0("DELETE"));
      bindWA->setErrStatus();
      return NULL;
    }
  }
  // QSTUFF

  // Fix "browse access mode incorrectly starts transaction" genesis case
  // 10-021111-1080. Here's a glimpse at what may have been the original
  // intent of the old code (taken from RelExpr.h comment for the now
  // defunct RelExpr::propagateAccessOptions):
  //
  // At parse time, user can specify statement level access options.
  // (See SQL/ARK Language spec). These options are attached to the
  // RelRoot node and could be different for different Scans in the query.
  // All Scan and Update nodes under a RelRoot have the same Access
  // type and the Lock Mode.
  //
  // The problem is propagateAccessOptions did not visit all the Scans,
  // eg, it did not propagate to subquery Scans, and it did not propagate
  // to internal RelRoots. This "push" model seems harder to understand
  // and to do correctly.
  //
  // So, we go with the "pull" model. An interesting node such as a Scan,
  // GenericUpdate, RelRoot that needs a user-specified access/lock mode
  // can "pull" one from BindWA. BindWA already implements SQL scoping
  // and visibility rules. It's easier to explain also. Each table
  // reference inherits the user-specified access/lock mode of the
  // nearest SQL scope, going from the table outwards. If the entire
  // query has no user-specified access/lock mode, then it uses the
  // session-level default access/lock mode.
  //
  // if we have no user-specified access options then
  // get it from nearest enclosing scope that has one (if any)
  if (!accessOptions().userSpecified()) {
    StmtLevelAccessOptions *axOpts = bindWA->findUserSpecifiedAccessOption();
    if (axOpts) {
      accessOptions() = *axOpts;
    }
  }
  // The above code is in RelRoot::bindNode also.
  // It would be nice to refactor this common code; someday.

  // See Halloween handling code in GenericUpdate::bindNode
  if (accessOptions().userSpecified()) {
    if ( accessOptions().accessType() == TransMode::REPEATABLE_READ_ACCESS_ ||
         accessOptions().accessType() == TransMode::READ_COMMITTED_ACCESS_  ||
         accessOptions().accessType() == TransMode::READ_UNCOMMITTED_ACCESS_
      ) {
        naTable->setRefsIncompatibleDP2Halloween();
    }
  }
  else {
    TransMode::IsolationLevel il = CmpCommon::transMode()->getIsolationLevel();
    if((CmpCommon::transMode()->ILtoAT(il) == TransMode::REPEATABLE_READ_ACCESS_ ) ||
       (CmpCommon::transMode()->ILtoAT(il) == TransMode::READ_COMMITTED_ACCESS_  ) ||
       (CmpCommon::transMode()->ILtoAT(il) == TransMode::READ_UNCOMMITTED_ACCESS_     )) {
        naTable->setRefsIncompatibleDP2Halloween();
    }
  }

  const NAString * tableLockVal = 
      ActiveControlDB()->getControlTableValue(
            getTableName().getUgivenName(), "TABLELOCK");
  if (*tableLockVal == "ON")
        naTable->setRefsIncompatibleDP2Halloween();

  //Embedded update/delete queries on partitioned table
  //generates assertion when ATTEMPT_ASYNCHRONOUS_ACCESS
  //flag is OFF.This is because split operator is used.
  //Removing of split top operator causes some problems.
  //Error 66 from file system is one of them.
  //So, for now compiler will generate error if these
  //conditions occur.
  if (getGroupAttr()->isEmbeddedUpdateOrDelete() &&
       naTable->getClusteringIndex()->isPartitioned() &&
       (CmpCommon::getDefault(ATTEMPT_ASYNCHRONOUS_ACCESS) == DF_OFF)) {

     *CmpCommon::diags() << DgSqlCode(-4321)
       << DgTableName(naTable->getTableName().getQualifiedNameAsAnsiString());
     bindWA->setErrStatus();
     return NULL;
  }
  // Stream access not allowed on a multi-partioned access paths, when
  // CQD ATTEMPT_ASYNCHRONOUS_ACCESS is set to OFF.If we find 
  // that all access paths are partitioned we give an error.

   if (getGroupAttr()->isStream() &&
      (CmpCommon::getDefault(ATTEMPT_ASYNCHRONOUS_ACCESS) == DF_OFF)) {
    NABoolean atleastonenonpartitionedaccess = FALSE;
    NAFileSetList idescList = naTable->getIndexList();
 
    for(CollIndex i = 0; 
        i < idescList.entries() && !atleastonenonpartitionedaccess; i++)
       if(!(idescList[i]->isPartitioned()) )
        atleastonenonpartitionedaccess = TRUE;
 
    if (!atleastonenonpartitionedaccess) {
     *CmpCommon::diags() << DgSqlCode(-4320)
       << DgTableName(naTable->getTableName().getQualifiedNameAsAnsiString());
     bindWA->setErrStatus();
     return NULL;
    }
  }

   if (hbaseAccessOptions_)
     {
       if (hbaseAccessOptions_->isMaxVersions())
         {
           hbaseAccessOptions_->setHbaseVersions
             (
              getTableDesc()->getClusteringIndex()->getNAFileSet()->numMaxVersions()
              );
         }
     }

  return boundExpr;
} // Scan::bindNode()

//----------------------------------------------------------------------------
RelExpr *Scan::bindExpandedMaterializedView(BindWA *bindWA, NATable *naTable)
{
  CollHeap *heap = bindWA->wHeap();
  MVInfoForDML *mvInfo = naTable->getMVInfo(bindWA);
  QualifiedName mvName(mvInfo->getNameOfMV(), 3, heap, bindWA);
  CorrName mvCorrName(mvName, heap, getTableName().getCorrNameAsString());

  RelExpr *viewTree = mvInfo->buildMVSelectTree();
  viewTree = new(heap) RenameTable(TRUE, viewTree, mvCorrName);
  viewTree->addSelPredTree(removeSelPredTree());
  RelExpr *boundExpr = viewTree->bindNode(bindWA);
  if (bindWA->errStatus())
    return this;

  if (naTable->getClusteringIndex()->hasSyskey())
  {
    // In case the MV on top of this MV is an MJV, it needs the SYSKEY
    // column of this MV. Since the SYSKEY column is not projected from
    // the select list of this MV, just fake it. It's value will never be
    // used anyway - just it's existance.
    ConstValue *dummySyskey = new(heap) ConstValue(0);
    dummySyskey->changeType(new(heap) SQLLargeInt(heap));
    ItemExpr *dummySyskeyCol = dummySyskey->bindNode(bindWA);
    if (bindWA->errStatus())
      return this;

    ColRefName syskeyName("SYSKEY", mvCorrName);
    boundExpr->getRETDesc()->addColumn(bindWA,
                                       syskeyName,
                                       dummySyskeyCol->getValueId(),
                                       SYSTEM_COLUMN);
  }

  bindWA->getCurrentScope()->setRETDesc(boundExpr->getRETDesc());
  return boundExpr;
}

//----------------------------------------------------------------------------
// This Scan needs to project the CurrentEpoch column.
// Create and bind the CurrentEpoch function
void Scan::projectCurrentEpoch(BindWA *bindWA)
{
  ItemExpr *currEpoch =
    new(bindWA->wHeap()) GenericUpdateOutputFunction(ITM_CURRENTEPOCH);
  currEpoch->bindNode(bindWA);

  // Add it to the RETDesc
  ColRefName virtualColName(InliningInfo::getEpochVirtualColName());
  getRETDesc()->addColumn(bindWA, virtualColName, currEpoch->getValueId());

  // And force the generator to project it even though it is not
  // a column in the IndexDesc.
  ValueIdSet loggingCols;
  loggingCols.insert(currEpoch->getValueId());
  setExtraOutputColumns(loggingCols);
}

// -----------------------------------------------------------------------
// methods for class Tuple
// -----------------------------------------------------------------------

// Genesis 10-990226-4329 and 10-000221-6676.
static RelExpr *checkTupleElementsAreAllScalar(BindWA *bindWA, RelExpr *re)
{
  if (!re) return NULL;
  RETDesc *rd = re->getRETDesc();
  CMPASSERT(rd);

  // an empty tuple is okay (dummy for Triggers, e.g.)
  const ColumnDescList &cols = *rd->getColumnList();
  for (CollIndex i = cols.entries(); i--; ) {
    ColumnDesc *col = cols[i];
    Subquery *subq = (Subquery *)cols[i]->getValueId().getItemExpr();
    if (subq->isASubquery()) {
      if (cols.entries() > 1 && subq->getDegree() > 1) {
        // 4125 The select list of a subquery in a VALUES clause must be scalar.
        *CmpCommon::diags() << DgSqlCode(-4125);
        bindWA->setErrStatus();
        return NULL;
      }      
      else if (cols.entries() == 1) {  // if cols.entries() > 1 && subq->getDegree() > 1
          // we do not want to make the transformation velow. We want to keep the 
         // values clause, so that it cann be attached by a tsj to the subquery 
        // during transform.
        CMPASSERT(subq->isARowSubquery());
        if (CmpCommon::getDefault(COMP_BOOL_137) == DF_ON)
        {
          ValueIdList subqSelectList;
          RETDesc *subqRD = subq->getSubquery()->getRETDesc()->nullInstantiate(
            bindWA, TRUE/*forceCast for GenRelGrby*/, subqSelectList);
          subq->getSubquery()->setRETDesc(subqRD);
          ItemExpr *agg = new(bindWA->wHeap())
            Aggregate(ITM_ONE_ROW, subqSelectList.rebuildExprTree());
          RelExpr * gby = new(bindWA->wHeap())
            GroupByAgg(subq->getSubquery(), REL_GROUPBY, NULL, agg);
          NABoolean save = bindWA->getCurrentScope()->context()->inTupleList();
          bindWA->getCurrentScope()->context()->inTupleList() = TRUE;
          gby = gby->bindNode(bindWA);
          bindWA->getCurrentScope()->context()->inTupleList() = save;
          return gby;
        }
        else
        {
          return subq->getSubquery();
        }

      }
    }
  }
  return re;
}

RelExpr *Tuple::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }
  
  // Used by rowsets. We search for occurrences of arrays within this node to
  // replace them with scalar variables
  
  if (bindWA->getHostArraysArea() && !bindWA->getHostArraysArea()->done()) 
    {
      RelExpr *boundExpr = bindWA->getHostArraysArea()->modifyTupleNode(this);

      if (boundExpr)
        return checkTupleElementsAreAllScalar(bindWA, boundExpr);
    }

  bindChildren(bindWA);
  if (bindWA->errStatus()) return this;

  // Detach the item expression tree for the value list and bind it.
  // We use counterForRowValues() and pass in parent, for DEFAULT processing
  // (Ansi 7.1 SR 1).
  //
  CollIndex counterRowVals = 0;
  CMPASSERT(!bindWA->getCurrentScope()->context()->counterForRowValues());
  bindWA->getCurrentScope()->context()->counterForRowValues() = &counterRowVals;
  //
  setRETDesc(bindRowValues(bindWA, removeTupleExprTree(), tupleExpr(), this, FALSE));
  if (bindWA->errStatus()) return this;
  //
  bindWA->getCurrentScope()->context()->counterForRowValues() = NULL;

  // Do NOT set currently scoped RETDesc to this VALUES(...) RETDesc --
  // makes  "select * from t where ((values(1)),a) = (1,2);"
  // fail with error 4001 "column A not found, no named tables in scope"
  //
  //	bindWA->getCurrentScope()->setRETDesc(getRETDesc());

  // Bind the base class.
  //
  RelExpr *boundExpr = bindSelf(bindWA);
  // -- Trigger
  if (bindWA->errStatus()) return this;

  //
  //for case 10-020716-5497
  RelExpr *newExpr = checkTupleElementsAreAllScalar(bindWA, boundExpr);

  //before doing anything with newExpr make sure it is not null it can
  //be null if there is an error incheckTupleElementsAreAllScalar.

  getGroupAttr()->addCharacteristicOutputs(tupleExpr());

  return newExpr;
} // Tuple::bindNode()

// -----------------------------------------------------------------------
// methods for class TupleList
// -----------------------------------------------------------------------

RelExpr *TupleList::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  RelExpr * boundExpr = NULL;
  bindChildren(bindWA);
  if (bindWA->errStatus()) return this;

  ExprValueId eVid(tupleExprTree());
  ItemExprTreeAsList tupleList(&eVid, ITM_ITEM_LIST);
  NABoolean castTo = castToList().entries() > 0;

  if (tupleExprTree()->containsSubquery() ||
      tupleExprTree()->containsUDF() 
      #ifndef NDEBUG
      ||
      getenv("UNIONED_TUPLES")
      #endif
     ) {

    // Make a union'ed tree of all the tuples in tupleList.	##
    // This is done coz TupleList doesn't handle transformation	##
    // of subqueries in tuples correctly yet.			##
    CollIndex nTupleListEntries = (CollIndex)tupleList.entries();
    for (CollIndex i = 0; i < nTupleListEntries ; i++) {

      ItemExpr *ituple = tupleList[i]->child(0)->castToItemExpr();
      RelExpr  *rtuple = new(bindWA->wHeap()) Tuple(ituple);
      rtuple = rtuple->bindNode(bindWA);
      if (bindWA->errStatus()) return this;

      // If INSERTing a TupleList, make some Assign's (even tmp's work!)
      // to do some error-checking for MP-NCHAR-as-single-byte target columns.
      //
      // Similar code exists in
      // (a) the loop further down, (b) TupleList::codeGen()
      // and yes, it needs to be in all three places.
      //
      // NOTE:  tmpAssign MUST BE ON HEAP --
      //   Cannot be done with a stack-allocated tmpAssign
      //   because ItemExpr destructor will delete children,
      //   which we (and parent) are still referencing!
      if (castTo) {
        const ColumnDescList &itms = *rtuple->getRETDesc()->getColumnList();
        for (CollIndex j = 0; j < (CollIndex)itms.entries(); j++) {
          ValueId src = itms[j]->getValueId();

          Assign *tmpAssign = new(bindWA->wHeap())
            Assign(castToList()[j].getItemExpr(), src.getItemExpr());
          tmpAssign = (Assign *)tmpAssign->bindNode(bindWA);
          if (bindWA->errStatus()) return this;
        }
      }

      if (!boundExpr)
        boundExpr = rtuple;
      else
        boundExpr = new(bindWA->wHeap()) Union(boundExpr, rtuple);
    } // for loop over tupleList

    CMPASSERT(boundExpr);
    return boundExpr->bindNode(bindWA);

  } // containsSubquery

  // Detach the item expression tree for the value list and bind it.
  // We use counterForRowValues() and pass in parent, for DEFAULT processing
  // (Ansi 7.1 SR 1).
  //
  CollIndex counterRowVals = 0;
  CMPASSERT(!bindWA->getCurrentScope()->context()->counterForRowValues());
  bindWA->getCurrentScope()->context()->counterForRowValues() = &counterRowVals;

  // tupleExprTree() contains a list of tuples.
  // Each tuple is also a list of values (this list may contain one item).
  // Bind all values in all the tuples.
  // Check that the number of elements in each tuple is the same,
  // and that the types of corresponding elements are compatible.
  //
  numberOfTuples_ = tupleList.entries();
  CollIndex prevTupleNumEntries = NULL_COLL_INDEX;

  // A list of ValueIdUnions nodes.  Will create as many as there are
  // entries in each tuple.  The valIds from corresponding elements of
  // the tuples will be added so that each ValueIdUnion represents a
  // column of the tuple virtual table.  Used to determine the
  // union-compatible type to be used for the result type produced by
  // the tuplelist.
  // 
  ItemExprList vidUnions(bindWA->wHeap());
  ValueIdUnion *vidUnion;

  CollIndex i = 0;
  CollIndex nEntries = (CollIndex)tupleList.entries() ;
  for (i = 0; i < nEntries ; i++) {

    counterRowVals = 0;

    ValueIdList vidList;
    ItemExpr *tuple = tupleList[i]->child(0)->castToItemExpr();
    tuple->convertToValueIdList(vidList, bindWA, ITM_ITEM_LIST, this);
    if (bindWA->errStatus())
      return NULL;

    if (prevTupleNumEntries == NULL_COLL_INDEX) {
      prevTupleNumEntries = vidList.entries();
    }
    else if (prevTupleNumEntries != vidList.entries()) {
      // 4126 The row-value-ctors of a VALUES must be of equal degree.
      *CmpCommon::diags() << DgSqlCode(-4126);
      bindWA->setErrStatus();
      return NULL;
    }

    // Genesis 10-980611-7153
    if (castTo && prevTupleNumEntries != castToList().entries()) break;

    for (CollIndex j = 0; j < prevTupleNumEntries; j++) {
      // If any unknown type in the tuple, coerce it to the target type.
      // Also do same MP-NCHAR magic as above.
      if (castTo) {
        ValueId src = vidList[j];
        src.coerceType(castToList()[j].getType());

        // tmpAssign MUST BE ON HEAP -- see note above!
        Assign *tmpAssign = new(bindWA->wHeap())
          Assign(castToList()[j].getItemExpr(), src.getItemExpr());
        tmpAssign = (Assign *)tmpAssign->bindNode(bindWA);
        if (bindWA->errStatus()) 
          return this;

      }
 
      if(i == 0) {
        ValueIdList vids;

        // Create an empty ValueIdUnion.  Will create as many as there
        // are entries in each tuple.  Add the valIds from
        // corresponding elements of the tuples so that each
        // ValueIdUnion represents a column of the tuple virtual
        // table.
        //
        vidUnion = new(bindWA->wHeap()) 
          ValueIdUnion(vids, NULL_VALUE_ID);

        vidUnion->setWasDefaultClause(TRUE);

        vidUnions.insertAt(j, vidUnion);
      }

      // Add the valIds from corresponding elements of the tuples so
      // that each ValueIdUnion represents a column of the tuple
      // virtual table.
      //
      vidUnion = (ValueIdUnion *)vidUnions[j];
      vidUnion->setSource((Lng32)i, vidList[j]);
        
      if (NOT vidList[j].getItemExpr()->wasDefaultClause())
        vidUnion->setWasDefaultClause(FALSE);
    } // for loop over entries in tuple

  } // for loop over tupleList

  if (castTo && prevTupleNumEntries != castToList().entries()) 
  {

    // 4023 degree of row value constructor must equal that of target table
    *CmpCommon::diags() << DgSqlCode(-4023)
                        << DgInt0((Lng32)prevTupleNumEntries)
                        << DgInt1((Lng32)castToList().entries());
    bindWA->setErrStatus();
    return NULL;
  }

  // do INFER_CHARSET fixup
  if (!doInferCharSetFixup(bindWA, CharInfo::ISO88591, prevTupleNumEntries, 
                           tupleList.entries())) {
    return NULL;
  }

  ItemExpr * outputList = NULL;
  for (CollIndex j = 0; j < prevTupleNumEntries; j++) {

    // Get the ValueIdUnion node corresponding to this column of the
    // tuple list virtual table
    //
    vidUnion = (ValueIdUnion *)vidUnions[j];

    if (castTo) {
      // Make sure the place holder type can support all the values in
      // the tuple list and target column
      //
      vidUnion->setSource(numTuples(), castToList()[j]);

      vidUnion->setIsCastTo(TRUE);
    }

    vidUnion->bindNode(bindWA);
    if (bindWA->errStatus())
      return NULL;

    if (castTo) {
      // Check that the source and target types are compatible.
      //   Cannot be done with a stack-allocated tmpAssign
      //   because ItemExpr destructor will delete children,
      //   which we (and parent) are still referencing!
      Assign *tmpAssign = new(bindWA->wHeap())
        Assign(castToList()[j].getItemExpr(), vidUnion);

      if ( CmpCommon::getDefault(ALLOW_IMPLICIT_CHAR_CASTING) == DF_ON )
      {
        tmpAssign->tryToDoImplicitCasting(bindWA);
      }
      const NAType *targetType = tmpAssign->synthesizeType();
      if (!targetType) {
        bindWA->setErrStatus();
        return NULL;
      }
    }
  

    NAType *phType = vidUnion->getValueId().getType().newCopy(bindWA->wHeap());

    NATypeToItem *placeHolder = new(bindWA->wHeap()) NATypeToItem(phType);

    Cast * cnode;
    if (castTo)
      {
        cnode = new(bindWA->wHeap()) Cast(placeHolder, phType, ITM_CAST, TRUE);
        if (vidUnion->getValueId().getItemExpr()->wasDefaultClause())
          cnode->setWasDefaultClause(TRUE);
      }
    else
      cnode = new(bindWA->wHeap()) Cast(placeHolder, phType);
    cnode->setConstFoldingDisabled(TRUE);
    cnode->bindNode(bindWA);

    if (!outputList)
      outputList = cnode;
    else
      outputList = new(bindWA->wHeap()) ItemList(outputList, cnode);
  }

  setRETDesc(bindRowValues(bindWA, outputList, tupleExpr(), this, FALSE));

  if (bindWA->errStatus()) return this;

  bindWA->getCurrentScope()->context()->counterForRowValues() = NULL;

  // Bind the base class.
  //
  boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus()) return this;

   // need to add system columns as well....?

  NABoolean inSubquery = FALSE;
  BindScope *currScope   = bindWA->getCurrentScope();
  BindScope *prevScope   = bindWA->getPreviousScope(currScope);
  if (prevScope)
    inSubquery = prevScope->context()->inSubquery();

  if (inSubquery)
  {
    // need to change tupleExpr() & make it null-instantiated as RETDesc stores
    // null instantiated columns (most probably these are constants, but not
    // necessarily)

    const ColumnDescList *viewColumns = getRETDesc()->getColumnList();

    tupleExpr().clear();
    for (CollIndex k=0; k < viewColumns->entries(); k++)
    {
      ValueId vid = (*viewColumns)[k]->getValueId();

      // Special logic in Normalizer to optimize away a LEFT JOIN is not to
      // be explored there, as this is not a LEFT JOIN
      // Genesis case: 10-010312-1675
      // If the query were to be a LEFT JOIN, we would not be here
      if (vid.getItemExpr()->getOperatorType() == ITM_INSTANTIATE_NULL)

        {
          ((InstantiateNull *)vid.getItemExpr())->NoCheckforLeftToInnerJoin
                       = TRUE;
        }

      tupleExpr().insert(vid);
    }
  }
  getGroupAttr()->addCharacteristicOutputs(tupleExpr());

  return boundExpr;
} // TupleList::bindNode()

// set vidlist = ith tuple of this tuplelist and return TRUE
RelExpr* TupleList::getTuple
(BindWA *bindWA, ValueIdList& vidList, CollIndex i)
{
  ExprValueId eVid(tupleExprTree());
  ItemExprTreeAsList tupleList(&eVid, ITM_ITEM_LIST);
  ItemExpr *tuple = tupleList[i]->child(0)->castToItemExpr();
  tuple->convertToValueIdList(vidList, bindWA, ITM_ITEM_LIST, this);
  return bindWA->errStatus() ? NULL : this;
}

// set needsFixup to TRUE iff tuplelist needs INFER_CHARSET fixup
RelExpr*
TupleList::needsCharSetFixup(BindWA *bindWA, 
                             CollIndex arity, 
                             CollIndex nTuples,
                             NAList<NABoolean> &strNeedsFixup,
                             NABoolean &needsFixup)
{
  // assume it needs no INFER_CHARSET fixup until proven otherwise
  needsFixup = FALSE;
  if (CmpCommon::wantCharSetInference()) {
    CollIndex t, x;
    for (x = 0; x < arity; x++) { // initialize
      strNeedsFixup.insert(FALSE); 
    }
    // go thru tuplelist looking for unprefixed string literals
    for (t = 0; t < nTuples; t++) {
      // get tuple
      ValueIdList tup;
      if (!getTuple(bindWA, tup, t)) {
        return NULL; // something wrong
      } 
      else {
        // go thru columns of tuple looking for unprefixed string literals
        for (x = 0; x < arity; x++) {
          if (!strNeedsFixup[x] && tup[x].inferableCharType()) {
            strNeedsFixup[x] = TRUE;
            needsFixup = TRUE;
          }
        }
      }
    }
  }
  return this; // all OK
}

// find fixable strings' inferredCharTypes
RelExpr*
TupleList::pushDownCharType(BindWA *bindWA,
                            enum CharInfo::CharSet cs,
                            NAList<const CharType*> &inferredCharType,
                            NAList<NABoolean> &strNeedsFixup,
                            CollIndex arity, 
                            CollIndex nTuples)
{
  // mimic CharType::findPushDownCharType() logic
  const CharType* dctp = CharType::desiredCharType(cs);
  NAList<const CharType*> sampleCharType(CmpCommon::statementHeap(),arity);
  NAList<Int32> total(CmpCommon::statementHeap(),arity);
  NAList<Int32> ct   (CmpCommon::statementHeap(),arity);
  CollIndex t, x;
  for (x = 0; x < arity; x++) { // initialize
    total.insert(0);
    ct.insert(0);
    sampleCharType.insert(NULL);
  }
  // go thru tuplelist looking for fixable strings' inferredCharType
  for (t = 0; t < nTuples; t++) {
    // get tuple
    ValueIdList tup;
    if (!getTuple(bindWA, tup, t)) {
      return NULL; // something wrong
    }
    else {
      // go thru tuple looking for fixable strings' inferredCharType
      for (x = 0; x < arity; x++) {
        if (strNeedsFixup[x]) {
          total[x] += 1;
          const CharType *ctp;
          if (tup[x].hasKnownCharSet(&ctp)) {
            ct[x] += 1;
            if (sampleCharType[x] == NULL) {
              sampleCharType[x] = ctp;
            }
          }
        }
      }
    }
  }
  for (x = 0; x < arity; x++) {
    if (ct[x] == total[x]) { 
      // all have known char set or none need fixup
      inferredCharType.insert(NULL); // nothing to fix
    }
    else {
      inferredCharType.insert(sampleCharType[x] ? sampleCharType[x] : dctp);
    }
  }
  return this; // all OK
}

// do INFER_CHARSET fixup
RelExpr*
TupleList::doInferCharSetFixup(BindWA *bindWA,
                               enum CharInfo::CharSet cs,
                               CollIndex arity, 
                               CollIndex nTuples)
{
  NABoolean needsFixup;
  NAList<NABoolean> strNeedsFixup(CmpCommon::statementHeap(),arity);
  RelExpr *result = needsCharSetFixup
    (bindWA, arity, nTuples, strNeedsFixup, needsFixup);
  if (!result || // something went wrong
      !needsFixup) { // no INFER_CHARSET fixup needed
    return result;
  }
  else { // some string literal needs INFER_CHARSET fixup
    NAList<const CharType*> inferredCharType(CmpCommon::statementHeap(),arity);
    if (!pushDownCharType(bindWA, cs, inferredCharType, 
                          strNeedsFixup, arity, nTuples)) {
      return NULL; // something went wrong
    }
    else {
      // go thru tuplelist fixing up literals' char sets
      CollIndex t, x;
      for (t = 0; t < nTuples; t++) {
        // get tuple
        ValueIdList tup;
        if (!getTuple(bindWA, tup, t)) {
          return NULL; // something went wrong
        }
        else {
          // go thru tuple fixing up literals' char sets
          for (x = 0; x < arity; x++) {
            if (strNeedsFixup[x] && tup[x].inferableCharType()) {
              // coerce literal to have column's inferred char set
              tup[x].coerceType(*(inferredCharType[x]), NA_CHARACTER_TYPE);
            }
          }
        }
      }
    }
  }
  return this;
}

// -----------------------------------------------------------------------
// member functions for class RenameTable
// -----------------------------------------------------------------------

RelExpr *RenameTable::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc()); // -- Triggers
    return this;
  }

  //
  // Create a new table name scope.
  //
  bindWA->getCurrentScope()->xtnmStack()->createXTNM();

  // code to enforce the specification that if an index expression is specified
  // with a rowset and the index is included in the derived table, the index
  // must be the last column of the derived column list
  if((getTableName().getCorrNameAsString() != "Rowset___") && (getArity() != 0))
    {
       if(child(0)->getOperatorType() == REL_ROWSET)
         {
           NAString indexExpr(bindWA->wHeap());
           NAString lastString("", bindWA->wHeap());
           ItemExpr *tempPtr;

           indexExpr = ((Rowset *)getChild(0))->getIndexName();
           if((indexExpr != "") && newColNamesTree_)
             {
                for (tempPtr = newColNamesTree_; tempPtr; tempPtr=tempPtr->child(1))
                  {
                     Int32 arity = tempPtr->getArity();
                     if(arity == 1)
                       {
                          lastString = ((RenameCol *)tempPtr)->getNewColRefName()->getColName();
                       }
                  }
                if(indexExpr != lastString)
                  {
                     *CmpCommon::diags() << DgSqlCode(-30012)
                              << DgString0(indexExpr)
                              << DgString1(getTableName().getCorrNameAsString());
                     bindWA->setErrStatus();
                     return NULL;
                  }
             }
         }
    }

  //
  // Bind the child nodes.
  //
  bindChildren(bindWA);
  if (bindWA->errStatus()) return this;

  //
  // Remove the table name scope.
  //
  bindWA->getCurrentScope()->xtnmStack()->removeXTNM();
  //
  // Create the result table.
  //
  RETDesc *resultTable = new (bindWA->wHeap()) RETDesc(bindWA);
  const RETDesc &sourceTable = *child(0)->getRETDesc();
  const CorrName &tableName = getTableName();
  ItemExpr *derivedColTree = removeColNameTree();
  ItemExprList derivedColList(bindWA->wHeap());
  const NAString *simpleColNameStr;
  CollIndex i;
  //
  // Check that there are an equal number of columns to values.
  //
  if (derivedColTree) {
    derivedColList.insertTree(derivedColTree);
    if (derivedColList.entries() != sourceTable.getDegree()) {
      // 4016 The number of derived columns must equal the degree of the derived table.
      *CmpCommon::diags() << DgSqlCode(-4016)
        << DgInt0(derivedColList.entries()) << DgInt1(sourceTable.getDegree());
      bindWA->setErrStatus();
      delete resultTable;
      return this;
    }
  }
  //
  // Insert the derived column names into the result table.
  // By ANSI 6.3 SR 6 (applies to explicit derived column list),
  // duplicate names are not allowed.
  // If user did not specify a derived column name list,
  // expose the select list's column names (implicit derived column list);
  // ANSI does not say that these cannot be duplicates --
  // if there's a later (i.e. in an outer scope) reference to a duplicately
  // named column, ColReference::bindNode will issue an error
  // (in particular, if all references are to constants, e.g. "count(*)",
  // then duplicates are not disallowed in the implicit derived column list!).
  //
  // When Create View DDL uses this Binder, we must enforce
  // ANSI 11.19 SR 8 + 9, clearly disallowing dups/ambigs
  // (and disallowing implem-dependent names, i.e. our unnamed '(expr)' cols!).
  //
  for (i = 0; i < sourceTable.getDegree(); i++) {
    //
    if (derivedColTree) {      // explicit derived column list
      CMPASSERT(derivedColList[i]->getOperatorType() == ITM_RENAME_COL);
      simpleColNameStr = &((RenameCol *) derivedColList[i])->
                                     getNewColRefName()->getColName();
      if (*simpleColNameStr != "") {   // named column, not an expression
        if (resultTable->findColumn(*simpleColNameStr)) {
          ColRefName errColName(*simpleColNameStr, tableName);
          // 4017 Derived column name $ColumnName was specified more than once.
          *CmpCommon::diags() << DgSqlCode(-4017)
            << DgColumnName(errColName.getColRefAsAnsiString());
          bindWA->setErrStatus();
          delete resultTable;
          return this;
        }
      }
    } else            // implicit derived column list
      simpleColNameStr = &sourceTable.getColRefNameObj(i).getColName();
    //
    ColRefName colRefName(*simpleColNameStr, tableName);
    ValueId valId = sourceTable.getValueId(i);
    resultTable->addColumn(bindWA, colRefName, valId);
  } // for-loop
  //
  // Insert system columns similarly, completely ignoring dup names.
  //
  const ColumnDescList &sysColList = *sourceTable.getSystemColumnList();
  for (i = 0; i < sysColList.entries(); i++) {
    simpleColNameStr = &sysColList[i]->getColRefNameObj().getColName();
    if (NOT resultTable->findColumn(*simpleColNameStr)) {
      ColRefName colRefName(*simpleColNameStr, tableName);
      ValueId valId = sysColList[i]->getValueId();   // (slight diff from the
      resultTable->addColumn(bindWA, colRefName, valId, SYSTEM_COLUMN);   //above)
    }
  }
  setRETDesc(resultTable);

  // MVs --
  // When binding INTERNAL REFRESH commands, the SYSKEY and @OP columns should
  // be propageted to the scope above, even when they are not specified in the
  // select list.
  if (bindWA->isPropagateOpAndSyskeyColumns())
    getRETDesc()->propagateOpAndSyskeyColumns(bindWA, FALSE);

  bindWA->getCurrentScope()->setRETDesc(resultTable);
  //
  // Insert the table name into the XTNM,
  // casting away constness on the correlation name
  // in order to have default cat+sch filled in.
  //
  bindWA->getCurrentScope()->getXTNM()->insertNames(bindWA,
                                                    (CorrName &)tableName);

  if (bindWA->errStatus()) {
    delete resultTable;
    return this;
  }

  if (getViewNATable())
  {
    const NATable * natable = getViewNATable() ;
    const ColumnDescList &columnsRET = *(resultTable->getColumnList());
    for (i = 0; i < natable->getColumnCount(); i++)
    {
      columnsRET[i]->setViewColPosition(
        ((natable->getNAColumnArray())[i])->getPosition());
      columnsRET[i]->setViewFileName((const char*)natable->getViewFileName());
    }
  }

  //
  // Bind the base class.
  //
  return bindSelf(bindWA);
} // RenameTable::bindNode()

// -----------------------------------------------------------------------
// member functions for class RenameReference
// -----------------------------------------------------------------------

// This method replaces the RETDesc of the current scope, with a new RETDesc
// that contains the columns of the transition values (OLD@ and NEW@) but
// with correlation names specified by the user in the REFERENCING clause
// of the row trigger.
void RenameReference::prepareRETDescWithTableRefs(BindWA *bindWA)
{
  CollIndex  refsToFind = getRefList().entries();
  CollIndex  refsFound = 0;
  RETDesc   *retDesc;

  // First find the NEW@ and OLD@ tables in one of the scopes.
  BindScope *scope = bindWA->getCurrentScope();
  // For each BindScope,
  while ((scope!=NULL) && (refsToFind > refsFound))
  {    // until we find all the references.
    retDesc = scope->getRETDesc();
    // Skip if an empty RETDesc
    if ((retDesc!=NULL) && !retDesc->isEmpty())
    {
      // For each reference to change
      for (CollIndex i=0; i<refsToFind; i++)
        // Find the table name in the RETDesc, and save a pointer to it's
        // column list in the TableRefName object.
        if(getRefList().at(i).lookupTableName(retDesc))
          refsFound++;
    }

    // Get the next BindScope to search.
    scope = bindWA->getPreviousScope(scope);
  } // while not done

  RETDesc *resultTable = new (bindWA->wHeap()) RETDesc(bindWA);

  // Create an empty RETDesc for the current scope.
  bindWA->getCurrentScope()->setRETDesc(resultTable);

  // For each table reference, add to the RETDesc of the current scope, the
  // columns of the columns of the referenced tables with the new referencing
  // names as correlation names.
  for (CollIndex i=0; i<refsToFind; i++)
    getRefList()[i].bindRefColumns(bindWA);
}

// The RenaneReference node renames values flowing down through it.
// It is used above a row trigger body, to implement the REFERENCING clause
// of the trigger definition - renaming the OLD and NEW transition variables
// to user specified names.
//
// This bind is top-down, so we first prepare the RETDesc, and then bind
// the children using this RETDesc.
RelExpr *RenameReference::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  // Save the current RETDesc.
  RETDesc *prevRETDesc = bindWA->getCurrentScope()->getRETDesc();

  // Replace the RETDesc of the current scope with one that contains the user
  // names (MY_NEW, MY_OLD) instead of the reference names (NEW@, OLD@).
  prepareRETDescWithTableRefs(bindWA);

  // Bind the child nodes, in a new BindScope.
  // If we don't open a new scope here, the bindChildren() method will
  // overwrite the RETDesc of the current scope with NULL.
  bindWA->initNewScope();

  bindChildren(bindWA);
  if (bindWA->errStatus())
    return this;

  // Bind the base class.
  RelExpr *boundNode = bindSelf(bindWA);

  // Save this scope's outer references before removing the scope.
  const ValueIdSet myOuterRefs = bindWA->getCurrentScope()->getOuterRefs();

  setRETDesc(bindWA->getCurrentScope()->getRETDesc());

  bindWA->removeCurrentScope();
  bindWA->getCurrentScope()->setRETDesc(prevRETDesc);

  // Now merge the outer references into the previous scope.
  bindWA->getCurrentScope()->mergeOuterRefs(myOuterRefs, FALSE);

  return boundNode;
}  // RenameReference::bindNode()

// -----------------------------------------------------------------------
// member functions for class BeforeTrigger
// -----------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////
// Find the name and position of a column SET to by this before Trigger.
// The targetColName is an output parameter, saving the bindSetClause()
// method the work of finding the column name.
// The naTable parameter is NULL during DML. and is only used for DDL
// semantic checks.
//////////////////////////////////////////////////////////////////////////////
Lng32 BeforeTrigger::getTargetColumn(CollIndex i,  // Index of Assign expr.
                                    ColRefName* targetColName,
                                    const NATable *naTable)
{
  ItemExpr *currentAssign = setList_->at(i);
  CMPASSERT(currentAssign->getOperatorType() == ITM_ASSIGN);

  ItemExpr *targetColReference = currentAssign->child(0);
  CMPASSERT(targetColReference->getOperatorType() == ITM_REFERENCE);
  ColRefName& targetColRefName =
    ((ColReference *)targetColReference)->getColRefNameObj();

  if (targetColName != NULL)  // return the column name to the binder.
    *targetColName = targetColRefName;

  const NAString& colName = targetColRefName.getColName();

  // If called during DML binding of the BeforeTrigger node, the
  // column position will not be used, because the check for duplicate
  // SET columns was done in DDL time.
  if (naTable == NULL)
    return 0;

  // We get here from DDL binding of the BeforeTrigger node, or from
  // the Inlining code.
  NAColumn *colObj  = naTable->getNAColumnArray().getColumn(colName);

  // If colObj is NULL, it's a bad column name.
  if (colObj == NULL)
    return -1;

  return colObj->getPosition();
}

//////////////////////////////////////////////////////////////////////////////
// This method is called only during DDL (CREATE TRIGGER) of a before trigger
// with a SET clause.
// Each of the columns updated by the SET clause goes through several
// semantic checks, that cannot be done in the parser.
//////////////////////////////////////////////////////////////////////////////
void BeforeTrigger::doSetSemanticChecks(BindWA *bindWA, RETDesc *origRETDesc)
{
  UpdateColumns localCols = UpdateColumns(FALSE);
  ColRefName currentCol;
  const NATable *scanNaTable = NULL;
  NABoolean isUpdateOp=FALSE;

  Scan *scanNode = getLeftmostScanNode();
  CMPASSERT(scanNode != NULL);
  scanNaTable = scanNode->getTableDesc()->getNATable();

  CorrName oldCorr(OLDCorr);
  if (origRETDesc->getQualColumnList(oldCorr))
    isUpdateOp = TRUE;

  for (CollIndex i=0; i<setList_->entries(); i++)
  {
    // Get the name and position of the Assign target column.
    Lng32 targetColPosition = getTargetColumn(i, &currentCol, scanNaTable);

    if (!currentCol.getCorrNameObj().isATriggerTransitionName(bindWA, TRUE))
    {
      // 11017 Left hand of SET assignment must be qualified with the name of the NEW transition variable
      *CmpCommon::diags() << DgSqlCode(-11017) ; // must be NEW name
      bindWA->setErrStatus();
      return;
    }

    if (targetColPosition == -1)
    {
      // 11022 Column $0~ColumnName is not a column in table $0~TableName
      NAString tableName = scanNaTable->getTableName().getQualifiedNameAsString();
      *CmpCommon::diags() << DgSqlCode(-11022)
        << DgColumnName(currentCol.getColName())
        << DgTableName(tableName);
      bindWA->setErrStatus();
      return;
    }

    // We need to check for duplicate SET columns in DDL time only.
    if (localCols.contains(targetColPosition))
    {
      // 4022 column specified more than once
      *CmpCommon::diags() << DgSqlCode(-4022)
        << DgColumnName(currentCol.getColName());
      bindWA->setErrStatus();
      return;
    }
    localCols.addColumn(targetColPosition);

    // Is this a SET into a column that is part of the clustering key?
    // This is only allowed on Inserts, not on Updates (Deletes never get here).
    if (isUpdateOp  &&
      scanNaTable->getNAColumnArray().getColumn(targetColPosition)->isClusteringKey())
    {
      // 4033 Column $0~ColumnName is a primary or clustering key column and cannot be updated.
      *CmpCommon::diags() << DgSqlCode(-4033)
        << DgColumnName(currentCol.getColName());
      bindWA->setErrStatus();
      return;
    }
  }
}

//////////////////////////////////////////////////////////////////////////////
// This method is called for before triggers that use the SET clause.
// For each column to be set using SET MYNEW.<colname> = <setExpr> do:
// 1. Find NEW@.<colname> in origRETDesc.
// 2. Verify that there is such a column, and that the user is allowd to
//    change it.
// 3. Get the column's ItemExpr expression, and save it in passThruExpr.
// 4. Create an ItemExpr tree as follows:
//                     case
//                       |
//                  IfThenElse
//                 /     |     \
//        condition    setExpr  passThruExpr
//
//    where condition is the WHEN clause expression.
// 5. Bind this new expression in the RETDesc of the current scope.
// 6. remove NEW@.<colname> from origRETDesc, and re-insert it as the new
//    expression.
//////////////////////////////////////////////////////////////////////////////
void BeforeTrigger::bindSetClause(BindWA *bindWA, RETDesc *origRETDesc, CollHeap *heap)
{
  // Semantic checks are only needed during DDL.
  if (bindWA->inDDL())
  {
    doSetSemanticChecks(bindWA, origRETDesc);
    if (bindWA->errStatus())
      return;
  }

  CorrName newCorr(NEWCorr);
  const TableRefName *newRefName = getRefList().findTable(newCorr);
  CMPASSERT(newRefName!=NULL);
  CorrName newRef = newRefName->getTableCorr();
  ColRefName currentCol;

  // For each Assign expression in the list.
  for (CollIndex i=0; i<setList_->entries(); i++)
  {
    // Get the name and position of the Assign target column.
    Lng32 targetColPosition = getTargetColumn(i, &currentCol, NULL);

    currentCol.getCorrNameObj() = newRef;
    ItemExpr *setExpr = setList_->at(i)->child(1);
    // Find the current value of this NEW@ column.
    ColumnNameMap *currentColExpr = origRETDesc->findColumn(currentCol);
    CMPASSERT(currentColExpr != NULL); // Otherwise we would have been thrown with error 11022 - see above.
    ItemExpr *passThruExpr = currentColExpr->getValueId().getItemExpr();

    ItemExpr *colExpr = NULL;
    if (whenClause_ == NULL)
      // After we add the support for reading the trigger status from
      // the resource fork, and adding it to the condition, we should
      // never get here.
      colExpr = setExpr;
    else
    {
      IfThenElse *ifExpr = new(heap)
        IfThenElse(whenClause_, setExpr, passThruExpr);
      colExpr = new(heap) Case(NULL, ifExpr);
    }
    colExpr = colExpr->bindNode(bindWA);
    if (bindWA->errStatus())
    return;

    // Now remove and re-insert the column to the original RETDesc,
    // that will be restored at the bottom of the method.
      currentCol.getCorrNameObj() = newCorr;
    origRETDesc->delColumn(bindWA, currentCol, USER_COLUMN);
    origRETDesc->addColumn(bindWA, currentCol, colExpr->getValueId());

          // force binding of the assign here so that type incompatability is caught
          // during DDL
          if (bindWA->inDDL())
          {
               ItemExpr *currentAssign = setList_->at(i);
               CMPASSERT(currentAssign->getOperatorType() == ITM_ASSIGN);
               currentAssign->bindNode(bindWA);
          }
  }
}

//////////////////////////////////////////////////////////////////////////////
// This method is called for before triggers that use the SIGNAL clause.
// 1. Find the "virtual execId column" in origRETDesc.
// 3. Get the column's ItemExpr expression, and save it in passThruExpr.
// 4. Create an ItemExpr tree as follows:
//                     case
//                       |
//                  IfThenElse
//                 /     |       \
//              AND  passThruExpr passThruExpr
//            /    \
//    condition     RaiseError
//
//    where condition is the WHEN clause expression, and RaiseError is the
//    SIGNAL expression.
// 5. Bind this new expression in the RETDesc of the current scope.
// 6. remove "virtual execId column" from origRETDesc, and re-insert it as
//    the new expression.
//
// The value of the expression is always the passThruExpr, for type
// compatibility. since if the SIGNAL fires, the actual value returned does
// not matter. The AND will evaluate the RaiseError only if the condition
// evaluates to TRUE.
//////////////////////////////////////////////////////////////////////////////
void BeforeTrigger::bindSignalClause(BindWA *bindWA, RETDesc *origRETDesc, CollHeap *heap)
{
  if (bindWA->inDDL())
  {
    // In DDL time (CREATE TRIGGER) all we need is to bind the signal
    // expression for semantic checks.
    signal_->bindNode(bindWA);
    if (bindWA->errStatus())
    return;
  }
  else
  {
    // The SIGNAL expression is piggy-backed on the Unique ExecuteID
    // value inserted into the temp table.
    ColumnNameMap *execIdCol =
      origRETDesc->findColumn(InliningInfo::getExecIdVirtualColName());
    CMPASSERT(execIdCol != NULL);
    const ColRefName& ExecIdColName = execIdCol->getColRefNameObj();
    ItemExpr *passThruExpr = execIdCol->getValueId().getItemExpr();
    ItemExpr *whenAndSignal = NULL;

    // Case 10-040604-5021:
    // General AND logic uses "short circuiting" as follows: if the
    // left side is FALSE, evaluation of the right side is skipped, and
    // the result returned is FALSE. The following expression depends on
    // evaluation of the right side being skipped whenever the left side
    // is NOT TRUE, (i.e., FALSE or NULL). Therefore, an IS TRUE unary
    // predicate must be placed above the actual WHEN condition. Otherwise,
    // the signal will fire when the WHEN condition evaluates to NULL.
    if (whenClause_ != NULL)
    {
         if (whenClause_->getOperatorType() == ITM_AND ||
             whenClause_->getOperatorType() == ITM_OR)
         {
             ItemExpr *isTrueExpr = new (heap) UnLogic(ITM_IS_TRUE, whenClause_);
             whenAndSignal = new(heap) BiLogic(ITM_AND, isTrueExpr, signal_);
         }
         else
         {
             whenAndSignal = new(heap) BiLogic(ITM_AND, whenClause_, signal_);
         }
    }

    else
      // After we add the support for reading the trigger status from
      // the resource fork, and adding it to the condition, we should
      // never get here.
      whenAndSignal = signal_;

    // For type compatibity, the original value is used whatever the
    // WHEN clause evaluates to. However, if it evaluates to TRUE, the
    // evaluation of the signal expression will throw an SQLERROR.
    ItemExpr *condSignalExpr = new(heap)
      Case(NULL, new(heap)
        IfThenElse(whenAndSignal, passThruExpr, passThruExpr));
    condSignalExpr = condSignalExpr->bindNode(bindWA);
    if (bindWA->errStatus())
      return;

    // Now delete the original "virtual column" from the RETDesc, and
    // re-insert it with the new value.
    origRETDesc->delColumn(bindWA, ExecIdColName, USER_COLUMN);
    origRETDesc->addColumn(bindWA, ExecIdColName, condSignalExpr->getValueId());
  }
}

//////////////////////////////////////////////////////////////////////////////
// This bind is bottom-up, so we first bind the children, and then use
// and change the RETDesc they created.
//////////////////////////////////////////////////////////////////////////////
RelExpr *BeforeTrigger::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  bindChildren(bindWA);
  if (bindWA->errStatus())
    return this;

  // Now we know that we have the columns of OLD@ and NEW@ in the RETDesc
  // of the current scope. Save this scope so we can update it and restore
  // it when we are done.
  RETDesc   *origRETDesc = bindWA->getCurrentScope()->getRETDesc();
  CollHeap  *heap = bindWA->wHeap();
  CollIndex  refsToFind = getRefList().entries();

  // For each reference to change, Find the table name in the RETDesc,
  // and save a pointer to it's column list in the TableRefName object.
  CollIndex i=0;
  for (i=0; i<refsToFind; i++)
    getRefList().at(i).lookupTableName(origRETDesc);

  // Create an empty RETDesc for the current scope.
  // It will contain the names the user specified (MY_NEW, MY_OLD) for the
  // OLD@ and NEW@ transition variables, and will be used to bind this
  // node only.
  bindWA->getCurrentScope()->setRETDesc(new(heap) RETDesc(bindWA));

  // For each table reference, add to the RETDesc of the current scope,
  // the columns of the referenced tables with the new referencing names
  // as correlation names.
  for (i=0; i<refsToFind; i++)
    getRefList().at(i).bindRefColumns(bindWA);

  // First bind the condition. The ValueId will be used later (possibly
  // multiple times) so that during execution, the expression will be
  // evaluated only once.
  if (whenClause_ != NULL)
  {
    whenClause_ = whenClause_->bindNode(bindWA);
    if (bindWA->errStatus())
      return this;
  }

  // Use the bound condition to prepare the conditional expression
  // for each column modified by the trigger (SET MY_NEW.a = ...)
  if (setList_ != NULL)
    bindSetClause(bindWA, origRETDesc, heap);

  // Use the bound condition to prepare the conditional SIGNAL
  // expression, on the ExecuteId "virtual column".
  if (signal_ != NULL)
    bindSignalClause(bindWA, origRETDesc, heap);

  if (bindWA->errStatus())
    return this;

  // We don't need the RETDesc of the current scope anymore. Restore the
  // original RETDesc with the updated columns.
  bindWA->getCurrentScope()->setRETDesc(origRETDesc);
  if (parentTSJ_ != NULL)
  {
    // If this is the top most before trigger, save a copy of the RETDesc
    // for use by the transformNode() pass.
    RETDesc *savedRETDesc = new(heap) RETDesc(bindWA, *origRETDesc);
    setRETDesc(savedRETDesc);
  }
  //
  // Bind the base class.
  //
  RelExpr *boundNode = bindSelf(bindWA);

  return boundNode;
} // BeforeTrigger::bindNode()

// -----------------------------------------------------------------------
// member functions for class Insert
// -----------------------------------------------------------------------
static void bindInsertRRKey(BindWA *bindWA, Insert *insert,
                            ValueIdList &sysColList, CollIndex i)
{
  // For a KS round-robin partitioned table, the system column
  // (for now there is only one, SYSKEY) is initialized via the expression
  // "ProgDistribKey(partNum, rowPos, totalNumParts)".
  //
  const NAFileSet *fs =
    insert->getTableDesc()->getClusteringIndex()->getNAFileSet();

  // For now, round-robin partitioned tables are always stored in
  // key-sequenced files, and there is only one system column (SYSKEY)
  // which is at the beginning of the record.
  CMPASSERT(fs->isKeySequenced() && i==0);

  CollHeap *heap = bindWA->wHeap();

  // Host variables that provide access to partition number,
  // row position, and total number of partitions --
  // supplied at run-time by the executor insert node.
  //
  ItemExpr *partNum = new (heap)
    HostVar("_sys_hostVarInsertPartNum",
      new (heap) SQLInt(heap, FALSE,FALSE),   // int unsigned not null
      TRUE // is system-generated
     );
  partNum->synthTypeAndValueId();
  insert->partNumInput() = partNum->getValueId();  // for later use in codeGen

  ItemExpr *rowPos = new (heap)
    HostVar("_sys_hostVarInsertRowPos",
      new (heap) SQLInt(heap, FALSE,FALSE),  // int unsigned not null
      TRUE // is system-generated
     );
  rowPos->synthTypeAndValueId();
  insert->rowPosInput() = rowPos->getValueId();  // for later use in codeGen

  ItemExpr *totNumParts = new (heap)
    HostVar("_sys_hostVarInsertTotNumParts",
      new (heap) SQLInt(heap, FALSE,FALSE),  // int unsigned not null
      TRUE // is system-generated
     );
  totNumParts->synthTypeAndValueId();
  insert->totalNumPartsInput() = totNumParts->getValueId();   // for later use

  // Generate expression to compute a round-robin key.  Parameters to
  // ProgDistribKey are the partition number, the row position (which
  // is chosen randomly; the insert node will retry if a number is
  // selected that is already in use), and the total number of
  // partitions.
  ItemExpr *rrKey = new (heap) ProgDistribKey(partNum, rowPos, totNumParts);

  // Build and set round-robin key expression.
  Assign *assign = new (heap)
    Assign(sysColList[i].getItemExpr(), rrKey, FALSE /*not user-specified*/);
  assign->bindNode(bindWA);
  insert->rrKeyExpr() = assign->getValueId();
} // bindInsertRRKey

RelExpr *Insert::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  // Set local binding flags
  setInUpdateOrInsert(bindWA, this, REL_INSERT);
  // The 8108 (unique constraint on an ID column) error must be raised
  // only for system generated IDENTITY values and not for
  // user generated ID values. We use the GenericUpdate::identityColumnUniqueIndex_
  // to indicate to the EID that 8108 should be raised in place of 8102.
  // This variable is used to indicate that there is an IDENTITY column
  // in the table for which the system is generating the value

  // This is NULL if "DEFAULT VALUES" was specified,
  // non-NULL if a query-expr child was specified:  VALUES.., TABLE.., SELECT..
  RelExpr *someNonDefaultValuesSpecified = child(0);

  // Set flag for firstN in context
  if (child(0) && child(0)->getOperatorType() == REL_ROOT) // Indicating subquery
    if (child(0)->castToRelExpr() && 
        child(0)->castToRelExpr()->getFirstNRows() >= 0)
      if (bindWA && 
          bindWA->getCurrentScope() && 
          bindWA->getCurrentScope()->context())
        bindWA->getCurrentScope()->context()->firstN() = TRUE;

  if (NOT someNonDefaultValuesSpecified) {  // "DEFAULT VALUES" specified
    // Kludge up a dummy child before binding the GenericUpdate tree
    setChild(0, new(bindWA->wHeap()) Tuple(new(bindWA->wHeap()) SystemLiteral(0)));
  }

  // Bind the GenericUpdate tree.
  //
  RETDesc *incomingRETDescForSource = bindWA->getCurrentScope()->getRETDesc();
  RelExpr *boundExpr = GenericUpdate::bindNode(bindWA);
  if (bindWA->errStatus()) 
    return boundExpr;

  const NAFileSet* fileset = getTableDesc()->getNATable()->getClusteringIndex();
  const NAColumnArray& partKeyCols = fileset->getPartitioningKeyColumns();

  if (getTableDesc()->getNATable()->isHiveTable())
  {
    if (partKeyCols.entries() > 0)
      {
        // Insert into partitioned tables would require computing the target
        // partition directory name, something we don't support yet.
        *CmpCommon::diags() << DgSqlCode(-4222)
                            << DgString0("Insert into partitioned Hive tables");
        bindWA->setErrStatus();
        return this;
      }

    // specifying a list of column names to insert to is not yet supported
    if (insertColTree_) {
      *CmpCommon::diags() << DgSqlCode(-4223)
                          << DgString0("Target column list for insert into Hive table");
      bindWA->setErrStatus();
      return this;
    }
     
    // if my child is a TupleList, then all tuples are to be converted/cast
    // to the corresponding target type of the tgtColList.
    // Pass on the tgtColList to TupleList so it can generate the Cast nodes
    // with the target types during the TupleList::bindNode.
    if (child(0)->getOperatorType() == REL_TUPLE_LIST) {
      ValueIdList tgtColList;
      getTableDesc()->getUserColumnList(tgtColList);
      TupleList *tl = (TupleList *)child(0)->castToRelExpr();
      tl->castToList() = tgtColList;
    }
 
    RelExpr *feResult = FastExtract::makeFastExtractTree(
         getTableDesc(),
         child(0).getPtr(),
         getOverwriteHiveTable(),
         TRUE,  // called from within binder
         FALSE, // not a common subexpr
         bindWA);

    if (feResult)
      {
        feResult = feResult->bindNode(bindWA);
        if (bindWA->errStatus())
          return NULL;

        return feResult;
      }
    else
      return this;
  }

  if(!(getOperatorType() == REL_UNARY_INSERT &&
       (child(0)->getOperatorType() == REL_TUPLE || // VALUES (1,'b')
        child(0)->getOperatorType() == REL_TUPLE_LIST || // VALUES (1,'b'),(2,'Y')
        child(0)->getOperatorType() == REL_UNION))  &&      // VALUES with subquery
     (getOperatorType() != REL_LEAF_INSERT))
    {
      setInsertSelectQuery(TRUE);
    }



  // Prepare for any IDENTITY column checking later on
  NAString identityColumnName;
  NABoolean identityColumnGeneratedAlways = FALSE;
  
  identityColumnGeneratedAlways =
    getTableDesc()->isIdentityColumnGeneratedAlways(&identityColumnName);
    
  if ((getTableName().isVolatile()) &&
      (CmpCommon::context()->sqlSession()->volatileSchemaInUse()) &&
      (getTableName().getSpecialType() == ExtendedQualName::NORMAL_TABLE) &&
      ((ActiveSchemaDB()->getDefaults()).getAsLong(IMPLICIT_UPD_STATS_THRESHOLD) > -1) &&
      (bindWA->isInsertSelectStatement()) &&
      (NOT getTableDesc()->getNATable()->isVolatileTableMaterialized()))
    {
      if (NOT Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL))
        //      if (NOT Get_SqlParser_Flags(NO_IMPLICIT_VOLATILE_TABLE_UPD_STATS))
        {
          // treat this insert as a volatile load stmt.
          RelExpr * loadVolTab = 
            new (bindWA->wHeap()) 
            ExeUtilLoadVolatileTable(getTableName(),
                                     this,
                                     bindWA->wHeap());
          
          boundExpr = loadVolTab->bindNode(bindWA);
          if (bindWA->errStatus()) 
            return boundExpr;

          return boundExpr;
        }
      else
        {
          NATable * nat = (NATable*)(getTableDesc()->getNATable());
          nat->setIsVolatileTableMaterialized(TRUE);
        }
    }

  // Now we have to create the following three collections:
  //
  // - newRecExpr()
  //   An unordered set of Assign nodes of the form
  //   "col1 = value1, col2 = value2, ..." which is used by Norm/Optimizer.
  //
  // - newRecExprArray()
  //   An ordered array of Assign nodes of the same form,
  //   ordered by column position, which is used by Generator.
  //   This array must have the following properties:
  //
  //   - All columns not specified in the insert statement must be
  //     Assign'ed with their default values.
  //
  //   - If this is a key-sequenced table with a (non-RR) SYSKEY column,
  //     we must create the first entry in the newRecExprArray
  //     to be "SYSKEY_COL = 0".  This is a placeholder where the timestamp
  //     value will be moved at runtime.  Round-robin SYSKEY columns are
  //     initialized via an expression of the form "SYSKEY_COL =
  //     ProgDistribKey(..params..)".  SYSKEY columns for other table
  //     organizations are handled by the file system or disk process.
  //
  // - updateToSelectMap()
  //   A ValueIdMap that can be used to rewrite value ids of the
  //   target table in terms of the source table and vice versa.
  //   The top value ids are target value ids, the bottom value ids
  //   are those of the source.
  //

  NABoolean view = bindWA->getNATableInternal(getTableName())->getViewText() != NULL;

  ValueIdList tgtColList, userColList, sysColList, *userColListPtr;
  CollIndexList colnoList(STMTHEAP);
  CollIndex totalColCount, defaultColCount, i;

  getTableDesc()->getSystemColumnList(sysColList);

  //
  // Detach the column list and bind the columns to the target table.
  // Set up "colnoList" to map explicitly specified columns to where
  // in the ordered array we will be inserting later.
  //
  ItemExpr *columnTree = removeInsertColTree();
  CMPASSERT(NOT columnTree || someNonDefaultValuesSpecified);
  if (columnTree || (view && someNonDefaultValuesSpecified)) {
    //
    // INSERT INTO t(colx,coly,...) query-expr;
    // INSERT INTO v(cola,colb,...) query-expr;
    // INSERT INTO v query-expr;
    //  where  query-expr is VALUES..., TABLE..., or SELECT...,
    //  but not DEFAULT VALUES.
    //    userColList is the full list of columns in the target table
    //    colnoList contains, for those columns specified in tgtColList,
    //		their ordinal position in the target table user column list
    //		(i.e., not counting system columns, which can't be specified
    //		in the insert column list); e.g. '(Z,X,Y)' -> [3,1,2]
    //
    CMPASSERT(NOT columnTree ||
              columnTree->getOperatorType() == ITM_REFERENCE ||
              columnTree->getOperatorType() == ITM_ITEM_LIST);
    getTableDesc()->getUserColumnList(userColList);
    userColListPtr = &userColList;

    RETDesc *columnLkp;

    if (columnTree) {
      // bindRowValues will bind using the currently scoped RETDesc left in
      // by GenericUpdate::bindNode, which will be that of the naTableTop
      // (topmost view or table), *not* that of the base table (getTableDesc()).
      columnLkp = bindRowValues(bindWA, columnTree, tgtColList, this, FALSE);
      if (bindWA->errStatus()) return boundExpr;
    } 
    else 
    {
      columnLkp = bindWA->getCurrentScope()->getRETDesc();
      columnLkp->getColumnList()->getValueIdList(tgtColList);
    }

    if (GU_DEBUG) {
      cerr << "columnLkp " << flush;
      columnLkp->display();
    }

    for (i = 0; i < columnLkp->getDegree(); i++) {
      // Describes column in the base table:
      ValueId source = columnLkp->getValueId(i);
      const NAColumn *nacol = source.getNAColumn();

      // Gets name of the column in this (possibly view) table:
      const ColRefName colName = columnLkp->getColRefNameObj(i);
 
      // solution 10-081114-7315
      if (bindWA->inDDL() && bindWA->isInTrigger ())
      {
         if (!userColListPtr->contains(source))
         {
            // 4001 column not found
            *CmpCommon::diags() << DgSqlCode(-4001)
              << DgColumnName(colName.getColName())
              << DgString0(getTableName().getQualifiedNameObj().getQualifiedNameAsAnsiString())
              << DgString1(bindWA->getDefaultSchema().getSchemaNameAsAnsiString());
            bindWA->setErrStatus();
            delete columnLkp;
            return boundExpr;
         }
      }

      if (columnLkp->findColumn(colName)->isDuplicate()) {
        // 4022 column specified more than once
        *CmpCommon::diags() << DgSqlCode(-4022)
                            << DgColumnName(colName.getColName());
        bindWA->setErrStatus();
        delete columnLkp;
        return boundExpr;
      }

      colnoList.insert(nacol->getPosition());
      // Commented out this assert, as Assign::bindNode below emits nicer errmsg
      // CMPASSERT((long)nacol->getPosition() - (long)firstColNumOnDisk >= 0);
    }
    if (columnTree) {
      delete columnLkp;
      columnLkp = NULL;
    }
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
  }
  else {
    //
    // INSERT INTO t query-expr;
    // INSERT INTO t DEFAULT VALUES;
    // INSERT INTO v DEFAULT VALUES;
    //    userColListPtr points to tgtColList (which is the full list)
    //    userColList not used (because tgtColList already is the full list)
    //    colnoList remains empty (because tgtColList is already in order)
    //              if no system columns, set to list of user cols otherwise
    getTableDesc()->getUserColumnList(tgtColList);
    userColListPtr = &tgtColList;
    if (sysColList.entries()) {
      // set up colnoList to indicate the user columns, to help
      // binding DEFAULT clauses in DefaultSpecification::bindNode()
      for (CollIndex uc=0; uc<tgtColList.entries(); uc++) {
        colnoList.insert(tgtColList[uc].getNAColumn()->getPosition());
      }
    }
  }

  // Compute total number of columns. Note that there may be some unused
  // entries in newRecExprArray(), in the following case:
  // - For computed columns that are not stored on disk
  totalColCount = userColListPtr->entries() + sysColList.entries();
  newRecExprArray().resize(totalColCount);

  // Make sure children are bound -- GenericUpdate::bindNode defers
  // their binding to now if this is an INSERT..VALUES(..),
  // because only now do we have target column position info for
  // correct binding of INSERT..VALUES(..,DEFAULT,..)
  // in DefaultSpecification::bindNode.
  //
  // Save current RETDesc and XTNM.
  // Bind the source in terms of the original RETDesc,
  //   with target column position info available through
  //     bindWA->getCurrentScope()->context()->updateOrInsertNode()
  //   (see DefaultSpecification::bindNode, calls Insert::getColDefaultValue).
  // Restore RETDesc and XTNM.
  //
  RETDesc *currRETDesc = bindWA->getCurrentScope()->getRETDesc();
  bindWA->getCurrentScope()->setRETDesc(incomingRETDescForSource);
  bindWA->getCurrentScope()->xtnmStack()->createXTNM();
  setTargetUserColPosList(colnoList);

  // if my child is a TupleList, then all tuples are to be converted/cast
  // to the corresponding target type of the tgtColList.
  // Pass on the tgtColList to TupleList so it can generate the Cast nodes
  // with the target types during the TupleList::bindNode.
  TupleList *tl = NULL;
  if (child(0)->getOperatorType() == REL_TUPLE_LIST) {
    tl = (TupleList *)child(0)->castToRelExpr();
    tl->castToList() = tgtColList;
  }

  if (getTolerateNonFatalError() != RelExpr::UNSPECIFIED_) {
    HostArraysWA * arrayWA = bindWA->getHostArraysArea() ;
    if (arrayWA && arrayWA->hasHostArraysInTuple()) {
      if (getTolerateNonFatalError() == RelExpr::NOT_ATOMIC_)
        arrayWA->setTolerateNonFatalError(TRUE);
      else
        arrayWA->setTolerateNonFatalError(FALSE);  // Insert::tolerateNonfatalError == ATOMIC_
    }
    else if (NOT arrayWA->getRowwiseRowset()) {
      // NOT ATOMIC only for rowset inserts
      *CmpCommon::diags() << DgSqlCode(-30025) ;
      bindWA->setErrStatus();
      return boundExpr;
    }
  }

 


   
  bindChildren(bindWA);
  if (bindWA->errStatus()) return this;

  // if this is an insert into native hbase table in _ROW_ format, then
  // validate that only REL_TUPLE or REL_TUPLE_LIST is being used.
  if ((getOperatorType() == REL_UNARY_INSERT) &&
      (getTableDesc()->getNATable()->isHbaseRowTable()))
    {
      NABoolean isError = FALSE;
      if (NOT (child(0)->getOperatorType() == REL_TUPLE || // VALUES (1,'b')
               child(0)->getOperatorType() == REL_TUPLE_LIST)) // VALUES (1,'b'),(2,'Y')
        {
          isError = TRUE;
        }

      // Also make sure that inserts into column_details field of _ROW_ format
      // hbase virtual table are being done through column_create function.
      //   For ex: insert into hbase."_ROW_".hb values ('1', column_create('cf:a', '100'))
      //
      if ((NOT isError) && (child(0)->getOperatorType() == REL_TUPLE))
	{
          ValueIdList &tup = ((Tuple*)(child(0)->castToRelExpr()))->tupleExpr();
          if (tup.entries() == 2) // can only have 2 entries
            {
              ItemExpr * ie = tup[1].getItemExpr();
              if (ie && ie->getOperatorType() != ITM_HBASE_COLUMN_CREATE)
                {
                  isError = TRUE;
                }
            }
          else
            isError = TRUE;
        }

      if ((NOT isError) && (child(0)->getOperatorType() == REL_TUPLE_LIST))
	{
	  TupleList * tl = (TupleList*)(child(0)->castToRelExpr());
	  for (CollIndex x = 0; x < (UInt32)tl->numTuples(); x++)
	    {
	      ValueIdList tup;
	      if (!tl->getTuple(bindWA, tup, x)) 
		{
                  isError = TRUE;
		}

              if (NOT isError)
                {
                  if (tup.entries() == 2) // must have 2 entries
                    {
                      ItemExpr * ie = tup[1].getItemExpr();
                      if (ie->getOperatorType() != ITM_HBASE_COLUMN_CREATE)
                        {
                          isError = TRUE;
                        }
                    }
                  else
                    isError = TRUE;
                } // if
            } // for
        } // if

      if (isError)
        {
          *CmpCommon::diags() << DgSqlCode(-1429);
          bindWA->setErrStatus();
          
          return boundExpr; 
        }
    }

  // the only time that tgtColList.entries()(Insert's colList) != tl->castToList().entries()
  // (TupleList's colList) is when DEFAULTS are removed in TupleList::bindNode() for insert
  // into table with IDENTITY column, where the system generates the values
  // for it using SG (Sequence Generator).
  // See TupleList::bindNode() for detailed comments.
  // When tgtColList.entries()(Insert's col list) is not
  // equal to  tl->castToList().entries() (TupleList's column list)
  // make sure the correct colList is used during binding.
  ValueIdList newTgtColList;
  if(tl && (tgtColList.entries() != tl->castToList().entries()))
    {
    newTgtColList = tl->castToList();
    CMPASSERT(newTgtColList.entries() == (tgtColList.entries() -1));
    }
  else
    newTgtColList = tgtColList;

  setTargetUserColPosList();
  bindWA->getCurrentScope()->xtnmStack()->removeXTNM();
  bindWA->getCurrentScope()->setRETDesc(currRETDesc);
  NABoolean bulkLoadIndex = bindWA->isTrafLoadPrep() && noIMneeded() ;

  if (someNonDefaultValuesSpecified) 
    // query-expr child specified
    {

      const RETDesc &sourceTable = *child(0)->getRETDesc();
      if ((sourceTable.getDegree() != newTgtColList.entries())&& !bulkLoadIndex) {
      // 4023 degree of row value constructor must equal that of target table
      *CmpCommon::diags() << DgSqlCode(-4023)
        << DgInt0(sourceTable.getDegree()) << DgInt1(tgtColList.entries());
      bindWA->setErrStatus();
      return boundExpr;
      }

    
    OptSqlTableOpenInfo* stoiInList = NULL;
    for (CollIndex ii=0; ii < bindWA->getStoiList().entries(); ii++)
    {
      if (getOptStoi() && getOptStoi()->getStoi())
	{
	  if (strcmp((bindWA->getStoiList())[ii]->getStoi()->fileName(), 
		     getOptStoi()->getStoi()->fileName()) == 0) 
	    {
	      stoiInList = bindWA->getStoiList()[ii];
	      break;
	    }
	}
    }

    // Combine the ValueIdLists for the column list and value list into a
    // ValueIdSet (unordered) of Assign nodes and a ValueIdArray (ordered).
    // Maintain a ValueIdMap between the source and target value ids.
    CollIndex i2 = 0;
    const ColumnDescList *viewColumns = NULL;
    if (getBoundView())
      viewColumns = getBoundView()->getRETDesc()->getColumnList();

     if (bulkLoadIndex) {
       setRETDesc(child(0)->getRETDesc());
      } 



    for (i = 0; i < tgtColList.entries() && i2 < newTgtColList.entries(); i++) {
      if(tgtColList[i] != newTgtColList[i2])
        continue;

      ValueId target = tgtColList[i];
      ValueId source ;
      if (!bulkLoadIndex)
        source = sourceTable.getValueId(i2);
      else {
        ColRefName & cname = ((ColReference *)(baseColRefs()[i2]))->getColRefNameObj();
        source = sourceTable.findColumn(cname)->getValueId();
      }
      CMPASSERT(target != source);

      const NAColumn *nacol = target.getNAColumn();

      const NAType &sourceType = source.getType();
      const NAType &targetType = target.getType();

      if ( DFS2REC::isFloat(sourceType.getFSDatatype())  &&
           DFS2REC::isNumeric(targetType.getFSDatatype()) &&
           (getTableDesc()->getNATable()->getPartitioningScheme()  ==
                                                COM_HASH_V1_PARTITIONING ||
            getTableDesc()->getNATable()->getPartitioningScheme()  ==
                                                COM_HASH_V2_PARTITIONING) )
      {
        const NAColumnArray &partKeyCols = getTableDesc()->getNATable()
                         ->getClusteringIndex()->getPartitioningKeyColumns();

        for (CollIndex j=0; j < partKeyCols.entries(); j++)
        {
          if (partKeyCols[j]->getPosition() == nacol->getPosition())
          {
            ItemExpr *ie = source.getItemExpr();
            ItemExpr *cast = new (bindWA->wHeap())
                                Cast(ie, &targetType, ITM_CAST);
            cast = cast->bindNode(bindWA);
            if (bindWA->errStatus()) 
              return NULL;

            source = cast->getValueId();

          }
        }
      }

      Assign *assign = new (bindWA->wHeap())
        Assign(target.getItemExpr(), source.getItemExpr());
      assign->bindNode(bindWA);

      if(bindWA->errStatus())
	return NULL;



      if (stoiInList && !getUpdateCKorUniqueIndexKey())
      {
        if(!getBoundView())
          stoiInList->addInsertColumn(nacol->getPosition());
        else
        {
          NABoolean found = FALSE;
          for (CollIndex k=0; k < viewColumns->entries(); k++) {
            if ((*viewColumns)[k]->getValueId() == target) {
              stoiInList->addInsertColumn((Lng32) k);
              found = TRUE;
              // Updatable views cannot have any underlying basetable column
              // appear more than once, so it's safe to break out of the loop.
              break;
            }
          }  // loop k
          CMPASSERT(found);
        }
      }

      //
      // Check for automatically inserted TRANSLATE nodes.
      // Such nodes are inserted by the Implicit Casting And Translation feature.
      // If this node has a child TRANSLATE node, then that TRANSLATE node
      // is the real "source" that we must use from here on.
      //
      ItemExpr *assign_child = assign->child(1);
      if ( assign_child->getOperatorType() == ITM_CAST )
      {
         const NAType& type = assign_child->getValueId().getType();
         if ( type.getTypeQualifier() == NA_CHARACTER_TYPE )
         {
            ItemExpr *assign_grndchld = assign_child->child(0);
            if ( assign_grndchld->getOperatorType() == ITM_TRANSLATE )
            {
               source = assign_grndchld->getValueId();
               CMPASSERT(target != source);
            }
         }
      }

      const NAType *colType = nacol->getType();
      if (!colType->isSupportedType()) {
        *CmpCommon::diags() << DgSqlCode(-4027)     // 4027 table not insertable
        << DgTableName(nacol->getNATable()->getTableName().getQualifiedNameAsAnsiString());
        bindWA->setErrStatus();
      }

      if (bindWA->errStatus()) return boundExpr;
      newRecExprArray().insertAt(nacol->getPosition(), assign->getValueId());
      newRecExpr().insert(assign->getValueId());
    
      const NAType& assignSrcType = assign->getSource().getType();
      // if ( <we added some type of conversion> AND
      //      ( <tgt and src are both character> AND
      //        (<they are big and errors can occur> OR <charsets differ> OR <difference between tgt and src lengths is large>)))
      //      OR
      //      ( <we changed the basic type and we allow incompatible types> )
      //    )
      //   <then incorporate this added conversion into the updateToSelectMap>
      if ( source != assign->getSource() && 
           ((assignSrcType.getTypeQualifier() == NA_CHARACTER_TYPE &&
             sourceType.getTypeQualifier() == NA_CHARACTER_TYPE &&
             ((assign->getSource().getItemExpr()->getOperatorType() == ITM_CAST &&
               sourceType.errorsCanOccur(assignSrcType) && 
               sourceType.getNominalSize() > 
               CmpCommon::getDefaultNumeric(LOCAL_MESSAGE_BUFFER_SIZE)*1024) ||
              // Temporary code to fix QC4395 in M6. For M7, try to set source
              // to the right child of the assign after calling assign->bindNode.
              // We should then be able to eliminate this entire if statement
              // as well as the code to check for TRANSLATE nodes above.
              ((CharType &) assignSrcType).getCharSet() !=
              ((CharType &) sourceType).getCharSet() || 
              // The optimizer may ask for source data to be partitioned or sorted on original source columns
              // This is the reason we need to choose the else branch below unless we have a particular reason
              // to do otherwise. Each of the conditions in this if statement reflects one of those partcular
              // conditions. The bottomValues of updateToSelectMap will be placed in their entirety in the 
              // characteristic outputs of the source node. Outputs of the source node may be used to allocate
              // buffers at runtime and therefore we would like to keep the output as small as possible.
              // If the source cannot be partioned/sorted on a column because we have assign-getSource in the bottomValues
              // then the cost is that data will be repartitioned with an additional exchange node. If the difference in
              // length between source and assignSrc is large then the cost of repartition is less than the cost of 
              // allocating and using large buffers.
              sourceType.getNominalSize() > (assignSrcType.getNominalSize() + 
                                             (ActiveSchemaDB()->getDefaults()).getAsLong(COMP_INT_98))  // default value is 512
              ))
            ||
            // If we allow incompatible type assignments, also include the
            // added cast into the updateToSelectMap
            assignSrcType.getTypeQualifier() !=  sourceType.getTypeQualifier() &&
            CmpCommon::getDefault(ALLOW_INCOMPATIBLE_OPERATIONS) == DF_ON))
        {
          updateToSelectMap().addMapEntry(target,assign->getSource());
        }
      else
        {
          updateToSelectMap().addMapEntry(target,source);
        }

      i2++;
    }
  }
  setBoundView(NULL);

  // Is the table round-robin (horizontal) partitioned?
  PartitioningFunction *partFunc =
    getTableDesc()->getClusteringIndex()->getNAFileSet()->
    getPartitioningFunction();

  NABoolean isRRTable =
    partFunc && partFunc->isARoundRobinPartitioningFunction();

  // Fill in default values for any columns not explicitly specified.
  //
  if (someNonDefaultValuesSpecified)      // query-expr child specified, set system cols
    defaultColCount = totalColCount - newTgtColList.entries();
  else                  // "DEFAULT VALUES" specified
    defaultColCount = totalColCount;

  if (identityColumnGeneratedAlways)
    defaultColCount = totalColCount;

  NABoolean isAlignedRowFormat = getTableDesc()->getNATable()->isSQLMXAlignedTable();
  NABoolean omittedDefaultCols = FALSE;
  NABoolean omittedCurrentDefaultClassCols = FALSE;

  if (defaultColCount) {
    NAWchar zero_w_Str[2]; zero_w_Str[0] = L'0'; zero_w_Str[1] = L'\0';  // wide version
    CollIndex sysColIx = 0, usrColIx = 0;

    for (i = 0; i < totalColCount; i++) {

      ValueId target;
      NABoolean isASystemColumn = FALSE;
      const NAColumn *nacol = NULL;

      // find column on position i in the system or user column lists
      if (sysColIx < sysColList.entries() &&
          sysColList[sysColIx].getNAColumn()->getPosition() == i)
        {
          isASystemColumn = TRUE;
          target = sysColList[sysColIx];
        }
      else
        {
          CMPASSERT((*userColListPtr)[usrColIx].getNAColumn()->getPosition() == i);
          target = (*userColListPtr)[usrColIx];
        }
      nacol = target.getNAColumn();
      
      // if we need to add the default value, we don't have a new rec expr yet
      if (NOT newRecExprArray().used(i)) {
       
        const char* defaultValueStr = NULL;
        ItemExpr *  defaultValueExpr = NULL;
        NABoolean needToDeallocateColDefaultValueStr = FALSE;

        // Used for datetime columns with COM_CURRENT_DEFAULT.
        //
        NAType *castType = NULL;

        if (isASystemColumn) {
          if (isRRTable) {
            bindInsertRRKey(bindWA, this, sysColList, sysColIx);
            if (bindWA->errStatus()) return boundExpr;
          }

          if (nacol->isComputedColumn())
            {
              CMPASSERT(target.getItemExpr()->getOperatorType() == ITM_BASECOLUMN);
              ValueId defaultExprValId = ((BaseColumn *) target.getItemExpr())->
                getComputedColumnExpr();
              ValueIdMap updateToSelectMapCopy(updateToSelectMap());

              // Use a copy to rewrite the value, to avoid requesting additional
              // values from the child. We ask the child for all entries in this
              // map in GenericUpdate::pushdownCoveredExpr().
              updateToSelectMapCopy.rewriteValueIdDown(defaultExprValId, defaultExprValId);
              defaultValueExpr = defaultExprValId.getItemExpr();
            }
          else
            defaultValueStr = (char *)zero_w_Str;
        }
        else {            // a user column (cf. Insert::getColDefaultValue)
          CMPASSERT(NOT nacol->isComputedColumn()); // computed user cols not yet supported
          defaultValueStr = nacol->getDefaultValue();
        }
          
        if (NOT defaultValueStr && NOT defaultValueExpr) {
          // 4024 column has neither a default nor an explicit value.
          *CmpCommon::diags() << DgSqlCode(-4024) << DgColumnName(nacol->getColName());
          bindWA->setErrStatus();
          return boundExpr;
        }

        if (defaultValueStr) {
          // If the column has a default class of COM_CURRENT_DEFAULT,
          // cast the default value (which is CURRENT_TIMESTAMP) to
          // the type of the column.  Here we capture the type of the
          // column. COM_CURRENT_DEFAULT is only used for Datetime
          // columns.
          //
          if (nacol->getDefaultClass() == COM_CURRENT_DEFAULT || nacol->getDefaultClass() == COM_CURRENT_UT_DEFAULT 
             || nacol->getDefaultClass() == COM_UUID_DEFAULT) {
            castType = nacol->getType()->newCopy(bindWA->wHeap());
            omittedCurrentDefaultClassCols = TRUE;
            omittedDefaultCols = TRUE;
          }
          else if ((nacol->getDefaultClass() == COM_IDENTITY_GENERATED_ALWAYS) ||
                   (nacol->getDefaultClass() == COM_IDENTITY_GENERATED_BY_DEFAULT)) {
            setSystemGeneratesIdentityValue(TRUE);
          }
          else if (nacol->getDefaultClass() != COM_NO_DEFAULT)
            omittedDefaultCols = TRUE;

          // Bind the default value, make an Assign, etc, as above
          Parser parser(bindWA->currentCmpContext());

          // save the current parserflags setting
          ULng32 savedParserFlags = Get_SqlParser_Flags (0xFFFFFFFF);
          Set_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL);
          Set_SqlParser_Flags(ALLOW_VOLATILE_SCHEMA_IN_TABLE_NAME);
          defaultValueExpr = parser.getItemExprTree(defaultValueStr);
          CMPASSERT(defaultValueExpr);

          // Restore parser flags settings to what they originally were
          Assign_SqlParser_Flags (savedParserFlags);
	} // defaultValueStr != NULL

	Assign *assign = NULL;
	
	// If the default value string was successfully parsed,
	// Create an ASSIGN node and bind.
        //
        if (defaultValueExpr) {

          // If there is a non-NULL castType, then cast the default
          // value to the castType.  This is used in the case of
          // datetime value with COM_CURRENT_DEFAULT.  The default
          // value will be CURRENT_TIMESTAMP for all datetime types,
          // so must cast the CURRENT_TIMESTAMP to the type of the
          // column.
          //
          if(castType) {
            defaultValueExpr = new (bindWA->wHeap())
              Cast(defaultValueExpr, castType);
          }

          // system generates value for IDENTITY column.
          if (defaultValueExpr->getOperatorType() == ITM_IDENTITY &&
              (CmpCommon::getDefault(COMP_BOOL_210) == DF_ON))
            {
              // SequenceGenerator::createSequenceSubqueryExpression()
              // is called for introducing the subquery in
              // defaultValueExpr::bindNode() (IdentityVar::bindNode()).
              // We bind here to make sure the correct subquery
              // is used.
              defaultValueExpr = defaultValueExpr->bindNode(bindWA);
            }

	  if (((isUpsertLoad()) ||
               ((isUpsert()) && (getTableDesc()->getNATable()-> isSQLMXAlignedTable()))) &&
              (NOT defaultValueExpr->getOperatorType() == ITM_IDENTITY) &&
	      (NOT isASystemColumn))
	    {
	      // for 'upsert using load' construct, all values must be specified so
	      // data could be loaded using inserts.
	      // If some values are missing, then it becomes an update.
	      *CmpCommon::diags() << DgSqlCode(-4246) ;
	      bindWA->setErrStatus();

	      return boundExpr;
	    }
          assign = new (bindWA->wHeap())
            Assign(target.getItemExpr(), defaultValueExpr,
                    FALSE /*Not user Specified */);
          if ((nacol->getDefaultClass() != COM_CURRENT_DEFAULT) &&
              (nacol->getDefaultClass() != COM_CURRENT_UT_DEFAULT) &&
              (nacol->getDefaultClass() != COM_FUNCTION_DEFINED_DEFAULT) &&
              (nacol->getDefaultClass() != COM_UUID_DEFAULT) &&
              (nacol->getDefaultClass() != COM_USER_FUNCTION_DEFAULT))
             assign->setToBeSkipped(TRUE);
          assign->bindNode(bindWA);
        }

        //
        // Note: Parser or Binder errors from MP texts are possible.
        //
        if (!defaultValueExpr || bindWA->errStatus()) {
            // 7001 Error preparing default on <column> for <table>.
            *CmpCommon::diags() << DgSqlCode(-7001)
                                << DgString0(defaultValueStr)
                                << DgString1(nacol->getFullColRefNameAsAnsiString());
            bindWA->setErrStatus();
            return boundExpr;
          }

	newRecExprArray().insertAt(i, assign->getValueId());
	newRecExpr().insert(assign->getValueId());
	updateToSelectMap().addMapEntry(target,defaultValueExpr->getValueId());

	if (needToDeallocateColDefaultValueStr && defaultValueStr != NULL)
	  {
	    NADELETEBASIC((NAWchar*)defaultValueStr, bindWA->wHeap());
	    defaultValueStr = NULL;
	  }

        if (--defaultColCount == 0)
          break;  // tiny performance hack

      }   // NOT newRecExprArray().used(i)
      else 
      {
        if (nacol->getDefaultClass() == COM_IDENTITY_GENERATED_ALWAYS)
          {
            Assign * assign = (Assign*)newRecExprArray()[i].getItemExpr();
            ItemExpr * ie = assign->getSource().getItemExpr();

            // The IDENTITY column type of GENERATED ALWAYS AS IDENTITY
            // can not be used with user specified values.
            // However, if the override CQD is set, then
            // allow user specified values to be added
            // for a GENERATED ALWAYS AS IDENTITY column.
            if ((NOT ie->wasDefaultClause()) &&
                (CmpCommon::getDefault(OVERRIDE_GENERATED_IDENTITY_VALUES) == DF_OFF))
              {
                *CmpCommon::diags() << DgSqlCode(-3428)
                                    << DgString0(nacol->getColName());
                bindWA->setErrStatus();
                return boundExpr;
              }
          }
      }
      
      if (isASystemColumn)
        sysColIx++;
      else
        usrColIx++;
    }   // for i < totalColCount
  }   // defaultColCount

  // Now add the default values created as part of the Assigns above
  // to the charcteristic inputs. The user specified values are added
  // to the characteristic inputs during GenericUpdate::bindNode
  // executed earlier as part of this method.
  getGroupAttr()->addCharacteristicInputs(bindWA->
                                          getCurrentScope()->
                                          getOuterRefs());


  if (isRRTable) {
    const LIST(IndexDesc *) indexes = getTableDesc()->getIndexes();
    for(i = 0; i < indexes.entries(); i++) {
      indexes[i]->getPartitioningFunction()->setAssignPartition(TRUE);
    }
  }

 if ((getOperatorType() == REL_UNARY_INSERT) &&
     (getTableDesc()->getNATable()->hasLobColumn()) &&
     child(0)->getOperatorType() == REL_TUPLE_LIST) // VALUES (1,'b'),(2,'Y')
    {
      if (child(0)->getOperatorType() == REL_TUPLE_LIST)
	{
	  TupleList * tl = (TupleList*)(child(0)->castToRelExpr());
	  for (CollIndex x = 0; x < (UInt32)tl->numTuples(); x++)
	    {
	      ValueIdList tup;
	      if (!tl->getTuple(bindWA, tup, x)) 
		{
		  bindWA->setErrStatus();

		  return boundExpr; // something went wrong
		}
	      
	      for (CollIndex n = 0; n < tup.entries(); n++)
		{
		  ItemExpr * ie = tup[n].getItemExpr();
                  
		  if (ie->getOperatorType() == ITM_LOBINSERT)
		    {                                                          
                      // cannot have this function in a values list with
                      // multiple tuples. Use a single tuple.
                          *CmpCommon::diags() << DgSqlCode(-4483);
                          bindWA->setErrStatus();		      
                          return boundExpr; 
                        
                    }
               
                  else
                    {
                      Assign * assign = (Assign*)newRecExprArray()[n].getItemExpr();
                      ItemExpr *assign_child = NULL;
                      if (assign)
                        {
                           assign_child = assign->child(1);
                        }
                      if ( assign_child && assign_child->getOperatorType() == ITM_CAST )
                        {
                          const NAType& type = assign_child->getValueId().getType();
                          if ( type.getTypeQualifier() == NA_LOB_TYPE )
                            {
                              // cannot have this function in a values list with multiple
                              // tuples. Use a single tuple.
                              *CmpCommon::diags() << DgSqlCode(-4483);
                              bindWA->setErrStatus();		      
                              return boundExpr; 
                            }
                        }
                    }
                }
            }
        }
    }



  // It is a system generated identity value if
  // identityColumn() != NULL_VALUE_ID. The identityColumn()
  // is set two places (1) earlier in this method.
  // (2) DefaultSpecification::bindNode()

  // The IDENTITY column of type GENERATED ALWAYS AS IDENTITY
  // must be specified in the values list as (DEFAULT) or
  // must be excluded from the values list forcing the default.

  if (identityColumnGeneratedAlways &&
      NOT systemGeneratesIdentityValue())
    {
      // The IDENTITY column type of GENERATED ALWAYS AS IDENTITY
      // can not be used with user specified values.
      // However, if the override CQD is set, then
      // allow user specified values to be added
      // for a GENERATED ALWAYS AS IDENTITY column.

      if (CmpCommon::getDefault(OVERRIDE_GENERATED_IDENTITY_VALUES) == DF_OFF)
        {
          *CmpCommon::diags() << DgSqlCode(-3428)
                              << DgString0(identityColumnName.data());
           bindWA->setErrStatus();
           return boundExpr;
        }
    }

  ItemExpr *orderByTree = removeOrderByTree();
  if (orderByTree) {
    bindWA->getCurrentScope()->context()->inOrderBy() = TRUE;
    bindWA->getCurrentScope()->setRETDesc(child(0)->getRETDesc());
    orderByTree->convertToValueIdList(reqdOrder(), bindWA, ITM_ITEM_LIST);

    bindWA->getCurrentScope()->context()->inOrderBy() = FALSE;
    if (bindWA->errStatus()) return NULL;
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
  }

  setInUpdateOrInsert(bindWA);

  // Triggers --
  NABoolean insertFromValuesList =
    getOperatorType() == REL_UNARY_INSERT &&
    (child(0)->getOperatorType() == REL_TUPLE || // VALUES (1,'b')
    child(0)->getOperatorType() == REL_TUPLE_LIST || // VALUES (1,'b'),(2,'Y')
    child(0)->getOperatorType() == REL_UNION);       // VALUES with subquery

  // Insert from values that gets input from above should not use flow,
  // for performance. Cases, other than TUPLE, should be investigated.
  if (bindWA->findNextScopeWithTriggerInfo() != NULL
      && (getGroupAttr()->getCharacteristicInputs() != NULL)
      && (insertFromValuesList))
    setNoFlow(TRUE);

  if (getUpdateCKorUniqueIndexKey())
  {
    SqlTableOpenInfo * scanStoi = getLeftmostScanNode()->getOptStoi()->getStoi();
    short updateColsCount = scanStoi->getColumnListCount();
    getOptStoi()->getStoi()->setColumnListCount(updateColsCount);
    getOptStoi()->getStoi()->setColumnList(new (bindWA->wHeap()) short[updateColsCount]);
      for (short i=0; i<updateColsCount; i++)
        getOptStoi()->getStoi()->setUpdateColumn(i,scanStoi->getUpdateColumn(i));
  }
   
  if ((getIsTrafLoadPrep()) &&
      (getTableDesc()->getCheckConstraints().entries() != 0 ||
          getTableDesc()->getNATable()->getRefConstraints().entries() != 0  ))
  {
    // enabling/disabling constraints is not supported yet
    //4486--Constraints not supported with bulk load. Disable the constraints and try again.
    *CmpCommon::diags() << DgSqlCode(-4486)
                        <<  DgString0("bulk load") ;
    bindWA->setErrStatus();
    return boundExpr;
  }
  if (getIsTrafLoadPrep())
  {
    PartitioningFunction *pf = getTableDesc()->getClusteringIndex()->getPartitioningFunction();

    const NodeMap* np;
    Lng32 partns = 1;
    if ( pf && (np = pf->getNodeMap()) )
      {
        partns = np->getNumEntries();
        if(partns > 1  && CmpCommon::getDefault(ATTEMPT_ESP_PARALLELISM) == DF_OFF)
	  {
	    // 4490 - BULK LOAD into a salted table is not supported if 
	    // ESP parallelism is turned off
	    *CmpCommon::diags() << DgSqlCode(-4490);
	     bindWA->setErrStatus();
	     return boundExpr;
	  }
      }

    const NATable* naTable = getTableDesc()->getNATable();
    if (naTable->hasLobColumn())
      {
	NAColumn *nac = NULL;
	for (CollIndex c = 0; c < naTable->getColumnCount(); c++) 
	  {
	    nac = naTable->getNAColumnArray()[c];
	    if (nac->getType()->isLob())
	      break;
	  }
	*CmpCommon::diags() << DgSqlCode(-4494)
			    << DgTableName(naTable->getTableName().
					   getQualifiedNameAsAnsiString()) 
			    << DgColumnName(nac->getColName());
	bindWA->setErrStatus();
	return boundExpr;
      } // has Lob column
  } // isLoadPrep

  NABoolean toMerge = FALSE;
  if (isUpsertThatNeedsTransformation(isAlignedRowFormat, omittedDefaultCols, omittedCurrentDefaultClassCols,toMerge)) {
    if ((CmpCommon::getDefault(TRAF_UPSERT_TO_EFF_TREE) == DF_OFF) ||toMerge)	
      {
	boundExpr = xformUpsertToMerge(bindWA);  
	return boundExpr;
      }
    else 
      boundExpr = xformUpsertToEfficientTree(bindWA);
    
    
  }
  if (NOT (isMerge() || noIMneeded()))
    boundExpr = handleInlining(bindWA, boundExpr);

  // turn OFF Non-atomic Inserts for ODBC if we have detected that Inlining is needed
  // necessary warnings have been generated in handleInlining method.
  if (CmpCommon::getDefault(ODBC_PROCESS) == DF_ON) {
    if (bindWA->getHostArraysArea() &&
	(NOT bindWA->getHostArraysArea()->getRowwiseRowset()) &&
	!(bindWA->getHostArraysArea()->getTolerateNonFatalError()))
      setTolerateNonFatalError(RelExpr::UNSPECIFIED_);
  }
  
  
  // When mtsStatement_ or bulkLoadIndex is set Insert needs to return rows;
  // so potential outputs are added (note that it's not replaced) to 
  // the Insert node. Currently mtsStatement_ is set
  // for MTS queries and embedded insert queries.
  if (isMtsStatement() || bulkLoadIndex)
    {
      if(isMtsStatement())
        setRETDesc(new (bindWA->wHeap()) RETDesc(bindWA, getTableDesc()));

      bindWA->getCurrentScope()->setRETDesc(getRETDesc());

      ValueIdList outputs;
      getRETDesc()->getValueIdList(outputs, USER_AND_SYSTEM_COLUMNS);
      ValueIdSet potentialOutputs;
      getPotentialOutputValues(potentialOutputs);
      potentialOutputs.insertList(outputs); 
      setPotentialOutputValues(potentialOutputs);

      // this flag is set to indicate optimizer not to pick the
      // TupleFlow operator
      setNoFlow(TRUE);
    }

  return boundExpr;
} // Insert::bindNode()

/* Upsert into a table with an index is converted into a Merge to avoid
the problem described in Trafodion-14. An upsert may overwrite an existing row
in the base table (identical to the update when matched clause of Merge) or
it may insert a new row into the base table (identical to insert when not
matched clause of merge). If the upsert caused a row to be updated in the 
base table then the old version of the row will have to be deleted from 
indexes, and a new version inserted. Upsert is being transformed to merge
so that we can delete the old version of an updated row from the index.

Upsert is also converted into merge when TRAF_UPSERT_MODE is set to MERGE and 
there are omitted cols with default values in case of aligned format table or 
omitted current timestamp cols in case of non-aligned row format
*/
NABoolean Insert::isUpsertThatNeedsTransformation(NABoolean isAlignedRowFormat, 
                                                  NABoolean omittedDefaultCols,
                                                  NABoolean omittedCurrentDefaultClassCols,
                                                  NABoolean &toMerge) const
{
  toMerge = FALSE;
  // If the the table has an identity column in clustering key or has a syskey 
  // we dont need to do this transformation.The incoming row will always be 
  // unique. So first check if we any of the conditions are satisfied to 
  //even try the transform
  NABoolean mustTryTransform = FALSE;
  if (isUpsert() && 
      NOT ( getIsTrafLoadPrep() ||
            ( (getTableDesc()->isIdentityColumnGeneratedAlways() && 
               getTableDesc()->hasIdentityColumnInClusteringKey()))  || 
            ((getTableDesc()->getClusteringIndex()->getNAFileSet()->hasSyskey()))))
    {
      mustTryTransform = TRUE;
    }

  // Transform upsert to merge in case of special modes and
  // omitted default columns
  // Case 1 :  CQD is set to MERGE, omitted current(timestamp) default 
  //           columns with  non-aligned row format table or omitted 
  //           default columns with aligned row format tables 

  // Case 2 :  CQD is set to Optimal, for non-aligned row format with omitted 
  //           current(timestamp) columns, it is converted into merge 
  //           though it is not optimal for performance. This is done to ensure
  //           that when the CQD is set to optimal, non-aligned format would 
  //           behave like merge when any column is  omitted 
  if (isUpsert()  &&   
      mustTryTransform &&          
      ((CmpCommon::getDefault(TRAF_UPSERT_MODE) == DF_MERGE) &&     
       (((NOT isAlignedRowFormat) && omittedCurrentDefaultClassCols) ||
        (isAlignedRowFormat && omittedDefaultCols)))
      ||
      ((CmpCommon::getDefault(TRAF_UPSERT_MODE) == DF_OPTIMAL) &&
       ((NOT isAlignedRowFormat) && omittedCurrentDefaultClassCols)))
    {
      toMerge = TRUE;
      return TRUE;
    }

  // Transform upsert to efficient tree if none of the above conditions 
  // are true and the table has secondary indexes 
  if (isUpsert() &&  
      mustTryTransform &&
      (getTableDesc()->hasSecondaryIndexes()))
    {
      toMerge = FALSE;
      return TRUE;
    }
  
  return FALSE;
}

/** commenting the following method out for future work. This may be enabled 
as a further performance improvement if we can eliminate the sort node that 
gets geenrated as part of the Sequence Node. In case of no duplicates we won't
 need the Sequence node at all. 

// take an insert(src) node and transform it into
// a tuple_flow with old/new rows flowing to the IM tree.
// with a newly created input_scan
RelExpr* Insert::xformUpsertToEfficientTreeNoDup(BindWA *bindWA) 
{
  NATable *naTable = bindWA->getNATable(getTableName());
  if (bindWA->errStatus())
    return NULL;
  if ((naTable->getViewText() != NULL) && (naTable->getViewCheck()))		
    {		
      *CmpCommon::diags() << DgSqlCode(-3241) 		
			  << DgString0(" View with check option not allowed.");	    		
      bindWA->setErrStatus();		
      return NULL;		
    }

  RelExpr *topNode = this;
  // Create a new BindScope, to encompass the new nodes 
  // upsert(left_join(input_scan, tuple))
  // and any inlining nodes that will be created. Any values the upsert
  // and children will need from src will be marked as outer references in that
  // new BindScope. We assume that "src" is already bound.
  ValueIdSet currOuterRefs = bindWA->getCurrentScope()->getOuterRefs();

  CMPASSERT(child(0)->nodeIsBound());

  BindScope *upsertScope = bindWA->getCurrentScope();

  // columns of the target table
  const ValueIdList &tableCols = updateToSelectMap().getTopValues();
  const ValueIdList &sourceVals = updateToSelectMap().getBottomValues();

  // create a Join node - left join of the base table columns with the columns to be upserted.
  // columns of the target table
  CMPASSERT(child(0)->nodeIsBound());
  
  Scan * targetTableScan =
    new (bindWA->wHeap())
    Scan(CorrName(getTableDesc()->getCorrNameObj(), bindWA->wHeap()));

 
  //join predicate between source columns and target table.
  ItemExpr * keyPred = NULL;
  ItemExpr * keyPredPrev = NULL;
  BaseColumn* baseCol;
  ColReference * targetColRef;
  int predCount = 0;
  ValueIdSet newOuterRefs;
  ItemExpr * pkeyValPrev;
  ItemExpr * pkeyVals;
  for (CollIndex i = 0; i < tableCols.entries(); i++)
    {
      baseCol = (BaseColumn *)(tableCols[i].getItemExpr()) ;
      if (baseCol->getNAColumn()->isSystemColumn())
	continue;

      targetColRef = new(bindWA->wHeap()) ColReference(
						       new(bindWA->wHeap()) ColRefName(
										       baseCol->getNAColumn()->getFullColRefName(), bindWA->wHeap()));
    

      if (baseCol->getNAColumn()->isClusteringKey())
	{
	  // create a join/key predicate between source and target table,
	  // on the clustering key columns of the target table, making
	  // ColReference nodes for the target table, so that we can bind
	  // those to the new scan
	  keyPredPrev = keyPred;
	  keyPred = new (bindWA->wHeap())
	    BiRelat(ITM_EQUAL, targetColRef, 
		    sourceVals[i].getItemExpr(),
		    baseCol->getType().supportsSQLnull());
	  predCount++;
	  if (predCount > 1) 
	    {
	      keyPred = new(bindWA->wHeap()) BiLogic(ITM_AND,
						     keyPredPrev,
						     keyPred);  
	    }
	  pkeyValPrev = pkeyVals;
    
	  pkeyVals = tableCols[i].getItemExpr();
	  if (i > 0) 
	    {
	      pkeyVals = new(bindWA->wHeap()) ItemList(pkeyVals,pkeyValPrev);
      
	    }
	}
     
    }
 
  // Map the table's primary key values to the source lists key values
  ValueIdList tablePKeyVals = NULL;
  ValueIdList sourcePKeyVals = NULL;
  
  pkeyVals->convertToValueIdList(tablePKeyVals,bindWA,ITM_ITEM_LIST);
  updateToSelectMap().mapValueIdListDown(tablePKeyVals,sourcePKeyVals);
  
  Join *lj = new(bindWA->wHeap()) Join(child(0),targetTableScan,REL_LEFT_JOIN,keyPred);
  lj->doNotTransformToTSJ();	  
  lj->setTSJForWrite(TRUE);
   bindWA->getCurrentScope()->xtnmStack()->createXTNM();
  RelExpr *boundLJ = lj->bindNode(bindWA);
  if (bindWA->errStatus())
    return NULL;
  bindWA->getCurrentScope()->xtnmStack()->removeXTNM();
  setChild(0,boundLJ);
  topNode = handleInlining(bindWA,topNode);


  return topNode; 
}
*/

// take an insert(src) node and transform it into
// a tuple_flow with old/new rows flowing to the IM tree.
// with a newly created sequence node used to eliminate duplicates.
/*
               NJ
            /      \
         Sequence   NJ
        /            \  
     Left Join        IM Tree 
     /        \
    /          \
Input Tuplelist  Target Table Scan
or select list
*/
         
RelExpr* Insert::xformUpsertToEfficientTree(BindWA *bindWA) 
{
  NATable *naTable = bindWA->getNATable(getTableName());
  if (bindWA->errStatus())
    return NULL;
  if ((naTable->getViewText() != NULL) && (naTable->getViewCheck()))		
    {		
      *CmpCommon::diags() << DgSqlCode(-3241) 		
			  << DgString0(" View with check option not allowed.");	    		
      bindWA->setErrStatus();		
      return NULL;		
    }

  RelExpr *topNode = this;
 
  CMPASSERT(child(0)->nodeIsBound());

  BindScope *upsertScope = bindWA->getCurrentScope();
  // Create a new BindScope, to encompass the new nodes 
  // upsert(left_join(input_scan, tuple))
  // and any inlining nodes that will be created. Any values the upsert
  // and children will need from src will be marked as outer references in that
  // new BindScope. We assume that "src" is already bound.
  ValueIdSet currOuterRefs = bindWA->getCurrentScope()->getOuterRefs();
  // Save the current RETDesc.
  RETDesc *prevRETDesc = bindWA->getCurrentScope()->getRETDesc();

  // columns of the target table
  const ValueIdList &tableCols = updateToSelectMap().getTopValues();
  const ValueIdList &sourceVals = updateToSelectMap().getBottomValues();

  // create a Join node - left join of the base table columns with the columns to be upserted.
  // columns of the target table
  CMPASSERT(child(0)->nodeIsBound());
  
  Scan * targetTableScan =
    new (bindWA->wHeap())
    Scan(CorrName(getTableDesc()->getCorrNameObj(), bindWA->wHeap()));

   bindWA->getCurrentScope()->context()->inUpsertXform() = TRUE;
  //join predicate between source columns and target table.
  ItemExpr * keyPred = NULL;
  ItemExpr * keyPredPrev = NULL;
  BaseColumn* baseCol;
  ColReference * targetColRef;
  int predCount = 0;
  ValueIdSet newOuterRefs;
  ItemExpr * pkeyValPrev = NULL;
  ItemExpr * pkeyVals = NULL;
  for (CollIndex i = 0; i < tableCols.entries(); i++)
    {
      baseCol = (BaseColumn *)(tableCols[i].getItemExpr()) ;
      if (baseCol->getNAColumn()->isSystemColumn())
	continue;

      targetColRef = new(bindWA->wHeap()) ColReference(
           new(bindWA->wHeap()) ColRefName(
                baseCol->getNAColumn()->getFullColRefName(),
                bindWA->wHeap()));
    

      if (baseCol->getNAColumn()->isClusteringKey())
	{
	  // create a join/key predicate between source and target table,
	  // on the clustering key columns of the target table, making
	  // ColReference nodes for the target table, so that we can bind
	  // those to the new scan
	  keyPredPrev = keyPred;
	  keyPred = new (bindWA->wHeap())
	    BiRelat(ITM_EQUAL, targetColRef, 
		    sourceVals[i].getItemExpr(),
		    baseCol->getType().supportsSQLnull());
	  predCount++;
	  if (predCount > 1) 
	    {
	      keyPred = new(bindWA->wHeap()) BiLogic(ITM_AND,
						     keyPredPrev,
						     keyPred);  
	    }
          
          pkeyValPrev = pkeyVals;
    
	  pkeyVals = tableCols[i].getItemExpr();
	  
	  if (pkeyValPrev != NULL ) 
	    {
	      pkeyVals = new(bindWA->wHeap()) ItemList(pkeyVals,pkeyValPrev);
      
	    }
	}
     
    }
 
  // Map the table's primary key values to the source lists key values
  ValueIdList tablePKeyVals ;
  ValueIdList sourcePKeyVals ;
  
  pkeyVals->convertToValueIdList(tablePKeyVals,bindWA,ITM_ITEM_LIST);
  updateToSelectMap().mapValueIdListDown(tablePKeyVals,sourcePKeyVals);
  
  Join *lj = new(bindWA->wHeap()) Join(child(0),targetTableScan,REL_LEFT_JOIN,keyPred);

  bindWA->getCurrentScope()->xtnmStack()->createXTNM();

  
  RelExpr *boundLJ = lj->bindNode(bindWA);
  if (bindWA->errStatus())
    return NULL;
  bindWA->getCurrentScope()->xtnmStack()->removeXTNM();
 
  ValueId nullInstIndicator(
       lj->addNullInstIndicatorVar(
            bindWA,
            new(bindWA->wHeap()) SystemLiteral(
                 "U",
                 CharInfo::ISO88591)));
  ValueIdSet sequenceFunction ;		
 
  //Retrieve all the system and user columns of the left join output
  ValueIdList  ljOutCols = 0;
  boundLJ->getRETDesc()->getValueIdList(ljOutCols);
  //Retrieve the null instantiated part of the LJ output
  ValueIdList ljNullInstColumns = lj->nullInstantiatedOutput();
  
  //Create the olap node and use the primary key of the table as the 
  //"partition by" columns for the olap node.
  CMPASSERT(!bindWA->getCurrentScope()->getSequenceNode());
  RelSequence *seqNode = new(bindWA->wHeap()) RelSequence(boundLJ, sourcePKeyVals.rebuildExprTree(ITM_ITEM_LIST),  (ItemExpr *)NULL);
 

  // Create a LEAD Item Expr for a random value 999. 
  // Use this to eliminate rows which have a NULL for this LEAD value within 
  // a particular partition range.
  ItemExpr *leadItem, *boundLeadItem = NULL;
  ItemExpr *constLead999 = new (bindWA->wHeap()) ConstValue( 999);

  leadItem = new(bindWA->wHeap()) ItmLeadOlapFunction(constLead999,1);
  ((ItmLeadOlapFunction *)leadItem)->setIsOLAP(TRUE);
  boundLeadItem = leadItem->bindNode(bindWA);
  if (bindWA->errStatus()) return this;
  boundLeadItem->convertToValueIdSet(sequenceFunction);
  seqNode->setSequenceFunctions(sequenceFunction);
  
  // Add a selection predicate (post predicate) to check if the LEAD item is NULL
  ItemExpr *selPredOnLead = NULL;
  selPredOnLead = new (bindWA->wHeap()) UnLogic(ITM_IS_NULL,leadItem);
  selPredOnLead = selPredOnLead->bindNode(bindWA);
  if (bindWA->errStatus()) return this;
  seqNode->selectionPred() += selPredOnLead->getValueId();
  seqNode->setChild(0,boundLJ);

  RelExpr *boundSeqNode = seqNode->bindNode(bindWA);  
   
  setChild(0,boundSeqNode);

  // Fixup the newRecExpr() and newRecExprArray() to refer to the new 
  // valueIds of the new child - i.e RelSequence. Use the saved off valueIdMap
  // from the current bindScope for this.
  ValueIdSet newNewRecExpr;
  ValueIdMap notCoveredMap = bindWA->getCurrentScope()->getNcToOldMap();
  notCoveredMap.rewriteValueIdSetUp(newNewRecExpr, newRecExpr());
  newRecExpr() = newNewRecExpr;
  
  ValueIdList oldRecArrList(newRecExprArray());
  ValueIdList newRecArrList;
  notCoveredMap.rewriteValueIdListUp(newRecArrList, oldRecArrList);
  ValueIdArray newNewRecArray(newRecArrList.entries());
  
  for (CollIndex i = 0; i < newRecArrList.entries(); i++)
    {
      newNewRecArray.insertAt(i,newRecArrList.at(i));
    }
  newRecExprArray() = newNewRecArray;

  ValueId notCoveredNullInstIndicator;

  notCoveredMap.rewriteValueIdUp(notCoveredNullInstIndicator,
                                 nullInstIndicator);
  ItemExpr *nvl = new(bindWA->wHeap()) BuiltinFunction(
         ITM_NVL,
         bindWA->wHeap(),
         2,
         notCoveredNullInstIndicator.getItemExpr(),
         new(bindWA->wHeap()) SystemLiteral("I",
                                            CharInfo::ISO88591));
  nvl = nvl->bindNode(bindWA);
  setProducedMergeIUDIndicator(nvl->getValueId());

  setXformedEffUpsert(TRUE);
  bindWA->getCurrentScope()->context()->inUpsertXform() =  FALSE;
  return topNode; 
}


// take an insert(src) node and transform it into
// tsj_flow(src, merge_update(input_scan))
// with a newly created input_scan
RelExpr* Insert::xformUpsertToMerge(BindWA *bindWA) 
{
  NATable *naTable = bindWA->getNATable(getTableName());
  if (bindWA->errStatus())
    return NULL;
  if ((naTable->getViewText() != NULL) && (naTable->getViewCheck()))		
  {		
    *CmpCommon::diags() << DgSqlCode(-3241) 		
			<< DgString0(" View with check option not allowed.");	    		
    bindWA->setErrStatus();		
    return NULL;		
  }

  // columns of the target table
  const ValueIdList &tableCols = updateToSelectMap().getTopValues();
  const ValueIdList &sourceVals = updateToSelectMap().getBottomValues();

  NABoolean isAlignedRowFormat = getTableDesc()->getNATable()->isSQLMXAlignedTable();
		    
  // Create a new BindScope, to encompass the new nodes merge_update(input_scan)
  // and any inlining nodes that will be created. Any values the merge_update
  // and children will need from src will be marked as outer references in that
  // new BindScope. We assume that "src" is already bound.
  ValueIdSet currOuterRefs = bindWA->getCurrentScope()->getOuterRefs();

  CMPASSERT(child(0)->nodeIsBound());
  bindWA->initNewScope();
  BindScope *mergeScope = bindWA->getCurrentScope();

  // create a new scan of the target table, to be used in the merge
  Scan * inputScan =
    new (bindWA->wHeap())
    Scan(CorrName(getTableDesc()->getCorrNameObj(), bindWA->wHeap()));

  ItemExpr * keyPred = NULL;
  ItemExpr * keyPredPrev = NULL;
  ItemExpr * setAssign = NULL;
  ItemExpr * setAssignPrev = NULL;
  ItemExpr * insertVal = NULL;
  ItemExpr * insertValPrev = NULL;
  ItemExpr * insertCol = NULL;
  ItemExpr * insertColPrev = NULL;
  BaseColumn* baseCol;
  ColReference * targetColRef;
  int predCount = 0;
  int setCount = 0;
  ValueIdSet newOuterRefs;

  // loop over the columns of the target table
  for (CollIndex i = 0; i<tableCols.entries(); i++)
  {
    baseCol = (BaseColumn *)(tableCols[i].getItemExpr()) ;
    if (baseCol->getNAColumn()->isSystemColumn())
      continue;

    targetColRef = new(bindWA->wHeap()) ColReference(
         new(bindWA->wHeap()) ColRefName(
              baseCol->getNAColumn()->getFullColRefName(), bindWA->wHeap()));
    if (baseCol->getNAColumn()->isClusteringKey())
    {
      // create a join/key predicate between source and target table,
      // on the clustering key columns of the target table, making
      // ColReference nodes for the target table, so that we can bind
      // those to the new scan
      keyPredPrev = keyPred;
      keyPred = new (bindWA->wHeap())
        BiRelat(ITM_EQUAL, targetColRef, 
                sourceVals[i].getItemExpr(),
                baseCol->getType().supportsSQLnull());
      predCount++;
      if (predCount > 1) 
      {
         keyPred = new(bindWA->wHeap()) BiLogic(ITM_AND,
                                                keyPredPrev,
                                                keyPred);  
      }

    }
    if (sourceVals[i].getItemExpr()->getOperatorType() != ITM_CONSTANT)
      {
        newOuterRefs += sourceVals[i];
        mergeScope->addOuterRef(sourceVals[i]);
      }

    // create the INSERT (WHEN NOT MATCHED) part of the merge for this column, again
    // with a ColReference that we will then bind to the MergeUpdate target table
    insertValPrev = insertVal;
    insertColPrev = insertCol ;
    insertVal = sourceVals[i].getItemExpr();
    insertCol =  new(bindWA->wHeap()) ColReference(
                     new(bindWA->wHeap()) ColRefName(
                          baseCol->getNAColumn()->getFullColRefName(), bindWA->wHeap()));
    if (i > 0) 
    {
      insertVal = new(bindWA->wHeap()) ItemList(insertVal,insertValPrev);
      insertCol = new(bindWA->wHeap()) ItemList(insertCol,insertColPrev);
    }
  }
  inputScan->addSelPredTree(keyPred);
  for (CollIndex i = 0 ; i < newRecExprArray().entries(); i++) 
  {
      const Assign *assignExpr = (Assign *)newRecExprArray()[i].getItemExpr();
      ValueId tgtValueId = assignExpr->child(0)->castToItemExpr()->getValueId();
      NAColumn *col = tgtValueId.getNAColumn( TRUE );
      NABoolean copySetAssign = FALSE;
      if (col->isSystemColumn())
         continue;
      else
      if (! col->isClusteringKey()) 
      {
         // Create the UPDATE (WHEN MATCHED) part of the new MergeUpdate for
         // a non-key column. We need to bind in the new = old values
         // in GenericUpdate::bindNode. So skip the columns that are not user
         // specified. Note that we had a discussion on whether such a transformed
         // UPSERT shouldn't update all columns.
         //
         if (assignExpr->isUserSpecified())
             copySetAssign = TRUE;
         // If copy the Default values in case of replace mode or optiomal mode with
         // aligned row tables
         else if ((CmpCommon::getDefault(TRAF_UPSERT_MODE) == DF_REPLACE) ||
                (isAlignedRowFormat && CmpCommon::getDefault(TRAF_UPSERT_MODE) == DF_OPTIMAL))
             copySetAssign = TRUE;
         if (copySetAssign)
         { 
            setAssignPrev = setAssign;
            setAssign = (ItemExpr *)assignExpr;
            setCount++;
            if (setCount > 1) 
               setAssign = new(bindWA->wHeap()) ItemList(setAssignPrev, setAssign);
         }
     }
  }
  MergeUpdate *mu = new (bindWA->wHeap())
    MergeUpdate(CorrName(getTableDesc()->getCorrNameObj(), bindWA->wHeap()),
                NULL,
                REL_UNARY_UPDATE,
                inputScan, // USING
                setAssign, // WHEN MATCHED THEN UPDATE
                insertCol, // WHEN NOT MATCHED THEN INSERT (cols) ...
                insertVal, // ... VALUES()
                bindWA->wHeap(),
                NULL);

  mu->setXformedUpsert();
  // Use mergeScope, the scope we created here, for the MergeUpdate. We are
  // creating some expressions with outer references here in this method, so
  // we need to control the scope from here.
  mu->setNeedsBindScope(FALSE);

  RelExpr *boundMU = mu->bindNode(bindWA);

  // remove the BindScope created earlier in this method
  bindWA->removeCurrentScope();

  // Remove the outer refs from the parent scope, they are provided
  // by the left child of the TSJ_FLOW, unless they were already outer refs
  // when we started this method. The binder logic doesn't handle
  // that well, since they come from a child scope, not the current one,
  // so we help a little.
  newOuterRefs -= currOuterRefs;
  bindWA->getCurrentScope()->removeOuterRefs(newOuterRefs);

  Join * jn = new(bindWA->wHeap()) Join(child(0), boundMU, REL_TSJ_FLOW, NULL);

  jn->doNotTransformToTSJ();
  jn->setTSJForMerge(TRUE);	
  jn->setTSJForMergeWithInsert(TRUE);
  jn->setTSJForMergeUpsert(TRUE);
  jn->setTSJForWrite(TRUE);

  RelExpr *result = jn->bindNode(bindWA);
  if (bindWA->errStatus())
    return NULL;
  // Copy the userSecified and canBeSkipped attribute to mergeUpdateInsertExprArray
  ValueIdList mergeInsertExprArray = mu->mergeInsertRecExprArray();
  for (CollIndex i = 0 ; i < newRecExprArray().entries(); i++) 
  {
      const Assign *assignExpr = (Assign *)newRecExprArray()[i].getItemExpr();
      ((Assign *)mergeInsertExprArray[i].getItemExpr())->setToBeSkipped(assignExpr->canBeSkipped());
      ((Assign *)mergeInsertExprArray[i].getItemExpr())->setUserSpecified(assignExpr->isUserSpecified());
  }
 
  return result;
}

RelExpr *HBaseBulkLoadPrep::bindNode(BindWA *bindWA)
{
  //CMPASSERT((CmpCommon::getDefault(TRAF_LOAD) == DF_ON &&
   //   CmpCommon::getDefault(TRAF_LOAD_HFILE) == DF_ON));
  if (nodeIsBound())
  {
    return this;
  }

  Insert * newInsert = new (bindWA->wHeap())
                            Insert(getTableName(),
                                   NULL,
                                   REL_UNARY_INSERT,
                                   child(0)->castToRelExpr());


  newInsert->setInsertType(UPSERT_LOAD);
  newInsert->setIsTrafLoadPrep(true);
  newInsert->setCreateUstatSample(getCreateUstatSample());

  // Pass the flag to bindWA to guarantee that a range partitioning is 
  // always used for all source and target tables.
  bindWA->setIsTrafLoadPrep(TRUE);

  RelExpr *boundNewInsert = newInsert->bindNode(bindWA);

  if (bindWA->errStatus())
    return NULL;

  return boundNewInsert;



}

// This is a callback from DefaultSpecification::bindNode
// called from Insert::bindNode
// (you need to understand the latter to understand this).
//
const char *Insert::getColDefaultValue(BindWA *bindWA, CollIndex i) const
{
  CMPASSERT(canBindDefaultSpecification());

  CollIndexList &colnoList = *targetUserColPosList_;
  CollIndex pos = colnoList.entries() ? colnoList[i] : i;

  const ValueIdList &colList = getTableDesc()->getColumnList();

  if (colList.entries() <= pos) {
    // 4023 degree of row value constructor must equal that of target table
    *CmpCommon::diags() << DgSqlCode(-4023)
                        << DgInt0(++pos)
                        << DgInt1(colList.entries());
    bindWA->setErrStatus();
    return NULL;
  }

  ValueId target = colList[pos];
  const NAColumn *nacol = target.getNAColumn();
  const char* defaultValueStr = nacol->getDefaultValue();
  
  CharInfo::CharSet mapCS = CharInfo::ISO88591;
  NABoolean mapCS_hasVariableWidth = CharInfo::isVariableWidthMultiByteCharSet(mapCS);
  size_t defaultValueWcsLen = 0;
  NAWchar *defaultValueWcs = (NAWchar *) defaultValueStr;
  NABoolean ucs2StrLitPrefix = FALSE;

  if (nacol->getDefaultClass() == COM_USER_DEFINED_DEFAULT &&
      nacol->getType() &&
      nacol->getType()->getTypeQualifier() == NA_CHARACTER_TYPE &&
      ((CharType*)(nacol->getType()))->getCharSet() == CharInfo::ISO88591 &&
      mapCS_hasVariableWidth &&
      defaultValueWcs != NULL &&
      nacol->getNATable()->getObjectSchemaVersion() >= COM_VERS_2300 &&
      (defaultValueWcsLen = NAWstrlen(defaultValueWcs)) > 6 &&
      ( ( ucs2StrLitPrefix = ( NAWstrncmp(defaultValueWcs, NAWSTR("_UCS2\'"), 6) == 0 )) ||
        ( defaultValueWcsLen > 10 &&
          NAWstrncmp(defaultValueWcs, NAWSTR("_ISO88591\'"), 10) == 0 )) &&
      defaultValueWcs[defaultValueWcsLen-1] == NAWCHR('\''))
  {
    NAWcharBuf *pWcharBuf = NULL;
    if (ucs2StrLitPrefix)
    {
      // Strip the leading _UCS2 prefix.
      pWcharBuf =
        new (bindWA->wHeap()) NAWcharBuf(&defaultValueWcs[5],
                                         defaultValueWcsLen - 5,
                                         bindWA->wHeap());
    }
    else
    {
      // Keep the leading _ISO88591 prefix.
      pWcharBuf =
        new (bindWA->wHeap()) NAWcharBuf(defaultValueWcs,
                                         defaultValueWcsLen,
                                         bindWA->wHeap());
    }
    charBuf *pCharBuf = NULL; // must set this variable to NULL so the
                              // following function call will allocate
                              // space for the output literal string
    Int32 errorcode = 0;
    pCharBuf = unicodeTocset(*pWcharBuf, bindWA->wHeap(),
                             pCharBuf, mapCS, errorcode);
    // Earlier releases  treated the converted multibyte character
    // string, in ISO_MAPPING character set, as if it is a string of
    // ISO88591 characters and then convert it back to UCS-2 format;
    // i.e., for each byte in the string, insert an extra byte
    // containing the binary zero value.
    NADELETE(pWcharBuf, NAWcharBuf, bindWA->wHeap());
    pWcharBuf = NULL; // must set this variable to NULL to force the
                      // following call to allocate space for the
                      // the output literal string
    pWcharBuf = ISO88591ToUnicode(*pCharBuf, bindWA->wHeap(), pWcharBuf);
    // Prepare the converted literal string for the following CAST
    // function by setting pColDefaultValueStr to point to the string
    NAWchar *pWcs = NULL;
    if (ucs2StrLitPrefix)
    {
      pWcs = new (bindWA->wHeap()) NAWchar[10+NAWstrlen(pWcharBuf->data())];
      NAWstrcpy(pWcs, NAWSTR("_ISO88591"));
    }
    else
    {
      pWcs = new (bindWA->wHeap()) NAWchar[1+NAWstrlen(pWcharBuf->data())];
      pWcs[0] = NAWCHR('\0');
    }
    NAWstrcat(pWcs, pWcharBuf->data());
    defaultValueStr = (char *)pWcs;
    NADELETE(pWcharBuf, NAWcharBuf, bindWA->wHeap());
    NADELETE(pCharBuf, charBuf, bindWA->wHeap());
  }

  if (NOT defaultValueStr AND bindWA) {
    // 4107 column has no default so DEFAULT cannot be specified.
    *CmpCommon::diags() << DgSqlCode(-4107) << DgColumnName(nacol->getColName());
    bindWA->setErrStatus();
  }

  return defaultValueStr;
} // Insert::getColDefaultValue()


// -----------------------------------------------------------------------
// member functions for class Update
// -----------------------------------------------------------------------

RelExpr *Update::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }
  // Set flag for firstN in context 
  if (child(0) && child(0)->getOperatorType() == REL_SCAN)
    if (child(0)->castToRelExpr() && 
        ((Scan *)(child(0)->castToRelExpr()))->getFirstNRows() >= 0)
      if (bindWA && 
          bindWA->getCurrentScope() && 
          bindWA->getCurrentScope()->context())
        bindWA->getCurrentScope()->context()->firstN() = TRUE;

  setInUpdateOrInsert(bindWA, this, REL_UPDATE);

  RelExpr * boundExpr = GenericUpdate::bindNode(bindWA);
  if (bindWA->errStatus()) return NULL;
  setInUpdateOrInsert(bindWA);

  if (getTableDesc()->getNATable()->isHbaseCellTable())
    {
      *CmpCommon::diags() << DgSqlCode(-1425)
			  << DgTableName(getTableDesc()->getNATable()->getTableName().
					 getQualifiedNameAsAnsiString())
			  << DgString0("Reason: Cannot update an hbase table in CELL format. Use ROW format for this operation.");
    
      bindWA->setErrStatus();
      return this;
    }

  // QSTUFF
  if (getGroupAttr()->isStream() &&
     !getGroupAttr()->isEmbeddedUpdateOrDelete()) {
    *CmpCommon::diags() << DgSqlCode(-4173);
    bindWA->setErrStatus();
    return this;
  }
  // QSTUFF

  if (NOT bindWA->errStatus() AND
      NOT getTableDesc()->getVerticalPartitions().isEmpty())
    {
      // 4058 UPDATE query cannot be used on a vertically partitioned table.
      *CmpCommon::diags() << DgSqlCode(-4058) <<
        DgTableName(getTableDesc()->getNATable()->getTableName().
          getQualifiedNameAsAnsiString());
      bindWA->setErrStatus();
      return this;
    }

  // make sure scan done as part of an update runs in serializable mode so a
  // tsj(scan,update) implementation of a update runs as an atomic operation
  if (child(0)->getOperatorType() == REL_SCAN) {
    Scan *scanNode = (Scan*)(child(0)->castToRelExpr());
    if (!scanNode->accessOptions().userSpecified()) {
      scanNode->accessOptions().updateAccessOptions
        (TransMode::ILtoAT(TransMode::SERIALIZABLE_));
    }
  }

  // if FIRST_N is requested, insert a FirstN node.
  if ((getOperatorType() == REL_UNARY_UPDATE) &&
      (child(0)->getOperatorType() == REL_SCAN))
    {
      Scan * scanNode = (Scan *)(child(0)->castToRelExpr());
      if ((scanNode->getFirstNRows() != -1) &&
          (getGroupAttr()->isEmbeddedUpdateOrDelete()))
        {
          *CmpCommon::diags() << DgSqlCode(-4216);
          bindWA->setErrStatus();
          return NULL;
        }

      if (scanNode->getFirstNRows() >= 0)
        {
          FirstN * firstn = new(bindWA->wHeap())
            FirstN(scanNode, scanNode->getFirstNRows(), FALSE /* there's no ORDER BY on an UPDATE */, NULL);
          firstn->bindNode(bindWA);
          if (bindWA->errStatus())
            return NULL;

          setChild(0, firstn);
        }
    }

  // if rowset is used in set clause a direct rowset that is not in subquery 
  // must be present in the where clause
  if ((bindWA->getHostArraysArea()) &&
        (bindWA->getHostArraysArea()->hasHostArraysInSetClause()) &&
        (!(bindWA->getHostArraysArea()->hasHostArraysInWhereClause()))) {
      *CmpCommon::diags() << DgSqlCode(-30021) ;
      bindWA->setErrStatus();
      return this;
    }

  NABoolean transformUpdateKey = updatesClusteringKeyOrUniqueIndexKey(bindWA);
  if (bindWA->errStatus()) // error occurred in updatesCKOrUniqueIndexKey()
    return this;

  if ((transformUpdateKey) && (NOT isMerge()))
    {
      boundExpr = transformUpdatePrimaryKey(bindWA);
    }
  else
    boundExpr = handleInlining(bindWA, boundExpr);
  
  if (bindWA->errStatus()) // error occurred in transformUpdatePrimaryKey()
    return this;    // or handleInlining()
  
  return boundExpr;
} // Update::bindNode()

// -----------------------------------------------------------------------
// member functions for class MergeUpdate
// -----------------------------------------------------------------------

RelExpr *MergeUpdate::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
    {
      bindWA->getCurrentScope()->setRETDesc(getRETDesc());
      return this;
    }

  if (needsBindScope_)
    bindWA->initNewScope();

  // For an xformed upsert any UDF or subquery is guaranteed to be 
  // in the using clause. Upsert will not generate a merge without using 
  // clause. ON clause, when matched SET clause and when not matched INSERT
  // clauses all use expressions from the using clause. (same vid).
  // Therefore any subquery or UDF in the using clause will flow to the
  // rest of he tree through the TSJ and will be available. Each subquery
  // will be evaluated only once, and will be evaluated prior to the merge
  if (isMerge() && child(0) && !xformedUpsert())
  {
    ItemExpr *selPred = child(0)->castToRelExpr()->selPredTree();
    if (selPred || where_)
    {
      NABoolean ONhasSubquery = (selPred && selPred->containsSubquery());
      NABoolean ONhasAggr = (selPred && selPred->containsAnAggregate());
      NABoolean whrHasSubqry = FALSE;
      if (ONhasSubquery || ONhasAggr ||
	  (where_ && ((whrHasSubqry=where_->containsSubquery()) ||
                      where_->containsAnAggregate())))
      {
	*CmpCommon::diags() << DgSqlCode(-3241) 
			    << DgString0
	  (ONhasSubquery ? "Subquery in ON clause not allowed." :
           (ONhasAggr ? "aggregate function in ON clause not allowed." :
            (whrHasSubqry ?
             "subquery in UPDATE ... WHERE clause not allowed." :
             "aggregate function in UPDATE ... WHERE clause not allowed.")));  
	bindWA->setErrStatus();
	return this;
      }
      ItemExpr *ONhasUDF = (selPred ? selPred->containsUDF() : NULL);
      ItemExpr *whereHasUDF = (where_ ? where_->containsUDF() : NULL);
      if (ONhasUDF || whereHasUDF)
      {
	*CmpCommon::diags() << DgSqlCode(-4471)
			    << DgString0
	  (((UDFunction *)(ONhasUDF ? ONhasUDF : whereHasUDF))->
	   getFunctionName().getExternalName()); 
	bindWA->setErrStatus();
	return this;
      }
    }
  }

  if (isMerge() && recExprTree() && !xformedUpsert())
  {
    if (recExprTree()->containsSubquery())
    {
      *CmpCommon::diags() << DgSqlCode(-3241) 
                          << DgString0(" Subquery in SET clause not allowed.");
      bindWA->setErrStatus();
      return this;
    }
    if (recExprTree()->containsUDF())
    {
      *CmpCommon::diags() << DgSqlCode(-4471) 
                          << DgString0(((UDFunction *)recExprTree()->containsUDF())->
                                       getFunctionName().getExternalName());    
      bindWA->setErrStatus();
      return this;
    }
  }

  // if insertValues, then this is an upsert stmt.
  if (insertValues())
    {
      if (insertValues()->containsSubquery() && !xformedUpsert())
        {
          *CmpCommon::diags() << DgSqlCode(-3241) 
                              << DgString0(" Subquery in INSERT clause not allowed.");
          bindWA->setErrStatus();
          return this;
        }
      if (insertValues()->containsUDF() && !xformedUpsert())
        {
          *CmpCommon::diags() << DgSqlCode(-4471) 
                              << DgString0(((UDFunction *)insertValues()->containsUDF())->
                                           getFunctionName().getExternalName());
          bindWA->setErrStatus();
          return this;
        }

      Tuple * tuple = new (bindWA->wHeap()) Tuple(insertValues());
      Insert * ins = new (bindWA->wHeap())
        Insert(getTableName(),
               NULL,
               REL_UNARY_INSERT,
               tuple,
               insertCols(),
               NULL);
      ins->setInsertType(Insert::SIMPLE_INSERT);
      if (isMergeUpdate())
        ins->setIsMergeUpdate(TRUE);
      else
        ins->setIsMergeDelete(TRUE);

      ins->setTableDesc(getTableDesc());
      bindWA->getCurrentScope()->xtnmStack()->createXTNM();
      ins = (Insert*)ins->bindNode(bindWA);
      if (bindWA->errStatus()) 
        return NULL;
      bindWA->getCurrentScope()->xtnmStack()->removeXTNM();

      mergeInsertRecExpr() = ins->newRecExpr();
      mergeInsertRecExprArray() = ins->newRecExprArray();
    }

  NATable *naTable = bindWA->getNATable(getTableName());
  if (bindWA->errStatus())
    return NULL;
 
  if ((naTable->getViewText() != NULL) && (naTable->getViewCheck()))		
  {		
    *CmpCommon::diags() << DgSqlCode(-3241) 		
			<< DgString0(" View with check option not allowed.");	    		
    bindWA->setErrStatus();		
    return NULL;		
  }

  if ((naTable->isHbaseCellTable()) ||
      (naTable->isHbaseRowTable()))
    {
      *CmpCommon::diags() << DgSqlCode(-3241) 
			  << DgString0("Hbase tables not supported.");
      bindWA->setErrStatus();
      return NULL;
    }

  if (naTable->isHiveTable())
    {
      *CmpCommon::diags() << DgSqlCode(-3241) 
			  << DgString0("Hive tables not supported.");
      bindWA->setErrStatus();
      return NULL;
    }

  bindWA->setMergeStatement(TRUE);  

  // Create a merge IUD indicator, a CHAR(1) CHARACTER SET ISO88591
  // NOT NULL variable, that can be used by index maintenance and
  // other operations to find out what action the WHEN clause
  // indicated, insert (I), update (U) or delete (D). This will be
  // removed in GenericUpdate::normalizeNode() if nobody asked for
  // it. The actual value will be produced by the executor work
  // method, there is no expression for it.
  if (getProducedMergeIUDIndicator() == NULL_VALUE_ID)
    {
      ItemExpr *mergeIUDIndicator = new(bindWA->wHeap()) NATypeToItem(
           new(bindWA->wHeap()) SQLChar(bindWA->wHeap(), 
                1, FALSE, FALSE, FALSE, FALSE, CharInfo::ISO88591));

      mergeIUDIndicator = mergeIUDIndicator->bindNode(bindWA);
      if (bindWA->errStatus())
        return NULL;
      setProducedMergeIUDIndicator(mergeIUDIndicator->getValueId());
    }

  RelExpr * boundExpr = Update::bindNode(bindWA);
  if (bindWA->errStatus()) 
    return NULL;

  if (checkForMergeRestrictions(bindWA))
    return NULL;

  if (where_) {
    bindWA->getCurrentScope()->context()->inWhereClause() = TRUE;
    where_->convertToValueIdSet(mergeUpdatePred(), bindWA, ITM_AND);
    bindWA->getCurrentScope()->context()->inWhereClause() = FALSE;

    if (bindWA->errStatus()) return NULL;

    // any values added by where_ to Outer References Set should be
    // added to input values that must be supplied to this MergeUpdate
    getGroupAttr()->addCharacteristicInputs
      (bindWA->getCurrentScope()->getOuterRefs());
  }

  if (needsBindScope_)
    bindWA->removeCurrentScope();

  bindWA->setMergeStatement(TRUE);

  return boundExpr;
} // MergeUpdate::bindNode()

// -----------------------------------------------------------------------
// member functions for class Delete
// -----------------------------------------------------------------------

RelExpr *Delete::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }
  // Save the current scope and node for children to peruse if necessary.
  BindContext *context = bindWA->getCurrentScope()->context();
  if (context) {
    context->deleteScope() = bindWA->getCurrentScope();
    context->deleteNode()  = this;
    if (getFirstNRows() >= 0) context->firstN() = TRUE;
  }

  RelExpr * boundExpr = GenericUpdate::bindNode(bindWA);
  if (bindWA->errStatus()) return boundExpr;

  if ((csl_) &&
      (NOT getTableDesc()->getNATable()->isHbaseRowTable()))
    {
      *CmpCommon::diags() << DgSqlCode(-1425)
			  << DgTableName(getTableDesc()->getNATable()->getTableName().
					 getQualifiedNameAsAnsiString());
    
      bindWA->setErrStatus();
      return this;
    }

  if (getTableDesc()->getNATable()->isHbaseCellTable())
    {
      *CmpCommon::diags() << DgSqlCode(-1425)
			  << DgTableName(getTableDesc()->getNATable()->getTableName().
					 getQualifiedNameAsAnsiString())
			  << DgString0("Reason: Cannot delete from an hbase table in CELL format. Use ROW format for this operation.");
    
      bindWA->setErrStatus();
      return this;
    }

  // QSTUFF
  if (getGroupAttr()->isStream() &&
     !getGroupAttr()->isEmbeddedUpdateOrDelete()) {
    *CmpCommon::diags() << DgSqlCode(-4180);
    bindWA->setErrStatus();
    return this;
  }
  // QSTUFF

  // Not only are check constraints on a DELETE nonsensical,
  // but they can cause VEGReference::replaceVEGReference to assert
  // with valuesToBeBound.isEmpty (Genesis 10-980202-0718).
  //
  // in case we are binding a generic update within a generic update
  // due to view expansion we would like to ensure that all constraints
  // are checked properly for the update operation performed on the
  // underlying base table
  if (NOT (bindWA->inViewExpansion() && bindWA->inGenericUpdate())) {  // QSTUFF
    getTableDesc()->checkConstraints().clear();
    checkConstraints().clear();
  }

  if (NOT getTableDesc()->getVerticalPartitions().isEmpty())
    {
      // 4029 DELETE query cannot be used on a vertically partitioned table.
      *CmpCommon::diags() << DgSqlCode(-4029) <<
        DgTableName(getTableDesc()->getNATable()->getTableName().
                      getQualifiedNameAsAnsiString());
      bindWA->setErrStatus();
      return this;
    }

  Scan *scanNode = NULL;
  // make sure scan done as part of a delete runs in serializable mode so a
  // tsj(scan,delete) implementation of a delete runs as an atomic operation
  if (child(0)->getOperatorType() == REL_SCAN) {
    scanNode = (Scan*)(child(0)->castToRelExpr());
    if (!scanNode->accessOptions().userSpecified()) {
      scanNode->accessOptions().updateAccessOptions
        (TransMode::ILtoAT(TransMode::SERIALIZABLE_));
    }
  }
  
  BindScope *prevScope   = NULL;
  BindScope *currScope   = bindWA->getCurrentScope();
  NABoolean inUnion = FALSE;

  while (currScope && !inUnion)
  {
    BindContext *currContext = currScope->context();
    if (currContext->inUnion())
    {
      inUnion = TRUE;
    }
    prevScope = currScope;
    currScope = bindWA->getPreviousScope(prevScope);
  }

  RelRoot *root =  bindWA->getTopRoot();

  if (getFirstNRows() >= 0)  // First N Delete
  {
    CMPASSERT(getOperatorType() == REL_UNARY_DELETE);

    // First N Delete on a partitioned table. Not considered a MTS delete.
    if (getTableDesc()->getClusteringIndex()->isPartitioned())
    {

      if (root->getCompExprTree() || inUnion ) // for unions we know there is a select
      {  // outer selectnot allowed for "non-MTS" first N delete
        *CmpCommon::diags() << DgSqlCode(-4216);
        bindWA->setErrStatus();
        return this;
      }

      RelExpr * childNode = child(0)->castToRelExpr();
      FirstN * firstn = new(bindWA->wHeap())
        FirstN(childNode, getFirstNRows(), FALSE /* There's no ORDER BY on a DELETE */, NULL);
      firstn->bindNode(bindWA);
      if (bindWA->errStatus())
        return NULL;

      setChild(0, firstn);
      setFirstNRows(-1);

    }
    else
    {
      // First N delete on a single partition. This is considered a MTS Delete.
      if ((bindWA->getHostArraysArea()) &&
          ((bindWA->getHostArraysArea()->hasHostArraysInWhereClause()) ||
          (bindWA->getHostArraysArea()->getHasSelectIntoRowsets())))
      { // MTS delete not supported with rowsets
        *CmpCommon::diags() << DgSqlCode(-30037);
        bindWA->setErrStatus();
        return this;
      }

    
      if (scanNode && scanNode->getSelectionPred().containsSubquery())
      {
        // MTS Delete not supported with subquery in where clause
        *CmpCommon::diags() << DgSqlCode(-4138);

        bindWA->setErrStatus();
        return this;

      }

      if (root->hasOrderBy())
      { // mts delete not supported with order by
        *CmpCommon::diags() << DgSqlCode(-4189);
        bindWA->setErrStatus();
        return this;
      }
      if (root->getCompExprTree() || // MTS Delete has an outer select
          bindWA->isInsertSelectStatement() || // Delete inside an Insert Select statement, Soln:10-061103-0274
          inUnion )  // for unions we know there is a select
      {                                                                 
        if (root->getFirstNRows() < -1 || 
            inUnion) // for unions we wish to raise a union 
        {  // The outer select has a Last 1/0 clause      // specific error later, so set the flag now. 
          setMtsStatement(TRUE);  
        }
        else
        { // raise an error if no Last 1 clause is found.
          *CmpCommon::diags() << DgSqlCode(-4136);
          bindWA->setErrStatus();
          return this;
        }
      }
    }
  }

  // Triggers --
  
  if (NOT noIMneeded())
    boundExpr = handleInlining(bindWA, boundExpr);
  else if (hbaseOper() && (getGroupAttr()->isEmbeddedUpdateOrDelete()))
  {
     setRETDesc(new (bindWA->wHeap()) RETDesc(bindWA));

     CorrName corrOLDTable (getScanNode(TRUE)->getTableDesc()->getCorrNameObj().getQualifiedNameObj(),
             bindWA->wHeap(),"OLD");

     // expose OLD table columns
     getRETDesc()->addColumns(bindWA, *child(0)->getRETDesc(), &corrOLDTable);

     ValueIdList outputs;
     getRETDesc()->getValueIdList(outputs, USER_AND_SYSTEM_COLUMNS);
     addPotentialOutputValues(outputs);

     bindWA->getCurrentScope()->setRETDesc(getRETDesc());
  }

  if (isMtsStatement())
    bindWA->setEmbeddedIUDStatement(TRUE);

   if (getFirstNRows() > 0) 
    {
      // create a firstN node to delete FIRST N rows, if no such node was created
      // during handleInlining. Occurs when DELETE FIRST N is used on table with no
      // dependent objects. 
      FirstN * firstn = new(bindWA->wHeap())
        FirstN(boundExpr, getFirstNRows(), FALSE /* There's no ORDER BY on a DELETE */ );
      if (NOT(scanNode && scanNode->getSelectionPred().containsSubquery()))
        firstn->setCanExecuteInDp2(TRUE);
      firstn->bindNode(bindWA);
      if (bindWA->errStatus())
        return NULL;

      setFirstNRows(-1);
      boundExpr = firstn;
    }

   if (csl())
     {
       for (Lng32 i = 0; i < csl()->entries(); i++)
	 {
	   NAString * nas = (NAString*)(*csl())[i];
	   
	   bindWA->hbaseColUsageInfo()->insert
	     ((QualifiedName*)&getTableDesc()->getNATable()->getTableName(), nas);
	 }
     }

  return boundExpr;
} // Delete::bindNode()

// -----------------------------------------------------------------------
// member functions for class MergeDelete
// -----------------------------------------------------------------------

RelExpr *MergeDelete::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
    {
      bindWA->getCurrentScope()->setRETDesc(getRETDesc());
      return this;
    }
  
  bindWA->initNewScope();

  if ((isMerge()) && 
      (child(0)) && 
      (child(0)->castToRelExpr()->selPredTree()))
  {
    if (child(0)->castToRelExpr()->selPredTree()->containsSubquery())
    {
      *CmpCommon::diags() << DgSqlCode(-3241) 
                          << DgString0(" Subquery in ON clause not allowed.");    
      bindWA->setErrStatus();
      return this;
    }
    if (child(0)->castToRelExpr()->selPredTree()->containsUDF())
    {
      *CmpCommon::diags() << DgSqlCode(-4471)
                          << DgString0(((UDFunction *)child(0)->
                                       castToRelExpr()->selPredTree()->
                                       containsUDF())->
                                       getFunctionName().getExternalName());
      bindWA->setErrStatus();
      return this;
    }
  }


  // if insertValues, then this is an upsert stmt.
  if (insertValues())
    {
      if (insertValues()->containsSubquery())
      {
        *CmpCommon::diags() << DgSqlCode(-3241) 
                            << DgString0(" Subquery in INSERT clause not allowed.");
        bindWA->setErrStatus();
        return this;
      }
      if (insertValues()->containsUDF())
      {
        *CmpCommon::diags() << DgSqlCode(-4471)
                            << DgString0(((UDFunction *)insertValues()->
                                          containsUDF())->
                                         getFunctionName().getExternalName());
        bindWA->setErrStatus();
        return this;
      }
      if (CmpCommon::getDefault(COMP_BOOL_175) == DF_OFF)
      {
        // MERGE DELETE + INSERT is buggy, so disallow it unless CQD is on. In
        // particular, the optimizer sometimes fails to produce a plan in phase 1.
        // JIRA TRAFODION-1509 covers completing the MERGE DELETE + INSERT feature.
	*CmpCommon::diags() << DgSqlCode(-3241)
			    << DgString0(" MERGE DELETE not allowed with INSERT.");

      }

      Tuple * tuple = new (bindWA->wHeap()) Tuple(insertValues());
      Insert * ins = new (bindWA->wHeap())
      Insert(getTableName(),
             NULL,
             REL_UNARY_INSERT,
             tuple,
             insertCols(),
             NULL);
      ins->setInsertType(Insert::SIMPLE_INSERT);
      ins->setIsMergeDelete(TRUE);

      ins->setTableDesc(getTableDesc());
      bindWA->getCurrentScope()->xtnmStack()->createXTNM();
      ins = (Insert*)ins->bindNode(bindWA);
      if (bindWA->errStatus()) 
        return NULL;
      bindWA->getCurrentScope()->xtnmStack()->removeXTNM();

      mergeInsertRecExpr() = ins->newRecExpr();
      mergeInsertRecExprArray() = ins->newRecExprArray();
    }

  NATable *naTable = bindWA->getNATable(getTableName());
  if (bindWA->errStatus())
    return NULL;
  
  if ((naTable->getViewText() != NULL) && (naTable->getViewCheck()))		
  {		
    *CmpCommon::diags() << DgSqlCode(-3241) 		
			<< DgString0(" View with check option not allowed.");	    		
    bindWA->setErrStatus();		
    return NULL;		
  }

  bindWA->setMergeStatement(TRUE);  
  RelExpr * boundExpr = Delete::bindNode(bindWA);
  if (bindWA->errStatus()) 
    return NULL;

  if (checkForMergeRestrictions(bindWA))
    return NULL;

  bindWA->removeCurrentScope(); 

  bindWA->setMergeStatement(TRUE);

  return boundExpr;
} // MergeDelete::bindNode()

static const char NEWTable [] = "NEW";    // QSTUFF:  corr for embedded d/u
static const char OLDTable [] = "OLD";    // QSTUFF:  corr for embedded d/u

// QSTUFF
// this method binds both, the set clauses applied to the after
// image as well as the set clauses applied to the before image
// the new set on rollback clause allows an application to modify
// the before image.
// delete from tab set on rollback x = 1;
// update tab set x = 1 set on rollback x = 2;
void GenericUpdate::bindUpdateExpr(BindWA        *bindWA,
                                   ItemExpr      *recExpr,
                                   ItemExprList  &assignList,
                                   RelExpr       *boundView,
                                   Scan          *scanNode,
                                   SET(short)    &stoiColumnSet,
                                   NABoolean     onRollback)
{

  RETDesc *origScope = NULL;

  ValueIdSet &newRecExpr =
    (onRollback == TRUE) ? newRecBeforeExpr() : this->newRecExpr();
  ValueIdArray &newRecExprArray =
    (onRollback == TRUE) ? newRecBeforeExprArray() : this->newRecExprArray();

  if (onRollback &&
      ((!getTableDesc()->getClusteringIndex()->getNAFileSet()->isAudited()) ||
       (getTableDesc()->getNATable()->hasLobColumn()))) {
    // SET ON ROLLBACK clause is not allowed on a non-audited table
    *CmpCommon::diags() << DgSqlCode(-4214)
      << DgTableName(getTableDesc()->getNATable()->getTableName().
        getQualifiedNameAsAnsiString());
    bindWA->setErrStatus();
    return;
  }

  CollIndex     i, j;
  CollIndexList colnoList(STMTHEAP);   // map of col nums (row positions)
  CollIndex a = assignList.entries();

  const ColumnDescList *viewColumns = NULL;

  // if this is a view then get the columns of the view
  if (boundView) {
    viewColumns = boundView->getRETDesc()->getColumnList();
  }

  // if the GU has a SET ON ROLLBACK clause this method is called
  // twice: once to bind the columns in the SET clause and a second
  // time to bind the columns in the SET ON ROLLBACK clause.
  // Initially the update column list of the stoi_ is empty.
  // If this is the second call, store the update column list
  // from the first call.
  short *stoiColumnList = NULL;
  CollIndex currColumnCount = 0;
  if (currColumnCount = stoi_->getStoi()->getColumnListCount())
  {
       stoiColumnList = new (bindWA->wHeap()) short[currColumnCount];

       for (i = 0;  i < currColumnCount; i++)
              stoiColumnList[i] = stoi_->getStoi()->getUpdateColumn(i);
  }

  stoi_->getStoi()->setColumnList(new (bindWA->wHeap()) short[a + currColumnCount]);

  for (i = 0; i < a; i++) {
    CMPASSERT(assignList[i]->getOperatorType() == ITM_ASSIGN);
    assignList[i]->child(0)->bindNode(bindWA);                  // LHS
    if (bindWA->errStatus()) return;
    const NAColumn *nacol = assignList[i]->child(0).getNAColumn();
    if(getOperatorType() == REL_UNARY_UPDATE)
    {
        stoi_->getStoi()->setUpdateColumn(i, (short) nacol->getPosition());
        stoi_->getStoi()->incColumnListCount();
        stoi_->addUpdateColumn(nacol->getPosition());
    }
    const NAType *colType = nacol->getType();
    if (!colType->isSupportedType()) {
      *CmpCommon::diags() << DgSqlCode(-4028)     // 4028 table not updatatble
      << DgTableName(nacol->getNATable()->getTableName().getQualifiedNameAsAnsiString());
      bindWA->setErrStatus();
      return;
    }

    // If this is a sequence generator IDENTITY column
    // with a default type of GENERATED ALWAYS,
    // then post error -3428.  GENERATED ALWAYS
    // IDENTITY columns may not be updated.
    if(getOperatorType() == REL_UNARY_UPDATE         &&
       CmpCommon::getDefault(COMP_BOOL_210) == DF_ON &&
       nacol->isIdentityColumnAlways())
      {
        *CmpCommon::diags() << DgSqlCode(-3428)
                              << DgString0(nacol->getColName());
        bindWA->setErrStatus();
        return;
      }

    colnoList.insert(nacol->getPosition());         // save colno for next loop

    // in case its not a view we record the column position of the
    // base table, otherwise that of the view

    if (NOT boundView)
      stoiColumnSet.insert((short) nacol->getPosition());

    // if this is a view get the positions of the columns
    // within the view that are being updated.
    if (boundView) {
      ValueId vid = assignList[i]->child(0).getValueId();
      NABoolean found = FALSE;
      for (CollIndex k=0; k < viewColumns->entries(); k++) {
        if ((*viewColumns)[k]->getValueId() == vid) {
          stoiColumnSet.insert((short) k);
          found = TRUE;
          // Updatable views cannot have any underlying basetable column
          // appear more than once, so it's safe to break out of the loop.
          break;
        }
      }  // loop k
      CMPASSERT(found);
    }  // boundView
  }  // loop i<a

  // If this is the second call to this method, restore the update
  // columns bound in the first call
  if (currColumnCount)
  {
      for (i = a;  i < (currColumnCount + a); i++)
      {
          stoi_->getStoi()->setUpdateColumn(i,  stoiColumnList[i-a]);
          stoi_->addUpdateColumn(stoiColumnList[i-a]);
      }
  }

  // RHS:  Bind the right side of the Assigns such that the source expressions
  // reference the columns of the source table.
  //
  //### With a cascade of views, should this be "getRETDesc" as is,
  //### or "scanNode->getRETDesc" ?                     --?
  //### Should I set this->setRD to be the target(new)tbl at the beginning,
  //### explicitly say "scanNode..." here?              --i think not
  //

  if (GU_DEBUG) GU_DEBUG_Display(bindWA, this, "u");

  origScope = bindWA->getCurrentScope()->getRETDesc();

  // this sets the scope to the scan table for the before values
  // the previous scope was to the "UPDATE" table
  // we will reset the scope before returning in order not to introduce
  // hidden side effects but have the generic update explicitely point
  // to the scan scope

  bindWA->getCurrentScope()->setRETDesc(getRETDesc());

  //this has to be done after binding the LHS because of triggers
  //Soln :10-050110-3403 : Don't side-effect the SET on ROLLBACK list
  //when we come down to process it the next time over.So process only
  //the assignList
  ItemExpr* tempExpr = assignList.convertToItemExpr();
  tempExpr->convertToValueIdSet(newRecExpr, bindWA, ITM_ITEM_LIST);
  if (bindWA->errStatus()) return;

  if (NOT onRollback)
  {
    for (ValueId v = newRecExpr.init(); newRecExpr.next(v);
	 newRecExpr.advance(v))
      {
	CMPASSERT(v.getItemExpr()->getOperatorType() == ITM_ASSIGN);
	
        // remove all the onrollack expressions
	if (((Assign *)v.getItemExpr())->onRollback())
	  {
	    newRecExpr.remove(v);
	  }
      }
  }
  else
  {
     for (ValueId v = newRecExpr.init(); newRecExpr.next(v);
              newRecExpr.advance(v))
     {
        CMPASSERT(v.getItemExpr()->getOperatorType() == ITM_ASSIGN);

        // remove all the NON-onrollack expressions
        if ((getOperatorType() == REL_UNARY_UPDATE) &&
               !(((Assign *)v.getItemExpr())->onRollback()))
        {
            newRecExpr.remove(v);
        }
     }

     if (getOperatorType() == REL_UNARY_DELETE)
     {
        recExpr->convertToValueIdSet(this->newRecExpr(), bindWA, ITM_ITEM_LIST);
     }
  }

  // now we built the RHS
  // Now we have our colnoList map with which to build a temporary array
  // (with holes) and get the update columns ordered (eliminating dups).
  // Actually we store the ids of the bound Assign nodes corresponding
  // to the columns, of course.
  //
  CollIndex totalColCount = getTableDesc()->getColumnList().entries();
  ValueIdArray holeyArray(totalColCount);
  ValueId assignId;                                 // i'th newRecExpr valueid
  for (i = 0, assignId = newRecExpr.init();         // bizarre ValueIdSet iter
         newRecExpr.next(assignId);
         i++, newRecExpr.advance(assignId)) {
     j = colnoList[i];
     if (holeyArray.used(j)) {
       const NAColumn *nacol = holeyArray[j].getItemExpr()->child(0).getNAColumn();
       //4022 target column multiply specified
       *CmpCommon::diags() << DgSqlCode(-4022) << DgColumnName(nacol->getColName());
       bindWA->setErrStatus();
       return;
     }
     holeyArray.insertAt(j, assignId);
   }

   //
   // Now we have the holey array.  The next loop ignores unused entries
   // and copies the used entries into newRecExprArray(), with no holes.
   // It also builds a list of the columns being updated that contain
   // a column on the right side of the SET assignment expression.
   //
   // Entering this loop, i is the number of specified update columns;
   // exiting, j is.
   //
   CMPASSERT(i == a);

   // we built a map between identifical old and new columns, i.e. columns
   // which are not updated and thus identical. We insert the resulting
   // equivalence relationships e.g. old.a = new.a during transformation
   // into the respective VEGGIES this allows the optimizer to select index
   // scan for satisfying order requirements specified by an order by clause
   // on new columns, e.g.
   // select * from (update t set y = y + 1 return new.a) t order by a;
   // we cannot get the benefit of this VEG for a merge statement when IM is required
   // allowing a VEG in this case causes corruption on base table key values because
   // we use the "old" value of key column from fetchReturnedExpr, which can be junk
   // in case there is no row to update/delete, and a brand bew row is being inserted
   NABoolean mergeWithIndex = isMerge() && getTableDesc()->hasSecondaryIndexes() ;
   if ((NOT onRollback) && (NOT mergeWithIndex)){
     for (i = 0;i < totalColCount; i++){
       if (!(holeyArray.used(i))){
         oldToNewMap().addMapEntry(
           scanNode->getTableDesc()->
           getColumnList()[i].getItemExpr()->getValueId(),
           getTableDesc()->
           getColumnList()[i].getItemExpr()->getValueId());
       }
     }
   }

   // when binding a view which contains an embedded update
   // we must map update valueids to scan value ids
   // to allow for checking of access rights.
   for (i = 0; i < getTableDesc()->getColumnList().entries();i++)
     bindWA->getUpdateToScanValueIds().addMapEntry(
     getTableDesc()->getColumnList()[i].getItemExpr()->getValueId(),
     scanNode->getTableDesc()->getColumnList()[i].getItemExpr()->getValueId());

   newRecExprArray.resize(i);
   TableDesc *scanDesc = scanNode->getTableDesc();
   NABoolean rightContainsColumn = FALSE;

   for (i = j = 0; i < totalColCount; i++) {
     if (holeyArray.used(i)) {
       ValueId assignExpr = holeyArray[i];
       newRecExprArray.insertAt(j++, assignExpr);
       ItemExpr *right = assignExpr.getItemExpr()->child(1);

       // even if a column is set to a constant we mark it
       // as updated to prevent indices covering this column from
       // being used for access
       ItemExpr *left = assignExpr.getItemExpr()->child(0);

       scanDesc->addColUpdated(left->getValueId());

       if (right->containsColumn())
         rightContainsColumn = TRUE;
     }
   }

   // WITH NO ROLLBACK not supported if rightside of update 
   // contains a column expression. Also this feature is not
   // supported with the SET ON ROLLBACK feature
   if (isNoRollback() ||
       (CmpCommon::transMode()->getRollbackMode() == TransMode::NO_ROLLBACK_))
  {
    if ((rightContainsColumn && CmpCommon::getDefault(ALLOW_RISKY_UPDATE_WITH_NO_ROLLBACK) == DF_OFF) || onRollback)        
    {
      NAString warnMsg = "";
      if(rightContainsColumn)
      {
	warnMsg = "Suggestion: Set ALLOW_RISKY_UPDATE_WITH_NO_ROLLBACK CQD to ON to allow";
	if (getOperatorType() == REL_UNARY_DELETE)
	  warnMsg += " DELETE ";
	else
	  warnMsg += " UPDATE ";
	warnMsg += "command with right-hand side SET clause consisting of columns.";
      }

      if (getOperatorType() == REL_UNARY_DELETE)
	*CmpCommon::diags() << DgSqlCode(-3234) << DgString0(warnMsg);
      else
	*CmpCommon::diags() << DgSqlCode(-3233) << DgString0(warnMsg);
      bindWA->setErrStatus();
      return ;
    }
  }

   CMPASSERT(j == a);
   bindWA->getCurrentScope()->setRETDesc(origScope);
}

void getScanPreds(RelExpr *start, ValueIdSet &preds)
{
  RelExpr *result = start;

  while (result) {
    preds += result->selectionPred();

    if (result->getOperatorType() == REL_SCAN) break;
    if (result->getArity() > 1) {
      return ;
    }
    result = result->child(0);
  }

  return;
}


// Note that this is the R2 compatible way to handle Halloween problem.
// This update (only insert for now) contains a reference to the
// target in the source.  This could potentially run into the so
// called Halloween problem.  Determine if this is a case we may be
// able to handle.  The cases that we handle are:
//
//   -- The reference to the target is in a subquery
//   -- There any number of references to the target in the source
//   -- The subquery cannot be a row subquery.
//   -- The subquery must contain only one source (the reference to the target)
//   -- 
//
//  Return TRUE if this does represent a Halloween problem and the caller will
//  then issue the error message
//
//  Return FALSE is this is a case we can handle.  Set the
//  'avoidHalloweenR2' flag in the subquery and this generic Update so
//  that the optimizer will pick a plan that is Halloween safe.
//
NABoolean GenericUpdate::checkForHalloweenR2(Int32 numScansToFind)
{
  
  // If there are no scans, no problem, return okay (FALSE)
  //
  if(numScansToFind == 0) {
    return FALSE;
  }

  // Allow any number of scans

  // Do not support for general NEO users.
  if (CmpCommon::getDefault(MODE_SPECIAL_1) == DF_OFF)
    return TRUE;

  // Number of scans of the target table found so far.
  //
  Int32 numHalloweenScans = 0;

  // Get the primary source of the generic update.  We are looking for
  // the halloween scans in the predicates of this scan node
  //
  ValueIdSet preds;
  getScanPreds(this, preds);

  Subquery *subq;

  // Search the preds of this scan for subqueries.
  //
  //    ValueIdSet &preds = scanNode->selectionPred();

  for(ValueId p = preds.init(); preds.next(p); preds.advance(p)) {
    ItemExpr *pred = p.getItemExpr();

    // If this pred contains a subquery, find the scans
    //
    if(pred->containsSubquery()) {
      ValueIdSet subqPreds;
      subqPreds += pred->getValueId();

      // Search all the preds and their children
      //
      while(subqPreds.entries()) {
        ValueIdSet children;
        for(ValueId s = subqPreds.init();
            subqPreds.next(s);
            subqPreds.advance(s)) {
          ItemExpr *term = s.getItemExpr();

          // Found a subquery, now look for the scan...
          //
          if(term->isASubquery()) {
            subq = (Subquery *)term;
              
            // We don't support row subqueries, keep looking for the scan
            // in the next subquery.
            if(!subq->isARowSubquery()) {

              // Is this the subquery that has the scan of the table
              // we are updating?
              //
              Scan *halloweenScan = subq->getSubquery()->getScanNode(FALSE);
              if(halloweenScan) { 
                  
                // Is this the scan we are looking for?
                //
                if(halloweenScan->getTableDesc()->getNATable() == 
                   getTableDesc()->getNATable()) {
                  subq->setAvoidHalloweenR2(this);
                  numHalloweenScans++;
                }
              }
            }
          }
            
          // Follow all the children as well.
          //
          for(Int32 i = 0; i < term->getArity(); i++) {
            children += term->child(i)->getValueId();
          }
        }
        subqPreds = children;
      }
    }
  }

  setAvoidHalloweenR2(numScansToFind);

  // If we found and marked all the halloween scans, then return FALSE (allow).
  // We have marked the subqueries to avoid the halloween problem.  This will
  // force the optimizer to pick a plan that will be safe.
  //
  if(numHalloweenScans == numScansToFind)
    return FALSE;

  return TRUE;
}

// See ANSI 7.9 SR 12 + 6.3 SR 8 for definition of "updatable" table
// references;  in particular, note that one of the requirements for a view's
// being updatable is that ultimately underlying it (passing through a
// whole stack of views) is *exactly one* wbase table -- i.e., no joins
// allowed.
//
RelExpr * GenericUpdate::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  // QSTUFF
  // we indicate that we are in a generic update. If we are
  // already in a generic update we know that this time we are
  // binding a generic update within a view.
  // however be aware of the following scenario. We currently
  // reject embedded updates and streams in the source but
  // obviously allow view with embedded updates as a target.
  // Since its already within a generic update we will only
  // return the scan node to the  insert
  //
  // insert into select ... from (update/delete ....) t;
  //
  // but not cause the update to be bound in when doing
  //
  // insert into viewWithDeleteOrUpdate values(...);
  //
  // in both cases we got an insert->update/delete->scan
  NABoolean inGenericUpdate = FALSE;

  if (getOperatorType() != REL_UNARY_INSERT)
    inGenericUpdate = bindWA->setInGenericUpdate(TRUE);

  NABoolean returnScanNode =
    (inGenericUpdate && bindWA->inViewExpansion() &&
    ( getOperatorType() == REL_UNARY_DELETE ||
      getOperatorType() == REL_UNARY_UPDATE ));

  // those group attributes should be set only by the topmost
  // generic update once we are invoked when already binding
  // another generic we reset those group attributes since we
  // already know that we will only return a scan node

  if ((returnScanNode) && (child(0))) {
    child(0)->getGroupAttr()->setStream(FALSE);
    child(0)->getGroupAttr()->setSkipInitialScan(FALSE);
    child(0)->getGroupAttr()->setEmbeddedIUD(NO_OPERATOR_TYPE);
  }

  // if we have no user-specified access options then
  // get it from nearest enclosing scope that has one (if any)
  if (!accessOptions().userSpecified()) {
    StmtLevelAccessOptions *axOpts = bindWA->findUserSpecifiedAccessOption();
    if (axOpts) {
      accessOptions() = *axOpts;
    }
  }
  // The above code is in Scan::bindNode also.
  // It would be nice to refactor this common code; someday.

  // Make sure we have the appropriate transaction mode & isolation level
  // in order to do the update.  Genesis 10-970922-3488.
  // Keep this logic in sync with Generator::verifyUpdatableTransMode()!
  Lng32 sqlcodeA = 0, sqlcodeB = 0;

  // fix case 10-040429-7402 by checking our statement level access options
  // first before declaring any error 3140/3141.
  TransMode::IsolationLevel il;
  ActiveSchemaDB()->getDefaults().getIsolationLevel
    (il,
     CmpCommon::getDefault(ISOLATION_LEVEL_FOR_UPDATES));
  verifyUpdatableTrans(&accessOptions(), CmpCommon::transMode(),
                       il,
                       sqlcodeA, sqlcodeB);

  if (sqlcodeA || sqlcodeB) {
    // 3140 The isolation level cannot be READ UNCOMMITTED.
    // 3141 The transaction access mode must be READ WRITE.
    if (sqlcodeA) *CmpCommon::diags() << DgSqlCode(sqlcodeA);
    if (sqlcodeB) *CmpCommon::diags() << DgSqlCode(sqlcodeB);
    bindWA->setErrStatus();
    return this;
  }

  Int64 transId=-1;
  if ((isNoRollback() && 
       (NOT (Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL)))) &&
      ((CmpCommon::transMode()->getAutoCommit() != TransMode::ON_ ) ||
       (NAExecTrans(0, transId)))) {

    // do not return an error if this is a showplan query being compiled
    // in the second arkcmp.
    const NAString * val =
      ActiveControlDB()->getControlSessionValue("SHOWPLAN");
    if (NOT ((val) && (*val == "ON")))
      {
	*CmpCommon::diags() << DgSqlCode(-3231);   // Autocommit must be ON,
	bindWA->setErrStatus(); // if No ROLLBACK is specified in IUD statement syntax
	return this;
      }
  }

  if (isNoRollback() ||
      (CmpCommon::transMode()->getRollbackMode() == TransMode::NO_ROLLBACK_))
  {
    if ((child(0)->getGroupAttr()->isStream()) || 
        (child(0)->getGroupAttr()->isEmbeddedUpdateOrDelete()) ||
        (updateCurrentOf()))
    {
      if (getOperatorType() == REL_UNARY_DELETE)
        *CmpCommon::diags() << DgSqlCode(-3234);
      else
        *CmpCommon::diags() << DgSqlCode(-3233);
      bindWA->setErrStatus();
      return this;
    }
  }

  // The SQL standard as defined in ISO/IEC JTC 1/SC 32 date: 2009-01-12
  // CD 9075-2:200x(E) published by ISO/IEC JTC 1/SC 32/WG 3
  // "Information technology -- Database languages -- SQL --
  //  Part2: Foundation (SQL/Foundation)", page 920, section 14.14,
  // page 918, section 14.13, page 900, section 14.9, page 898, section 14.8
  // does allow correlation names in update & delete statements.
  // Therefore, we delete this unnecessary restriction as part of the fix
  // for genesis solution 10-090921-4747:
  // Many places in this method assume the specified target table
  // has no correlation name -- indeed, Ansi syntax does not allow one --
  // this assert is to catch any future syntax-extensions we may do.
  //
  // E.g., see code marked
  //	##SQLMP-SYNTAX-KLUDGE##
  // in SqlParser.y + SqlParserAux.cpp,
  // which add a non-Ansi corr name to all table refs
  // when they really only should add to SELECTed tables.
  // So here, in an INSERT/UPDATE/DELETEd table,
  // we UNDO that kludge.
  //
  //if (!getTableName().getCorrNameAsString().isNull()) {
    //CMPASSERT(SqlParser_NAMETYPE == DF_NSK ||
    // HasMPLocPrefix(getTableName().getQualifiedNameObj().getCatalogName()));
    //getTableName().setCorrName("");			// UNDO that kludge!
  //}

  // Genesis 10-980831-4973
  if (((getTableName().isLocationNameSpecified() || 
        getTableName().isPartitionNameSpecified()) &&
     (!Get_SqlParser_Flags(ALLOW_SPECIALTABLETYPE))) &&
     (getOperatorType() != REL_UNARY_DELETE)) {
    *CmpCommon::diags() << DgSqlCode(-4061);   // 4061 a partn not ins/upd'able
    bindWA->setErrStatus();
    return this;
  }
  
   // -- Triggers
  // If this node is part of the action of a trigger,
  // then don't count the rows that are affected.
  if (bindWA->findNextScopeWithTriggerInfo() != NULL)
  {
    rowsAffected_ = DO_NOT_COMPUTE_ROWSAFFECTED;

    // Does the table name match the name of one of the transition tables?
    if (updatedTableName_.isATriggerTransitionName(bindWA))
    {
      // 11020 Ambiguous or illegal use of transition name $0~string0.
      *CmpCommon::diags() << DgSqlCode(-11020)
                          << DgString0(getTableName().getQualifiedNameAsString());

      bindWA->setErrStatus();
      return this;
    }
  }

  // Get the NATable for this object, and an initial ref count.
  // Set up stoi.
  //
  // We do not suppress mixed name checking in getNATable for R1
  // from here, because prototype name executes through here.  We
  // want to check prototype name.

  const NATable *naTable = bindWA->getNATable(getTableName());
  if (bindWA->errStatus()) return this;

  if (naTable && naTable->isHbaseTable())
    hbaseOper() = TRUE;

  if (naTable && naTable->isHbaseMapTable() &&
      (CmpCommon::getDefault(TRAF_HBASE_MAPPED_TABLES_IUD) == DF_OFF))
    {
      *CmpCommon::diags() << DgSqlCode(-4223)
			  << DgString0("Insert/Update/Delete on HBase mapped tables is");
      
      bindWA->setErrStatus();
      return this;
    }

  if ((CmpCommon::getDefault(ALLOW_DML_ON_NONAUDITED_TABLE) == DF_OFF) &&
      naTable && naTable->getClusteringIndex() && 
      (!naTable->getClusteringIndex()->isAudited())
      // && !bindWA->isBindingMvRefresh()  // uncomment if non-audit MVs are ever supported
     )
  {
     *CmpCommon::diags() << DgSqlCode(-4211)
       << DgTableName(
           naTable->getTableName().getQualifiedNameAsAnsiString());
     bindWA->setErrStatus();
     return NULL;
  }
  
  Int32 beforeRefcount = naTable->getReferenceCount();

  OptSqlTableOpenInfo *listedStoi
    = setupStoi(stoi_, bindWA, this, naTable, getTableName());

  if (getOperatorType() == REL_UNARY_INSERT &&
      NOT naTable->isInsertable()) {
    *CmpCommon::diags() << DgSqlCode(-4027)  // 4027 table not insertable
      << DgTableName(naTable->getTableName().getQualifiedNameAsAnsiString());
    bindWA->setErrStatus();
    return this;
  }
  if (NOT naTable->isUpdatable()) {
    *CmpCommon::diags() << DgSqlCode(-4028)  // 4028 table not updatable
      << DgTableName(naTable->getTableName().getQualifiedNameAsAnsiString());
    bindWA->setErrStatus();
    return this;
  }

  if (naTable->isVerticalPartition()) {
    // On attempt to update an individual VP, say: 4082 table not accessible
    *CmpCommon::diags() << DgSqlCode(-4082) <<
       DgTableName(naTable->getTableName().getQualifiedNameAsAnsiString());
    bindWA->setErrStatus();
    return this;
  }


  if (naTable->isAnMV())
  {
    // we currently don't allow updating (deleting) MVs in a trigger action
    if (bindWA->inDDL() && bindWA->isInTrigger ())
    {
        *CmpCommon::diags() << DgSqlCode(-11051);
        bindWA->setErrStatus();
        return this;
    }

    // This table is a materialized view. Are we allowed to change it?
    if ((getTableName().getSpecialType() != ExtendedQualName::MV_TABLE) &&
        (getTableName().getSpecialType() != ExtendedQualName::GHOST_MV_TABLE))
    {
      // The special syntax flag was not used -
      // Only on request MV allows direct DELETE operations by the user.
      MVInfoForDML *mvInfo = ((NATable *)naTable)->getMVInfo(bindWA);
      if (mvInfo->getRefreshType() == COM_ON_REQUEST &&
          getOperatorType() == REL_UNARY_DELETE)
      {
        // Set NOLOG flag.
        setNoLogOperation();
      }
      else
      {
        // Direct update is only allowed for User Maintainable MVs.
        if (mvInfo->getRefreshType() != COM_BY_USER)
        {
          // A Materialized View cannot be directly updated.
          *CmpCommon::diags() << DgSqlCode(-12074);
          bindWA->setErrStatus();
          return this;
        }
      }
    }

    // If this is not an INTERNAL REFRESH command, make sure the MV is
    // initialized and available.
    if (!bindWA->isBindingMvRefresh())
    {
      if (naTable->verifyMvIsInitializedAndAvailable(bindWA))
        return NULL;
    }
  }

  if (naTable->isAnMVMetaData() &&
      getTableName().getSpecialType() != ExtendedQualName::MVS_UMD)
  {
    if (getTableName().getPrototype() == NULL ||
        getTableName().getPrototype()->getSpecialType() != ExtendedQualName::MVS_UMD)
    {  // ERROR 12075: A Materialized View Metadata Table cannot be directly updated.
      *CmpCommon::diags() << DgSqlCode(-12075);
      bindWA->setErrStatus();
      return this;
    }
  }

  if ((naTable->isSeabaseTable()) &&
      (naTable->isSeabaseMDTable() || 
       naTable->isSeabasePrivSchemaTable()) &&
      (NOT naTable->isUserUpdatableSeabaseMDTable()) &&
      (NOT Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL)))
    {
      // IUD on hbase metadata is only allowed for internal queries.
     *CmpCommon::diags() << DgSqlCode(-1391)
			 <<  DgString0(naTable->getTableName().getQualifiedNameAsAnsiString())
                         << DgString1("metadata");
      bindWA->setErrStatus();
      return this;
    }
  else if ((naTable->isSeabaseTable()) &&
           (naTable->getTableName().getSchemaName() == SEABASE_REPOS_SCHEMA) &&
           (NOT Get_SqlParser_Flags(INTERNAL_QUERY_FROM_EXEUTIL)))
    {
      // IUD on hbase metadata is only allowed for internal queries.
      *CmpCommon::diags() << DgSqlCode(-1391)
			 <<  DgString0(naTable->getTableName().getQualifiedNameAsAnsiString())
                         << DgString1("repository");
      bindWA->setErrStatus();
      return this;
    }
  
  if ((naTable->isHbaseTable()) &&
      (naTable->isHbaseCellTable() || naTable->isHbaseRowTable()) &&
      (CmpCommon::getDefault(HBASE_NATIVE_IUD) == DF_OFF))
    {
      *CmpCommon::diags() << DgSqlCode(-4223)
			  << DgString0("Insert/Update/Delete on native HBase tables or in CELL/ROW format is");
      
      bindWA->setErrStatus();
      return this;
     }

  NABoolean insertFromValuesList =
   (getOperatorType() == REL_UNARY_INSERT &&
    (child(0)->getOperatorType() == REL_TUPLE ||  // VALUES(1,'b')
     child(0)->getOperatorType() == REL_TUPLE_LIST ||  // VALUES(1,'b'),(2,'Y')
     child(0)->getOperatorType() == REL_UNION)) ||  // VALUES..(with subquery inside the list)
    getOperatorType() == REL_LEAF_INSERT;          // index type of inserts

   if((!insertFromValuesList) && (getOperatorType() == REL_UNARY_INSERT))
    bindWA->setInsertSelectStatement(TRUE);

  // an update/delete node is created as an update/delete with child
  // of a scan node by parser. If this is the case, then no security
  // checks are needed on child Scan node.
  if ((getOperatorType() == REL_UNARY_UPDATE ||
       getOperatorType() == REL_UNARY_DELETE) &&
      (child(0) && (child(0)->getOperatorType() == REL_SCAN))) {
    Scan * scanNode = (Scan *)(child(0)->castToRelExpr());
    scanNode->setNoSecurityCheck(TRUE);
  }

  // Setting the begin index for TableViewUsageList to zero, instead
  // of the bindWA->tableViewUsageList().entries(); Becasue
  // bindWA->tableViewUsageList().entries() sets the index to the current
  //entry in the list, which excludes previous statements executed in a CS.
  CollIndex begSrcUsgIx = 0;
  if (!insertFromValuesList) {
    //
    // Create a new table name scope for the source table (child node).
    // Bind the source.
    // Reset scope context/naming.
    //
    bindWA->getCurrentScope()->xtnmStack()->createXTNM();
    bindChildren(bindWA);
    if (bindWA->errStatus()) return this;
    bindWA->getCurrentScope()->xtnmStack()->removeXTNM();

    // QSTUFF

    // we currently don't support streams and embedded updates
    // for "insert into select from" statements.
    if (getOperatorType() == REL_UNARY_INSERT){

      if (child(0)->getGroupAttr()->isStream()){
        *CmpCommon::diags() << DgSqlCode(-4170);
        bindWA->setErrStatus();
        return this;
      }

      if (child(0)->getGroupAttr()->isEmbeddedUpdateOrDelete() ||
          child(0)->getGroupAttr()->isEmbeddedInsert()){
        *CmpCommon::diags() << DgSqlCode(-4171)
			    << DgString0(getGroupAttr()->getOperationWithinGroup());
        bindWA->setErrStatus();
        return this;
      }
    }

    // binding a generic update within a generic update
    // can only occur when binding an updatable view containing
    // an embedded delete or embedded update. We don't continue
    // binding the generic update and but return the bound scan node.
    // the scan node may be either a base table scan or a RenameTable
    // node in case we are updating a view
    // Since an embedded generic update may have referred to the OLD
    // and NEW table we set a binder flag causing the table name to
    // be changed to the name of the underlying scan table in the
    // RelRoot on top of the generic update. Since we
    // know that the normalizer has checked before allowing an update
    // on the view that not both, i.e.new and old column values have been
    // referred this is a safe operation.

    if (returnScanNode){
      // this line is a hack to get through Update::bindNode on the return
      setTableDesc(getScanNode()->getTableDesc());

      bindWA->setInGenericUpdate(inGenericUpdate);
      bindWA->setRenameToScanTable (TRUE);
      NATable *nTable = bindWA->getNATable(getTableName());

      // decr once for just getting it here
      // and again to compensate for the reference taken out
      // previously which becomes obsolete since we just return a scan node
      nTable->decrReferenceCount();
      nTable->decrReferenceCount();

      return getViewScanNode();
    }
    // QSTUFF
  }
  else {
    // else, Insert::bindNode does VALUES(...) in its Assign::bindNode loop
    // in particular, it does      VALUES(..,DEFAULT,..)
  }

  #ifndef NDEBUG
    GU_DEBUG_Display(bindWA, this, "incoming", NULL, TRUE);
  #endif

  // QSTUFF
  // in case of an insert operation we don't set it initially in order
  // to prevent that an embedded update or delete may be accidentially
  // removed from a source view. However we need it for binding the
  // target because it may be a view and its embedded updates have to
  // be removed.

  if (getOperatorType() == REL_UNARY_INSERT)
    inGenericUpdate = bindWA->setInGenericUpdate(TRUE);

  CMPASSERT(NOT(updateCurrentOf() &&
                getGroupAttr()->isEmbeddedUpdateOrDelete()));

  // this is a patch to allow for embedded updates in view definitions
  ParNameLocList * pLoc = NULL;
  if (getGroupAttr()->isEmbeddedUpdate()) {
    pLoc =  bindWA->getNameLocListPtr();
    bindWA->setNameLocListPtr(NULL);
  }
  // QSTUFF

  // Allocate a TableDesc and attach it to the node.
  //
  // Note that for Update/Delete, which always have a Scan node attached
  // (see below), we cannot reuse the Scan's TableDesc:
  // GenMapTable.C doesn't find the proper ValueIds when processing an
  // update/delete on a table with an index.
  // So we must always create a new (target) TableDesc, always a base table.
  //
  // Note that bindWA->getCurrentScope()->setRETDesc() is implicitly called:
  // 1) by createTableDesc, setting it to this new (target) base table;
  // 2) by bindView (if called), resetting it to the view's RenameTable RETDesc
  //    atop the new (target) table.
  //
  const NATable *naTableTop = naTable;
  NABoolean isView = naTable->getViewText() != NULL;
  RelExpr *boundView = NULL;      // ## delete when done with it?
  Scan *scanNode = NULL;

  if (getOperatorType() == REL_UNARY_INSERT ||
      getOperatorType() == REL_LEAF_INSERT) {
    if (isView) {        // INSERT into a VIEW:
    //
    // Expand the view definition as if it were a Scan child of the Insert
    // (like all children, must have its own table name scope).
    //
    bindWA->getCurrentScope()->xtnmStack()->createXTNM();
    boundView = bindWA->bindView(getTableName(),
                                 naTable,
                                 accessOptions(),
                                 removeSelPredTree(),
                                 getGroupAttr());
    #ifndef NDEBUG
      GU_DEBUG_Display(bindWA, this, "bv1", boundView);
    #endif
    if (bindWA->errStatus()) return this;
    scanNode = boundView->getScanNode();
    bindWA->getCurrentScope()->xtnmStack()->removeXTNM();
    }
  }
  else if (getOperatorType() == REL_UNARY_UPDATE ||
           getOperatorType() == REL_UNARY_DELETE) {
    scanNode = getScanNode();
  }

  if (updateCurrentOf()) {
    CMPASSERT(scanNode);
    scanNode->bindUpdateCurrentOf(bindWA,
                                  (getOperatorType() == REL_UNARY_UPDATE));
    if (bindWA->errStatus()) return this;
  }

  // As previous comments indicated, we're creating a TableDesc for the target,
  // the underlying base table.  Here we go and do it:

  NABoolean isScanOnDifferentTable = FALSE;
  if (isView) {
    // This binding of the view sets up the target RETDesc.
    // This is the first bindView for UPDATE and DELETE on a view,
    // and the second for INSERT into a view (yes, we *do* need to do it again).
    boundView = bindWA->bindView(getTableName(),
                                 naTable,
                                 accessOptions(),
                                 removeSelPredTree(),
                                 getGroupAttr(),
                                 TRUE);   // QSTUFF
    setTableDesc(boundView->getScanNode()->getTableDesc());
    if ((getOperatorType() == REL_INSERT)||
        (getOperatorType() == REL_UNARY_INSERT) ||
        (getOperatorType() == REL_LEAF_INSERT))
    {
      ((Insert *)this)->setBoundView(boundView);
    }
    // for triggers
    if (scanNode)
      {
        const NATable *naTableLocal = scanNode->getTableDesc()->getNATable();
        if ((naTableLocal != naTable) && (naTableLocal->getSpecialType() == ExtendedQualName::TRIGTEMP_TABLE))
          isScanOnDifferentTable = TRUE;
      }
  } else if (NOT (getUpdateCKorUniqueIndexKey() && (getOperatorType() == REL_UNARY_INSERT))) {
    // an insert that is introduced to implement a phase of update primary key already 
    // has the right tabledesc (obtained from the update that it is replacing), so 
    // do not create another tablesdesc for such an insert.
    if (scanNode)
      naTable = scanNode->getTableDesc()->getNATable();
    CorrName tempName(naTableTop->getTableName(),
                      bindWA->wHeap(),
                      "",
                      getTableName().getLocationName(),
                      getTableName().getPrototype());
    
    tempName.setUgivenName(getTableName().getUgivenName());
    
    tempName.setSpecialType(getTableName().getSpecialType());
    //    tempName.setIsVolatile(getTableName().isVolatile());
    TableDesc * naTableToptableDesc = bindWA->createTableDesc(
                                                             naTableTop,
                                                             tempName);

    if(naTableToptableDesc)
    {
      naTableToptableDesc->setSelectivityHint(NULL);
      naTableToptableDesc->setCardinalityHint(NULL);
    }

    setTableDesc(naTableToptableDesc);

    // Now naTable has the Scan's table, and naTableTop has the GU's table.
    // Rather than compare naTable pointers we now compare the extended
    // qualified name contained in them. This name is the key to an natable
    // object in NATableDB and will enable us to tell if scan's table and 
    // GU's table are the same.
    isScanOnDifferentTable = (naTable->getExtendedQualName() != 
			      naTableTop->getExtendedQualName());
  }

  if (bindWA->errStatus())
    return this;


  // QSTUFF
  // in case of a delete or update we may have to bind set clauses.
  // first we bind the left target column, second we bind the right hand side
  // we also have to separate the set on rollback clauses in a separate
  // list. The set clauses generate a newRecExpr list, the set on rollback
  // clause generate a newRecBeforeExpr list.

  // we add the old to new valueid map as it allows us to generate
  // a subset operator in the presence of order by. the compiler
  // needs to understand that the old and new valueids are identical

  // inlined trigger may update and scan different tables
  if ((getOperatorType() == REL_UNARY_DELETE) && 
    (!isScanOnDifferentTable && !getUpdateCKorUniqueIndexKey())) {
    const ValueIdList &dkeys =
      getTableDesc()->getClusteringIndex()->getClusteringKeyCols();
    const ValueIdList &skeys =
      scanNode->getTableDesc()->getClusteringIndex()->getClusteringKeyCols();
    CollIndex j = skeys.entries();
    for (CollIndex i = 0; i < j; i++) {
      oldToNewMap().addMapEntry(skeys[i].getItemExpr()->getValueId(),
                                dkeys[i].getItemExpr()->getValueId());
    }
  }

  ItemExpr *recExpr = removeNewRecExprTree();

  if (recExpr &&
      (getOperatorType() == REL_UNARY_DELETE ||
       getOperatorType() == REL_UNARY_UPDATE)) {

    ItemExprList  recList(recExpr, bindWA->wHeap());
    ItemExprList  recBeforeList(bindWA->wHeap());
    SET(short)    stoiColumnSet(bindWA->wHeap());

    // in case a delete statement has a recEpxr, set on rollback
    // clauses have been defined and need to be bound

    // as part of binding any set on rollback clause we have check
    // that no contraints are defined for the specific clauses; otherwise
    // the statement is rejected.
    // the target columns are bound to the update table, the source
    // columns are bound to the scan table

    if (getOperatorType() == REL_UNARY_DELETE){
      recBeforeList.insert(recList);
      bindUpdateExpr(bindWA,recExpr,recBeforeList,boundView,scanNode,stoiColumnSet,TRUE);
      if (bindWA->errStatus()) return this;
    }

    // in case of an update operator we have to separate the set and
    // set on rollback clauses

    if (getOperatorType() == REL_UNARY_UPDATE) {
      CMPASSERT(recList.entries());

      NABoolean leftIsList      = FALSE;
      NABoolean rightIsList     = FALSE;
      NABoolean legalSubqUdfExpr = FALSE;

      for (CollIndex i = 0;i < recList.entries(); i++){

        CMPASSERT(recList[i]->getOperatorType() == ITM_ASSIGN);

        if (recList[i]->child(0)->getOperatorType() == ITM_ITEM_LIST)
          leftIsList = TRUE;
        if (recList[i]->child(1)->getOperatorType() == ITM_ITEM_LIST)
          rightIsList = TRUE;

        if (((Assign *)recList[i])->onRollback()){

          // On rollback clause currently not allowed with update lists.
          if ((leftIsList) || (rightIsList))
            {
              *CmpCommon::diags() << DgSqlCode(-3242) 
                                  << DgString0(" ON ROLLBACK not supported with SET lists.");
              bindWA->setErrStatus();
              return this;
            }
          //          CMPASSERT((NOT leftIsList) && (NOT rightIsList))
          
          recBeforeList.insert(recList[i]);
          recList.removeAt(i);
          i--;
        }
      }
      

      if ((leftIsList) &&
          (NOT rightIsList) && 
          (recList.entries() == 1) &&
          ((recList[0]->child(1)->getOperatorType() == ITM_ROW_SUBQUERY) ||
          (recList[0]->child(1)->getOperatorType() == ITM_USER_DEF_FUNCTION)))
        {
          ItemExpr   * expr = NULL;

          // Both Subqueries and UDFs are now using the ValueIdProxy
          // to carry the each of the valueIds representing the select list
          // or UDF outputs. The transformation of the ValueIdProxy will do the
          // right thing, and we don't need setSubqInUpdateAssing() anymore.

          // Bind the subquery
          if (recList[0]->child(1)->getOperatorType() == ITM_ROW_SUBQUERY) 
          {
             RowSubquery * rs = 
               (RowSubquery*)(recList[0]->child(1)->castToItemExpr());

             // Not sure that we ever have a subquery without a REL_ROOT
             // left this additional check from the old code.
             if (rs->getSubquery()->getOperatorType() == REL_ROOT)
             {
                rs = (RowSubquery *) rs->bindNode(bindWA);
                if (bindWA->errStatus())
                  return this;

                legalSubqUdfExpr = TRUE;
                expr = (ItemExpr *) rs;
             }
          
          }
          else
          {
             UDFunction * rudf = 
               (UDFunction*)(recList[0]->child(1)->castToItemExpr());

             //  Need to bind the UDFunction to get its outputs.
             rudf = (UDFunction *) rudf->bindNode(bindWA);
             if (bindWA->errStatus())
               return this;

             legalSubqUdfExpr = TRUE;
             expr = (ItemExpr *) rudf;

          }

          // Update the recList with the bound itemExpr
          recList[0]->child(1) = expr;


          // Use the ItemExprList to flatten the Subquery or UDF
          ItemExprList *exprList = (ItemExprList *) new(bindWA->wHeap())
                                  ItemExprList(expr,bindWA->wHeap());

          // Convert the ItemExprList to a Tree
          ItemExpr * ie = exprList->convertToItemExpr();
          ie = ie->bindNode(bindWA);
          if (bindWA->errStatus())
            return this;
  
          Assign * assignNode = (Assign *)recList[0];
          assignNode->child(1) = ie;

          rightIsList = TRUE;
        }

      if ((leftIsList) || (rightIsList)) // some elements as lists
        {
          ItemExprList  newRecList(bindWA->wHeap());
          for (CollIndex i = 0; i < recList.entries(); i++)
            {
              Assign * assignNode = (Assign *)recList[i];

                // Need to bind any UDFs or Subqieries in the expression 
                // so that we know the degree before we expand the list.
              assignNode->child(0) = 
                          assignNode->child(0)->bindUDFsOrSubqueries(bindWA); 
              if (bindWA->errStatus())
                return this;

                // Need to bind any UDFs or Subqieries in the expression 
                // so that we know the degree before we expand the list.
              assignNode->child(1) = 
                          assignNode->child(1)->bindUDFsOrSubqueries(bindWA); 
              if (bindWA->errStatus())
                return this;

              ItemExprList leftList(assignNode->child(0), bindWA->wHeap());
              ItemExprList rightList(assignNode->child(1), bindWA->wHeap());
              Lng32 numLeftElements = (Lng32) leftList.entries();
              Lng32 numRightElements = (Lng32) rightList.entries();

              // See if ALLOW_SUBQ_IN_SET is enabled. It is enabled if
              // the default is ON, or if the default is SYSTEM and
              // ALLOW_UDF is ON.
              NABoolean allowSubqInSet_Enabled = FALSE;
              DefaultToken allowSubqTok =
                CmpCommon::getDefault(ALLOW_SUBQ_IN_SET);
              if ((allowSubqTok == DF_ON) ||
                  (allowSubqTok == DF_SYSTEM))
                allowSubqInSet_Enabled = TRUE;

              if (!allowSubqInSet_Enabled)
                 {
                   for (CollIndex j = 0; j < rightList.entries(); j++)
                     {
                       if (((numLeftElements > 1) ||
                           (numRightElements > 1)) &&
                           (((rightList[j]->getOperatorType() == ITM_ROW_SUBQUERY) ||
                             (rightList[j]->getOperatorType() == ITM_VALUEID_PROXY)) &&
                             (legalSubqUdfExpr == FALSE)))
                         {
                           *CmpCommon::diags() << DgSqlCode(-3242) 
                             << DgString0(" Multiple elements or multiple subqueries are not allowed in this SET clause.");    
                           bindWA->setErrStatus();
                           return this;
                         }
                     }
                 }

              if (numLeftElements != numRightElements)
                {
                  *CmpCommon::diags() << DgSqlCode(-4023)
                    << DgInt0(numRightElements) 
                    << DgInt1(numLeftElements);
                  bindWA->setErrStatus();
                  return this;
                }
              
              // create newRecList with one Assign node for each element.
              for (CollIndex k = 0; k < leftList.entries(); k++)
                {
                  ItemExpr * leftIE = leftList[k];
                  ItemExpr * rightIE = rightList[k];
                  Assign *assign = new (bindWA->wHeap())
                    Assign(leftIE, rightIE);
                  // We do not bind the above Assign as it will be done
                  // in bindUpdateExpr below. (bug #1893)
                  newRecList.insert(assign);
                }

            } // for

	  bindUpdateExpr(bindWA,recExpr,newRecList,boundView,scanNode,stoiColumnSet);
	  if (bindWA->errStatus()) 
	    return this;
	} // some elements as lists
      else
	{ // no elements as lists
	  if (recList.entries()){
	    bindUpdateExpr(bindWA,recExpr,recList,boundView,scanNode,stoiColumnSet);
	    if (bindWA->errStatus()) return this;
	  }
	}

      if (recBeforeList.entries()){
      bindUpdateExpr(bindWA,recExpr,recBeforeList,boundView,scanNode,stoiColumnSet,TRUE);
      if (bindWA->errStatus()) return this;
      }

    } // UNARY_UPDATE

  // now we record the columns updated for the SqlTableOpenInfo
  if (listedStoi) {
    listedStoi->getStoi()->setColumnListCount((short)stoiColumnSet.entries());

    short *stoiColumnList = new (bindWA->wHeap())
      short[stoiColumnSet.entries()];

    for (CollIndex i = 0; i < stoiColumnSet.entries(); i++)
    {
      stoiColumnList[i] = stoiColumnSet[i];
      listedStoi->addUpdateColumn(stoiColumnSet[i]);
    }

    listedStoi->getStoi()->setColumnList(stoiColumnList);
  }

    // the previous implementation assumed that the scope points
    // to the scan table; we don't want to disturb the code and
    // make that happen --

    #ifndef NDEBUG
      GU_DEBUG_Display(bindWA, this, "u");
    #endif

    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
  }
  // QSTUFFF

  CollIndex endSrcUsgIx = bindWA->tableViewUsageList().entries();

  if ((!isScanOnDifferentTable) &&
      (((getOperatorType() == REL_UNARY_INSERT) &&
       !insertFromValuesList && !getGroupAttr()->isEmbeddedInsert()) ||
      (getOperatorType() == REL_UNARY_UPDATE) ||
      (getOperatorType() == REL_UNARY_DELETE))){

    // Special handling of statements that could suffer the 
    // Halloween problem, e.g., "insert into t select from t"
    // or "insert into v select from t", if v references t

    DBG( if (getenv("TVUSG_DEBUG")) bindWA->tableViewUsageList().display(); )

    const NATable *naTableBase = naTable;
    const QualifiedName *viewName = NULL;
    if (isView) {
      // Currently, per Ansi rules, we can only insert through a view if
      // there is a single underlying base table without joins or unions.
      // Since we are binding the view twice for INSERTS,
      // the variable beforeRefcount for the *single* base table has to be 2.
      //
      beforeRefcount = beforeRefcount + 1;
      naTableBase = getTableDesc()->getNATable();
      viewName = &naTable->getTableName();
    }
    if ((getOperatorType() == REL_UNARY_UPDATE ||
         getOperatorType() == REL_UNARY_DELETE) &&
        (child(0)->getOperatorType() == REL_SCAN)) {
      // The table is referenced twice; once for the update/delete and
      // the second time for the scan below it.
      beforeRefcount = beforeRefcount + 1;
    }

    const QualifiedName &tableBaseName = naTableBase->getTableName();
    Int32 afterRefcount =  naTableBase->getReferenceCount();
    NABoolean isSGTableType = getTableName().getSpecialType() == ExtendedQualName::SG_TABLE;

    NAString viewFmtdList(bindWA->wHeap());
    Int32 baseSeenInSrc = 0;
    
    // The views on the table do not need to be obtained
    // if the table type is a SEQUENCE GENERATOR

    if (!isSGTableType)
      baseSeenInSrc = bindWA->tableViewUsageList().getViewsOnTable(
                               begSrcUsgIx, endSrcUsgIx,
                               bindWA->viewCount(),
                               tableBaseName,
                               getTableName().getSpecialType(),
                               viewName,
                               viewFmtdList);

    NABoolean halloween = FALSE;
    if (CmpCommon::getDefault(R2_HALLOWEEN_SUPPORT) == DF_ON) {

      if (beforeRefcount != afterRefcount) {

          // Check to see if we can support this update.
          //
          if(checkForHalloweenR2(afterRefcount - beforeRefcount)) {
            halloween = TRUE;
          }
      }
      else {
        Scan *scanSrc = getScanNode(FALSE/*no assert*/);
        if ((baseSeenInSrc > beforeRefcount) &&
            ((scanSrc && scanSrc->getTableName().isLocationNameSpecified())||
             (getTableName().isLocationNameSpecified()))) {
          halloween = TRUE;
        }
        if (Get_SqlParser_Flags(ALLOW_SPECIALTABLETYPE)) {
          if ((scanSrc && scanSrc->getTableName().isLocationNameSpecified())||
              (getTableName().isLocationNameSpecified())){
            // Do not enforce Halloween check if it is a
            // partition only operation.
            // We assume the programmer knows what he's doing
            // -- hopefully, by doing insert/update/delete
            // operations as part of Partition Management
            // (Move Partition Boundary or Split Partition or
            // Merge Partition. See TEST057 and TEST058)
            halloween = FALSE;
          }
        }
      }
      if (halloween) {
        CMPASSERT(!(isView && viewFmtdList.isNull()));
        *CmpCommon::diags() << DgSqlCode(viewFmtdList.isNull() ? -4026 : -4060)
                            << DgTableName(
                                  tableBaseName.getQualifiedNameAsAnsiString())
                            << DgString0(viewFmtdList);
        bindWA->setErrStatus();
        return this;
      }
    } 
    else {
      // Support for self-referencing updates/Halloween problem.
      if (beforeRefcount != afterRefcount) {

        setAvoidHalloween(TRUE);

        bindWA->getTopRoot()->setAvoidHalloween(TRUE);

        // Decide if access mode (default or specified) is compatible
        // with the use of DP2 locks.  If access mode was specified,
        // it is a property of the naTableBase.
        NABoolean cannotUseDP2Locks = 
             naTableBase->getRefsIncompatibleDP2Halloween();

        // Now check the transaction isolation level, which can override
        // the access mode.  Note that il was initialized above for the
        // check for an updatable trans, i.e., errors 3140 and 3141.
        if((CmpCommon::transMode()->ILtoAT(il) == TransMode::REPEATABLE_READ_ACCESS_ ) ||
           (CmpCommon::transMode()->ILtoAT(il) == TransMode::READ_COMMITTED_ACCESS_     ) ||
           (CmpCommon::transMode()->ILtoAT(il) == TransMode::READ_UNCOMMITTED_ACCESS_     )) 
           cannotUseDP2Locks = TRUE;

        // Save the result with this GenericUpdate object.  It will be 
        // used when the nextSubstitute  methods of TSJFlowRule or TSJRule 
        // call GenericUpdate::configTSJforHalloween.
        if (NOT getHalloweenCannotUseDP2Locks())
          setHalloweenCannotUseDP2Locks(cannotUseDP2Locks);

        // Keep track of which table in the query is the self-ref table.
        // This is a part of the fix for solution 10-071204-9253.
        ((NATable *)naTableBase)->setIsHalloweenTable();
      }
      else {
        Scan *scanSrc = getScanNode(FALSE/*no assert*/);
        if ((baseSeenInSrc > beforeRefcount) &&
            ((scanSrc && scanSrc->getTableName().isLocationNameSpecified())||
             (getTableName().isLocationNameSpecified()))) {
          halloween = TRUE;
        }
        if (Get_SqlParser_Flags(ALLOW_SPECIALTABLETYPE)) {
          if ((scanSrc && scanSrc->getTableName().isLocationNameSpecified())||
              (getTableName().isLocationNameSpecified())){
            // Do not enforce Halloween check if it is a
            // partition only operation.
            // We assume the programmer knows what he's doing
            // -- hopefully, by doing insert/update/delete
            // operations as part of Partition Management
            // (Move Partition Boundary or Split Partition or
            // Merge Partition. See TEST057 and TEST058)
            halloween = FALSE;
          }
        }
        if (halloween) {
          CMPASSERT(!(isView && viewFmtdList.isNull()));
          *CmpCommon::diags() << DgSqlCode(viewFmtdList.isNull() ? -4026 : -4060)
                              << DgTableName(
                                  tableBaseName.getQualifiedNameAsAnsiString())
                              << DgString0(viewFmtdList);
          bindWA->setErrStatus();
          return this;
        }
      }
    }
  }

  // Bind the base class.
  // Allocate an empty RETDesc and attach it to this node, *but* leave the
  // currently scoped RETDesc (that of naTableTop) as is, for further binding
  // in caller Insert::bindNode or LeafInsert/LeafDelete::bindNode.
  //
  RelExpr *boundExpr = bindSelf(bindWA);
  CMPASSERT(boundExpr == this);  // assumed by RETDesc/RI/IM code below
  if (bindWA->errStatus()) return boundExpr;
  setRETDesc(new (bindWA->wHeap()) RETDesc(bindWA));

  // Copy the check constraints to the private memory of the GenericUpdate.
  //
  checkConstraints() = getTableDesc()->getCheckConstraints();

  // Create a key expression for the table to be updated.
  // The code specific to the Insert node is handled in Insert::bindNode.
  //
  if (getOperatorType() == REL_UNARY_UPDATE ||
      getOperatorType() == REL_UNARY_DELETE) {

    if (getTableDesc()->getNATable()->isHiveTable())
      {
        *CmpCommon::diags() << DgSqlCode(-4223)
                            << DgString0("Update/Delete on Hive table is");
        bindWA->setErrStatus();
        return this;
      }

    // SQL syntax requires (and the parser ensures) that a direct descendant
    // (passing thru views) of an update/delete node is a scan node on the
    // same table that is being updated (note that normalizer transformations
    // may change this at a later time).
    // An exception to this rule happens when before triggers are inlined.
    // In this case, the update/delete on the subject table is driven by
    // a Scan on a temp table. The primary key columns of the subject table are
    // a subset of the primary key columns of the temp table, and using the
    // same column names, but not neccessarily in the same order.
    //
    // Update/Delete nodes require expressions in their newRecExpr that can
    // be used to form the primary key of the table to update/delete.
    //
    const NAColumnArray &keyColArray =
      getTableDesc()->getNATable()->getClusteringIndex()->getIndexKeyColumns();
    CollIndex numKeyCols = keyColArray.entries();
    const NAColumnArray &scanColArray =
    scanNode->getTableDesc()->getNATable()->getNAColumnArray();

    for (CollIndex i = 0; i < numKeyCols; i++) {
      // The scan node and the update/delete node both use the SAME table,
      // so their column names are also the same.
      //
      Lng32 colPos = keyColArray[i]->getPosition();
      ItemExpr *guCol = getTableDesc()->getColumnList()[colPos].getItemExpr();
      ItemExpr *scanCol;  // - Triggers
      if (!isScanOnDifferentTable)
        scanCol = scanNode->getTableDesc()->getColumnList()[colPos].getItemExpr();
      else
      {
        // Make sure this is a BaseColumn.
        CMPASSERT(guCol->getOperatorType() == ITM_BASECOLUMN);
        // Find the column name.
        const NAString& colName = ((BaseColumn *)guCol)->getColName();
        // Find a column with the same name, in the table from the Scan node.
        // SYSKEY is an exception since its name in the temp table is "@SYSKEY"
        ExtendedQualName::SpecialTableType tableType =
          scanNode->getTableDesc()->getCorrNameObj().getSpecialType();
        NAColumn *scanNaCol = NULL;
        if (ExtendedQualName::TRIGTEMP_TABLE == tableType && colName == "SYSKEY")
        {
          scanNaCol = scanColArray.getColumn("@SYSKEY");
        }
        else
        {
          scanNaCol = scanColArray.getColumn(colName);
        }
        CMPASSERT(scanNaCol != NULL)
        // Get the position of this column in the Scan table.
        Lng32 scanColPos = scanNaCol->getPosition();
        // Get the Scan BaseColumn.
        scanCol = scanNode->getTableDesc()->getColumnList()[scanColPos].getItemExpr();
      }
      ItemExpr *newKeyPred = new (bindWA->wHeap())
        BiRelat(ITM_EQUAL, guCol, scanCol);
      newKeyPred->bindNode(bindWA);
      beginKeyPred().insert(newKeyPred->getValueId());

      updateToSelectMap().addMapEntry(
           newKeyPred->child(0)->getValueId(),
           newKeyPred->child(1)->getValueId());

    } // loop over key columns

    // All of the indexes also require expressions that can be used to
    // form the primary key of the index to update/delete. Create these
    // item expressions here.
    // (From here to the end of the loop over indexes structurally resembles
    // GenericUpdate::imBindAllIndexes(), but has significant differences.)
    //
    // Remember the value ID's of the scan node index columns for
    // code generation time.
    //

    if ((this->getOperatorType() == REL_UNARY_UPDATE) && isScanOnDifferentTable)
    {
      setScanIndexDesc(NULL);  // for triggers
    }
    else
    {
      setScanIndexDesc(scanNode->getTableDesc()->getClusteringIndex());
    }
  } // REL_UNARY_UPDATE or REL_UNARY_DELETE


  // QSTUFF
  // we need to check whether this code is executed as part of a create view
  // ddl operation using bindWA->inDDL() and prevent indices, contraints and
  // triggers to be added as the catalog manager binding functions cannot
  // handle it right now
  // QSTUFF

  // QSTUFF hack !
  if (getGroupAttr()->isEmbeddedUpdate())
    bindWA->setNameLocListPtr(pLoc);
  bindWA->setInGenericUpdate(inGenericUpdate);
  // QSTUFF

  // set flag that we are binding an Insert/Update/Delete operation
  // Used to disable Join optimization when necessary
  bindWA->setBindingIUD();

  return boundExpr;
} // GenericUpdate::bindNode()

NABoolean GenericUpdate::checkForMergeRestrictions(BindWA *bindWA)
{
  if (!isMerge())
    return FALSE;


  ValueIdList tempVIDlist;
  getTableDesc()->getIdentityColumn(tempVIDlist);
  NAColumn *identityCol = NULL;
  if (tempVIDlist.entries() > 0)
  {
    ValueId valId = tempVIDlist[0];
    identityCol = valId.getNAColumn();
  }

  // MERGE on a table with BLOB columns is not supported
  if (getTableDesc()->getNATable()->hasLobColumn())
  {
    *CmpCommon::diags() << DgSqlCode(-3241) 
                        << DgString0(" LOB column not allowed.");
    bindWA->setErrStatus();
    return TRUE;

  }
  
  if (getTableDesc()->hasUniqueIndexes() && 
      (CmpCommon::getDefault(MERGE_WITH_UNIQUE_INDEX) == DF_OFF))
  {
    *CmpCommon::diags() << DgSqlCode(-3241) 
			<< DgString0(" unique indexes not allowed.");
    bindWA->setErrStatus();
    return TRUE;
  }
  
  if ((accessOptions().accessType() == TransMode::SKIP_CONFLICT_ACCESS_) ||
      (getGroupAttr()->isStream()) ||
      (newRecBeforeExprArray().entries() > 0)) // set on rollback
  {
    *CmpCommon::diags() << DgSqlCode(-3241)
                        << DgString0(" Stream, skip conflict or SET ON ROLLBACK not allowed.");
    bindWA->setErrStatus();
    return TRUE;
  }

  if (getGroupAttr()->isEmbeddedUpdateOrDelete())
  {
    *CmpCommon::diags() << DgSqlCode(-3241)
                        << DgString0(" Embedded update/deletes not allowed.");
    bindWA->setErrStatus();
    return TRUE;
  }

  if ((getInliningInfo().hasInlinedActions()) ||
      (getInliningInfo().isEffectiveGU()))
  {
    if (getInliningInfo().hasTriggers()) 
    {
      *CmpCommon::diags() << DgSqlCode(-3241)
                          << DgString0(" Triggers not allowed.");
      bindWA->setErrStatus();
      return TRUE;
    }
  }

  return FALSE;
}

// This class LeafInsert and its companion LeafDelete
// are currently used only by Index Maintenance,
// but we ought not make any assumptions.
// ##IM: It might be useful to add a flag such as GenericUpdate::isIndexTable_
// ##IM: and set it to TRUE in createIMNode().
//
RelExpr *LeafInsert::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  #ifndef NDEBUG
    if (GU_DEBUG) cerr << "\nLeafInsert " << getUpdTableNameText() << endl;
  #endif

  setInUpdateOrInsert(bindWA, this, REL_INSERT);

  if (getPreconditionTree()) {
    ValueIdSet pc;
    
    getPreconditionTree()->convertToValueIdSet(pc, bindWA, ITM_AND);
    if (bindWA->errStatus())
      return this;
    
    setPreconditionTree(NULL);
    setPrecondition(pc);
  }

  RelExpr *boundExpr = GenericUpdate::bindNode(bindWA);
  if (bindWA->errStatus()) return boundExpr;

  // Make newRecExprArray_ be an ordered set of assign nodes of the form
  //   "ixcol1 = basetblcol1, ixcol2 = basecol2, ..." (for Index Maintenance)

  // Note: For SQL/MP tables, ixcol0 is the keytag, and will need to be
  // handled differently from other columns.


  const ValueIdList &tgtcols = getTableDesc()->getColumnList();

  CMPASSERT(tgtcols.entries() == baseColRefs().entries());
  for (CollIndex i = 0; i < tgtcols.entries(); i++) {
    Assign *assign;
    assign = new (bindWA->wHeap())
      Assign(tgtcols[i].getItemExpr(), baseColRefs()[i], FALSE);
    assign->bindNode(bindWA);
    if (bindWA->errStatus()) return NULL;
    newRecExprArray().insertAt(i, assign->getValueId());
    newRecExpr().insert(assign->getValueId());
    updateToSelectMap().addMapEntry(assign->getTarget(), assign->getSource());
  }

  if (getReferencedMergeIUDIndicator() != NULL_VALUE_ID)
    bindWA->getCurrentScope()->addOuterRef(getReferencedMergeIUDIndicator());
  // RelExpr::bindSelf (in GenericUpdate::bindNode) has done this line, but now
  // any outer refs discovered in bindNode's in the above loop must be added.
  // For Index Maintenance, these must be exactly the set of baseColRefs vids
  // (all the target index cols are from the locally-scoped RETDesc left by
  // the GenericUpdate::bindNode), plus the merge IUD indicator, if used.
  getGroupAttr()->addCharacteristicInputs(bindWA->getCurrentScope()->getOuterRefs());

  // The NATable of getTableName() had been set to INDEX_TABLE so that
  // getNATable would search the right namespace.
  // Now we make the Optimizer treat this as a regular table, not an index
  // (in particular, don't have it choose VSBB sidetree-insert).
  //
  // The TableDesc setting may be redundant/unnecessary, but we do it
  // for completeness and safety.
  //
  // -- Triggers
  // If it is NOT an index table (like maybe a TRIGTEMP_TABLE), leave it alone
  if (getTableName().getSpecialType() == ExtendedQualName::INDEX_TABLE)
  {
    getTableName().setSpecialType(ExtendedQualName::NORMAL_TABLE);
    getTableDesc()->getCorrNameObj().setSpecialType(ExtendedQualName::NORMAL_TABLE);
  }

  setInUpdateOrInsert(bindWA);
  return boundExpr;

} // LeafInsert::bindNode()

RelExpr *LeafDelete::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  #ifndef NDEBUG
    if (GU_DEBUG) cerr << "\nLeafDelete " << getUpdTableNameText() << endl;
  #endif

  if (getPreconditionTree()) {
    ValueIdSet pc;

    getPreconditionTree()->convertToValueIdSet(pc, bindWA, ITM_AND);
    if (bindWA->errStatus())
      return this;

    setPreconditionTree(NULL);
    setPrecondition(pc);
  }

  RelExpr *boundExpr = GenericUpdate::bindNode(bindWA);
  if (bindWA->errStatus()) return boundExpr;

  //Set the beginKeyPred
  if (TriggersTempTable *tempTableObj = getTrigTemp())
    {      
     
      const ValueIdList &keycols = getTableDesc()->getClusteringIndex()->getIndexKey();
      ItemExpr *keyExpr;
  
      // Normal case - use the UniqueExecuteId builtin function.
      keyExpr = new(bindWA->wHeap()) UniqueExecuteId();
      
      ItemExpr  *tempKeyPred = new(bindWA->wHeap()) BiRelat(ITM_EQUAL, keycols[0].getItemExpr(), keyExpr);     
      tempKeyPred->bindNode(bindWA);
      if (bindWA->errStatus()) return NULL;
      beginKeyPred().insert(tempKeyPred->getValueId());
      // Create the ItemExpr for the constant UniqueIudNum 
      ItemExpr *col2 = new(bindWA->wHeap()) 
             ColReference(new(bindWA->wHeap()) ColRefName(UNIQUEIUD_COLUMN));

      // Compare it to the correct offset.
      BindWA::uniqueIudNumOffset offset = BindWA::uniqueIudNumForInsert ; 
       
      ItemExpr *iudConst = new(bindWA->wHeap()) ConstValue(bindWA->getUniqueIudNum(offset));
      ItemExpr *predIudId = new(bindWA->wHeap()) BiRelat(ITM_EQUAL, keycols[1].getItemExpr(), iudConst);
      predIudId->bindNode(bindWA);
      if (bindWA->errStatus()) return NULL;
      beginKeyPred().insert(predIudId->getValueId());
      
      
       for (CollIndex i = 2; i<keycols.entries(); i++)
         {
           ItemExpr *keyPred = NULL;
           ItemExpr *keyItemExpr = keycols[i].getItemExpr();
           ItemExpr *baseItemExpr = NULL;
           Lng32 keyColPos = keycols[i].getNAColumn()->getPosition();
           baseItemExpr = baseColRefs()[keyColPos];
           keyPred = new (bindWA->wHeap())
             BiRelat(ITM_EQUAL, keyItemExpr, baseItemExpr);
         
           keyPred->bindNode(bindWA);
           if (bindWA->errStatus()) return NULL;
           beginKeyPred().insert(keyPred->getValueId());
         }
    }
    
  else
    {
    
  
  const ValueIdList &keycols = getTableDesc()->getClusteringIndex()->getIndexKey();

  for (CollIndex i = 0; i < keycols.entries() ; i++) 
    {
    ItemExpr *keyPred = 0;
    ItemExpr *keyItemExpr = keycols[i].getItemExpr();
    Lng32 keyColPos = keycols[i].getNAColumn()->getPosition();
    
    ItemExpr *baseItemExpr = NULL;
    // For a unique index (for undo) we are passing in all the index
    // columns in baseColRefs. So we need to find the index key col 
    // position in the index col list and compare the key columns with
    // it's corresponding column in the index column list
    if (isUndoUniqueIndex())
      baseItemExpr = baseColRefs()[keyColPos];
    else
      baseItemExpr = baseColRefs()[i];
    
    keyPred = new (bindWA->wHeap())
      BiRelat(ITM_EQUAL, keyItemExpr, baseItemExpr);

    keyPred->bindNode(bindWA);
    if (bindWA->errStatus()) return NULL;
    beginKeyPred().insert(keyPred->getValueId());
  }
    }
 

  if (isUndoUniqueIndex())
    {
      setUpExecPredForUndoUniqueIndex(bindWA) ;
    }
 
  if (getTrigTemp())
    {
      setUpExecPredForUndoTempTable(bindWA);
    }

  // See LeafInsert::bindNode for comments on remainder of this method.

  if (getReferencedMergeIUDIndicator() != NULL_VALUE_ID)
    bindWA->getCurrentScope()->addOuterRef(getReferencedMergeIUDIndicator());
  getGroupAttr()->addCharacteristicInputs(bindWA->getCurrentScope()->getOuterRefs());

  getTableName().setSpecialType(ExtendedQualName::NORMAL_TABLE);
  getTableDesc()->getCorrNameObj().setSpecialType(ExtendedQualName::NORMAL_TABLE);

  return boundExpr;

} // LeafDelete::bindNode()

void LeafDelete::setUpExecPredForUndoUniqueIndex(BindWA *bindWA)
{
  // Set up the executor predicate . Used in the case of Undo to undo the
  // exact row that caused an error.Note that if we used only the key 
  // columns  to undo, we may end up undoing existing rows . 
  // This is done only for unique indexes 
  ItemExpr *execPred  = NULL;


  const ValueIdList &indexCols = getTableDesc()->getClusteringIndex()->getIndexColumns();
  for ( CollIndex i = 0; i < indexCols.entries(); i++)
    {  
      execPred = new (bindWA->wHeap())
        BiRelat(ITM_EQUAL, indexCols[i].getItemExpr(), baseColRefs()[i]);
      execPred->bindNode(bindWA);
      if (bindWA->errStatus()) return ;
        executorPred() += execPred->getValueId();
    }
  return;
}
void LeafDelete::setUpExecPredForUndoTempTable(BindWA *bindWA)
{

ItemExpr *execPred  = NULL;
 
  const ValueIdList &tempCols = getTableDesc()->getClusteringIndex()->getIndexColumns();
  for ( CollIndex i = 0; i < tempCols.entries(); i++)
    {
      NAString colName(tempCols[i].getNAColumn()->getColName());
      if (colName.data()[0] == '@' && colName.compareTo("@SYSKEY"))
        continue;
      execPred = new (bindWA->wHeap())
        BiRelat(ITM_EQUAL, tempCols[i].getItemExpr(), baseColRefs()[i]);
      execPred->bindNode(bindWA);
      if (bindWA->errStatus()) return;
      executorPred() += execPred->getValueId();
    }

  return;
}

// -----------------------------------------------------------------------
// RelRoutine
// -----------------------------------------------------------------------
RelExpr *RelRoutine::bindNode(BindWA *bindWA)
{
  CMPASSERT(0); // For the time being, all classes above implement their own.

  //
  // Allocate an RETDesc and attach it to this and the BindScope.
  // Needs to occur in later classes when we know if we are at table
  // type or not..
  // XXX setRETDesc(new (bindWA->wHeap()) RETDesc(bindWA, getTableDesc()));
  // bindWA->getCurrentScope()->setRETDesc(getRETDesc());
  //
  // Bind the base class.
  //
  RelExpr *boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus()) return boundExpr;
  //
  // Assign the set of columns that belong to the virtual table
  // as the output values that can be produced by this node.
  //
  //  XXX done in later clasees 
  //  getGroupAttr()->addCharacteristicOutputs(getTableDesc()->getColumnList());
  return boundExpr;
} // RelRoutine::bindNode()

// -----------------------------------------------------------------------
// BuiltinTableValuedFunction
// will be called by 
// ExplainFunc and StatisticsFunc
//   Rely on function implementation in TableValuedFunction 
// -----------------------------------------------------------------------

// -----------------------------------------------------------------------
// Explain/Statistics/HiveMD Func
// -----------------------------------------------------------------------
RelExpr *BuiltinTableValuedFunction::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  //
  // Bind the child nodes.
  //
  bindChildren(bindWA);
  if (bindWA->errStatus())
    return this;

  //
  // Check if there is already an NATable for the Explain/Statistics table.
  //
  if (getOperatorType() == REL_EXPLAIN ||
      getOperatorType() == REL_STATISTICS  ||
      getOperatorType() == REL_HIVEMD_ACCESS ||
      getOperatorType() == REL_HBASE_ACCESS)
  {
    NATable *naTable =  NULL;

    if (getOperatorType() == REL_HBASE_ACCESS)
      {
	// should not reach here
	CMPASSERT(0); 
      }
    else
      {
	CorrName corrName(getVirtualTableName());
	corrName.setSpecialType(ExtendedQualName::VIRTUAL_TABLE);
	NATable *naTable = bindWA->getSchemaDB()->getNATableDB()->
	  get(&corrName.getExtendedQualNameObj());
	
	if (NOT naTable) 
	  {
	    TrafDesc *tableDesc = createVirtualTableDesc();
	    if (tableDesc)
	      naTable = bindWA->getNATable(corrName, FALSE/*catmanUsages*/, tableDesc);
	    
	    if ( ! tableDesc || bindWA->errStatus() )
	      return this;
	  }
	
	// Allocate a TableDesc and attach it to this.
	//
	TableDesc * td = bindWA->createTableDesc(naTable, corrName);
	if (! td || bindWA->errStatus())
	  return this;
	
	setTableDesc(td);
	if (bindWA->errStatus())
	  return this;
      }

    if (getProcAllParamsTree()) 
      {
	((ItemExpr *)getProcAllParamsTree())->convertToValueIdList(getProcAllParamsVids(), bindWA, ITM_ITEM_LIST);
	if (bindWA->errStatus())
	  return this;
	
	// Clear the Tree since we now have gotten vids for all the parameters.
	setProcAllParamsTree(NULL);
	
	Lng32 sqlcode = 0;
	if (getProcAllParamsVids().entries() != numParams()) 
	  {
	    sqlcode = -4067;
	    
	    // 4067 Explain/Statistics requires two operands, of type character.
	    *CmpCommon::diags() << DgSqlCode(sqlcode) << DgString0(getTextForError());
	    bindWA->setErrStatus();
	    return NULL;
	  }
	
	// type any param arguments to fixed char since runtime explain
	// expects arguments to be fixed char.
	Lng32 len = (Lng32)CmpCommon::getDefaultNumeric(VARCHAR_PARAM_DEFAULT_SIZE);
	SQLChar c(NULL, len);
	
	for (Lng32 i = 0; i < numParams(); i++)
	  {
	    getProcAllParamsVids()[i].coerceType(c, NA_CHARACTER_TYPE);
	    if (getProcAllParamsVids()[i].getType().getTypeQualifier() != NA_CHARACTER_TYPE)
	      {
		sqlcode = -4067;
		
		// 4067 Explain/Statistics requires two operands, of type character.
		*CmpCommon::diags() << DgSqlCode(sqlcode) << DgString0(getTextForError());
		bindWA->setErrStatus();
		return NULL;
	      }
	    
	    const NAType &typ = getProcAllParamsVids()[i].getType();
	    
	    CharInfo::CharSet chld_cs = ((const CharType&)typ).getCharSet();
	    ItemExpr *ie;
	    if ( chld_cs == CharInfo::UNICODE )
	      {
		ie = new (bindWA->wHeap()) Translate(
						     getProcAllParamsVids()[i].getItemExpr(),
						     Translate::UNICODE_TO_ISO88591);
		ie = ie->bindNode(bindWA);
		getProcAllParamsVids()[i] = ie->getValueId();
	      }
	    
	    if (bindWA->errStatus())
	      return NULL;
	    
	    // For Explain and Statistics all parameters are inputs
	    getProcInputParamsVids().insert(getProcAllParamsVids());
	  } // for
      }
  } // if
  
  return TableValuedFunction::bindNode(bindWA);
    
}

// -----------------------------------------------------------------------
// TableValuedFunction
// -----------------------------------------------------------------------
RelExpr *TableValuedFunction::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  //
  // Bind the child nodes.
  //
  bindChildren(bindWA);
  if (bindWA->errStatus())
    return this;


  //
  // Allocate an RETDesc and attach it to this and the BindScope.
  //
  setRETDesc(new (bindWA->wHeap()) RETDesc(bindWA, getTableDesc()));
  bindWA->getCurrentScope()->setRETDesc(getRETDesc());
  //
  // Bind the base class.
  //
  RelExpr *boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus()) return boundExpr;
  //
  // Assign the set of columns that belong to the virtual table
  // as the output values that can be produced by this node.
  //
  getGroupAttr()->addCharacteristicOutputs(getTableDesc()->getColumnList());
  return boundExpr;
} // TableValuedFunction::bindNode()


// -----------------------------------------------------------------------
// Member functions for classes Control*
// must be written allowing for a NULL BindWA to be passed in!
//
// This happens when called from the SQLC/SQLCO Preprocessor,
// which needs to bind certain "static-only" statements --
// those which evaluate to STATIC_ONLY_WITH_WORK_FOR_PREPROCESSOR --
// see ControlAbstractClass::isAStaticOnlyStatement().
// -----------------------------------------------------------------------

RelExpr * ControlAbstractClass::bindNode(BindWA *bindWA)
{
  if (nodeIsBound()) return this;

  // Early return if called by SQLC/SQLCO Preprocessor
  if (!bindWA) return this;

  // Allocate an empty RETDesc and attach it to this node and the BindScope.
  setRETDesc(new(bindWA->wHeap()) RETDesc(bindWA));
  bindWA->getCurrentScope()->setRETDesc(getRETDesc());

  return bindSelf(bindWA);
} // ControlAbstractClass::bindNode()


RelExpr * ControlQueryShape::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  // remember the required shape in the control table
  if (alterArkcmpEnvNow())
    {
      if (getShape())
        ActiveControlDB()->setRequiredShape(this);
      else
        {
          // no shape passed in. Hold or Restore.
          if (holdShape())
            ActiveControlDB()->saveCurrentCQS();
          else
            ActiveControlDB()->restoreCurrentCQS();
          if (ActiveControlDB()->getRequiredShape())
            ActiveControlDB()->getRequiredShape()->holdShape() = holdShape();
        }
    }

  return ControlAbstractClass::bindNode(bindWA);
} // ControlQueryShape::bindNode()


RelExpr * ControlQueryDefault::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  // Alter the current Defaults settings if this is a static CQD.
  //
  // "AffectYourself" is coming to you courtesy of the Staple Singers:
  // 'Affect yourself, na na na, na na na na, affect yourself, re re re re.'
  // It's neat to find such Binder-relevant lyrics, eh?
  //
  NABoolean affectYourself = alterArkcmpEnvNow();

  assert(!bindWA || bindWA->getSchemaDB() == ActiveSchemaDB());
  NADefaults &defs = ActiveSchemaDB()->getDefaults();
  defs.setState(NADefaults::SET_BY_CQD);

  if ( defs.isReadonlyAttribute(token_) == TRUE )
    {
      Int32 attrNum = defs.lookupAttrName(token_);
      
      if (stricmp(value_, defs.getValue(attrNum)) != 0 ) 
      {
         if (CmpCommon::getDefault(DISABLE_READ_ONLY) == DF_OFF)
         {
           if (bindWA) bindWA->setErrStatus();
           *CmpCommon::diags() << DgSqlCode(-4130) << DgString0(token_);
           return NULL;
         }
       }
    }


  if (holdOrRestoreCQD_ == 0)
    {
      if (affectYourself)
        attrEnum_ =  defs.validateAndInsert(token_, value_, reset_);
      else
        attrEnum_ = defs.validate(token_, value_, reset_);
      if (attrEnum_ < 0)
        {
          if (bindWA) bindWA->setErrStatus();
          return NULL;
        }
      
      // remember this control in the control table
      if (affectYourself)
        ActiveControlDB()->setControlDefault(this);
    }
  else if ((holdOrRestoreCQD_ > 0) && (affectYourself))
    {
      attrEnum_ = defs.holdOrRestore(token_, holdOrRestoreCQD_);
      if (attrEnum_ < 0)
        {
          if (bindWA) bindWA->setErrStatus();
          return NULL;
        }
    }
  
  return ControlAbstractClass::bindNode(bindWA);
} // ControlQueryDefault::bindNode()


RelExpr * ControlTable::bindNode(BindWA *bindWA)
{
  if (nodeIsBound()) return this;

  CMPASSERT(bindWA);  // can't handle it yet if called from SQLC Preprocessor

  // remember this control in the control table
  tableName_->applyDefaults(bindWA, bindWA->getDefaultSchema());

  NABoolean ok = alterArkcmpEnvNow() ?
                      ActiveControlDB()->setControlTableValue(this) :
                      ActiveControlDB()->validate(this);
  if (NOT ok)
    {
      if (bindWA) bindWA->setErrStatus();
      return NULL;
    }

  return ControlAbstractClass::bindNode(bindWA);
} // ControlTable::bindNode()


RelExpr * ControlSession::bindNode(BindWA *bindWA)
{
  if (nodeIsBound()) return this;

  // remember this control in the control session
  NABoolean ok = alterArkcmpEnvNow() ?
                      ActiveControlDB()->setControlSessionValue(this) :
                      ActiveControlDB()->validate(this);
  if (NOT ok)
    {
      if (bindWA) bindWA->setErrStatus();
      return NULL;
    }

  return ControlAbstractClass::bindNode(bindWA);
} // ControlSession::bindNode()


RelExpr * SetSessionDefault::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  if (getOperatorType() == REL_SET_SESSION_DEFAULT)
    {
      // trim leading and trailing spaces from token_ and value_
      // and upcase token
      token_ = token_.strip(NAString::both);
      value_ = value_.strip(NAString::both);
      token_.toUpper();

      // TBD:  perhaps add a component privilege that allows others
      //       to set parserflags
      if ((token_ == "SET_PARSERFLAGS") ||
          (token_ == "RESET_PARSERFLAGS"))
        {
          if (!ComUser::isRootUserID())
            {
              *CmpCommon::diags() << DgSqlCode(-1017);
              bindWA->setErrStatus();
              return this;
            }
        }

    }

  return ControlAbstractClass::bindNode(bindWA);
} // SetSessionDefault::bindNode()



// -----------------------------------------------------------------------
// member function for class RelSetTimeout
// -----------------------------------------------------------------------

RelExpr * RelSetTimeout::bindNode(BindWA *bindWA)
{
  if (nodeIsBound()) return this;

  // Allocate an empty RETDesc and attach it to this node and the BindScope.
  setRETDesc(new(bindWA->wHeap()) RETDesc(bindWA));
  bindWA->getCurrentScope()->setRETDesc(getRETDesc());

  if (timeoutValueExpr_) {  // bind the timeout-value expression
    timeoutValueExpr_->bindNode(bindWA);
    if (bindWA->errStatus()) return this;
  }

  if ( ! strcmp("*", userTableName_.getCorrNameAsString()) )
    isForAllTables_ = TRUE ;

  HostVar *proto = userTableName_.getPrototype() ;

  // Check for the not-supported  "SET STREAM TIMEOUT" on a specific stream
  if ( isStream_ && ! isForAllTables_ ) {
    *CmpCommon::diags() << DgSqlCode(-3187);
    bindWA->setErrStatus();
    return this;
  }

  if ( isForAllTables_ ) { /* do nothing */ }
  else if ( proto ) { // it is a HOSTVAR or DEFINE
    userTableName_.applyDefaults(bindWA, bindWA->getDefaultSchema());
    CMPASSERT ( proto->isPrototypeValid() ) ;
    userTableName_.getPrototype()->bindNode(bindWA);
  } else { // i.e., an explicit table name was specified
    // Get the NATable for this table.
    NATable *naTable = bindWA->getNATable(userTableName_, FALSE);
    if (bindWA->errStatus()) return this;  // e.g. error: table does not exist

    if ( naTable->getViewText() ) {  // can not set lock timeout on a view
      *CmpCommon::diags() << DgSqlCode(-3189);
      bindWA->setErrStatus();
      return this;
    }

    // Extract and keep the physical file name
    const NAFileSet * clstInd = naTable->getClusteringIndex() ;
    setPhysicalFileName( clstInd->getFileSetName().getQualifiedNameAsString().data() );
  }

  // Bind the base class.
  return bindSelf(bindWA);
}
// -----------------------------------------------------------------------
// member functions for class Describe
// (see sqlcomp/CmpDescribe.cpp for execution of the request)
// -----------------------------------------------------------------------

RelExpr *Describe::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  // SHOWCONTROL DEFAULT "magic string"; -- see ShowSchema.h and ExSqlComp.cpp
  if (getFormat() == CONTROL_DEFAULTS_) {
    if (getDescribedTableName().getQualifiedNameObj().getObjectName() ==
        ShowSchema::ShowControlDefaultSchemaMagic())
    {
      // Return info in an error message (a warning msg doesn't cut it).
      const SchemaName &catsch = bindWA->getDefaultSchema();
      NAString cat(catsch.getCatalogNameAsAnsiString(),bindWA->wHeap());
      NAString sch(catsch.getUnqualifiedSchemaNameAsAnsiString(),bindWA->wHeap());
      //
      *CmpCommon::diags() << DgSqlCode(-ABS(ShowSchema::DiagSqlCode()))
        << DgCatalogName(cat) << DgSchemaName (sch);
      bindWA->setErrStatus();
      return this;
    }
    if (getDescribedTableName().getQualifiedNameObj().getObjectName() ==
        GetControlDefaults::GetExternalizedDefaultsMagic())
    {
      // Return info in an error message (a warning msg doesn't cut it).
      NAString cqdPairs(bindWA->wHeap());
      size_t lenN, lenV;
      char lenbufN[10], lenbufV[10];
      const char *nam, *val;
      NADefaults &defs = bindWA->getSchemaDB()->getDefaults();
      for (CollIndex i = 0; i < defs.numDefaultAttributes(); i++ ) {
        if (defs.getCurrentDefaultsAttrNameAndValue(i, nam, val, TRUE)) {
          lenN = strlen(nam);
          lenV = strlen(val);
          CMPASSERT(lenN <= 999 && lenV <= 999);  // %3d coming up next
          sprintf(lenbufN, "%3d", (UInt32)lenN);
          sprintf(lenbufV, "%3d", (UInt32)lenV);
          cqdPairs += NAString(lenbufN) + nam + lenbufV + val;
        }
      }
      *CmpCommon::diags()
        << DgSqlCode(-ABS(GetControlDefaults::DiagSqlCode()))
        << DgString0(cqdPairs);
      bindWA->setErrStatus();
      return this;
    }
  }

  // Create a descriptor for a virtual table to look like this:
  // 
  //	CREATE TABLE DESCRIBE__ (DESCRIBE__COL VARCHAR(3000) NOT NULL);
  // For SeaQuest Unicode:
  //	CREATE TABLE DESCRIBE__ (DESCRIBE__COL VARCHAR(3000 BYTES) CHARACTER SET UTF8 NOT NULL);
  //
  #define MAX_DESCRIBE_LEN 3000 // e.g., SQL/MP Views.ViewText column

  // TrafAllocateDDLdesc requires that HEAP (STMTHEAP) be used for new's!

  TrafDesc * table_desc = TrafAllocateDDLdesc(DESC_TABLE_TYPE, NULL);
  table_desc->tableDesc()->tablename = new HEAP char[strlen("DESCRIBE__")+1];
  strcpy(table_desc->tableDesc()->tablename, "DESCRIBE__");

  // see nearly identical code below for indexes file desc
  TrafDesc * files_desc = TrafAllocateDDLdesc(DESC_FILES_TYPE, NULL);
  table_desc->tableDesc()->files_desc = files_desc;

  Lng32 colnumber = 0, offset = 0;
  TrafDesc * column_desc = TrafMakeColumnDesc(
       table_desc->tableDesc()->tablename,
       "DESCRIBE__COL",
       colnumber,      // INOUT
       REC_BYTE_V_ASCII,
       MAX_DESCRIBE_LEN,
       offset,      // INOUT
       FALSE/*not null*/,
       SQLCHARSETCODE_UNKNOWN,
       NULL);
  column_desc->columnsDesc()->character_set    = CharInfo::UTF8;
  column_desc->columnsDesc()->encoding_charset = CharInfo::UTF8;

  table_desc->tableDesc()->colcount = colnumber;
  table_desc->tableDesc()->record_length = offset;

  TrafDesc * index_desc = TrafAllocateDDLdesc(DESC_INDEXES_TYPE, NULL);
  index_desc->indexesDesc()->tablename = table_desc->tableDesc()->tablename;
  index_desc->indexesDesc()->indexname = table_desc->tableDesc()->tablename;
  index_desc->indexesDesc()->keytag = 0; // primary index
  index_desc->indexesDesc()->record_length = table_desc->tableDesc()->record_length;
  index_desc->indexesDesc()->colcount = table_desc->tableDesc()->colcount;
  index_desc->indexesDesc()->blocksize = 4096; // anything > 0

  TrafDesc * i_files_desc = TrafAllocateDDLdesc(DESC_FILES_TYPE, NULL);
  index_desc->indexesDesc()->files_desc = i_files_desc;

  TrafDesc * key_desc = TrafAllocateDDLdesc(DESC_KEYS_TYPE, NULL);
  key_desc->keysDesc()->keyseqnumber = 1;
  key_desc->keysDesc()->tablecolnumber = 0;
  key_desc->keysDesc()->setDescending(FALSE);

  index_desc->indexesDesc()->keys_desc = key_desc;
  table_desc->tableDesc()->columns_desc = column_desc;
  table_desc->tableDesc()->indexes_desc = index_desc;

  //
  // Get the NATable for this object.
  //
  CorrName corrName("DESCRIBE__");
  corrName.setSpecialType(ExtendedQualName::VIRTUAL_TABLE);
  NATable *naTable = bindWA->getNATable(corrName, FALSE/*CatBind*/, table_desc);
  if (bindWA->errStatus())
    return this;
  //
  // Allocate a TableDesc (which is not the table_desc we just constructed)
  // and attach it to the Scan node.
  //
  setTableDesc(bindWA->createTableDesc(naTable, corrName));
  if (bindWA->errStatus())
    return this;
  //
  // Allocate an RETDesc and attach it to the Scan node and the BindScope.
  //
  setRETDesc(new (bindWA->wHeap()) RETDesc(bindWA, getTableDesc()));
  bindWA->getCurrentScope()->setRETDesc(getRETDesc());
  //
  // Bind the described table CorrName member, the children, and the base class.
  //

  if (! describedTableName_.getQualifiedNameObj().getObjectName().isNull())
    {
       if (getIsControl())
          describedTableName_.applyDefaults(bindWA, bindWA->getDefaultSchema());
        if (NOT getIsControl())
        {
          // do not override schema for showddl
          bindWA->setToOverrideSchema(FALSE);  
          
          // check if we need to consider public schema before 
          // describedTableName_ is qualified by getNATable
          if (describedTableName_.getQualifiedNameObj().getSchemaName().isNull())
            setToTryPublicSchema(TRUE);

          if ((getFormat() == Describe::INVOKE_) ||
              (getFormat() == Describe::SHOWDDL_) &&
              (getLabelAnsiNameSpace() == COM_TABLE_NAME) &&
              (NOT getIsSchema()))
            {
              bindWA->getNATableInternal(describedTableName_);
              if (bindWA->errStatus())
                {
                  return this;
                }
            }
          else
            describedTableName_.applyDefaults(bindWA, bindWA->getDefaultSchema());
        }
      if (pUUDFName_ NEQ NULL AND NOT pUUDFName_->getObjectName().isNull())
      {
          pUUDFName_->applyDefaults(bindWA->getDefaultSchema());
      }
    }
  
  bindChildren(bindWA);
  RelExpr *boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus()) return boundExpr;
  //
  // Assign the set of columns that belong to the table to be scanned
  // as the output values that can be produced by this scan.
  //
  getGroupAttr()->addCharacteristicOutputs(getTableDesc()->getColumnList());
  return boundExpr;
} // Describe::bindNode()

// -----------------------------------------------------------------------
// member functions for class RelLock
// -----------------------------------------------------------------------

RelExpr * RelLock::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  // do not do override schema for this
  bindWA->setToOverrideSchema(FALSE);

  // Get the NATable for this object.
  NATable *naTable = bindWA->getNATable(getTableName());
  if (bindWA->errStatus())
    return this;

  NABoolean isView = !!naTable->getViewText();
  if (isView && !naTable->isAnMV())
    {
      *CmpCommon::diags() << DgSqlCode(-4222)
                          << DgString0("Views");
      bindWA->setErrStatus();
      return this;
    }
  else
    {
      baseTableNameList_.insert((CorrName *)getPtrToTableName());
    }

  Int32 locSpec = 0;
  NAString tabNames(bindWA->wHeap());

  for (CollIndex i = 0; i < baseTableNameList_.entries(); i++) {
    naTable = bindWA->getNATable(*baseTableNameList_[i]);
    if (bindWA->errStatus())
      return this;

    // Genesis 10-990212-6908:
    // Ignore the user-specified correlation name --
    // use just the 3-part tblname (and any LOCATION clause, etc).
    // Then, insert only unique names into tabIds_ --
    // to prevent XTNM duplicates (errmsg 4056)
    // when multiple layered views reference the same table or corr-name.

    CorrName bt(*baseTableNameList_[i]);
    bt.setCorrName("");

    NABoolean haveTDforThisBT = FALSE;
    for (CollIndex j = 0; j < tabIds_.entries(); j++) {
      if (bt == tabIds_[j]->getCorrNameObj()) {
        haveTDforThisBT = TRUE;
        break;
      }
    }

    if (!haveTDforThisBT) {
      if (bt.isLocationNameSpecified()) locSpec++;
      tabNames += NAString(", ") +
                    bt.getQualifiedNameObj().getQualifiedNameAsAnsiString();
      tabIds_.insert(bindWA->createTableDesc(naTable, bt));
      if (bindWA->errStatus()) return this;
    }
  }

  if (tabIds_.entries() > 1) {
    CMPASSERT(locSpec == 0);
    tabNames.remove(0, 2);   // remove leading ", "
    // Warning 4124: More than one table will be locked: $0~String0.
    // (warning, so user realizes the effects of this command
    // when run on a view which joins tables...).
    *CmpCommon::diags() << DgSqlCode(+4124) << DgString0(tabNames);
  }

  if ((isView) ||
      (tabIds_.entries() > 1) ||
      (baseTableNameList_.entries() > 1) ||
      (CmpCommon::getDefault(ATTEMPT_ESP_PARALLELISM) == DF_OFF))
    {
      parallelExecution_ = FALSE;
    }

  // Allocate an empty RETDesc and attach it to this node and the BindScope.
  setRETDesc(new(bindWA->wHeap()) RETDesc(bindWA));
  bindWA->getCurrentScope()->setRETDesc(getRETDesc());

  // Bind the base class.
  return bindSelf(bindWA);
} // RelLock::bindNode()

// -----------------------------------------------------------------------
// member functions for class RelTransaction
// -----------------------------------------------------------------------

RelExpr * RelTransaction::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  // Allocate an empty RETDesc and attach it to this node and the BindScope.
  setRETDesc(new(bindWA->wHeap()) RETDesc(bindWA));
  bindWA->getCurrentScope()->setRETDesc(getRETDesc());

  if (diagAreaSizeExpr_) {
    diagAreaSizeExpr_->bindNode(bindWA);
    if (bindWA->errStatus()) return this;
  }

  // "mode_" is NULL if BEGIN/COMMIT/ROLLBACK WORK, nonNULL if SET TRANSACTION.
  if (mode_) {
    if ((mode_->autoCommit() != TransMode::AC_NOT_SPECIFIED_) || 
        (mode_->getAutoBeginOn() != 0) ||
        (mode_->getAutoBeginOff() != 0))
    {
      if (NOT (mode_->isolationLevel() == TransMode::IL_NOT_SPECIFIED_ &&
               mode_->accessMode()     == TransMode::AM_NOT_SPECIFIED_))
        {
          *CmpCommon::diags() << DgSqlCode(-3242)
                              << DgString0("Isolation level or Access mode options cannot be specified along with autocommit or autobegin options.");
          bindWA->setErrStatus();
          return this;
        }
    }
    else 
    {
      // See Ansi 14.1, especially SR 4.
      // Similar code must be maintained in
      // comexe/ExControlArea::addControl() and NADefaults::validateAndInsert().

      // SET TRANSACTION w/o specifying ISOLATION LEVEL reverts TransMode to
      // the NADefaults setting of ISOLATION_LEVEL
      // (which the user should set to SERIALIZABLE if they want
      // SET TRANSACTION to be Ansi conformant).

      if (mode_->isolationLevel() == TransMode::IL_NOT_SPECIFIED_)
      {
        if (CmpCommon::getDefault(ISOLATION_LEVEL_FOR_UPDATES) == DF_NONE)
          bindWA->getSchemaDB()->getDefaults().getIsolationLevel(
            mode_->isolationLevel()); // short int
        else
          bindWA->getSchemaDB()->getDefaults().getIsolationLevel(
            mode_->isolationLevel(), // short int
            CmpCommon::getDefault(ISOLATION_LEVEL_FOR_UPDATES));
      }

      if (mode_->accessMode() == TransMode::AM_NOT_SPECIFIED_)
        mode_->updateAccessModeFromIsolationLevel(
          mode_->getIsolationLevel());   // enum

      // 3114 Transaction access mode RW is incompatible with isolation level RU
      if (mode_->accessMode() == TransMode::READ_WRITE_ &&
          mode_->isolationLevel() == TransMode::READ_UNCOMMITTED_) {
        *CmpCommon::diags() << DgSqlCode(-3114);
        bindWA->setErrStatus();
        return this;
      }

      if (mode_->rollbackMode() == TransMode::ROLLBACK_MODE_NOT_SPECIFIED_)
          mode_->rollbackMode() = TransMode::ROLLBACK_MODE_WAITED_ ;
      // 4352 - 
      if (mode_->multiCommit() == TransMode::MC_ON_)
        {
          if (mode_->invalidMultiCommitCompatibility())
            {
              *CmpCommon::diags() << DgSqlCode(-4352);
              bindWA->setErrStatus();
              return this;
            }

        }
    }
  } // SET TRANSACTION stmt

  // Bind the base class.
  return bindSelf(bindWA);
}


// Transpose::bindNode - Bind the transpose node.
// Coming into the node (from the parser) there are two ItemExpr Trees:
//
//   keyCol_: The ItemExpr contains a ColReference to the key column which
//   is added by the transpose node. This pointer ia set to NULL by bindNode.
//   If keyCol_ is NULL coming into the bindNode, then no key Column is
//   generated for this transpose.
//
//   transValsTree_: This ItemExpr tree contains a list of pairs which is
//   NULL terminated (for ease of processing).  Each pair contains in child(0),
//   a list of transpose items for a given transpose set and in child(1), a
//   list of ColReferences to the new value columns associated with this
//   transpose set. A transpose item is a list of value expressions.
//   This pointer is set to NULL by bindNode.
//
// For Example:
//
//           SELECT *
//             FROM Table
//        TRANSPOSE A,B AS C1
//                  X,Y,Z as C2
//                  (1,'hello'),(2,'world') AS (C3, C4)
//           KEY BY K1
//
//   For the above query, after parsing, the TRANSPOSE node will look like:
//
//                  TRANSPOSE
//               keyCol_  transValsTree_
//                  |      |
//                  K1     O------O---------O---NULL
//                         |      |         |
//                         O      O         O--O
//                         |\     |\        |  |\
//                         O C1   O C2      | C3 C4
//                         |\     |\        O---------O---NULL
//                         A O    X O       |         |
//                           |\     |\      O         O
//                           B NULL Y O     |\        |\
//                                    |\    1 'hello' 2 'world'
//                                    Z NULL
//
// O - represent ITM_LIST nodes.
//
// bindNode binds this structure to form a new structure contained in
// the vector of ValueIdLists, transUnionVector_.
//
//   transUnionVector_: This is a vector of ValueIdLists. There is one entry
//   for each transpose set, plus one entry for the key values. Each entry
//   contains a list of ValueIdUnion Nodes. The first entry contains a list
//   with one ValueIdUnion node. This node is for the Const. Values (1 - N)
//   representing the Key Values. The other entries contain lists of
//   ValueIdUnion nodes for the Transposed Values. Each of these entries of
//   the vector represent a transpose set.  If the transpose set contains a
//   list of values, then there will be only one ValueIdUnion node in the
//   list.  If the transpose set contains a list of lists of values, then
//   there will be as many ValueIdUnion nodes as there are items in the
//   sublists. (see example below.)
//   transUnionVector_ is generated in bindNode().
//
//   transUnionVectorSize_: This is the number of entries in transUnionVector_.
//
// For the above query, after binding, the TRANSPOSE node will look like:
//
//               TRANSPOSE
//                 transUnionVectorSize_: 4
//                 transUnionVector_:
//                     ValueIdUnion(1,2,3,4,5,6,7)
//                     ValueIdUnion(A,B)
//                     ValueIdUnion(X,Y,Z)
//                     ValueIdUnion(1,2) , ValueIdUnion('hello','world')
//
//
RelExpr *Transpose::bindNode(BindWA *bindWA)
{

  // If this node has already been bound, we are done.
  //
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  BindContext *curContext = bindWA->getCurrentScope()->context();
  curContext->inTransposeClause() = TRUE;

  // Bind the child nodes.
  //
  bindChildren(bindWA);
  if (bindWA->errStatus()) return this;

  // At this point the Transpose relational operator has two or three
  // expressions:
  // keyCol_        --- A ColReference to the new keyCol. (possibly NULL)
  // transValsTree_ --- expressions for the transposed values and their
  //                    ColReferences.
  //
  // transpose::bindNode() performs the following steps:
  //
  // 1 - Construct a list of transpose set expressions
  //     and a list of ColReferences associated with each transpose set
  //     expression.
  //
  // 2 - Allocate a return descriptor and add the columns from the
  //     childs descriptor to it.
  //
  // 3 - Allocate the transUnionVector_
  //
  // 4 - Construct a ValueIdUnion node for the Key Values. Bind this node.
  //     Add the keyColName to the return descriptor with the valueId of this
  //     node.  Add the valueId of this node as the first entry of
  //     a ValueIdList in the first entry of transUnionVector_.
  //
  // 5 - For each transpose set, Construct as many ValueIdUnion nodes as
  //     there are values in each item of the transpose set. Within a
  //     given transpose set, the number of values per item must be the
  //     same.  In the example above, the third transpose set contains the
  //     items (1, 'hello') and (2, 'world'). These both have two values per
  //     item.  The others all have 1 value per item. The ValueIdUnions
  //     generated will contain the i'th value from each item. Bind each
  //     of these ValueUnionId nodes. Add the value column name to the
  //     return descriptor with the valueId of this node. Add the valueId
  //     of this node the ValueIdList in the proper entry of
  //     transUnionVector_.
  //
  // 6 - Set the return descriptor, and bindSelf.
  //

  CollIndex i, j, k;
  CollIndex numTransSets = 0;

  // Get a pointer to the head of this list of pairs.
  // This is the last time we will have to reference this tree.
  //
  ItemExpr *transTree = (ItemExpr *)removeTransValsTree();

  // Allocate two ItemExpr Lists. One for the list of lists of (lists of)
  // expressions. And the other for the list of (lists of)  ColReferences.
  //
  ItemExprList transSetsList(bindWA->wHeap());
  ItemExprList newColsList(bindWA->wHeap());

  // Populate these lists and
  // determine how many transpose sets there are in this tree.
  // In the example above, there should be three.
  //
  while (transTree) {
    transSetsList.insert(transTree->child(0)->child(0));
    newColsList.insert(transTree->child(0)->child(1));
    numTransSets++;
    transTree = transTree->child(1);
  }

  // Must have at least one value expression in the transpose values list.
  //
  CMPASSERT(numTransSets > 0);

  // Using the example above, at this point:
  //
  //   transSetsList                          newColsList
  //  |      |      |                          |   |   |
  //  O      O      O---------O---NULL         C1  C2  O
  //  |\     |\     |         |                        |\
  //  A O    X O    O         O                       C3 C4
  //    |\     |\   |\        |\
  //    B NULL Y O  1 'hello' 2 'world'
  //             |\
  //             Z NULL
  //
  // Allocate the return descriptor.  This will contain the
  // columns of the child node as well as the new columns added
  // by the transpose operator.  The column order is:
  //
  //       [childs columns][keyCol][valCol1][valCol2] ...
  //
  // Using the example, this would be:
  //
  //       [childs columns], K1, C1, C2, C3, C4
  //
  RETDesc *resultTable = new(bindWA->wHeap()) RETDesc(bindWA);

  // Add the columns from the child to the RETDesc.
  //
  const RETDesc &childTable = *child(0)->getRETDesc();
  resultTable->addColumns(bindWA, childTable);

  transUnionVectorSize_ = numTransSets + 1;
  transUnionVector() = new(bindWA->wHeap())
    ValueIdList[transUnionVectorSize_];
  //If there is a lob column return error. Transpose not allowed on lob columns.
 
  for (i = 0; i < resultTable->getDegree(); i++)
    {
      if ((resultTable->getType(i)).getFSDatatype() == REC_BLOB || 
	  (resultTable->getType(i)).getFSDatatype() == REC_CLOB)
	{
	  *CmpCommon::diags() << DgSqlCode(-4322);
	  bindWA->setErrStatus();
	  return this;
	}
    }
 
    

  // Get the key column reference
  // This is the last time we need this ItemExpr.
  //
  ColReference *keyColumn = (ColReference *)removeKeyCol();

  // If no key column has been specified, then no key col will be
  // generated.
  //
  if (keyColumn) {

    //Get the key column name.
    //
    NAString keyColName(keyColumn->getColRefNameObj().getColName(), bindWA->wHeap());

    // Construct and Bind the ValueIdUnion node as the union of constants
    // from 1 to the total number of transpose expressions. In the above
    // example this will be from 1 to 9, since there are 3 transpose sets
    // and each set has 3 expressions.
    //
    ValueIdList constVals;
    ItemExpr *constExpr;

    CollIndex keyVal;

    // For each expression in each transpose set.
    //
    for (i = 0, keyVal = 1; i < numTransSets; i++) {

      // Determine how many expressions are in each transpose set.
      //
      CollIndex numTransItems = 0;

      ItemExpr *transSet = transSetsList[i];

      while (transSet) {
        numTransItems++;
        transSet = transSet->child(1);
      }

      for (j = 0; j < numTransItems; j++, keyVal++) {

        // Construct the constant value
        //
        constExpr = new(bindWA->wHeap()) SystemLiteral(keyVal);

        // Bind the constant value.
        //
        constExpr->bindNode(bindWA);
        if (bindWA->errStatus()) return this;

        // Insert the valueId into the list
        //
        constVals.insert(constExpr->getValueId());
      }
    }

    // Construct the ValueIdUnion node which will represent the key Col.
    //
    ValueIdUnion *keyVidu = new(bindWA->wHeap())
      ValueIdUnion(constVals, NULL_VALUE_ID);

    // Bind the ValueIdUnion node.
    //
    keyVidu->bindNode(bindWA);
    if (bindWA->errStatus()) return this;

    // Add the key column to the RETDesc (as the union of all the constants)
    //
    resultTable->addColumn(bindWA, keyColName, keyVidu->getValueId());

    // The ValueIdUnion for the Key Values is the first entry in
    // the ValueIdList of the first entry of transUnionVector_.
    //
    transUnionVector()[0].insert(keyVidu->getValueId());
  }

  // For each transpose set,
  //   - bind the list of expressions.
  //   - Construct a ValueIdUnion node containing the resulting valueIds.
  //   - Bind this ValueIdUnion node
  //   - Add the associate column name to the return descriptor with the
  //     valueId of the ValueIdUnion node.
  //
  ValueIdList transVals;

  for (i = 0; i < numTransSets; i++) {

    // The column(s) associated with this transpose set.
    // (will be used below, within the inner loop)
    //
    ItemExprList newCols(newColsList[i], bindWA->wHeap());

    // Determine how many expressions are in each transpose set.
    //
    CollIndex numTransItems = 0;

    ItemExpr *transSet = transSetsList[i];

    ItemExprList transItemList(bindWA->wHeap());

    // Populate this list.
    //
    while (transSet) {
      transItemList.insert(transSet->child(0));
      numTransItems++;
      transSet = transSet->child(1);
    }

    ItemExprList transItem(transItemList[0], bindWA->wHeap());

    CollIndex numTransVals = transItem.entries();

    // For a given transpose set, the number of new columns declared
    // must be the same as the number of items per value.  In the example
    // above, the third transpose  set contains the items (1, 'hello') and
    // the columns (C3,C4) both have two entries.
    //
    if (numTransVals != newCols.entries()) {
      *CmpCommon::diags() << DgSqlCode(-4088);
      bindWA->setErrStatus();
      return this;
    }

    for (k = 0; k < numTransVals; k++) {

      ItemExpr *transValueUnionExpr = NULL;

      for (j = 0; j < numTransItems; j++) {

        transItem.clear();
        transItem.insertTree(transItemList[j], ITM_ITEM_LIST);

        // Within a given transpose set, the number of values per item
        // must be the same.  In the example above, the third transpose
        // set contains the items (1, 'hello') and (2, 'world'). These
        // both have two values per item.  The others all have 1 value
        // per item.
        //

        if (numTransVals != transItem.entries()) {
          *CmpCommon::diags() << DgSqlCode(-4088);
          bindWA->setErrStatus();
          return this;
        }

        if (transValueUnionExpr == NULL) {
          transValueUnionExpr = transItem[k];
        }
        else
        {
          transValueUnionExpr = new (bindWA->wHeap())
          ItemList(transValueUnionExpr, transItem[k]);
        }
      }


      // Bind the Transpose Values expressions. Get the expression value Id's
      //
      transVals.clear();
      if(transValueUnionExpr != NULL )
       transValueUnionExpr->convertToValueIdList(transVals,
                                                 bindWA,
                                                 ITM_ITEM_LIST);
      if (bindWA->errStatus()) return this;

      // If there are more than one transpose set, the value columns
      // generated by transpose can be NULL. So, make sure the typing is
      // done properly. This is done by setting the first in the list to
      // be nullable, then the ValueIdUnion will be nullable and the new
      // column will be nullable.  This is not done on the ValueIdUnion
      // node itself, since it will add an Null Instantiate node, and
      // we later assume that this node will always be a ValueIdUnion
      // node.
      //
      if (numTransSets > 1) {
        ValueId valId = transVals[0];

        transVals[0] = valId.nullInstantiate(bindWA, FALSE);
      }

      // Construct and Bind the ValueIdUnion node for the transpose vals.
      //
      ValueIdUnion *valVidu = new(bindWA->wHeap())
      ValueIdUnion(transVals, NULL_VALUE_ID);

      valVidu->bindNode(bindWA);
      if (bindWA->errStatus()) return this;

      // Insert this valueIdUnion node into the list of valueIdUnions
      // in the proper entry in transUnionVector_
      //
      transUnionVector()[i + 1].insert(valVidu->getValueId());

      // Get the val column reference
      //
      ColReference *valCol = (ColReference *)newCols[k];

      // Must have Column Refs to val column.
      //
      CMPASSERT(valCol);

      //Get the val column name.
      //
      NAString valColName( valCol->getColRefNameObj().getColName(), bindWA->wHeap());

      // Add the transpose column
      // (as the union of all of the transposed value columns)
      //
      resultTable->addColumn(bindWA, valColName, valVidu->getValueId());
    }
  }

  // Set the return descriptor
  //
  setRETDesc(resultTable);
  bindWA->getCurrentScope()->setRETDesc(resultTable);

  //
  // Bind the base class.
  //
  return bindSelf(bindWA);
} // Transpose::bindNode()

// -----------------------------------------------------------------------
// The Pack node binds itself by componsing its packing expression from
// all the columns available in its child's RETDesc. The packed columns
// produced by the packing expression are then made available in the Pack
// node's own RETDesc.
// -----------------------------------------------------------------------
RelExpr* Pack::bindNode(BindWA* bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  bindChildren(bindWA);
  if (bindWA->errStatus()) return this;

  // ---------------------------------------------------------------------
  // The Pack node has a packing expression stored as packingExprTree_
  // before binding. If packingExprTree_ is NULL, we are just going to
  // pick up all the columns from the output of its child. During binding,
  // this tree is converted into a value id list.
  // ---------------------------------------------------------------------

  // Create and bind the packing factor item expression.
  ItemExpr* pfie = new (bindWA->wHeap()) SystemLiteral(packingFactorLong());
  pfie->bindNode(bindWA);
  if (bindWA->errStatus()) return this;

  // Insert vid of bound constant into packingFactor valueIdSet.
  packingFactor().clear();
  packingFactor().insert(pfie->getValueId());

  // Create my RETDesc to hold the packed columns.
  RETDesc* resultTable = new (bindWA->wHeap()) RETDesc (bindWA);

  // Bind the tree if its present.
  if (packingExprTree_)
  {
    ItemExpr* packExprTree = removePackingExprTree();
    packExprTree->convertToValueIdList(packingExpr(), bindWA, ITM_ITEM_LIST);
    if (bindWA->errStatus()) return this;

    for (CollIndex i = 0; i < packingExpr().entries(); i++)
    {
      // Add all columns to result table.
      NAString packedColName( "PACKEDCOL_", bindWA->wHeap());
      packedColName += bindWA->fabricateUniqueName();
      Int32 length = packedColName.length();
      char * colName = new (bindWA->wHeap()) char[length + 1];
      colName[length] = 0;
      str_cpy_all(colName, packedColName, packedColName.length());

      ColRefName colRefName(colName);
      resultTable->addColumn(bindWA,
                             colRefName,
                             packingExpr().at(i),
                             USER_COLUMN,
                             colName);
    }
  }
  else // no packing expr tree, get all the columns from child.
  {
    // Get RETDesc from child which is assumed to be a RelRoot. too strict?
    const RETDesc& childTable = *child(0)->getRETDesc();
    ValueIdList childTableVidList;

    // These are only the user columns. Are SYS columns important?
    childTable.getValueIdList(childTableVidList);

    // Initialize packing expression.
    packingExpr().clear();

    // For each column in child's RETDesc, put a PackFunc() on top of it.
    for (CollIndex i = 0; i < childTableVidList.entries(); i++)
    {
      ItemExpr* childItemExpr = childTableVidList[i].getItemExpr();
      PackFunc* packedItemExpr = new (bindWA->wHeap())
                                             PackFunc(childItemExpr,pfie);
      // Bind the packed column.
      packedItemExpr->bindNode(bindWA);
      if (bindWA->errStatus()) return this;

      // Insert into both the result table and my packingExpr_.
      packingExpr().insert(packedItemExpr->getValueId());

      // $$$ Any implications of this? Needed to be seen.
      // Use the original column name as the packed column name. The index
      // is on USER columns only. SYS columns matter?
      ColRefName colRefName = childTable.getColRefNameObj(i);
      const char* heading = childTable.getHeading(i);

      // Insert into RETDesc for RelRoot above it to pick up as select-list.
      resultTable->addColumn(bindWA,
                             colRefName,
                             packedItemExpr->getValueId(),
                             USER_COLUMN,
                             heading);
      // $$$
      // OR: start with making a copy of child's RETDesc and change each col
      // to point to the vid for the packed column instead of the original.
    }
  }

  // Set the result table, bind self and return.
  setRETDesc(resultTable);
  bindWA->getCurrentScope()->setRETDesc(resultTable);
  bindSelf(bindWA);

  // To test packing. Add a unpack node on top of this pack node to check.
  char* env = getenv("PACKING_FACTOR");
  if (env && atol(env) > 0)
  {
    Lng32 pf = atol(env);

    ItemExpr* unPackExpr = NULL;
    ItemExpr* rowFilter = NULL;
    ItemExpr* unPackItem;
    ItemExpr* numRows;
    const NAType* typeInt = new(bindWA->wHeap()) SQLInt(bindWA->wHeap(), TRUE,FALSE);

    ValueIdList packedCols;
    resultTable->getValueIdList(packedCols);

    NAString hostVarName("_sys_UnPackIndex", bindWA->wHeap());
    hostVarName += bindWA->fabricateUniqueName();
    ItemExpr* indexHostVar = new(bindWA->wHeap())
        HostVar(hostVarName,new(bindWA->wHeap()) SQLInt(bindWA->wHeap(), TRUE,FALSE),TRUE);
    indexHostVar->synthTypeAndValueId();

    for (CollIndex i=0; i < packedCols.entries(); i++)
    {
      const NAType* colType =
            &(packedCols[i].getItemExpr()->child(0)->getValueId().getType());

      Lng32 width = colType->getNominalSize();
      Lng32 base = (colType->supportsSQLnullPhysical() ? (pf-1)/CHAR_BIT +1 : 0)
                   + sizeof(Int32);

      // $$$ Some duplicate code to be moved to PackColDesc later.
      ColRefName colRefName;
      colRefName = resultTable->getColRefNameObj(i);
      unPackItem = new(bindWA->wHeap())
        UnPackCol(packedCols[i].getItemExpr(),
                  indexHostVar,
                  width,
                  base,
                  colType->supportsSQLnull(),
                  colType);

      numRows = new(bindWA->wHeap())
       UnPackCol(packedCols[i].getItemExpr(),
                 new(bindWA->wHeap()) SystemLiteral(0),
                 typeInt->getNominalSize(),
                 0,
                 FALSE,
                 typeInt);

      unPackExpr = (unPackExpr ?
                    new(bindWA->wHeap()) ItemList(unPackExpr,unPackItem) :
                    unPackItem);

      rowFilter = (rowFilter ?
                   new(bindWA->wHeap()) ItemList(rowFilter,numRows) :
                   numRows);
    }

    RelExpr* unpack =
           new(bindWA->wHeap()) UnPackRows(pf,unPackExpr,rowFilter,NULL,
                                           this, indexHostVar->getValueId());
    return unpack->bindNode(bindWA);
  }

  return this;

} // Pack::bindNode()

RelExpr * Rowset::bindNode(BindWA* bindWA)
{
  // If this node has already been bound, we are done.
  if (nodeIsBound())
    return this->transformRelexpr_;

  if (bindWA->getHostArraysArea()) {
    bindWA->getHostArraysArea()->done() = TRUE;
  }

  //
  // Bind the child nodes.
  //
  bindChildren(bindWA);
  if (bindWA->errStatus()) return this;

  // Transform current node into a new subtree which performs access to
  // RowSet based on the unpacking and tuple node expression operators.
  // The formed tuple is composed of all input RowSet host variables:
  // Rowset-tuple: array_hv1, array_hv2, ... array_hvN.
  // The Unpack expression is used to retrieve the elements of the Rowset
  // with an indexed operator. For example, retrieve values for index two
  // for each Rowset host variable.
  // The transformed subtree has the following structure
  //
  //         UNPACK
  //            |
  //         TUPLE
  //
  // Note that the original Rowset relational expression has a rename node
  // on top.
  //

  // First find the maxRowSetSize and its rowsetSizeExpr. The rowset size is
  // the smallest declared dimension of the arrays composing the rowset.
  // If a constant rowset size was given in the SQL statement, it must be
  // samaller than the computed value.

  NABoolean hasDifferentSizes = FALSE;
  Lng32  maxRowsetSize  = 0; /* Maximum number of Rows in Rowset */
  ItemExpr *rowsetSizeExpr;
  ItemExpr *hostVarTree;

  // We get the list of input host vars, which is stored in the root of the
  // parse tree
  HostArraysWA *arrayArea = bindWA->getHostArraysArea();
  RelRoot *root =  bindWA->getTopRoot();

  // Do any extra checking at this moment.
  for (hostVarTree = inputHostvars_;
       hostVarTree;
       hostVarTree = hostVarTree->child(1)) {
    CMPASSERT(hostVarTree->getOperatorType() == ITM_ITEM_LIST);
    HostVar *hostVar = (HostVar *)hostVarTree->getChild(0);

    if (hostVar->getOperatorType() != ITM_HOSTVAR ||
        hostVar->getType()->getTypeQualifier() != NA_ROWSET_TYPE) {
      // 30001 A rowset must be composed of host variable arrays
      *CmpCommon::diags() << DgSqlCode(-30001);
      bindWA->setErrStatus();
      return NULL;
    }

    // Get the smallest dimension for rowset size

    SQLRowset* hostVarType  = (SQLRowset *)hostVar->getType();

    if (hostVarType->getNumElements() <= 0) {
      // 30004 The dimesion of the arrays composing the RowSet must be greater
      //       than zero. A value of $0~Int0 was given
      *CmpCommon::diags() << DgSqlCode(-30004)
                          << DgInt0((Int32)hostVarType->getNumElements());
      bindWA->setErrStatus();
      return NULL;
    }

    if (maxRowsetSize == 0)
      maxRowsetSize = hostVarType->getNumElements();
    else if (hostVarType->getNumElements() != maxRowsetSize) {
      // 30005 The dimensions of the arrays composing the RowSet are
      //       different. The smallest dimesnion is assumed.
      // This is just a warning

      // Give the warning only once
      if (hasDifferentSizes == FALSE) {
        if (arrayArea->hasDynamicRowsets()) {
           // 30015 The dimesion of the arrays composing the RowSet must be same
           // in dynamic SQL
            *CmpCommon::diags() << DgSqlCode(-30015) ;
            bindWA->setErrStatus();
            return NULL;
        } // for static SQL this is only a warning.
        hasDifferentSizes = TRUE;
        *CmpCommon::diags() << DgSqlCode(30005);
      }
      // Pick the smallest one
      if (hostVarType->getNumElements() < maxRowsetSize)
        maxRowsetSize = hostVarType->getNumElements();
    }

    // Make sure that the element type null indicator and the corresponding
    // rowset array are both nullable or not nullable. That is, force it

    NAType* hostVarElemType       = hostVarType->getElementType();
    NABoolean hostVarElemNullInd  = !(hostVar->getIndName().isNull());
    // If hostVarType is Unknown then this a dynamic param that has been
    // converted into a hostvar. For dynamic params there is no null 
    // indicator variable/param specified in the query text, so the previous
    // check will always return FALSE. We will set all dynamic params to be 
    // nullable and let type synthesis infer nullability later on.
    if (hostVarElemType->getTypeQualifier() == NA_UNKNOWN_TYPE)
      hostVarElemNullInd = TRUE;

    hostVarElemType->setNullable(hostVarElemNullInd);
  }

  // If a rowset size expression was produced during parsing, it is used
  // to restrict the rowset size during execution. The expression must be
  // an numeric literal (known at compile time) or an integer host variable
  // (known at execution time). We do not allow other type of expression
  // since the rowset size must be know before the statement is executed to
  // avoid copying a lot when the host variable arrays are sent down the
  // execution queue

  // If there is no size specification of the form ROWSET <size> ( <list> ) then
  // we take the size from ROWSET FOR INPUT SIZE <size>
  if (!sizeExpr_ && bindWA->getHostArraysArea()) {
    sizeExpr_ = bindWA->getHostArraysArea()->inputSize();
    if ((bindWA->getHostArraysArea()->getInputArrayMaxSize() > 0) &&
        (!sizeExpr_ )) {
       // ODBC process is performing a bulk insert and we need to create
       // an input parameter to simulate the functionality of ROWSET FOR INPUT
       // SIZE ... syntax.

       NAString name = "__arrayinputsize" ;
       HostVar *node = new (bindWA->wHeap())
                                    HostVar(name,
                                            new(bindWA->wHeap()) SQLInt(bindWA->wHeap(), TRUE,FALSE),
                                            TRUE);
       node->setHVRowsetForInputSize();
       root->addAtTopOfInputVarTree(node);
       sizeExpr_ = (ItemExpr *) node ;
    }
  }

  if (sizeExpr_) {
    if (sizeExpr_->getOperatorType() == ITM_CONSTANT) {
      if (((ConstValue *)sizeExpr_)->getType()->getTypeQualifier()
          != NA_NUMERIC_TYPE) {
        // 30003 Rowset size must be an integer host variable or an
        //       integer constant
        *CmpCommon::diags() << DgSqlCode(-30003);
        bindWA->setErrStatus();
        return NULL;
      }

      if (((ConstValue *)sizeExpr_)->getExactNumericValue() <= 0) {
        // 30004 The dimesion of the arrays composing the RowSet must be
        //       greater than zero. A value of $0~Int0 was given
        *CmpCommon::diags() << DgSqlCode(-30004)
                            << DgInt0((Int32) (((ConstValue *)sizeExpr_)
                                             ->getExactNumericValue()));
        bindWA->setErrStatus();
        return NULL;
      }

      if (((ConstValue *)sizeExpr_)->getExactNumericValue() > maxRowsetSize) {
        // 30002 The given RowSet size ($0~Int0) must be smaller or
        //       equal to the smallest dimension ($1Int1) of the
        //       arrays composing the rowset
        *CmpCommon::diags() << DgSqlCode(-30002)
                            << DgInt0((Int32)
                                      ((ConstValue *)sizeExpr_)
                                      ->getExactNumericValue())
                            << DgInt1(maxRowsetSize);
        bindWA->setErrStatus();
        return NULL;
      }
      else {
        maxRowsetSize = (Lng32)((ConstValue *)sizeExpr_)->getExactNumericValue() ;
      }
    }
    else
      if (!((sizeExpr_->getOperatorType() == ITM_HOSTVAR &&
          ((HostVar *)sizeExpr_)->getType()->getTypeQualifier()
           == NA_NUMERIC_TYPE) ||
          (sizeExpr_->getOperatorType() == ITM_DYN_PARAM ) ||
          ((sizeExpr_->getOperatorType() == ITM_CAST) &&
          (sizeExpr_->child(0)->getOperatorType() == ITM_DYN_PARAM))))
    {
      // 30003 Rowset size must be an integer host variable or an
      //       integer constant
      *CmpCommon::diags() << DgSqlCode(-30014);
      bindWA->setErrStatus();
      return NULL;
    }
    
      // We return a -1 if the execution time rowset size exceeds the maximum
      // declared size
      ItemExpr *maxSize = new (bindWA->wHeap()) SystemLiteral(maxRowsetSize);
      ItemExpr *neg = new (bindWA->wHeap()) SystemLiteral(-1);
      ItemExpr *constrPred = new (bindWA->wHeap())
                               BiRelat(ITM_GREATER, sizeExpr_, maxSize);
      rowsetSizeExpr = new (bindWA->wHeap())
                         IfThenElse(constrPred, neg, sizeExpr_);

      // IfThenElse only works if Case is its parent.
      rowsetSizeExpr = new (bindWA->wHeap()) Case (NULL, rowsetSizeExpr);

      // At code generation time, it is assumed that the size expression
      // is of size integer, so we do this cast. We do not allow null
      // values.
      rowsetSizeExpr = new (bindWA->wHeap())
        Cast(rowsetSizeExpr, new (bindWA->wHeap()) SQLInt(bindWA->wHeap(), TRUE,FALSE));

      // For dynamic rowsets, the parameter specifying rowset for input size
      // must be typed as an non-nullable integer.
      if (sizeExpr_->getOperatorType() == ITM_DYN_PARAM ) {
        sizeExpr_->synthTypeAndValueId();
        SQLInt intType(bindWA->wHeap(), TRUE,FALSE); // TRUE -> allow neagtive values, FALSE -> not nullable
        (sizeExpr_->getValueId()).coerceType(intType, NA_NUMERIC_TYPE);
      }


  }
  else
  {
    rowsetSizeExpr = new (bindWA->wHeap()) SystemLiteral(maxRowsetSize);
  }

  // Construct an index host variable to iterate over the elements of the
  // rowset. The name of the host variable must be unique (fabricated
  // by calling fabricateUniqueName). This host variable is bound since it
  // is not an input of the parse tree. Call synthTypeAndValueId()
  // which does the minimum binding.

  NAString indexName(bindWA->wHeap());
  if (indexExpr_) {
    // Get the name.
    indexName = ((ColReference *)indexExpr_)->getColRefNameObj().getColName();
  } else {
    indexName = "_sys_rowset_index" + bindWA->fabricateUniqueName();
  }

  const NAType *indexType = new (bindWA->wHeap()) SQLInt(bindWA->wHeap(), TRUE, FALSE);
  ItemExpr *indexHostVar = new (bindWA->wHeap())
    HostVar(indexName, indexType,
            TRUE // is system-generated
            );

  indexHostVar->synthTypeAndValueId();

  // Generate the RowsetArrayScan expressions which are used to extract
  // an element value of the rowset array given an index.

  ItemExpr *unPackExpr = NULL;

  for (hostVarTree = inputHostvars_;
       hostVarTree;
       hostVarTree = hostVarTree->child(1)) {
    HostVar *hostVar = (HostVar *)hostVarTree->getChild(0);
    SQLRowset* hostVarType        = (SQLRowset *)hostVar->getType();
    NAType* hostVarElemType       = hostVarType->getElementType();
    Lng32  hostVarElemSize         = hostVarElemType->getTotalSize();
    NABoolean hostVarElemNullInd  = !(hostVar->getIndName().isNull());

    // Force all host variable to have the same number of elements which was
    // found previously
    hostVarType->setNumElements(maxRowsetSize);

    // The element size must be align
    hostVarElemSize = ALIGN(hostVarElemSize,
                            hostVarElemType->getDataAlignment());

    // Assign a valueId for this Host variable. UnPackRows node will need
    // this valueId during its binding.
    //hostVar->synthTypeAndValueId();
    hostVar->bindNode(bindWA);

    ItemExpr *unPackCol =
      new (bindWA->wHeap())
      RowsetArrayScan(hostVar,          // Rowset Host Var array
                      indexHostVar,     // Index
                      maxRowsetSize,    // Cannot go over this size
                      hostVarElemSize,  // Element size in bytes
                      hostVarElemNullInd,
                      hostVarElemType
                      );

    // Construct a list of expressions to extract the Data value from
    // the packed row.  During normalization, this list (or a ValueIdList
    // representing this list) will be reduced to the minimum required.

    // This should be a NULL terminated list, unfortunately, there are
    // many parts in the SQL/MX code that loops over the arity instead
    // of checking for NULL terminated list...the effect a segmentation
    // violation.

    unPackExpr = (unPackExpr
                  ? new (bindWA->wHeap()) ItemList(unPackExpr, unPackCol)
                  : unPackCol);

  }

  // enable rowsetrowcount for rowset update and deletes
  // if the user has not turned the feature OFF.
  // if we have rowsets in where clause and are not in a select
  // then we have either rowset ypdate or delete, for direct rowsets.
  if (arrayArea && 
      (!(arrayArea->getHasDerivedRowsets())) &&
      arrayArea->hasHostArraysInWhereClause() && 
      (arrayArea->hasInputRowsetsInSelectPredicate() != HostArraysWA::YES_) &&
      (CmpCommon::getDefault(ROWSET_ROW_COUNT) == DF_ON)) {
    arrayArea->setRowsetRowCountArraySize(maxRowsetSize);
  }

  if (indexExpr_) {
    /*
     * Create and item expression to obtain the index
     */
    ItemExpr *unPackCol =
      new (bindWA->wHeap())
      RowsetArrayScan(indexHostVar,     // Index
                      indexHostVar,     // Index
                      maxRowsetSize,    // Cannot go over this size
                      indexType->getTotalSize(),
                      0,
                      indexType,
                      ITM_ROWSETARRAY_ROWID
                      );

    unPackExpr = (unPackExpr
                  ? new (bindWA->wHeap()) ItemList(unPackExpr, unPackCol)
                  : unPackCol);
  }

  // Now create a Tuple node to hang the children and input values of the
  // actual Rowset Node to it. Make sure to copy the RelExpr part of Rowset
  // to tuple.

  // Kludge up a dummy child for the index
  ItemExpr *inputs = ((indexExpr_)
                      ? new (bindWA->wHeap()) ItemList(inputHostvars_,
                                                       indexHostVar)
                      : inputHostvars_);

  Tuple *tupleExpr = new (bindWA->wHeap()) Tuple(inputs);
  tupleExpr->setBlockStmt(isinBlockStmt());

  copyTopNode(tupleExpr);

  // Construct the replacement tree for the Rowset operator.
  RelExpr *newSubTree = (new (bindWA->wHeap())
                         UnPackRows(maxRowsetSize,
                                    unPackExpr,
                                    rowsetSizeExpr,
                                    NULL,
                                    tupleExpr,
                                    indexHostVar->getValueId()));

  newSubTree->setBlockStmt(isinBlockStmt());

  // do not set this flag for derived rowsets. This flag is used in generator to determine
  // in onlj and TF TDB must set rownumber when encountering a execution time rowset error.
  if (arrayArea && 
      (!(arrayArea->getHasDerivedRowsets())) &&
      (arrayArea->hasInputRowsetsInSelectPredicate() != HostArraysWA::YES_)) 
  {
    newSubTree->setRowsetIterator(TRUE);
  }

  // Move any predicate on the packed table to be on the result
  // of unpacking.
  newSubTree->addSelPredTree(removeSelPredTree());

  // Remember the transform tree, just in case someone is trying to bind this
  // node again.
  transformRelexpr_  = newSubTree;

  // Bind the new generated subtree.
  return newSubTree->bindNode(bindWA);

} // Rowset::bindNode()

RelExpr * RowsetRowwise::bindNode(BindWA* bindWA)
{
  // If this node has already been bound, we are done.
  if (nodeIsBound())
    return this->transformRelexpr_;

  if (bindWA->getHostArraysArea()) {
    bindWA->getHostArraysArea()->done() = TRUE;
  }

  //
  // Bind the child nodes.
  //
  bindChildren(bindWA);
  if (bindWA->errStatus()) 
    return this;

  // Transform current node into a new subtree which performs access to
  // RowSet based on the unpacking.
  //         UNPACK
  //            |
  //         TUPLE
  //

  // We get the list of input host vars, which is stored in the root of the
  // parse tree
  HostArraysWA *arrayArea = bindWA->getHostArraysArea();
  
  if ((arrayArea->rwrsMaxSize()->getOperatorType() != ITM_CONSTANT) ||
      (((ConstValue *)arrayArea->rwrsMaxSize())->getType()->getTypeQualifier()
       != NA_NUMERIC_TYPE))
    {
      // 30003 Rowset size must be an integer host variable or an
      //       integer constant
      *CmpCommon::diags() << DgSqlCode(-30003);
      bindWA->setErrStatus();
      return NULL;
    }

  // if partition number has been specified, then we don't unpack
  // rows. The whole buffer is shipped to the specified partition.
  if (arrayArea->partnNum())
    return child(0)->castToRelExpr();

  Lng32 maxRowsetSize = 
    (Lng32)((ConstValue *)arrayArea->rwrsMaxSize())->getExactNumericValue() ;

  NAType * typ = new(bindWA->wHeap()) SQLInt(bindWA->wHeap(), FALSE, FALSE); 
  ItemExpr * rwrsInputSizeExpr = 
    new(bindWA->wHeap()) Cast(arrayArea->inputSize(), typ);
  if (bindWA->errStatus()) 
    return this;

  ItemExpr * rwrsMaxInputRowlenExpr =
    new(bindWA->wHeap()) Cast(arrayArea->rwrsMaxInputRowlen(), typ);
  if (bindWA->errStatus()) 
    return this;

  ItemExpr * rwrsBufferAddrExpr = arrayArea->rwrsBuffer(); 
  if (bindWA->errStatus()) 
    return this;
  
  // Construct the replacement tree for the Rowset operator.
  RelExpr *newSubTree = (new (bindWA->wHeap())
                         UnPackRows(maxRowsetSize,
                                    rwrsInputSizeExpr,
                                    rwrsMaxInputRowlenExpr,
                                    rwrsBufferAddrExpr,
                                    child(0)));

  // Remember the transform tree, just in case someone is trying to bind this
  // node again.
  transformRelexpr_  = newSubTree;

  // Bind the new generated subtree.
  return newSubTree->bindNode(bindWA);
} // RowsetRowwise::bindNode()

RelExpr * RowsetFor::bindNode(BindWA* bindWA)
{
  // Binding of this node should not happen. It should have been eliminated
  // by now by the pre-binding step. Its content is used to populate the
  // RowSet node with options.

  CMPASSERT(0);
  return NULL;
}

RelExpr * RowsetInto::bindNode(BindWA* bindWA)
{
  // If this node has already been bound, we are done.
  if (nodeIsBound())
    return this->transformRelexpr_;

  //
  // Bind the child nodes.
  //
  bindChildren(bindWA);
  if (bindWA->errStatus()) return this;

  NABoolean hasDifferentSizes = FALSE;
  Lng32  maxRowsetSize  = 0; /* Maximum number of Rows in Rowset */
  ULng32 numOutputHostvars = 0;

  ItemExpr *rowsetSizeExpr;
  ItemExpr *hostVarTree;

  // Do any extra checking at this moment.
  for (hostVarTree = outputHostvars_;
       hostVarTree;
       hostVarTree = hostVarTree->child(1)) {
    numOutputHostvars++;
    CMPASSERT(hostVarTree->getOperatorType() == ITM_ITEM_LIST);
    HostVar *hostVar = (HostVar *)hostVarTree->getChild(0);

    if (hostVar->getOperatorType() != ITM_HOSTVAR ||
        hostVar->getType()->getTypeQualifier() != NA_ROWSET_TYPE) {
      // 30001 A rowset must be composed of host variable arrays
      *CmpCommon::diags() << DgSqlCode(-30001);
      bindWA->setErrStatus();
      return NULL;
    }

    // Get the smallest dimension for rowset size


    SQLRowset* hostVarType  = (SQLRowset *)hostVar->getType();

    if (hostVarType->getNumElements() <= 0) {
      // 30004 The dimesion of the arrays composing the RowSet must be greater
      //       than zero. A value of $0~Int0 was given
      *CmpCommon::diags() << DgSqlCode(-30004)
                          << DgInt0((Int32)hostVarType->getNumElements());
      bindWA->setErrStatus();
      return NULL;
    }

    if (maxRowsetSize == 0)
      maxRowsetSize = hostVarType->getNumElements();
    else if (hostVarType->getNumElements() != maxRowsetSize) {
      // 30005 Warning: the dimensions of the arrays composing the RowSet are
      //       different. The smallest dimesnion is assumed.
      // This is just a warning

      // Give the warning only once
      if (hasDifferentSizes == FALSE) {
        hasDifferentSizes = TRUE;
        *CmpCommon::diags() << DgSqlCode(30005);
      }
      // Pick the smallest one
      if (hostVarType->getNumElements() < maxRowsetSize)
        maxRowsetSize = hostVarType->getNumElements();
    }

    // Make sure that the element type null indicator and the corresponding
    // rowset array are both nullable or not nullable. That is, force it

    NAType* hostVarElemType       = hostVarType->getElementType();
    NABoolean hostVarElemNullInd  = !(hostVar->getIndName().isNull());

    hostVarElemType->setNullable(hostVarElemNullInd);
  }

  // If a rowset size expression was produced during parsing, it is used
  // to restrict the rowset size during execution. The expression must be
  // an numeric literal (known at compile time) or an integer host variable
  // (known at execution time). We do not allow other type of expression
  // since the rowset size must be know before the statement is executed to
  // avoid copying a lot when the host variable arrays are sent down the
  // execution queue

  if (sizeExpr_) {
    if (sizeExpr_->getOperatorType() == ITM_CONSTANT) {
      if (((ConstValue *)sizeExpr_)->getType()->getTypeQualifier()
          != NA_NUMERIC_TYPE) {
        // 30003 Rowset size must be an integer host variable or an
        //       integer constant
        *CmpCommon::diags() << DgSqlCode(-30003);
        bindWA->setErrStatus();
        return NULL;
      }

      if (((ConstValue *)sizeExpr_)->getExactNumericValue() > maxRowsetSize) {
        // 30002 The given RowSet size ($0~Int0) must be smaller or
        //       equal to the smallest dimension ($1Int1) of the
        //       arrays composing the rowset
        *CmpCommon::diags() << DgSqlCode(-30002)
                            << DgInt0((Int32)
                                      ((ConstValue *)sizeExpr_)
                                      ->getExactNumericValue())
                            << DgInt1(maxRowsetSize);
        bindWA->setErrStatus();
        return NULL;
      }
    }
    else
      if (!(sizeExpr_->getOperatorType() == ITM_HOSTVAR &&
            ((HostVar *)sizeExpr_)->getType()->getFSDatatype()
            == REC_BIN32_SIGNED)) {
        // 30003 Rowset size must be an integer host variable or an
        //       integer constant
        *CmpCommon::diags() << DgSqlCode(-30003);
        bindWA->setErrStatus();
        return NULL;
      }
    rowsetSizeExpr = sizeExpr_;
  }
  else
    rowsetSizeExpr = new (bindWA->wHeap()) SystemLiteral(maxRowsetSize);


  if (getGroupAttr()->isEmbeddedUpdateOrDelete()){
    // 30020 Embedded update/delete cannot be used with SELECT...INTO and rowset.
    *CmpCommon::diags() << DgSqlCode(-30020);
    bindWA->setErrStatus();
    return NULL;
  }

  // Generate the RowsetArrayInto expressions which are used to append
  // an element value to the rowset array.

  // Get RETDesc from its only child one which must be RelRoot type.
  const RETDesc& childTable = *child(0)->getRETDesc();
  ValueIdList childTableVidList;

  childTable.getValueIdList(childTableVidList);

  if (numOutputHostvars != childTableVidList.entries()) {
    // 4094 The number of output host vars  ($0) must equal the number of cols
    *CmpCommon::diags() << DgSqlCode(-4094)
      << DgInt0(numOutputHostvars) << DgInt1(childTableVidList.entries());
    bindWA->setErrStatus();
    return NULL;
  }

  ItemExpr *packExpr = NULL;
  Lng32 i;

  for (hostVarTree = outputHostvars_, i = 0;
       hostVarTree;
       hostVarTree = hostVarTree->child(1), i++) {
    HostVar *hostVar = (HostVar *)hostVarTree->getChild(0);


    SQLRowset* hostVarType        = (SQLRowset *)hostVar->getType();
    NAType* hostVarElemType       = hostVarType->getElementType();
    // hostVarElemType->setNullable(TRUE);
    Lng32  hostVarElemSize         = hostVarElemType->getTotalSize();
    NABoolean hostVarElemNullInd  = !(hostVar->getIndName().isNull());
    ItemExpr* sourceExpr          = childTableVidList[i].getItemExpr();

    ValueId sourceId = childTableVidList[i];
    const NAType& targetType = *hostVarElemType;
    sourceId.coerceType(targetType);
    const NAType& sourceType = sourceId.getType();

    NABoolean relaxCharTypeMatchingRule = FALSE;

    // We make sure that the types that are coming from below this
    // node match properly with the types it has
    if (NOT targetType.isCompatible(sourceType)) {
      // JQ
      // Relaxing Characet Data Type mismatching rule.
      if ( targetType.getTypeQualifier() == NA_CHARACTER_TYPE &&
           sourceType.getTypeQualifier() == NA_CHARACTER_TYPE &&
           ((const CharType&)targetType).getCharSet() == CharInfo::UNICODE &&
           ((const CharType&)sourceType).getCharSet() == CharInfo::ISO88591
         )
      {
        relaxCharTypeMatchingRule = TRUE;
      }

      if ( !relaxCharTypeMatchingRule ) {
        // Incompatible assignment from type $0~String0 to type $1~String1
        *CmpCommon::diags() << DgSqlCode(-30007)
                            << DgString0(sourceType.getTypeSQLname(TRUE /*terse*/))
                            << DgString1(targetType.getTypeSQLname(TRUE /*terse*/));
        bindWA->setErrStatus();
        return FALSE;
      }
    }

    // Force all host variable to have the same number of elements which was
    // found previously
    hostVarType->setNumElements(maxRowsetSize);

    // The element size must be align
    hostVarElemSize = ALIGN(hostVarElemSize,
                            hostVarElemType->getDataAlignment());

    // Preserve the length that is coming from the node below this one
    if (hostVarElemType->getTypeQualifier() == NA_CHARACTER_TYPE &&
        sourceType.getTypeQualifier() == NA_CHARACTER_TYPE) {
      Int32 sourceSize = ((CharType *) &sourceType)->getDataStorageSize();
      Int32 targetSize = ((CharType *) hostVarElemType)->getDataStorageSize();
      if (sourceSize > targetSize ) {
     // Adjust the layout size instead of changing the element size?
        ((CharType *) hostVarElemType)->setDataStorageSize(sourceSize);
      }
    }

    if ( relaxCharTypeMatchingRule == TRUE )
      sourceExpr = new (bindWA->wHeap())
           Translate(sourceExpr, Translate::ISO88591_TO_UNICODE);

    // If the type is external (for instance, decimal or varchar), we must first
    // convert to our internal equivalent type
    if (hostVarElemType->isExternalType()) {
      NAType *internalType = hostVarElemType->equivalentType();
      sourceExpr = new (bindWA->wHeap()) Cast(sourceExpr, internalType);
    }

    sourceExpr = new (bindWA->wHeap()) Cast(sourceExpr, hostVarElemType);

    ItemExpr *packCol =
      new (bindWA->wHeap())
      RowsetArrayInto(sourceExpr,
                      rowsetSizeExpr,    // Runtime size
                      maxRowsetSize,     // Cannot go over this size
                      hostVarElemSize,   // Element size in bytes
                      hostVarElemNullInd,
                      hostVarType
                      );

    // Construct a list of expressions to append the Data value to the
    // RowSet array. This list should be a NULL terminated list,
    // unfortunately, there are many parts in the SQL/MX code that
    // loops over the arity instead of checking for NULL terminated
    // list...the effect a segmentation violation.

    packExpr = (packExpr
                ? new (bindWA->wHeap()) ItemList(packExpr, packCol)
                : packCol);
  }

  // Construct the replacement tree for the RowsetInto operator.
  RelExpr *newSubTree = (new (bindWA->wHeap())
                         Pack(maxRowsetSize,
                              child(0)->castToRelExpr(),
                              packExpr));

  newSubTree->setFirstNRows(getFirstNRows());

  // If we have an ORDER BY when there is an INTO :array, then we
  // add the requirement that the tuples that this Pack node will
  // receive must be sorted

  ValueIdList *ptrReqOrder;

  ptrReqOrder = new (bindWA->wHeap())
      ValueIdList(((RelRoot *) (RelExpr *) newSubTree->child(0))->reqdOrder());

  ((Pack *) newSubTree)->setRequiredOrder(*ptrReqOrder);


  // Remember the transform tree, just in case someone is trying to bind this
  // node again.
  transformRelexpr_  = newSubTree;

  // Bind the new generated subtree.
  return newSubTree->bindNode(bindWA);

} // RowsetInto::bindNode

RelExpr *
IsolatedScalarUDF::bindNode (BindWA *bindWA)
{

  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

     // If we have a RoutineDesc, it means we got transformed from a 
     // a UDFunction ItemExpr, and do NOT need to check all the metadata
     // params etc. 
  if (getRoutineDesc() == NULL ) 
  {
        // If we get here, we created a IsolatedScalarUDF some other way
        // than through the transformation of UDFunction. Either that or
        // we have someone walking over our memory...

     CMPASSERT(0);
     bindWA->setErrStatus();
     return this;
                                                 

  }
  else
  {
     markAsBound();
  }


  return this;
} // IsolatedScalarUDF::bindNode ()

/*
 * This method performs binder functions for the CALLSP node
 * It performs semantic checks on the called stored procedure
 * creates a Tuple child and allocates ValueIds for the parameters
 * It also provides support for the CLI layer processing for OUT
 * parameter processing.
 */
RelExpr *CallSP::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  if (bindWA->getHoldableType() == SQLCLIDEV_ANSI_HOLDABLE)
  {
    *CmpCommon::diags() << DgSqlCode(-4382);
    bindWA->setErrStatus();
    bindWA->setBindingCall (FALSE);
    return this;
  }

  bindWA->setBindingCall (TRUE);
  bindWA->setCurrOrdinalPosition (1);
  bindWA->setCurrParamMode (COM_UNKNOWN_DIRECTION);
  bindWA->clearHVorDPinSPDups ();
  bindWA->setDupWarning (FALSE);
  bindWA->setMaxResultSets(0);

  // try PUBLIC SCHEMA only when no schema was specified
  // and CQD PUBLIC_DEFAULT_SCHEMA is specified
  NAString pSchema = 
    ActiveSchemaDB()->getDefaults().getValue(PUBLIC_SCHEMA_NAME);
  ComSchemaName pubSchema(pSchema);
  NAString pubSchemaIntName = "";
  if ( (getRoutineName().getSchemaName().isNull()) && 
       (!pubSchema.getSchemaNamePart().isEmpty()) )
  {
    pubSchemaIntName = pubSchema.getSchemaNamePart().getInternalName();
  }

  // Invoke GetNARoutine () to retrieve the corresponding NARoutine from
  // NARoutineDB_
  QualifiedName name = getRoutineName();
  const SchemaName &defaultSchema =
    bindWA->getSchemaDB ()->getDefaultSchema();
  name.applyDefaults(defaultSchema);
  setRoutineName(name);
  bindWA->setCurrSPName(&name);

    // in open source, only the SEABASE catalog is allowed.
    // Return an error if some other catalog is being used.
  if ((NOT name.isSeabase()) && (NOT name.isHive()))
      {
	*CmpCommon::diags()
	  << DgSqlCode(-1002)
	  << DgCatalogName(name.getCatalogName());
	
	bindWA->setErrStatus();
	return NULL;
      }


  CmpSeabaseDDL cmpSBD((NAHeap*)bindWA->wHeap());
  TrafDesc *catRoutine = 
	    cmpSBD.getSeabaseRoutineDesc(
				       name.getCatalogName(),
				       name.getSchemaName(),
				       name.getObjectName());

  // try public schema
  if ( !catRoutine && 
       !pubSchemaIntName.isNull() )
  {
    getRoutineName().setSchemaName(pubSchemaIntName);
    if ( !pubSchema.getCatalogNamePart().isEmpty() )
    {
      getRoutineName().setCatalogName(pubSchema.getCatalogNamePart().getInternalName());
    }

    // in open source, only the SEABASE catalog is allowed.
    // Return an error if some other catalog is being used.
    if ((NOT getRoutineName().isSeabase()) && (NOT getRoutineName().isHive()))
      {
	*CmpCommon::diags()
	  << DgSqlCode(-1002)
	  << DgCatalogName(getRoutineName().getCatalogName());
	
	bindWA->setErrStatus();
	return NULL;
      }

    bindWA->resetErrStatus();
    catRoutine = 
	    cmpSBD.getSeabaseRoutineDesc(
                 getRoutineName().getCatalogName(),
                 getRoutineName().getSchemaName(),
                 getRoutineName().getObjectName());
    if ( !bindWA->errStatus() && catRoutine )
    { // if found in public schema, do not show previous error
      CmpCommon::diags()->clear();
    }
  }

  if (bindWA->violateAccessDefaultSchemaOnly(getRoutineName()))
    return NULL;

  if ( NULL == catRoutine )
  {
    // Diagnostic error is set by the readRoutineDef, we just need to
    // make sure the rest of the compiler knows that an error occurred.
    bindWA->setBindingCall (FALSE);
    bindWA->setErrStatus ();
    return this;
  }

  // Create a new NARoutine object
  Int32 error = FALSE;
  NARoutine *routine = new (bindWA->wHeap()) NARoutine ( getRoutineName(),
                                                         catRoutine,
                                                         bindWA,
                                                         error );

  if ( bindWA->errStatus () )
  {
    // Error
    bindWA->setBindingCall (FALSE);
    bindWA->setErrStatus ();
    return this;
  }

  NABoolean createRETDesc=TRUE;
  RoutineDesc *rDesc = new (bindWA->wHeap()) RoutineDesc(bindWA, routine); 
  if (rDesc == NULL ||  bindWA->errStatus ())
  {
    // Error
    bindWA->setBindingCall (FALSE);
    bindWA->setErrStatus ();
    return this;
  }
 
  if (rDesc->populateRoutineDesc(bindWA, createRETDesc) == FALSE ) 
  {
    bindWA->setBindingCall (FALSE);
    bindWA->setErrStatus ();
    return this;
  }

  setRoutineDesc(rDesc);


  //
  // Semantic checks
  //

  // if in trigger and during DDL make sure to Fix up the name 
  // location list so that the name is fully qualified when stored 
  // in the TEXT metadata table
  if ( bindWA->inDDL() && bindWA->isInTrigger () )
  {
     ParNameLocList *pNameLocList = bindWA->getNameLocListPtr();
     if (pNameLocList)
     {
       ParNameLoc * pNameLoc
         = pNameLocList->getNameLocPtr(getRoutineName().getNamePosition());
       CMPASSERT(pNameLoc);
       pNameLoc->setExpandedName(getRoutineName().getQualifiedNameAsAnsiString());
     }
  }

  // Cannot support result sets or out params when
  // SP is invoked within a trigger
  if ( bindWA->isInTrigger () &&
       getNARoutine()->hasOutParams ())
  {
    *CmpCommon::diags() <<  DgSqlCode(-UDR_BINDER_OUTPARAM_IN_TRIGGER)
                          << DgTableName (getRoutineName().getQualifiedNameAsString());
    bindWA->setErrStatus ();
    bindWA->setBindingCall (FALSE);
    return this;
  }

  if ( bindWA->isInTrigger () &&
       getNARoutine()->hasResultSets ())
  {
    *CmpCommon::diags() <<  DgSqlCode(-UDR_BINDER_RESULTSETS_IN_TRIGGER)
                          << DgTableName (getRoutineName().getQualifiedNameAsString());
    bindWA->setErrStatus ();
    bindWA->setBindingCall (FALSE);
    return this;
  }

  const NAColumnArray &params = getNARoutine()->getParams ();
  CollIndex i = 0;
  CollIndex numParams = getNARoutine()->getParamCount ();

  CollIndex numSuppliedParams = countSuppliedParams (getRWProcAllParamsTree());
  if (numSuppliedParams != numParams)
  {
    *CmpCommon::diags() << DgSqlCode(-UDR_BINDER_INCORRECT_PARAM_COUNT)
                        << DgTableName(getRoutineName().getQualifiedNameAsString())
                        << DgInt0((Lng32) numParams)
                        << DgInt1((Lng32) numSuppliedParams);
    bindWA->setErrStatus ();
    bindWA->setBindingCall (FALSE);
    return this;
  }

  short numResultSets = (short) getNARoutine()->getMaxResults();
  bindWA->setMaxResultSets(numResultSets);

  // On to the binding
  // Invoke populateAndBindItemExpr, set up needed data structures

  // Set up a RETDesc if we don't already have one.
  RETDesc *resultTable = getRETDesc();
  if (resultTable == NULL) 
  {
       resultTable = new (bindWA->wHeap()) RETDesc(bindWA);
       setRETDesc(resultTable);
  }

  populateAndBindItemExpr ( getRWProcAllParamsTree(),
                            bindWA );
  if ( bindWA->errStatus ())
  {
    bindWA->setBindingCall (FALSE);
    return this;
  }

  // Clear the Tree since we now have gotten vids for all the parameters.
  setProcAllParamsTree(NULL);

  // Now fix the param index value of the dynamic params or host vars
  LIST (ItemExpr *) &bWA_HVorDPs = bindWA->getSpHVDPs();
  CollIndex numHVorDPs = bWA_HVorDPs.entries();

  ARRAY(ItemExpr *) local_HVorDPs(HEAP, numHVorDPs);
  CollIndex idx, idx1, idx2;

  // Sort the ItemExpr in the order they appeared in the stmt
  for (idx = 0; idx < numHVorDPs; idx++)
  {
    // Copy ItemExpr ptrs to a sorted Array.
    local_HVorDPs.insertAt(bWA_HVorDPs[idx]->getHVorDPIndex() - 1,
                           bWA_HVorDPs[idx]);
  }

  // The following code goes through the list of Exprs and
  // sets index values. The rules are:
  // 1. When a DP or HV is repeated, all of them get the same
  // index value which is equal to the index of the first occurrence
  // 2. Two DPs or HVs are same if their names and the modes are same.
  Int32 currParamIndex = 1;
  for (idx1 = 0; idx1 < numHVorDPs; idx1++)
  {
    ItemExpr *src = local_HVorDPs[idx1];
    const NAString &name1 = (src->getOperatorType() == ITM_HOSTVAR) ?
      ((HostVar *)src)->getName() : ((DynamicParam *)src)->getName();
    ComColumnDirection mode1 = src->getParamMode();

    NABoolean encounteredElement = FALSE;

    for (idx2 = idx1; idx2 < numHVorDPs; idx2++)
    {
      ItemExpr *dest = local_HVorDPs[idx2];

      if (!encounteredElement && dest->getHVorDPIndex() >= currParamIndex)
      {
        // The parameter is encountered the first time
        encounteredElement = TRUE;
        dest->setPMOrdPosAndIndex(dest->getParamMode(),
                                  dest->getOrdinalPosition(),
                                  currParamIndex);
        continue;
      }

      // The parameter is already corrected
      if (dest->getHVorDPIndex() < currParamIndex)
        continue;

      const NAString &name2 = (dest->getOperatorType() == ITM_HOSTVAR) ?
        ((HostVar *)dest)->getName() : ((DynamicParam *)dest)->getName();
      ComColumnDirection mode2 = dest->getParamMode();

      if (name2.compareTo("") == 0)
        continue;

      if (name1.compareTo(name2) == 0 && mode1 == mode2)
      {
        dest->setPMOrdPosAndIndex(dest->getParamMode(),
                                  dest->getOrdinalPosition(),
                                  currParamIndex);
      }
    }

    if (encounteredElement)
      currParamIndex++;
  }

  // Restore the bindWA's HVorDP list since it might be needed
  // while binding the root node in case of HVs.
  bindWA->clearHVorDPinSPDups();
  for (idx = 0; idx < numHVorDPs; idx++)
    bindWA->addHVorDPToSPDups(local_HVorDPs[idx]);

  // Create a tuple child for any subqueries or UDF inputs
  // The hasSubquery() / hasUDF() flag gets set in setInOrOutParam if any of our
  // passed in parameters is a subquery.

  
  if ((getProcInputParamsVids().entries() != 0)  && 
      (hasSubquery() || hasUDF())) 
  {
     Tuple *inTuple = new (bindWA->wHeap()) 
                Tuple(getProcInputParamsVids().rebuildExprTree(ITM_ITEM_LIST), 
                      bindWA->wHeap());
   
     if ( inTuple )
     {
       // Now set and bind the Tuple child
       setChild (0, inTuple);
   
       // Bind this Tuple child
       inTuple->bindNode (bindWA);
       if ( bindWA->errStatus ())
       {
         bindWA->setBindingCall (FALSE);
         return this;
       }
   
       // Get each IN entry from the Tuple and put it in
       //the super's list

       // Need to clear the list to avoid duplicates
       getProcInputParamsVids().clear();

       // Now reinitialize the inputs based on the Tuple processing.
       inTuple->getRETDesc ()->getValueIdList (getProcInputParamsVids());
   
     } // if inTuple
     else
     {
         // Out of memory ...
         bindWA->setBindingCall (FALSE);
         bindWA->setErrStatus();
         return this;
     }
  } // if getProcInputParamVids().entries()
  else
  {

    // If we dont have a subquery parameter, we dont need to go thru
    // Optimization time rules and transformations, hence mark this
    // as a physical node.

    isPhysical_ = TRUE;
  }


  //
  // Not sure whether we need to set the currently scoped RETDesc
  // before binding the base class. Tuple::bindNode() does not do it
  // so we won't either (for now)
  //
  //bindWA->getCurrentScope()->setRETDesc(getRETDesc());

  // add the routine to the UdrStoiList.  The UdrStoi list is used
  // to check valid privileges
  LIST(OptUdrOpenInfo *) udrList = bindWA->getUdrStoiList ();
  ULng32 numUdrs = udrList.entries();
  NABoolean udrReferenced = FALSE;

  // See if UDR already exists
  for (ULng32 stoiIndex = 0; stoiIndex < numUdrs; stoiIndex++)
  {
    if ( 0 ==
         udrList[stoiIndex]->getUdrName().compareTo(
                           getRoutineName().getQualifiedNameAsAnsiString()
                                                  )
       )
    {
      udrReferenced = TRUE;
      break;
    }
  }

  // UDR has not been defined, go ahead an add one
  if ( FALSE == udrReferenced )
  {
    SqlTableOpenInfo *udrStoi = new (bindWA->wHeap ())SqlTableOpenInfo ();
    udrStoi->setAnsiName ( convertNAString(
                           getRoutineName().getQualifiedNameAsAnsiString(),
                           bindWA->wHeap ())
                         );

    OptUdrOpenInfo *udrOpenInfo = new (bindWA->wHeap ())
      OptUdrOpenInfo( udrStoi
                    , getRoutineName().getQualifiedNameAsAnsiString()
                    , (NARoutine *)getNARoutine()
                    );
    bindWA->getUdrStoiList().insert(udrOpenInfo);
  }


  //
  // Bind the base class
  //
  RelExpr *boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus())
  {
    bindWA->setBindingCall (FALSE);
    return boundExpr;
  }

  // Our characteristic inputs get set for us, we don't need to do it
  // ourselves, however, we need to set our characteristic outputs
  getGroupAttr()->addCharacteristicOutputs(getProcOutputParamsVids());

  if (getNARoutine()->isProcedure())
    bindWA->setHasCallStmts(TRUE);

  bindWA->setBindingCall (FALSE);
  return boundExpr;
} // CallSP::bindNode()



// This is the main entry point to walking the ItemExpr tree built by the
// parser, separating the IN and OUT parameters, setting appropriate
// characteristics of the IN/OUT parameters and binding them
// Currently only CallSP uses this code. If this routine needs to be shared
void IsolatedNonTableUDR::populateAndBindItemExpr ( ItemExpr *param,
                                       BindWA *bindWA )
{
  // This method is called recursively
  CollIndex numParams = getEffectiveNARoutine()->getParamCount ();
  CollIndex ordinalPosition = bindWA->getCurrOrdinalPosition ();

  // No parameters, or we are done with the leaf node
  if ( NULL == param )
  {
    return;
  }

  ComColumnDirection mode =
     getEffectiveNARoutine()->getParams()[ordinalPosition-1]->getColumnMode ();

  // This is the structure of the ItemExpr tree
  // For 1 param
  //    ItemExpr
  //
  //  2 params
  //    ItemList
  //     /    \
  //  Param1  Param2
  //
  // > 2 params
  //              ItemList
  //             /        \
  //        Param1         ItemList
  //                    /       \
  //                 Param2    ItemList
  //                        ...        ...
  //                     ...             ...
  //                      /              /   \
  //                    Param (N-2)    /      \
  //                                 /         \
  //                              Param(N-1)   Param(N)
  if ( ITM_ITEM_LIST == param->getOperatorType ())
  {
    // Use left child
    CMPASSERT ((ItemExpr *) NULL != (*param).child (0));

    populateAndBindItemExpr ( (*param).child(0),
                              bindWA );

    if ( bindWA->errStatus ())
      return;

    // Now for the right child
    CMPASSERT ((ItemExpr *) NULL != (*param).child (1));
    populateAndBindItemExpr ( (*param).child(1),
                              bindWA );

    return;

  } // if ITM_ITEM_LIST == param->getOperatorType ()

  // For all leaf nodes we must come here (see the recursive call to
  // populateAndBindItemExp above)
  // Set the bindWA's current ordinal position and parameter mode
  // Let HV and DynamicParam's bindNode take care of the
  // settings. To ensure this, do a bindNode here
  bindWA->setCurrParamMode (mode);
  param->bindNode (bindWA);
  if (bindWA->errStatus ())
    return;

  // Add the IN or OUT params to their respective lists
  // and also create and bind a new ItemExpr for INOUT and OUT
  // params.
  // Also bump up the ordinalPosition count since we are done with this
  // parameter.
  setInOrOutParam (param,/* ordinalPosition,*/ mode, bindWA);
  if ( bindWA->errStatus ())
    return;

  bindWA->setCurrOrdinalPosition (bindWA->getCurrOrdinalPosition () + 1);

} // PopulateAndBindItemExpr



void
IsolatedNonTableUDR::setInOrOutParam (ItemExpr *expr,
                              ComColumnDirection paramMode,
                              BindWA *bindWA)
{
    // Should not get here..
   CMPASSERT(FALSE);
}


// This method separates the IN and OUT parameters Each IN/INOUT param
// is cast to the formal type (from NARoutine). This Cast'ed item expr
// is added to an ItemList tree to be passed to the Tuple ()
// constructor.  For each OUT/INOUT, we create a NATypeToItem
// ItemExpr, bind it and add it to procOutParams_.
//
// This method is called once for each CALL statement argument. If an
// input argument to a CALL is an expression tree such as "? + ?" or
// "abs(:x)" then this method is called once for the entire tree.
//
// Side Effects: OUT: hasSubquery_
//                    neededValueIds_
//                    procAllParamsVids_
//                    procInputParamsVids_
//                    procOutputParamsVids_
void CallSP::setInOrOutParam ( ItemExpr *expr,
                               ComColumnDirection paramMode,
                               BindWA *bindWA)
{

  // Depending on whether this is an IN or OUT parameter, we need to
  // take different actions.

  // For an IN (and INOUT) param, do the following
  // Cast the parameter to its formal type and add it to the list of
  // IN params. This will be used later to create a Tuple child and
  // be bound by the Tuple itself
  CollIndex ordinalPosition = bindWA->getCurrOrdinalPosition ();

  const NAColumnArray &formalParams = getNARoutine()->getParams();
  NAColumn &naColumn = *(formalParams[ordinalPosition-1]);
  const NAType &paramType = *(naColumn.getType());

  // Don't really want to bind this, but how else can we
  // get the ItemExpr's type
  ItemExpr *boundExpr = expr->bindNode (bindWA);
  if ( bindWA->errStatus ())
  {
    return;
  }



  //10-061031-0188-Begin
  //Need to infer charset for string literals part of CALLSP
  //parameters
  ValueId inputTypeId = boundExpr->getValueId();

  if(inputTypeId.getType().getTypeQualifier() == NA_CHARACTER_TYPE)
  {
   const CharType* stringLiteral = (CharType*)&(inputTypeId.getType());

  if(CmpCommon::wantCharSetInference())
  {
    const CharType* desiredType =
       CharType::findPushDownCharType(((CharType&)paramType).getCharSet(), stringLiteral, 0);

    if ( desiredType )
      inputTypeId.coerceType((NAType&)*desiredType, NA_CHARACTER_TYPE);
 }
 }

  NABoolean throwInTranslateNode = FALSE;
  CharInfo::CharSet paramCS = CharInfo::UnknownCharSet;
  CharInfo::CharSet inputCS = CharInfo::UnknownCharSet;

 const NABoolean isJdbc =
    (CmpCommon::getDefault(JDBC_PROCESS) == DF_ON ? TRUE : FALSE);
 const NABoolean isOdbc =
    (CmpCommon::getDefault(ODBC_PROCESS) == DF_ON ? TRUE : FALSE);

 const NAType &inputType = inputTypeId.getType();
  //10-061031-0188-End

  if ( COM_INPUT_COLUMN == paramMode ||
       COM_INOUT_COLUMN == paramMode )
  {
    // If this input argument to the CALL is a single dynamic param
    // then we want to record the formal parameter name. It will later
    // be written into the query plan by the code generator and
    // eventually if this CALL statement is DESCRIBEd, the formal
    // param name gets returned in the SQLDESC_NAME descriptor entry.
    if (expr->getOperatorType() == ITM_DYN_PARAM)
    {
      DynamicParam *dp = (DynamicParam *) expr;
      dp->setUdrFormalParamName(naColumn.getColName());
    }

    // Check to see if we have a Subquery as an input
    if ( !hasSubquery() )
      hasSubquery() = expr->containsSubquery ();


    // Check to see if we have a UDF as an input
    if ( !hasUDF() )
      hasUDF() = (expr->containsUDF () != NULL);

    // Do type checking,
    // If it is not a compatible type report an error
    if (!( NA_UNKNOWN_TYPE == inputType.getTypeQualifier () ||
           paramType.isCompatible(inputType) ||
           expr->getOperatorType () == ITM_DYN_PARAM
         )
       )
    {
      if ( inputType.getTypeQualifier() == NA_CHARACTER_TYPE )
      {
         paramCS = ((CharType&)paramType).getCharSet();
         inputCS = ((CharType&)inputType).getCharSet();

         NABoolean CS_unknown = (paramCS == CharInfo::UnknownCharSet) ||
                                (inputCS == CharInfo::UnknownCharSet) ;
         if ( paramType.NAType::isCompatible(inputType) &&
              paramCS != inputCS                        &&
              CS_unknown == FALSE                       &&
              CmpCommon::getDefault(ALLOW_IMPLICIT_CHAR_CASTING) == DF_ON
            )
               throwInTranslateNode = TRUE;
      }
      if ( throwInTranslateNode == FALSE )
      {
        // Error, data types dont match
        *CmpCommon::diags() <<  DgSqlCode(-UDR_BINDER_PARAM_TYPE_MISMATCH)
                            << DgInt0 (ordinalPosition)
                            << DgTableName(getRoutineName().getQualifiedNameAsString())
                            << DgString0 (inputType.getTypeSQLname (TRUE))
                            << DgString1 (paramType.getTypeSQLname (TRUE));
        bindWA->setErrStatus ();
        return;
      }
    } // if NOT isCompatible

    // Create a Cast node if the types are not identical
    if (! (inputType == paramType))
    {
       // First create a Translate node if the character sets are not identical

       if ( throwInTranslateNode )
       {
            Int32 tran_type = find_translate_type( inputCS, paramCS );

            ItemExpr * newTranslateChild =
                new (bindWA->wHeap()) Translate(boundExpr, tran_type );
            boundExpr = newTranslateChild->bindNode(bindWA);
            if (bindWA->errStatus())
               return;
            // NOTE: Leave "expr" at it's old value as code below needs to check
            //       that original ItemExpr rather than the new Translate node.
       }
       Cast *retExpr = new (bindWA->wHeap())
                          Cast(boundExpr, &paramType, ITM_CAST, TRUE);

       boundExpr = retExpr->bindNode (bindWA);
       if ( bindWA->errStatus ())
       {
          return;
       }
    }
    // Fill the ValueIdList for all the params
    getProcAllParamsVids().insert( boundExpr->getValueId());

    // Fill the ValueIdList for Input params
    getProcInputParamsVids().insert( boundExpr->getValueId());

  } // if INPUT or INOUT

  // For OUT (and INOUT) parameters, we create a NATypeToItem object,
  // bind it and add it to the list of OUT parameters (procOutParams_)
  if ( COM_OUTPUT_COLUMN == paramMode ||
       COM_INOUT_COLUMN == paramMode )
  {
    if (!( ITM_HOSTVAR == expr->getOperatorType () ||
           ITM_DYN_PARAM == expr->getOperatorType ()))
    {
      *CmpCommon::diags() << DgSqlCode(-UDR_BINDER_OUTVAR_NOT_HV_OR_DP)
                          << DgInt0(ordinalPosition)
                          << DgTableName(getRoutineName().getQualifiedNameAsString());
      bindWA->setErrStatus ();
      return;
    } // if NOT HOSTVAR or DYNAMIC PARAM

    NATypeToItem *paramTypeItem = new (bindWA->wHeap())
                                      NATypeToItem (naColumn.mutateType());
    ItemExpr *outputExprToBind = NULL;
    outputExprToBind = paramTypeItem->bindNode (bindWA);
    if ( bindWA->errStatus ())
    {
      return;
    }



    // Fill the ValueIdList for all the params
    getProcAllParamsVids().insert( outputExprToBind->getValueId());

    // Fill the ValueIdList for the output params
    addProcOutputParamsVid(outputExprToBind->getValueId ());

    //
    // Populate our RETDesc
    //
    // It has already been alocated
    RETDesc *resultTable = getRETDesc();

    const NAString &formalParamName = naColumn.getColName();
    const NAString *colParamName = &formalParamName;

    // Set the userParamName
    const NAString &userParamName =
            // cannot use the boundExpr here as it will be a cast()
            // for the HostVar or DynamicParam. Use the original
            // ItemExpr pointer instead.
        (ITM_HOSTVAR == expr->getOperatorType()) ?
        ((HostVar *)expr)->getName() :
        ((DynamicParam *)expr)->getName();


    // Typically the name for this output column will be the formal
    // parameter name. Exceptions:
    // - No formal name was specified in the CREATE PROCEDURE. Use
    //   the (possibly empty) dynamic parameter or host variable name
    //   instead.
    // - This is a JDBC or ODBC compile and the client is using a
    //   named host variable or dynamic parameter. JDBC and ODBC want
    //   us to use the client's name in this case.

    if (formalParamName.isNull() ||
        (!userParamName.isNull() && (isJdbc || isOdbc)))
    {
      colParamName = &userParamName;
    }

    ColRefName *columnName = 
        new (bindWA->wHeap())
            ColRefName(*colParamName, bindWA->wHeap());

    resultTable->addColumn(bindWA, *columnName, outputExprToBind->getValueId());

    //
    // We need the following line for static cursor declaration,
    // according to a comment in bindRowValues()
    //
    cmpCurrentContext->saveRetrievedCols_ = resultTable->getDegree();

  } // if OUTPUT or INOUT

} // setInOrOutParam





CollIndex RelRoutine::countSuppliedParams (ItemExpr *tree) const
{
  CollIndex numParams=0;

  if ( !tree )  return 0;

  if (ITM_ITEM_LIST == tree->getOperatorType ())
  {
    numParams += countSuppliedParams (tree->child (0));
    numParams += countSuppliedParams (tree->child (1));
  }
  else
    numParams++;

  return numParams;

} // RelRoutine::countSuppliedParams

void RelRoutine::gatherParamValueIds (const ItemExpr *tree, ValueIdList &paramsList) const
{
  if ( !tree )  return;

  if (ITM_ITEM_LIST == tree->getOperatorType ())
  {
    gatherParamValueIds (tree->child (0), paramsList);
    gatherParamValueIds (tree->child (1), paramsList);
  }
  else
    paramsList.insert(tree->getValueId());
} // RelRoutine::gatherParamValueIds

void ProxyFunc::createProxyFuncTableDesc(BindWA *bindWA, CorrName &corrName)
{
  // Map column definitions into a TrafDesc
  TrafDesc *tableDesc = createVirtualTableDesc();

  // Map the TrafDesc into an NATable. This will also add an
  // NATable entry into the bindWA's NATableDB.
  NATable *naTable =
    bindWA->getNATable(corrName, FALSE /*catmanUsages*/, tableDesc);
  if (bindWA->errStatus())
    return;

  // Allocate a TableDesc and attach it to this RelExpr instance
  setTableDesc(bindWA->createTableDesc(naTable, corrName));
  if (bindWA->errStatus())
    return;

  // Allocate a RETDesc and attach it to this and the BindScope
  setRETDesc(new (bindWA->wHeap()) RETDesc(bindWA, getTableDesc()));
  bindWA->getCurrentScope()->setRETDesc(getRETDesc());
}


RelExpr *ProxyFunc::bindNode(BindWA *bindWA)
{
  // This method now serves as a common bind node for SPProxy and 
  // ExtractSource classes, where we before had SPProxyFunc::bindNode()
  // and ExtractSource::bindNode().

  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  // Bind the child nodes
  bindChildren(bindWA);
  if (bindWA->errStatus())
    return this;

  // Declare a correlation name that is unique within this query
  switch (getOperatorType())
  {
    case REL_EXTRACT_SOURCE:
      virtualTableName_ = "EXTRACT_SOURCE_";
      break;
    case REL_SP_PROXY:
      virtualTableName_ = "SP_RESULT_SET_";
      break;
    default:
         CMPASSERT(0);
      break;
  }

  virtualTableName_ += bindWA->fabricateUniqueName();
  CorrName corrName(getVirtualTableName());
  corrName.setSpecialType(ExtendedQualName::VIRTUAL_TABLE);
  
  createProxyFuncTableDesc(bindWA, corrName);
  if (bindWA->errStatus())
    return this;

  // Bind the base class
  RelExpr *boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus())
    return boundExpr;

  // Assign the set of columns that belong to the virtual table
  // as the output values that can be produced by this node.
  getGroupAttr()->addCharacteristicOutputs(getTableDesc()->getColumnList());

  return boundExpr;

} // ProxyFunc::bindNode()

RelExpr *TableMappingUDF::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
    {
      bindWA->getCurrentScope()->setRETDesc(getRETDesc());
      return this;
    }

  // Create NARoutine object (no caching for TMUDF)
  NARoutine *tmudfRoutine =NULL;
  CorrName& tmfuncName = getUserTableName();
  tmfuncName.setSpecialType(ExtendedQualName::VIRTUAL_TABLE);

  
  QualifiedName name = getRoutineName();
  const SchemaName &defaultSchema =
    bindWA->getSchemaDB ()->getDefaultSchema();
  name.applyDefaults(defaultSchema);
  setRoutineName(name);

  // Return an error if an unsupported catalog is being used.
  if ((NOT name.isSeabase()) && (NOT name.isHive()))
      {
	*CmpCommon::diags()
	  << DgSqlCode(-1002)
	  << DgCatalogName(name.getCatalogName());
	
	bindWA->setErrStatus();
	return NULL;
      }

  Lng32 diagsMark = CmpCommon::diags()->mark();
  NABoolean errStatus = bindWA->errStatus();

  tmudfRoutine = getRoutineMetadata(name, tmfuncName, bindWA);
  if (tmudfRoutine == NULL)
    {
      // this could be a predefined TMUDF, which is not
      // recorded in the metadata at this time
      OperatorTypeEnum opType =
        PredefinedTableMappingFunction::nameIsAPredefinedTMF(tmfuncName);

      if (opType != REL_ANY_TABLE_MAPPING_UDF)
        {
          // yes, this is a predefined TMUDF
          PredefinedTableMappingFunction *result;

          // discard the errors from the failed name lookup
          CmpCommon::diags()->rewind(diagsMark);
          if (!errStatus)
            bindWA->resetErrStatus();

          // create a new RelExpr
          result = new(bindWA->wHeap())
            PredefinedTableMappingFunction(
                 getArity(),
                 tmfuncName,
                 const_cast<ItemExpr *>(getProcAllParamsTree()),
                 opType);

          // copy data members of the base classes
          TableMappingUDF::copyTopNode(result);

          // set children
          result->setArity(getArity());
          for (int i=0; i<getArity(); i++)
            result->child(i) = child(i);

          if (opType == REL_TABLE_MAPPING_BUILTIN_LOG_READER ||
              opType == REL_TABLE_MAPPING_BUILTIN_JDBC)
            {
              // The event log reader and JDBC TMUDFs are being migrated
              // to real UDFs, use of the predefined UDFs is deprecated.
              // Issue a warning. Eventually these predefined functions
              // will be removed.
              (*CmpCommon::diags())
                << DgSqlCode(4323)
                << DgString0(tmfuncName.getExposedNameAsAnsiString());
            }

          // Abandon the current node and return the bound new node.
          // Next time it will reach this method it will call an
          // overloaded getRoutineMetadata() that will succeed.
          return result->bindNode(bindWA);
        }

      // getRoutineMetadata has already set the diagnostics area
      // and set the error status
      CMPASSERT(bindWA->errStatus());
      return NULL;
    }

  // Bind the child nodes.
  bindChildren(bindWA);
  if (bindWA->errStatus())
    return this;

  // Use information from child to populate childInfo_
  NAHeap *heap = CmpCommon::statementHeap();
  for(Int32 i = 0; i < getArity(); i++)
  {
    NAString childName(heap);
    NAColumnArray childColumns(heap) ;
    RETDesc *childRetDesc = child(i)->getRETDesc();
    
    // Get Name
    LIST(CorrName*) nameList(STMTHEAP);
    childRetDesc->getXTNM().dumpKeys(nameList);
    if (nameList.entries() == 1)
    {
      childName = (nameList[0])->getExposedNameAsString();
    }
    else
    {
      childName = "_inputTable" + bindWA->fabricateUniqueName();
    }
    
    // ask for histograms of all child outputs, since we don't
    // know what the UDF will need and what predicates exist
    // on passthru columns of the UDF
    bindWA->getCurrentScope()->context()->inWhereClause() = TRUE;

    // Get NAColumns
    
    CollIndex numChildCols = childRetDesc->getColumnList()->entries();
    for(CollIndex j=0; j < numChildCols; j++)
    {
      const NAType &childColType = childRetDesc->getType(j);
      const NAType *adjustedChildColType = &childColType;
      NAColumn * childCol = NULL;

      if (childColType.getSimpleTypeName() == "NUMERIC" &&
          getBinaryStorageSize(childColType.getPrecision()) !=
          childColType.getNominalSize())
        {
          // In the optimizer code, we may choose different storage
          // sizes for the same type, for example a NUMERIC(1,0)
          // sometimes has one byte, sometimes 2 bytes of storage. For
          // examples, see NumericType::synthesizeType() and CQD
          // TRAF_CREATE_TINYINT_LITERAL.

          // In the TMUDF code, on the other hand, we compute the
          // storage size from the precision. So, make sure we follow
          // the TMUDF rules here, when we describe its input table
          adjustedChildColType = new(heap) SQLNumeric(heap,
               getBinaryStorageSize(childColType.getPrecision()),
               childColType.getPrecision(),
               childColType.getScale(),
               ((const NumericType &) childColType).isSigned(),
               childColType.supportsSQLnull());
        }

      childCol = new (heap) NAColumn(
        childRetDesc->getColRefNameObj(j).getColName().data(),
        j,
        adjustedChildColType->newCopy(heap),
        heap);
      childColumns.insert(childCol);

      bindWA->markAsReferencedColumn(childRetDesc->getValueId(j));
    }
    bindWA->getCurrentScope()->context()->inWhereClause() = FALSE;

    // get child root
    CMPASSERT(child(i)->getOperator().match(REL_ROOT) ||
      child(i)->getOperator().match(REL_RENAME_TABLE));
    RelRoot * myChild;
    if (child(i)->getOperator().match(REL_RENAME_TABLE))
      myChild = (RelRoot *) (child(i)->child(0).getPtr());
    else
      myChild = (RelRoot *) child(i).getPtr();

    // output vidList from child RetDesc, 
    // can also get from child Root compExpr
    ValueIdList vidList;
    childRetDesc->getValueIdList(vidList, USER_COLUMN);
    ValueIdSet childPartition(myChild->partitionArrangement());
    ValueIdList childOrder(myChild->reqdOrder());

    // request multi-column histograms for the PARTITION BY columns
    bindWA->getCurrentScope()->context()->inGroupByClause() = TRUE;

    // replace 1-based ordinals in the child's partition by / order by with
    // actual columns
    for (ValueId cp=childPartition.init();
         childPartition.next(cp);
         childPartition.advance(cp))
      {
        NABoolean negate;
        ConstValue *cv = cp.getItemExpr()->castToConstValue(negate);

        if (cv &&
            cv->canGetExactNumericValue())
        {
          Lng32 scale = 0;
          Int64 ordinal = cv->getExactNumericValue(scale);

          if (!negate && scale == 0 && ordinal >= 1 && ordinal <= vidList.entries())
            {
              // remove this ValueId from the set and add the corresponding
              // column value. Note that this won't cause problems with the
              // iterator through the set, since we don't need to apply
              // this conversion on the new element we are inserting
              childPartition -= cp;
              childPartition += vidList[ordinal-1];
            }
          else
            {
              *CmpCommon::diags()
                << DgSqlCode(-11154)
                << DgInt0(ordinal)
                << DgString0("PARTITION BY")
                << DgInt1(vidList.entries());
              bindWA->setErrStatus();
              return NULL;
            }
        }
        bindWA->markAsReferencedColumn(cp);
      }
    bindWA->getCurrentScope()->context()->inGroupByClause() = FALSE;

    for (CollIndex co=0; co<childOrder.entries(); co++)
      {
        NABoolean negate;
        ItemExpr *ie = childOrder[co].getItemExpr();
        ConstValue *cv = NULL;

        if (ie->getOperatorType() == ITM_INVERSE)
          ie = ie->child(0);
        cv = ie->castToConstValue(negate);

        if (cv &&
            cv->canGetExactNumericValue())
        {
          Lng32 scale = 0;
          Int64 ordinal = cv->getExactNumericValue(scale);

          // replace the const value with the actual column
          if (!negate && scale == 0 && ordinal >= 1 && ordinal <= vidList.entries())
            if (ie == childOrder[co].getItemExpr())
              {
                // ascending order
                childOrder[co] = vidList[ordinal-1];
              }
            else
              {
                // desc order, need to add an InverseOrder on top
                ItemExpr *inv = new(bindWA->wHeap()) InverseOrder(
                     vidList[ordinal-1].getItemExpr());
                inv->synthTypeAndValueId();
                childOrder[co] = inv->getValueId();
              }
          else
            {
              *CmpCommon::diags()
                << DgSqlCode(-11154)
                << DgInt0(ordinal)
                << DgString0("ORDER BY")
                << DgInt1(vidList.entries());
              bindWA->setErrStatus();
              return NULL;
            }
        }
      }

    TableMappingUDFChildInfo * cInfo = new (heap) TableMappingUDFChildInfo(
      childName, 
      childColumns,
      myChild->getPartReqType(), 
      childPartition,
      childOrder,
      vidList);
    childInfo_.insert(cInfo);
  }

  RoutineDesc *tmudfRoutineDesc = new (bindWA->wHeap()) RoutineDesc(bindWA, tmudfRoutine); 
  if (tmudfRoutineDesc == NULL ||  bindWA->errStatus ())
  {
    // Error
    bindWA->setBindingCall (FALSE);
    bindWA->setErrStatus ();
    return this;
  }
  setRoutineDesc(tmudfRoutineDesc);
  // xcnm will be empty because the routineDesc does not contain any 
  // output columns yet
  RETDesc *rDesc = new (bindWA->wHeap()) RETDesc(bindWA, tmudfRoutineDesc);
  bindWA->getCurrentScope()->setRETDesc(rDesc);
  setRETDesc(rDesc);

  dllInteraction_ = new (bindWA->wHeap()) TMUDFDllInteraction();

  // ValueIDList of the actual input parameters 
  // (tmudfRoutine has formal parameters)
  if (getProcAllParamsTree() && (getProcAllParamsVids().isEmpty() == TRUE)) 
  {
      ((ItemExpr *)getProcAllParamsTree())->convertToValueIdList(
		  getProcAllParamsVids(), bindWA, ITM_ITEM_LIST);
      if (bindWA->errStatus()) return NULL;
      
      // Clear the Tree since we now have gotten vids for all the parameters.
      setProcAllParamsTree(NULL);
  }
  getProcInputParamsVids().insert(getProcAllParamsVids());

  // invoke the optional UDF compiler interface or a default
  // implementation to validate scalar inputs and produce a list of
  // output columns

  NABoolean status = dllInteraction_->describeParamsAndMaxOutputs(this, bindWA);
  if (!status)
    {
      bindWA->setErrStatus();
      return NULL;
    }

  checkAndCoerceScalarInputParamTypes(bindWA);
  if (bindWA->errStatus())
    return NULL;

  createOutputVids(bindWA);
  if (bindWA->errStatus())
    return NULL;

  // create a ValueIdMap that allows us to translate
  // output columns that are passed through back to
  // input columns (outputs of the child), this can
  // be used to push down predicates, translate
  // required order and partitioning, etc.
  status = dllInteraction_->createOutputInputColumnMap(
       this,
       udfOutputToChildInputMap_);
  if (!status)
    {
      bindWA->setErrStatus();
      return NULL;
    }

  // add the routine to the UdrStoiList.  The UdrStoi list is used
  // to check valid privileges
  LIST(OptUdrOpenInfo *) udrList = bindWA->getUdrStoiList ();
  ULng32 numUdrs = udrList.entries();
  NABoolean udrReferenced = FALSE;

  // See if UDR already exists
  for (ULng32 stoiIndex = 0; stoiIndex < numUdrs; stoiIndex++)
  {
    if ( 0 ==
         udrList[stoiIndex]->getUdrName().compareTo(
                           getRoutineName().getQualifiedNameAsAnsiString()
                                                  )
       )
    {
      udrReferenced = TRUE;
      break;
    }
  }

  // UDR has not been defined, go ahead an add one
  if ( FALSE == udrReferenced )
  {
    SqlTableOpenInfo *udrStoi = new (bindWA->wHeap ())SqlTableOpenInfo ();
    udrStoi->setAnsiName ( convertNAString(
                           getRoutineName().getQualifiedNameAsAnsiString(),
                           bindWA->wHeap ())
                         );

    OptUdrOpenInfo *udrOpenInfo = new (bindWA->wHeap ())
      OptUdrOpenInfo( udrStoi
                    , getRoutineName().getQualifiedNameAsAnsiString()
                    , (NARoutine *)getNARoutine()
                    );
    bindWA->getUdrStoiList().insert(udrOpenInfo);
  }

  RelExpr *boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus())
    return NULL;
  return boundExpr;
}

RelExpr * FastExtract::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }


  // check validity of target location
  if (getTargetType() == FILE)
  {
    char reasonMsg[256];
    NABoolean raiseError = FALSE;
    if ((unsigned char)(getTargetName().data()[0]) != SLASH_C)
    {
      raiseError = TRUE;
      sprintf(reasonMsg,"Relative path name was used");
    }
    else if (getTargetName().length() > 512)
    {
      raiseError = TRUE;
      sprintf(reasonMsg,"Length exceeds 512 characters");
    }
    else
    {
      char * sqroot = getenv("TRAF_HOME");
      if (sqroot && (! CmpCommon::context()->getSqlmxRegress()) &&
          (strncmp(sqroot, getTargetName().data(),strlen(sqroot)) == 0))
      {
        raiseError = TRUE;
        sprintf(reasonMsg,"Database system directory was used");
      }
    }
    if (raiseError  && strncmp(getTargetName().data(),"hdfs://",7) != 0 )
    {
      *CmpCommon::diags() << DgSqlCode(-4378) << DgString0(reasonMsg) ;
      bindWA->setErrStatus();
      return NULL;
    }
  }


  if (getDelimiter().length() == 0)
  {
    delimiter_ = ActiveSchemaDB()->getDefaults().getValue(TRAF_UNLOAD_DEF_DELIMITER);
  }

  // if inserting into a hive table and an explicit null string was
  // not specified in the unload command, and the target table has a user
  // specified null format string, then use it.
  if ((isHiveInsert()) &&
      (hiveTableDesc_ && hiveTableDesc_->getNATable() && 
       hiveTableDesc_->getNATable()->getClusteringIndex()) &&
      (NOT nullStringSpec_))
    {
      const HHDFSTableStats* hTabStats = 
        hiveTableDesc_->getNATable()->getClusteringIndex()->getHHDFSTableStats();

      if (hTabStats->getNullFormat())
        {
          nullString_ = hTabStats->getNullFormat();
          nullStringSpec_ = TRUE;
        }
    }

  // if an explicit or user specified null format was not used, then
  // use the default null string.
  if (NOT nullStringSpec_) 
    {
      nullString_ = HIVE_DEFAULT_NULL_STRING;
    }
  
  if (getRecordSeparator().length() == 0)
  {
    recordSeparator_ = ActiveSchemaDB()->getDefaults().getValue(TRAF_UNLOAD_DEF_RECORD_SEPARATOR);
  }


  if (!isHiveInsert())
  {
    bindWA->setIsFastExtract();
  }
  // Bind the child nodes.
  bindChildren(bindWA);
  if (bindWA->errStatus())
    return this;

  // Use information from child to populate childInfo_
  NAHeap *heap = CmpCommon::statementHeap();

  RETDesc *childRETDesc = child(0)->getRETDesc();
  // output vidList from child RetDesc,
  // can also get from child Root compExpr
  ValueIdList vidList;
  childRETDesc->getValueIdList(vidList, USER_COLUMN);

  if (isHiveInsert())
    {
      // validate number of columns and column types of the select list
      ValueIdList tgtCols;

      hiveTableDesc_->getUserColumnList(tgtCols);

      if (vidList.entries() != tgtCols.entries())
        {
          // 4023 degree of row value constructor must equal that of target table
          *CmpCommon::diags() << DgSqlCode(-4023)
                              << DgInt0(vidList.entries())
                              << DgInt1(tgtCols.entries());
          bindWA->setErrStatus();
          return NULL;
        }

      // Check that the source and target types are compatible.
      for (CollIndex j=0; j<vidList.entries(); j++)
        {
          Assign *tmpAssign = new(bindWA->wHeap())
            Assign(tgtCols[j].getItemExpr(), vidList[j].getItemExpr());

          if ( CmpCommon::getDefault(ALLOW_IMPLICIT_CHAR_CASTING) == DF_ON )
            tmpAssign->tryToDoImplicitCasting(bindWA);
          const NAType *targetType = tmpAssign->synthesizeType();
          if (!targetType) {
            bindWA->setErrStatus();
            return NULL;
          }
        }
    }
  else 
    {
      NABoolean hasLob = FALSE;
      CollIndex i = 0;
      for (i = 0; (i < vidList.entries() && !hasLob); i++)
	hasLob = vidList[i].getType().isLob();
      if (hasLob) {
	*CmpCommon::diags() << DgSqlCode(-4495) 
			    << DgColumnName(childRETDesc->getColRefNameObj(i).
					    getColRefAsAnsiString());
	bindWA->setErrStatus();
	return NULL;
      }
      
    }
    

  setSelectList(vidList);

  if (includeHeader())
  {
    const ColumnDescList &columnsRET = *(childRETDesc->getColumnList());
    for (CollIndex i = 0; i < columnsRET.entries(); i++)
    {
      if (columnsRET[i]->getHeading())
        header_ += columnsRET[i]->getHeading();
      else if (!(columnsRET[i]->getColRefNameObj().isEmpty()))
        header_ += columnsRET[i]->getColRefNameObj().getColName();
      else
        header_ += "EXPR";

      if (i < (columnsRET.entries() -1))
      {
        header_ += " ";
        header_ += delimiter_;
        header_ += " ";
      }
    }
  }
  else
  {
          header_ = "NO_HEADER" ;
  }

  // no rows are returned from this operator.
  // Allocate an empty RETDesc and attach it to this and the BindScope.
  setRETDesc(new (bindWA->wHeap()) RETDesc(bindWA));

  RelExpr *boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus()) return NULL;
  return boundExpr;
}


RelExpr * ControlRunningQuery::bindNode(BindWA *bindWA)
{
  if (nodeIsBound()) {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }
  //
  // Check to see if user is authorized to control this query.
  //
  if (!isUserAuthorized(bindWA))
     return NULL;

  //
  // Bind the child nodes.
  //
  bindChildren(bindWA);
  if (bindWA->errStatus())
    return this;

  // no rows are returned from this operator. 
  // Allocate an empty RETDesc and attach it to this and the BindScope.
  //
  setRETDesc(new (bindWA->wHeap()) RETDesc(bindWA));

  //
  // Bind the base class.
  //
  RelExpr *boundExpr = bindSelf(bindWA);
  if (bindWA->errStatus()) 
    return boundExpr;


  ValueIdSet ov;
  getPotentialOutputValues(ov);
  getGroupAttr()->addCharacteristicOutputs(ov);

  return boundExpr;
} // ControlRunningQuery::bindNode()


bool ControlRunningQuery::isUserAuthorized(BindWA *bindWA)
{
  bool userHasPriv = false;
  Int32 sessionID = ComUser::getSessionUser();

  // Check to see if the current user owns the query id.
  // This only has to be done for the Cancel query request.
  // This option to check privilege is not available unless
  // the query Id was supplied.
  if ((action_ == Cancel) &&
      (qs_ == ControlQid))
  {
    // The user ID associated with the query is stored in the QID. 
    // To be safe, copy the QID to a character string.
    Int32 qidLen = queryId_.length();
    char *pQid = new (bindWA->wHeap()) char[qidLen+1];
    str_cpy_all(pQid, queryId_.data(), qidLen);
    pQid[qidLen] = '\0';

    // Set up the returned parameters
    // Max username can be (128 * 2) + 2 (delimiters) + 1 (null indicator)
    char username[2 * MAX_USERNAME_LEN + 2 + 1];
    Int64 usernameLen = sizeof(username) - 1;
 
    // Call function to extract the username from the QID
    Int32 retcode = ComSqlId::getSqlQueryIdAttr(ComSqlId::SQLQUERYID_USERNAME,
                                                pQid,
                                                qidLen,
                                                usernameLen,
                                                &username[0]);
    if (retcode == 0)
    {
      // The username stored in the QID is actually the userID preceeded with
      // a "U".  Check for a U and convert the succeeding characters 
      // to integer.  This integer value is compared against the current userID.
      username[usernameLen] = '\0';  
      if (username[0] == 'U')
      {
        Int64 userID = str_atoi(&username[1],usernameLen - 1);  
        if (sessionID == userID || sessionID == ComUser::getRootUserID())
          userHasPriv = true;
      }
      // If userName does not begin with a 'U', ignore and continue
    }
    // If retcode != 0, continue, an invalid QID could be specified which
    // is checked later in the code
  }
  
  // The current user does not own the query, see if the current user has 
  // the correct QUERY privilege.  Code above only supports cancel, but other 
  // checks could be added.  Component checks for all query operations.
  if (!userHasPriv)
  {
    SQLOperation operation;
    switch (ControlRunningQuery::action_)
    {
      case ControlRunningQuery::Suspend:
        operation = SQLOperation::QUERY_SUSPEND;
        break;
      case ControlRunningQuery::Activate:
        operation = SQLOperation::QUERY_ACTIVATE;
        break;
      case ControlRunningQuery::Cancel:
        operation = SQLOperation::QUERY_CANCEL;
        break;
      default:
        operation = SQLOperation::UNKNOWN;
    }
    
    NAString privMDLoc = CmpSeabaseDDL::getSystemCatalogStatic();
    privMDLoc += ".\"";
    privMDLoc += SEABASE_PRIVMGR_SCHEMA;
    privMDLoc += "\"";

    PrivMgrComponentPrivileges componentPriv(
      privMDLoc.data(),CmpCommon::diags());

    userHasPriv = componentPriv.hasSQLPriv(sessionID,operation,true);
    
    if (!userHasPriv)
    {
      // ANSI requests a special SqlState for cancel requests
      if (ControlRunningQuery::action_ == ControlRunningQuery::Cancel)
        *CmpCommon::diags() << DgSqlCode(-8029);
      else
        *CmpCommon::diags() << DgSqlCode(-1017);
      bindWA->setErrStatus();
    }
    
    if (bindWA->errStatus())
      return false;
  }
  return true;
  
}// ControlRunningQuery::isUserAuthorized()

RelExpr * CommonSubExprRef::bindNode(BindWA *bindWA)
{
  if (nodeIsBound()) {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }

  CSEInfo *info = CmpCommon::statement()->getCSEInfo(internalName_);
  CommonSubExprRef *parentCSE = bindWA->inCSE();

  DCMPASSERT(info);

  // eliminate any CommonSubExprRef nodes that are not truly common,
  // i.e. those that are referenced only once
  if (info->getNumConsumers() <= 1)
    {
      info->eliminate();
      return child(0).getPtr()->bindNode(bindWA);
    }

  bindWA->setInCSE(this);

  // establish the parent/child relationship
  addParentRef(parentCSE);

  bindChildren(bindWA);
  if (bindWA->errStatus())
    return this;

  // we know that our child is a RenameTable (same name as this CSE,
  // whose child is a RelRoot, defining the CTE. Copy the bound select
  // list of the CTE.
  CMPASSERT(child(0)->getOperatorType() == REL_RENAME_TABLE &&
            child(0)->child(0)->getOperatorType() == REL_ROOT);
  columnList_ = static_cast<RelRoot *>(child(0)->child(0).getPtr())->compExpr();

  bindWA->setInCSE(parentCSE);

  return bindSelf(bindWA);
}

RelExpr * OSIMControl::bindNode(BindWA *bindWA)
{
  if (nodeIsBound())
  {
    bindWA->getCurrentScope()->setRETDesc(getRETDesc());
    return this;
  }
  //Create OptimizerSimulator if this is called first time.
  if(!CURRCONTEXT_OPTSIMULATOR)
      CURRCONTEXT_OPTSIMULATOR = new(CTXTHEAP) OptimizerSimulator(CTXTHEAP);
      
  //in respond to force option of osim load, 
  //e.g. osim load from '/xxx/xxx/osim-dir', force
  //if true, when loading osim tables/views/indexes
  //existing objects with same qualified name 
  //will be droped first
  CURRCONTEXT_OPTSIMULATOR->setForceLoad(isForceLoad());
  //Set OSIM mode
  if(!CURRCONTEXT_OPTSIMULATOR->setOsimModeAndLogDir(targetMode_, osimLocalDir_.data()))
  {
      bindWA->setErrStatus();
      return this;
  }

  return ControlAbstractClass::bindNode(bindWA);
}

