/**********************************************************************
// @@@ 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:         GenPreCode.C
 * Description:  Fixes up the query tree before code generation.
 *               This is the post-opt and pre-gen stage.
 * Created:      4/15/95
 * Language:     C++
 *
 *
 *****************************************************************************
 */

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

#include "Platform.h"
#include <math.h>
#include "OperTypeEnum.h"

#include "Sqlcomp.h"
#include "GroupAttr.h"
#include "AllRelExpr.h"
#include "RelPackedRows.h"
#include "Generator.h"
#include "GenExpGenerator.h"
#include "dfs2rec.h"
#include "vegrewritepairs.h"
#include "exp_clause_derived.h"
#include "keycolumns.h"
#include "ValueDesc.h"
#include "BindWA.h"
#include "TriggerDB.h"
#include "Cost.h"
#include "CostMethod.h"
#include "ItmFlowControlFunction.h"
#include "UdfDllInteraction.h"
#include "StmtDDLNode.h"

#include "NATable.h"
#include "NumericType.h"

#include "CmpStatement.h"
#include "OptimizerSimulator.h"
#include "ItemFunc.h"
#include "ControlDB.h"
#include "CmpSeabaseDDL.h"
#include "NAExecTrans.h"
#include "exp_function.h"
#include "SqlParserGlobals.h"      // must be last #include

extern ItemExpr * buildComparisonPred (	ItemExpr *, ItemExpr *, ItemExpr *,
					OperatorTypeEnum,
					NABoolean specialNulls=FALSE //++MV - Irena
				      );


// -----------------------------------------------------------------------
// generateKeyExpr()
//
// This method is used by the code generator for building expressions
// that are of the form <key column> = <value> for each key column.
//
// Parameters:
//
// const ValueIdSet & externalInputs
//    IN : The set of values that are available here and can be
//         used for replacing any wildcards that appear in the
//         listOfKeyValues.
//
// const ValueIdList & listOfKeyColumns
//    IN : A read-only reference to the list of key columns
//         corresponding to which certain key values have
//         been chosen.
//
// const ValueIdList & listOfKeyValues
//    IN : A read-only reference to a list of key values that
//         are chosen for the corresponding listOfKeyColumns.
//         Values for missing key columns have already been
//         computed and supplied in this list.
//
// ValueIdList & listOfKeyExpr
//    OUT: An assignment expression of the form <key column> = <value>
//         for each key column.
//
// -----------------------------------------------------------------------
static void generateKeyExpr(const ValueIdSet & externalInputs,
			    const ValueIdList & listOfKeyColumns,
			    const ValueIdList & listOfKeyValues,
                            ValueIdList & listOfKeyExpr,
			    Generator* generator,
                            NABoolean replicatePredicates = FALSE)
  {
  ItemExpr * keyExpr;
  CollIndex keyCount = listOfKeyColumns.entries();

  for (CollIndex keyNum = 0; keyNum < keyCount; keyNum++)
    {
      // Build the assignment expression.
      ItemExpr *ieKeyVal = listOfKeyValues[keyNum].getItemExpr()
	->replaceVEGExpressions(externalInputs, externalInputs,
                                FALSE, NULL, replicatePredicates);
      ItemExpr *ieKeyCol = listOfKeyColumns[keyNum].getItemExpr();
      ValueId KeyColId = ieKeyCol->getValueId();

      keyExpr = new(generator->wHeap()) BiRelat(ITM_EQUAL,
						ieKeyCol,
						ieKeyVal);

      // Synthesize its type for and assign a ValueId to it.
      keyExpr->synthTypeAndValueId();

      // INsert it in the list of key expressions
      listOfKeyExpr.insertAt(keyNum, keyExpr->getValueId());
    } // end For Loop

} // static generateKeyExpr()

static NABoolean processConstHBaseKeys(Generator * generator,
                                       RelExpr *relExpr,
                                       const SearchKey *skey,
                                       const IndexDesc *idesc,
                                       const ValueIdSet &executorPreds,
                                       NAList<HbaseSearchKey*> &mySearchKeys,
                                       ListOfUniqueRows &listOfUpdUniqueRows,
                                       ListOfRangeRows  &listOfUpdSubsetRows)
{
  if (! skey)
    return TRUE;

  // convert built-in search key to entries with constants, if possible
  if (skey->areAllKeysConstants(TRUE))
    {
      ValueIdSet nonKeyColumnSet;
      idesc->getNonKeyColumnSet(nonKeyColumnSet);

      // seed keyPreds with only the full key predicate from skey
      ValueIdSet keyPreds = skey->getFullKeyPredicates();

      // include executorPreds and selection predicates 
      // but exclude the full key predicates.
      ValueIdSet exePreds;

      exePreds += executorPreds;
      exePreds += relExpr->getSelectionPred();
      exePreds.subtractSet(keyPreds);

      ValueId falseConst = NULL_VALUE_ID;
      if (exePreds.containsFalseConstant(falseConst))
        keyPreds += falseConst;

      HbaseSearchKey::makeHBaseSearchKeys(
           skey,
           skey->getIndexDesc()->getIndexKey(),
           skey->getIndexDesc()->getOrderOfKeyValues(),
           relExpr->getGroupAttr()->getCharacteristicInputs(),
           TRUE, /* forward scan */
           keyPreds,
           nonKeyColumnSet,
           idesc,
           relExpr->getGroupAttr()->getCharacteristicOutputs(),
           mySearchKeys);

      // Include any remaining key predicates that have not been 
      // picked up (to be used as the HBase search keys).
      exePreds += keyPreds;

      if(falseConst != NULL_VALUE_ID)
      {
	for (CollIndex i = 0; i<mySearchKeys.entries(); i++ ) 
        {
          HbaseSearchKey* searchKey = mySearchKeys[i];
	  searchKey->setIsFalsePred(TRUE);
	}
      }

      TableDesc *tdesc = NULL;
      if (mySearchKeys.entries()>0)
        {
          switch (relExpr->getOperatorType())
            {
            case REL_HBASE_ACCESS:
              {
                HbaseAccess *hba = static_cast<HbaseAccess *>(relExpr);
                hba->setSearchKey(NULL);
                hba->executorPred() = exePreds;
                tdesc = hba->getTableDesc();
              }
              break;

            case REL_HBASE_DELETE:
              {
                HbaseDelete *hbd = static_cast<HbaseDelete *>(relExpr);
                hbd->setSearchKey(NULL);
                hbd->beginKeyPred().clear();
                hbd->endKeyPred().clear();
                hbd->executorPred() = exePreds;
                tdesc = hbd->getTableDesc();
              }
              break;

            case REL_HBASE_UPDATE:
              {
                HbaseUpdate *hbu = static_cast<HbaseUpdate *>(relExpr);
                hbu->setSearchKey(NULL);
                hbu->beginKeyPred().clear();
                hbu->endKeyPred().clear();
                hbu->executorPred() = exePreds;
                tdesc = hbu->getTableDesc();
              }
              break;

            default:
              CMPASSERT(tdesc); // unsupported operator type
              break;
            }  // switch
          relExpr->selectionPred().clear();
        }

      if (HbaseAccess::processSQHbaseKeyPreds(generator, 
					      mySearchKeys,
					      listOfUpdUniqueRows,
					      listOfUpdSubsetRows))
	return FALSE;

    } // key uses all constants
  return TRUE;
}

//
// replaceVEGExpressions1() - a helper routine for ItemExpr::replaceVEGExpressions()
//
// NOTE: The code in this routine came from the previous version of 
//       ItemExpr::replaceVEGExpressions().   It has been pulled out
//       into a separate routine so that the C++ compiler will produce
//       code that needs signficantly less stack space for the 
//       recursive ItemExpr::replaceVEGExpressions() routine.
//
ItemExpr * ItemExpr::replaceVEGExpressions1( VEGRewritePairs* lookup )
{
   // see if this expression is already in there
   ValueId rewritten;
   if (lookup->getRewritten(rewritten /* out */, getValueId()))
   {
     if (rewritten == NULL_VALUE_ID)
       return NULL;
     else
       return rewritten.getItemExpr();
   }
   return (ItemExpr *)( (char *)(NULL) -1 ) ;
}

//
// replaceVEGExpressions2() - a helper routine for ItemExpr::replaceVEGExpressions()
//
// NOTE: The code in this routine came from the previous version of
//       ItemExpr::replaceVEGExpressions().   It has been pulled out
//       into a separate routine so that the C++ compiler will produce
//       code that needs signficantly less stack space for the
//       recursive ItemExpr::replaceVEGExpressions() routine.
//
void ItemExpr::replaceVEGExpressions2( Int32 index 
                                     , const ValueIdSet& availableValues
                                     , const ValueIdSet& inputValues
                                     ,       ValueIdSet& currAvailableValues
                                     , const GroupAttributes * left_ga
                                     , const GroupAttributes * right_ga
                                     )
{
   // If we have asked that the EquiPredicate resolve 
   // each child of the equipred by available values from the 
   // respectively input GAs, make sure we pick the right one.

   // First we find out what GA covers the current EquiPred child
   // we are processing (0 or 1), and pick the one that covers, unless
   // both GAs do. If both GAs cover, the just make sure we pick a 
   // different one for each child. The hash join will later fix up
   // the predicate expression to match its children.
   // If none of the GAs covers, we have a problem...

   // This fix was put in to solve solution: 10-100722-1962

   ValueIdSet dummy;

   NABoolean leftGaCovers = left_ga->covers(child(index)->getValueId(),
                                             inputValues,
                                             dummy);
   NABoolean rightGaCovers = right_ga->covers(child(index)->getValueId(),
                                             inputValues,
                                             dummy);

   if (leftGaCovers == FALSE && rightGaCovers == FALSE)
     {
       // for the moment it is assumed that this code is only
       // executed for hash and merge joins, and in general each 
       // side of the expression should be coverd by a child.
       // So if we have neither, we have a problem ..
       cout << "Unable to pick GA to use: " << getArity() << endl;
       CMPASSERT(FALSE);
     }
   else
     {
       const GroupAttributes *coveringGa =  NULL;
       currAvailableValues.clear();
       currAvailableValues += inputValues;
       if (leftGaCovers && rightGaCovers)
         coveringGa = (index == 0 ? left_ga : right_ga);
       else
         coveringGa = (leftGaCovers ? left_ga : right_ga);

       currAvailableValues += coveringGa->getCharacteristicOutputs();
       
     }
}

// -----------------------------------------------------------------------
// ItemExpr::replaceVEGExpressions()
// It performs a top-down, left-to-right tree walk in the ItemExpr tree
// and expands any wildcards (VEGReference or VEGPredicate expressions)
// by replacing them with an expression that belongs to the
// availableValues.
// IF isKeyPredicate is TRUE then the ItemExpr is a KeyPredicate:
// A KeyPredicate is of a restricted form. If we are here it is
// because the predicate is a KeyPredicate. Then, it must satisfy
// very specific characteristics (see Key::isAKeyPredicate(...))
// for instance, one of its sides must be a key column
// This method *guarantees* that a key predicate will be
// generated from the rewritten predicate (i.e. we avoid
// cases like VegRef{T1.A, 2} > 7 being generated like
// 2 > 7 when T1.A is a key column.
// -----------------------------------------------------------------------
ItemExpr * ItemExpr::replaceVEGExpressions
                        (const ValueIdSet& availableValues,
                         const ValueIdSet& inputValues,
			 NABoolean thisIsAnMdamKeyPredicate,
			 VEGRewritePairs* lookup,
			 NABoolean replicateExpression,
                         const ValueIdSet * joinInputAndPotentialOutput,
                         const IndexDesc * iDesc,
                         const GroupAttributes * left_ga,
                         const GroupAttributes * right_ga)
{
  // ---------------------------------------------------------------------
  // If this expression has already been resolved because it exists in
  // availableValues, the replacement of VEGReferences is not required.
  // ---------------------------------------------------------------------
  if (availableValues.contains(getValueId()))
    return this;  // terminate processing

  ItemExpr* iePtr = this;

  if (lookup && replicateExpression)  // if lookup table is present
    {
       ItemExpr* tmpIePtr = ItemExpr::replaceVEGExpressions1( lookup ) ;
       if ( tmpIePtr != (ItemExpr *)( (char *)(NULL) -1 ) )
          return tmpIePtr ;
    };

  if (replicateExpression)
    iePtr = copyTopNode(0, CmpCommon::statementHeap());
  // virtual copy constructor

  // -----------------------------------------------------------------------
  // In the case of mdam key predicates we need to be careful with
  // binary operators whose child is a VegRef that contains both a
  // key column and a constant because the rewrite logic for VEGRef
  // favors the generation of constants over other ItemExprs. In
  // MDAM we *need* to generate the key column and not the constant.
  // With the gated logic below we ensure this.
  // -----------------------------------------------------------------------

  if (thisIsAnMdamKeyPredicate)
    {

#if DEBUG
      // at the moment it is assumed the left and right ga's are only
      // used for hash/merge joins equijoin predicates and with the
      // mdamKeyPredicate flag turned off. If this assumption is no longer
      // true we need to add some additional code in this "if" clause.
      GENASSERT(left_ga == NULL && right_ga == NULL);
#endif

      switch (getArity())
	{
	case 0: // const, VEGRef, and VEGPred have arity 0
	  break; // If it reached here it means that
	  // the ItemExpr does not need to do any special
	  // processing for this operator (i.e. a constant)
	  // VEG predicates should never reach here
	case 1: // Example: T1.A IS NULL
	  {
	    ItemExpr *newChild;
	    // the child must be a key column:
	    newChild =
	      child(0)->replaceVEGExpressions(availableValues
					      ,inputValues
					      ,TRUE // no constants!
					      ,lookup
					      ,replicateExpression
                                              ,joinInputAndPotentialOutput
                                       ,iDesc
					      );
	    if (newChild != iePtr->child(0))
	      {
		if (replicateExpression)
		  iePtr = iePtr->copyTopNode(NULL, CmpCommon::statementHeap());
		iePtr->child(0) = newChild;
	      }
	  }
	  break;
	case 2:
	case 3:
	  {

	    // Rewrite children (one of them MUST be a key column, the
	    // other MUST be a constant or a host var)
	    ItemExpr
	      *leftChild = NULL,
	      *rightChild = NULL,
	      *thirdChild = NULL;
	    OperatorTypeEnum newOperType = getOperatorType();

	    if ((child(0)->getOperatorType() == ITM_VEG_REFERENCE)
		OR
		(child(1)->getOperatorType() == ITM_VEG_REFERENCE))
	      {

		//---------------------------------------------------------
		// Assume we have an expression of
                // the form VegRef{T1.A, 2} > 7
		//------------------------------------------------------

		// Force the generation of a key column by
		// telling replacevegexprs not to generate them:
		leftChild =
		  child(0)->replaceVEGExpressions(availableValues
						  ,inputValues
						  ,TRUE // want key col
						  ,lookup
						  ,replicateExpression
                                                  ,joinInputAndPotentialOutput
                                     ,iDesc
                                                  );
                // generate a constant in this branch
		rightChild =
		  child(1)->replaceVEGExpressions(availableValues
						  ,inputValues
						  ,FALSE // want constant
						  ,lookup
						  ,replicateExpression
                                                  ,joinInputAndPotentialOutput
                                                  ,iDesc
                                                  );

		// However, the above will fail if the predicate is
		// of the form
                // 7 < VegRef{T1.A,2}, thus, if it failed, redrive with
		// the roles reversed:
		if (leftChild == NULL OR rightChild == NULL)
		  {
		    leftChild =
		      child(1)->replaceVEGExpressions(availableValues
						      ,inputValues
						      ,TRUE // want constant
						      ,lookup
						      ,replicateExpression
                                                      ,joinInputAndPotentialOutput
                                         ,iDesc
                                                      );
		    rightChild =
		      child(0)->replaceVEGExpressions(availableValues
						      ,inputValues
						      ,FALSE // want key col
						      ,lookup
						      ,replicateExpression
                                                      ,joinInputAndPotentialOutput
                                         ,iDesc
                                                      );

		    // We have reversed the operands, reverse
		    // the operator if it is a greater/eq BiRelat operator:
		    switch(getOperatorType())
		      {
		      case ITM_LESS:
		      case ITM_LESS_EQ:
		      case ITM_GREATER:
		      case ITM_GREATER_EQ:
			// need to reverse!
			newOperType =
			  ((BiRelat*)iePtr)->getReverseOperatorType();
			break;
		      }

		  } // if need to reverse operands

		// now we must have succeeded!
		CMPASSERT(leftChild != NULL && rightChild != NULL);

	      } // if one of the children of the operator is a reference
	    else
	      {
		// No children are references, normal rewrite:

		leftChild =
		  child(0)->replaceVEGExpressions(availableValues,
						  inputValues,
						  FALSE, // constants OK
						  lookup,
						  replicateExpression,
                                      joinInputAndPotentialOutput,
                                      iDesc);
		rightChild =
		  child(1)->replaceVEGExpressions(availableValues,
						  inputValues,
						  FALSE, // constants OK
						  lookup,
						  replicateExpression,
                                      joinInputAndPotentialOutput,
                                      iDesc);

		CMPASSERT(leftChild != NULL && rightChild != NULL);

	      }

	    if (getArity() == 3)
	      { // rewrite the exclusion part of the PA key predicate:
		thirdChild =
		  child(2)->replaceVEGExpressions(availableValues,
						  inputValues,
						  thisIsAnMdamKeyPredicate,
						  lookup,
						  replicateExpression,
                                      joinInputAndPotentialOutput,
                                      iDesc);
	      }

	    if (iePtr->child(0) != (void *)leftChild OR
		iePtr->child(1) != (void *)rightChild OR
		(thirdChild AND iePtr->child(2) != (void *)thirdChild) OR
		iePtr->getOperatorType() != newOperType)
	      {
		// we have to change data members, make a copy of the
		// node if other users may share this node
		if (replicateExpression)
		  iePtr = iePtr->copyTopNode(NULL, CmpCommon::statementHeap());

		// Set the left and right children of the iePtr
		// to their rewritten nodes:
		// $$ What happens to all those nodes that were
		// $$ replicated and the rewrite failed?
		iePtr->child(0) = leftChild;
		iePtr->child(1) = rightChild;
		if (thirdChild)
		  iePtr->child(2) = thirdChild;
                iePtr->setOperatorType(newOperType);
	      }
	    break;
	  } // case 2, case 3

	default:
	  // $$ modify this when predicates of arity > 3 come into
	  // $$ existance
	  cout << "Invalid arity: " << getArity() << endl;
	  CMPASSERT(FALSE); // No predicates of arity > 3 (so far)
	}
    }
  else // ItemExpr is not an mdam key predicate, go ahead with the rewrite:
    for (Lng32 index = 0; index < getArity(); index++)
      {
        ValueIdSet currAvailableValues(availableValues);

        if (left_ga != NULL && 
            right_ga != NULL && 
            getArity() == 2 )
          {
            ItemExpr::replaceVEGExpressions2( index 
                                            , availableValues
                                            , inputValues
                                            , currAvailableValues
                                            , left_ga
                                            , right_ga
                                            ) ;
          }

	ItemExpr *newChild = child(index)->replaceVEGExpressions(
             currAvailableValues,
	     inputValues,
	     FALSE, // this is not a key predicate
	     lookup,
	     replicateExpression,
             joinInputAndPotentialOutput,
             iDesc);

        if ( newChild->isPreCodeGenNATypeChanged())
           iePtr->setpreCodeGenNATypeChangeStatus();

	// is the result a different ItemExpr or does iePtr not point to
	// the (possibly unchanged) result yet?
	if (iePtr->child(index) != (void *)newChild)
	  {
	    if (iePtr == this AND replicateExpression)
	      {
		// don't change "this" if it may be shared, make a
		// copy instead and also copy the unchanged children
		// so far
		iePtr = iePtr->copyTopNode(NULL, CmpCommon::statementHeap());
		for (Int32 j = 0; j < index; j++)
		  iePtr->child(j) = this->child(j);
	      }
	    iePtr->child(index) = newChild;
	  }
      }

  if(lookup && replicateExpression && iePtr != this)
    {
      iePtr->synthTypeAndValueId(FALSE);
      lookup->insert(getValueId(), iePtr->getValueId());
    }

  return iePtr;
} // ItemExpr::replaceVEGExpressions()

// -----------------------------------------------------------------------
// ValueIdUnion::replaceVEGExpressions()
// The parameter replicateExpression is ignored because the
// ValueIdUnion implements a special policy for rewriting
// an ItemExpr, in that it manages three sets of values.
// -----------------------------------------------------------------------
ItemExpr * ValueIdUnion::replaceVEGExpressions
                            (const ValueIdSet& availableValues,
			     const ValueIdSet& inputValues,
			     NABoolean thisIsAnMdamKeyPredicate,
			     VEGRewritePairs* lookup,
                             NABoolean replicateExpression,
                             const ValueIdSet * joinInputAndPotentialOutput,
                             const IndexDesc * iDesc,
                             const GroupAttributes * left_ga,
                             const GroupAttributes * right_ga)

{
  CMPASSERT(NOT thisIsAnMdamKeyPredicate); // sanity check
  // we are ignoring the replicateExpression and 
  // joinInputAndPotentialOutput flags ..

  ValueIdUnion * viduPtr = (ValueIdUnion *)this;

  // ---------------------------------------------------------------------
  // If this expression has already been resolved because it exists in
  // availableValues, the replacement of VEGExpressions is not required.
  // ---------------------------------------------------------------------

  if (availableValues.contains(getValueId()) )
    return this;

  for(CollIndex i = 0; i < entries(); i++) {
    viduPtr->
      setSource(i,
		(viduPtr->getSource(i).getItemExpr()
		 ->replaceVEGExpressions(availableValues,inputValues,
                                   thisIsAnMdamKeyPredicate,lookup, 
                                   FALSE, /* replicateExpression default */ 
                                   NULL,/*joinInputAndPotentialOutput default*/
                                   iDesc,
                                   left_ga,
                                   right_ga))
		->getValueId());
  }

  // If the result is not this ValueIdUnion
  if (viduPtr->getResult() != viduPtr->getValueId())
    viduPtr->setResult((viduPtr->getResult().getItemExpr()
			->replaceVEGExpressions(availableValues,
						inputValues,
						thisIsAnMdamKeyPredicate,
                                                  lookup,
                                                  FALSE,/*replicateExpression*/
                                                  NULL, /*joinInputAndPotentialOutput*/ 
                                                  iDesc,
                                                  left_ga,
                                                  right_ga))
		       ->getValueId());

  return this;
} // ValueIdUnion::replaceVEGExpressions()


// -----------------------------------------------------------------------
// VEGPredicate::replaceVEGExpressions()
// The parameter replicateExpression is ignored because the
// VEGPredicate implements a special policy for rewriting
// an ItemExpr. The policies are implemented by replaceVEGPredicate().
// -----------------------------------------------------------------------
ItemExpr * VEGPredicate::replaceVEGExpressions
                            (const ValueIdSet& availableValues,
			     const ValueIdSet& inputValues,
			     NABoolean /* thisIsAnMdamKeyPredicate*/,
			     VEGRewritePairs* lookup,
			     NABoolean /*replicateExpression*/,
                             const ValueIdSet * joinInputAndPotentialOutput,
                             const IndexDesc * iDesc,
                             const GroupAttributes * /* left_ga */,
                             const GroupAttributes * /* right_ga */)
{
  // we ignore the thisIsAnMdamKeyPredicate flag, and so we also ignore the
  // iDesc for VEGPredicates. No need to guarantee a keyColumn.

  return replaceVEGPredicate(availableValues,inputValues,lookup,joinInputAndPotentialOutput);

} // VEGPredicate::replaceVEGExpressions()


// -----------------------------------------------------------------------
// VEGReference::replaceVEGExpressions()
// The parameter replicateExpression is ignored because the
// VEGReference implements a special policy for rewriting
// an ItemExpr. The policies are implemented by replaceVEGReference().
// -----------------------------------------------------------------------
ItemExpr * VEGReference::replaceVEGExpressions
                            (const ValueIdSet& availableValues,
			     const ValueIdSet& inputValues,
			     NABoolean thisIsAnMdamKeyPredicate,
			     VEGRewritePairs* /*lookup*/,
			     NABoolean /*replicateExpression*/,
                             const ValueIdSet * joinInputAndPotentialOutput,
                             const IndexDesc * iDesc,
                             const GroupAttributes * /* left_ga */ ,
                             const GroupAttributes * /* right_ga */ )
{
  // we ignore the replicateExpression, lookup and 
  // joinInputAndPotentialOutput parameters.

  return replaceVEGReference(availableValues,inputValues,
                             thisIsAnMdamKeyPredicate, iDesc);

} // VEGReference::replaceVEGExpressions()

// -----------------------------------------------------------------------
// ItemExpr::replaceOperandsOfInstantiateNull()
// This method is used by the code generator for replacing the
// operands of an ITM_INSTANTIATE_NULL with a value that belongs
// to availableValues.
// -----------------------------------------------------------------------
void ItemExpr::replaceOperandsOfInstantiateNull(
                                           const ValueIdSet & availableValues,
                                           const ValueIdSet & inputValues)
{
  switch (getOperatorType())
  {
    case ITM_INSTANTIATE_NULL:
    {
      child(0) = child(0)->replaceVEGExpressions(availableValues,inputValues);
      break;
    }

    default:
    {
      for (Lng32 i = 0; i < getArity(); i++)
      {
        child(i) = child(i)->replaceVEGExpressions(availableValues,
                                                   inputValues);
      }
      break;
    }
  }

} // ItemExpr::replaceOperandsOfInstantiateNull()

// -----------------------------------------------------------------------
// VEG::setBridgeValue()
// -----------------------------------------------------------------------
void VEG::setBridgeValue(const ValueId & bridgeValueId)
{
  bridgeValues_ += bridgeValueId;
} // VEG::setBridgeValue()

// -----------------------------------------------------------------------
// VEG::markAsReferenced()
// Add a member of the set to the referenced values set to indicate
// that it has been used (at least once) in a "=" predicate that
// was generated by the code generator.
// -----------------------------------------------------------------------
void VEG::markAsReferenced(const ValueId & vid)
{
  referencedValues_ += vid;
  switch (vid.getItemExpr()->getOperatorType())
    {
    case ITM_INDEXCOLUMN:
      // Also add the ValueId of the column from the base table, which is
      // used as the key column for an index.
      referencedValues_ += ((IndexColumn *)(vid.getItemExpr()))
	                      ->getDefinition();
      break;
    default:
      break;
    }

} // VEG::markAsReferenced()

// -----------------------------------------------------------------------
// VEGPredicate::replaceVEGPredicate
//
// This method is used by the code generator for replacing a
// reference to a VEGPredicate with an tree of equality predicates.
// Each equality predicate is between two values that belong to
// the VEG as well as to availableValues.
//
// Terminology :
// ***********
// VEG
//   A ValueId Equality Group. It is a set of values such that its members
//   have an equality predicate specified on them.
//
// availableValues
//   This is the set of values that are available at the relational operator
//   with which the VEGPredicate is associated. It is usually the set union
//   of the Charactersitic Inputs of the operator with the Characteristic
//   Outputs of each of its children.
//
// inputValues
//   This is the set of values that is being provided to this node
//   from above, and therefore is constant for each invocation of
//   the operator when executing.
//   This are good values to use to build key predicates.
//
// bridgeValues
//   This is a set of values for which "=" predicates MUST be generated
//   for correctness as well as to guarantee that transitivity is upheld.
//   For example, the following query:
//
//    select ax, by, cx, dy
//      from (select A.x, B.y from A join B on A.x = B.y) T1(ax,by)
//      join (select C.x, D.y from C join D on C.x = D.y) T2(cx,dy)
//        on T1.ax = T2.cx
//
//   shows two "islands" (self-contained pool of rows) defined by the
//   derived tables T1 and T2 respectively. It is possible to deduce
//   that A.x = D.y only after the predicate A.x = C.x has been applied.
//   The values A.x, C.x establish the transitivity between the two
//   islands. Such values are called inter-island links or bridge values.
//
// referencedValues
//   A subset of the members of the VEG. Each member in this set is
//   referenced in at least one "=" predicate that was generated by
//   a call to replaceVEGPredicate.
//
// unboundValues
//   The unbound values of a VEG are those that require an "="
//   predicate to be generated between them. It is given by
//   bridge values union available values intersect members of the VEG.
//
// Note that if the outputs of the join have already been resolved then 
// joinInputAndPotentialOutput should really be joinInputAndOutputValues.
// All potential output values are no longer available, only the resolved
// values. Please see similar comment in Hashjoin::PrecodeGen.
// -----------------------------------------------------------------------
ItemExpr * VEGPredicate::replaceVEGPredicate(const ValueIdSet& origAvailableValues,
                                             const ValueIdSet& origInputValues,
                                             VEGRewritePairs* lookup,
                                             const ValueIdSet * joinInputAndPotentialOutput)
{
  // If we want processing to be idempotent, check to see if we have
  // already written this VEGPredicate.  And if so, return the rewritten
  // result.
  if (lookup)  // if lookup table is present
    {
      // see if this expression is already in there
      ValueId rewritten;
      if (lookup->getRewritten(rewritten /* out */,getValueId()))
	{
	  if (rewritten == NULL_VALUE_ID)
	    return NULL;
	  else
	    return rewritten.getItemExpr();
	}
    };

  // We assume that inputValues is a (perhaps improper) subset of
  // available values. Verify this.
  ValueIdSet scratchPad;
  scratchPad = origInputValues;
  scratchPad -= origAvailableValues;
  GenAssert(scratchPad.isEmpty(),"NOT scratchPad.isEmpty()");

  // Replace VEGReferences in the members of this VEG.
  // Copy values in the set and expand wild cards in the copy.
  ValueIdSet vegMembers;
  vegMembers.replaceVEGExpressionsAndCopy(getVEG()->getAllValues());

  // Constants are not passed as input values but they are available.
  // Have availableValues and availableInputs contain the VEG members
  // that are constant values.
  ValueIdSet availableValues = origAvailableValues;
  ValueIdSet inputValues = origInputValues;

  ValueIdSet vegConstants;
  vegMembers.getConstants(vegConstants);
  availableValues += vegConstants;
  inputValues += vegConstants;

  // If each member of this VEG is referenced in at least one "=" predicate
  // that was generated here and there is only one "unbound" value remaining,
  // then we are done. Terminate the generation of more "=" predicates.
  if ( (vegMembers == getVEG()->getReferencedValues())
       AND (getVEG()->getBridgeValues().entries() < 2) )
    return NULL;

  ItemExpr * rootPtr = NULL;
  // We can only bind those values that are available here.
  ValueIdSet valuesToBeBound = vegMembers;
  valuesToBeBound.intersectSet(availableValues);

  ValueIdSet unReferencedValues = vegMembers;
  unReferencedValues -= getVEG()->getReferencedValues();

    // Compute the set of values that are available, but
    // are already referenced and are not a bridge value.
    scratchPad = valuesToBeBound;
    scratchPad -= unReferencedValues;
    scratchPad -= getVEG()->getBridgeValues();
    valuesToBeBound -= scratchPad;

  // look for an invariant among the input values
  ValueIdSet vegInputs = valuesToBeBound;
  vegInputs.intersectSet(inputValues);

  // If we didn't have any input values that were a member of the
  // VEG then pick the invariant from the bridge Values
  if (vegInputs.isEmpty())
    {
      vegInputs = valuesToBeBound;
      vegInputs.intersectSet(getVEG()->getBridgeValues());
    }

  // If no input values are part of the VEG and there are
  // no available bridge value then just pick any of the
  // remaining (unreferenced) values
  if (vegInputs.isEmpty())
    {
      vegInputs = valuesToBeBound;
    }

  // look for an invariant value
  ValueId iterExprId, invariantExprId;
  NABoolean invariantChosen = FALSE;

  if (NOT vegInputs.isEmpty())
    {
      for (invariantExprId = vegInputs.init();
	   vegInputs.next(invariantExprId);
	   vegInputs.advance(invariantExprId))
	{
	  //check if the item expr is a non-strict constant
	  //a strict constant is somethine like cos(1)
	  //where as cos(?p) can be considered a constant
	  //in the non-strict definition since it remains
	  //constant for a given execution of a query - Solution 10-020912-1647
	  if (invariantExprId.getItemExpr()->doesExprEvaluateToConstant(FALSE))

	    {
              invariantChosen = TRUE;
	      break;
	    }

	} // endfor
      // if invariantExprId does not contain the ValueId of a constant value,
      // then it must be initialized to contain any one value from
      // the input values.
      if (NOT invariantChosen)
	{
          if (vegInputs.entries() <= 1)
            vegInputs.getFirst(invariantExprId);
          else {
            // The  EXISTS query reported in case 10-091027-8459, soln
            // 10-091028-5770 exposed a flaw in this code that used to 
            // implicitly assume that the first element of vegInputs is
            // always a valid choice for an invariantExprId. When replacing
            // a semijoin's VEGPredicate, the invariantExprId must be a
            // member of that semijoin's characteristic output. Otherwise,
            // *Join::preCodeGen hjp.replaceVEGExpressions() will silently
            // delete that equijoin predicate and incorrectly generate a
            // cartesian product.
            scratchPad = vegInputs;
            if (joinInputAndPotentialOutput) {
              // for an outer join, joinInputAndPotentialOutput will have
              // instantiate_null wrappers. intersectSetDeep digs into
              // those wrappers.
              scratchPad.intersectSetDeep(*joinInputAndPotentialOutput);
            }
#ifdef _DEBUG
            // we want to GenAssert here but regress/core/test027 raises
            // a false alarm. So, for now, we don't.
            // GenAssert(!scratchPad.isEmpty(),"vegInputs.isEmpty()");
#endif
            if (scratchPad.isEmpty())
              vegInputs.getFirst(invariantExprId); 
            else
              scratchPad.getFirst(invariantExprId);
          }
	}

      // remove it from further consideration
      valuesToBeBound -= invariantExprId;

    } // endif (NOT vegInputs.isEmpty())
  else // have no values
    {
      // The predicate pushdown logic places predicates on those
      // operators where it knows that values will be available
      // for evaluating the predicate.
      // If you have reached this point because of a bug,
      // ****************************************************************
      // DO NOT EVEN CONSIDER COMMENTING OUT THE FOLLOWING ASSERT.
      // ****************************************************************
      GenAssert(NOT valuesToBeBound.isEmpty(),"valuesToBeBound.isEmpty()");
      // ****************************************************************
      // YOU WILL BE DELIBERATELY MASKING OUT A SERIOUS BUG IF YOU
      // DISABLE THE ASSERT STATEMENT ABOVE. DON'T TOUCH IT!
      // ****************************************************************
    }

  if (valuesToBeBound.entries() >=  1)
    {
      // Replace this reference to the VEG with a tree of '=' predicates.
      for (iterExprId = valuesToBeBound.init();
	   valuesToBeBound.next(iterExprId);
	   valuesToBeBound.advance(iterExprId))
	{
	  rootPtr = buildComparisonPred
			( rootPtr, iterExprId.getItemExpr(),
			  invariantExprId.getItemExpr(), ITM_EQUAL,
			  getSpecialNulls() //++MV - Irena
			);
	  getVEG()->markAsReferenced(iterExprId);
	}
    }
  else
    {
      // We have only the invariant. Generate an IS NOT NULL if it
      // is nullable and has not been compared with someone else.
      // MVs:
      // If specialNulls option is set, nulls are values (null=null)
      // and ITM_IS_NOT_NULL  filters out some valid rows also.
      // For more info on specialNulls -- see <ItemOther.h>
      if (NOT getVEG()->getReferencedValues().contains(invariantExprId) &&
          invariantExprId.getType().supportsSQLnull() &&
	  NOT getVEG()->getVEGPredicate()->getSpecialNulls() // ++MV - Irena
	 )
        {
          rootPtr = new(CmpCommon::statementHeap())
		UnLogic(ITM_IS_NOT_NULL, invariantExprId.getItemExpr());
        }
    }

  // mark as referenced the invariant. Make it the Bridge value
  getVEG()->markAsReferenced(invariantExprId);
  getVEG()->removeBridgeValues(valuesToBeBound);
  getVEG()->setBridgeValue(invariantExprId);

  // Assign a ValueId to the "=" and synthesize the type for the expression.
  if (rootPtr != NULL) {
    rootPtr->synthTypeAndValueId();
  // If there is a lookup table, enter the rewritten tree in the table
  if (lookup)
    {
    if (rootPtr)
      lookup->insert(getValueId(),rootPtr->getValueId());
    else
      lookup->insert(getValueId(),NULL_VALUE_ID);
    }
  }
  // Return the tree of '=' predicates (or NULL)
  return rootPtr;
} // VEGPredicate::replaceVEGPredicate()

// -----------------------------------------------------------------------
// VEGReference::replaceVEGReference
// This method is used by the code generator. for replacing a
// VEGReference with one of its candidate values
// thisIsAnMdamKeyPredicate is FALSE by default. However, when
// key predicates are being rewritten, it should be set to TRUE
// when we need to guarantee that a key column must be generated by
// the veg reference.
// In this case,
// then bridge values MUST NOT be usen because we need to pick either
// a constant or a key column (depending on the child we are
// working on (see ItemExpr::replaceVEGExpressions(...))
// -----------------------------------------------------------------------
ItemExpr *
VEGReference::replaceVEGReference(const ValueIdSet &origAvailableValues,
                                  const ValueIdSet &origInputValues,
                                  NABoolean thisIsAnMdamKeyPredicate,
                                  const IndexDesc *iDesc)
{

  ItemExpr *result = NULL;

  #ifndef _DEBUG
    const NABoolean VEG_DEBUG = FALSE;
  #else
    NABoolean VEG_DEBUG = getenv("VEG_DEBUG") != NULL;
  #endif

  // We assume that inputValues is a (perhaps improper) subset of
  // available values. Verify it.
  ValueIdSet scratchPad;
  scratchPad = origInputValues;
  scratchPad -= origAvailableValues;
  GenAssert(scratchPad.isEmpty(),"NOT scratchPad.isEmpty()");

  // Copy values in the set and expand wild cards in the copy.
  ValueIdSet valuesToBeBound;
  valuesToBeBound.replaceVEGExpressionsAndCopy(getVEG()->getAllValues());

  // Constants are not passed as input values but they are available
  // Have availableValues and availableInputs contain the VEG members
  // that are constant values
  ValueIdSet availableValues = origAvailableValues;
  ValueIdSet inputValues = origInputValues;

  // --------------------------------------------------------------------
  // Don't add constants if the caller don't want them to be generated
  // from this vegref (i.e. when thisIsAnMdamKeyPredicate is TRUE)
  // --------------------------------------------------------------------

  ValueIdSet vegConstants;
  valuesToBeBound.getConstants(vegConstants);
  if (NOT thisIsAnMdamKeyPredicate)
    {
      availableValues += vegConstants;
      inputValues += vegConstants;
    }

  if (VEG_DEBUG)
    {
      NAString av,iv,vb,vr;
      availableValues.unparse(av);
      inputValues.unparse(iv);
      valuesToBeBound.unparse(vb);
      ValueIdSet thisVegRef(getValueId());
      thisVegRef.unparse(vr);
      cout << endl;
      cout << "VEGReference " << getValueId() << " (" << vr << "):" << endl;
      cout << "AV: " << av << endl;
      cout << "IV: " << iv << endl;
      cout << "VB: " << vb << endl;
    }

  // -----------------------------------------------------------------------
  // 
  // The commented out code implements a different resolution strategies
  // for VEGReference. Inputs are no longer favored. This is in order to
  // handle peculiar scenario where a predicate is not pushed down to the
  // right hand side of a NJ even if it's covered because of the special
  // semantics of the NJ itself (left join). The inputs from the operators
  // in the right leg of the NJ shouldn't be used to resolve the output
  // values since the VEGPred which relates the two hasn't been evaluated.
  //
  // This support is not ready yet for FCS, and therefore the code has been
  // commented out.
  // -----------------------------------------------------------------------
#if 0
  // non-input available values:
  ValueIdSet nonInputAvailableValues = availableValues;
  nonInputAvailableValues -= inputValues;
#endif

  // We can only bind those values that are available here.
  valuesToBeBound.intersectSet(availableValues);

#if 0
  // try using nonInputAvailableValues first.
  ValueIdSet nonInputValuesToBeBound = valuesToBeBound;
  nonInputValuesToBeBound.intersectSet(nonInputAvailableValues);

  // try not to use input values since some predicate might not have
  // be evaluated yet.
  if ( (NOT thisIsAnMdamKeyPredicate) AND
       (NOT nonInputValuesToBeBound.isEmpty()) )
  {
    // Try to pick a bridge value.
    ValueIdSet candidateValues = nonInputValuesToBeBound;
    candidateValues.intersectSet(getVEG()->getBridgeValues());

    // If unsuccessful, try to pick any of the remaining unreferenced.
    if (candidateValues.isEmpty())
    {
      candidateValues = nonInputValuesToBeBound;
    }

    CMPASSERT(NOT candidateValues.isEmpty());
    ValueId resultVid;
    candidateValues.getFirst(resultVid);
    return resultVid.getItemExpr();
  }
#endif


  if (thisIsAnMdamKeyPredicate )
    {
      GenAssert(iDesc != NULL,"VEGReference::replaceVEGReference: Mdam KeyPredicates flag requires an iDesc to go with");
      if (iDesc != NULL)
        {
        ValueIdSet keyCols = iDesc->getIndexKey();
  
        for (ValueId exprId = keyCols.init();
             keyCols.next(exprId);
             keyCols.advance(exprId))
          {
   
            // pick the first value - assuming it is the key column..
            if (valuesToBeBound.contains(exprId)) 
              {
                result = exprId.getItemExpr();
                break;
              }
          }
        }

      if (result && NOT (result->getValueId().getType() == getValueId().getType()) )
          result->setpreCodeGenNATypeChangeStatus();

      return result; // A null is fine here.

    }

  // look for an invariant among the input values
  ValueIdSet vegInputs = valuesToBeBound;
  vegInputs.intersectSet(inputValues);

  // If we didn't have any input values that were a member of the
  // VEG then pick the invariant from the bridge Values
  // Do not use bridge values for key predicates:
  if ((NOT thisIsAnMdamKeyPredicate) && vegInputs.isEmpty())
    {
      vegInputs = valuesToBeBound;
      vegInputs.intersectSet(getVEG()->getBridgeValues());
      if (VEG_DEBUG)
	{
	  NAString vb,br;
	  valuesToBeBound.unparse(vb);
	  // Stupid, ValueIdSet::unparse should be declared const;
	  // for now, just cast away constness...
	  ValueIdSet(getVEG()->getBridgeValues()).unparse(br);
	  cout << "VB: " << vb << endl;
	  cout << "BR: " << br << endl;
	}
    }

  // If no input values are part of the VEG and there are
  // no available bridge value then just pick any of the
  // remaining (unreferenced) values
  if (vegInputs.isEmpty())
    {
      vegInputs = valuesToBeBound;
    }

  // look for a constant value
  ValueId invariantExprId;
  NABoolean invariantChosen = FALSE;

  if (NOT vegInputs.isEmpty())
    {
      for (invariantExprId = vegInputs.init();
	   vegInputs.next(invariantExprId);
	   vegInputs.advance(invariantExprId))
	{
	  //check if the item expr is a non-strict constant
	  //a strict constant is somethine like cos(1)
	  //where as cos(?p) can be considered a constant
	  //in the non-strict definition since it remains
	  //constant for a given execution of a query - Solution 10-020912-1647
	  if (invariantExprId.getItemExpr()->doesExprEvaluateToConstant(FALSE))
	    {
              invariantChosen = TRUE;
	      break;
	    }

	} // endfor
      // if invariantExprId does not contain the ValueId of a constant value,
      // then it must be initialized to contain any one value from
      // the input values.
      if (NOT invariantChosen)
	{
	  vegInputs.getFirst(invariantExprId);
	}

      // we found the invariant assign it!
      result = invariantExprId.getItemExpr();
      CMPASSERT(result != NULL);

    } // endif (NOT vegInputs.isEmpty())
  else // have no values
    {
      // It is ok for an MDAM key pred to not have valuesToBeBound because
      // this is how ItemExpr::replaceVEGExpressions guarantees the generation of
      // key predicates. It expects a NULL pointer sometimes
      if (NOT thisIsAnMdamKeyPredicate)
      {
        // If there is a VEGReference to the value then a member of
        // the VEG should be available.
        GenAssert(NOT valuesToBeBound.isEmpty(),"valuesToBeBound.isEmpty()");
      }
    }

  // result can be NULL only if thisIsAnMdamKeyPredicate is TRUE (see note above)
  if (NOT thisIsAnMdamKeyPredicate)
  {
    CMPASSERT(result);
  }

  if (VEG_DEBUG)
  {
    // coverity cid 10004 thinks result may be null but we know it is not.
    // coverity[var_deref_model]
	cout << "Result: " << result->getValueId() << endl;
  }

  // see if NAType has changed, if so need to rebind it
  if (result && NOT (result->getValueId().getType() == getValueId().getType()) )
  {
     result->setpreCodeGenNATypeChangeStatus();
  }
  return result;

} // VEGReference::replaceVEGReference()


// -----------------------------------------------------------------------
// RelExpr::getOutputValuesOfMyChilren()
// Accumulates the characteristic outputs of all my children for
// operators that have one or more children. Returns the
// potential output values for operators that can have no children.
// -----------------------------------------------------------------------
void RelExpr::getOutputValuesOfMyChildren(ValueIdSet & vs) const
{
  ValueIdSet valueMask;
  Lng32 nc = getArity();
  if (nc > 0)
    {
      for (Lng32 i = 0; i < nc; i++)
	{
	  valueMask += child(i)->getGroupAttr()->getCharacteristicOutputs();
	}
    }
  else // if leaf operators, use all available values
    {
      getPotentialOutputValues(valueMask);
    }

  // Copy values in the set and expand wild cards in the copy.
  vs.clear();
  vs.replaceVEGExpressionsAndCopy(valueMask);

} // RelExpr::getOutputValuesOfMyChildren()

// -----------------------------------------------------------------------
// RelExpr::getInputValuesFromParentAndChildren()
// Uses getOutputValuesOfMyChildren() to collect the output values
// and adds the characteristic input values of this operator to them.
// -----------------------------------------------------------------------
void RelExpr::getInputValuesFromParentAndChildren(ValueIdSet & vs) const
{
  getOutputValuesOfMyChildren(vs);
  vs += getGroupAttr()->getCharacteristicInputs();
} // RelExpr::getInputValuesFromParentAndChildren()

// -----------------------------------------------------------------------
// RelExpr::getInputAndPotentialOutputValues()
// Uses getPotentialOutputs() to collect the output values
// and adds the characteristic input values of this operator to them.
// -----------------------------------------------------------------------
void RelExpr::getInputAndPotentialOutputValues(ValueIdSet & vs) const
{
  ValueIdSet potentialOutputValues;
  getPotentialOutputValues(potentialOutputValues);
  potentialOutputValues += getGroupAttr()->getCharacteristicInputs();
  vs.clear();
  vs.replaceVEGExpressionsAndCopy(potentialOutputValues);

} // RelExpr::getInputAndPotentialOutputValues()

// -----------------------------------------------------------------------
// GenericUpdate::replaceVEGExpressionsAndGet...
// -----------------------------------------------------------------------
void GenericUpdate::getInputValuesFromParentAndChildren(ValueIdSet & vs) const
{
  ValueIdSet updTableCols;
  ValueIdSet vs2;

  updTableCols.insertList (getIndexDesc()->getIndexColumns());
  //      updTableCols.insertList(getTableDesc()->getColumnVEGList());
  vs2.replaceVEGExpressionsAndCopy(updTableCols);


  getOutputValuesOfMyChildren(vs);
  vs += getGroupAttr()->getCharacteristicInputs();
  vs += vs2;
} // GenericUpdate::getInputValuesFromParentAndChildren()

// -----------------------------------------------------------------------
// HbaseDelete::replaceVEGExpressionsAndGet...
// -----------------------------------------------------------------------
void HbaseDelete::getInputValuesFromParentAndChildren(ValueIdSet & vs) const
{
  // Do not include IndexColumn as the input values. Otherwise, we will
  // have duplicated predicates in Executor predicate in HbaseDelete.

  getOutputValuesOfMyChildren(vs);
  vs += getGroupAttr()->getCharacteristicInputs();
} // HbaseDelete::getInputValuesFromParentAndChildren()

// -----------------------------------------------------------------------
// RelExpr::preCodeGen()
//
// RelExpr * result
//    OUT: a node that calls preCodeGen for its child should replace
//         that child with the result value. This allows preCodeGen
//         to transform the RelExpr tree. Examples for such trans-
//         formations are additional exchange nodes for repartitioning.
// Generator * generator
//  INOUT: a global work area with useful helper methods
// const ValueIdSet & externalInputs
//     IN: a value id set with values that already have been
//         replaced such that they don't contain VEGies any more.
//         Use this set to replace VEGies for expressions that depend
//         on the characteristic inputs of the node.
// ValueIdSet & pulledNewInputs
//    OUT: a set of value ids that the node wants to add to its
//         characteristic inputs ("pull" from its parent). There are
//         several cases in which we need to add value ids to
//         characteristic inputs during preCodeGen:
//         a) partition input variables for parallel execution,
//         b) the COMMON datetime function which needs to be generated
//            by the root node,
//         c) an "open cursor timestamp" that helps a materialize node
//            to decide whether it can reuse its materialized table.
// -----------------------------------------------------------------------
RelExpr * RelExpr::preCodeGen(Generator * generator,
			      const ValueIdSet & externalInputs,
			      ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  // Check if the pivs of this operator and it's child are the same.
  // If they are not, make them the same.
  replacePivs();

  // Resolve the VEGReferences and VEGPredicates, if any, that appear
  // in the Characteristic Inputs, in terms of the externalInputs.
  getGroupAttr()->resolveCharacteristicInputs(externalInputs);

  // My Characteristic Inputs become the external inputs for my children.
  Int32 nc = getArity();
  for (Int32 index = 0; index < nc; index++)
    {
      ValueIdSet childPulledInputs;

      child(index) = child(index)->preCodeGen(generator,
					      externalInputs,
					      childPulledInputs);

      if (! child(index).getPtr())
	return NULL;

      // process additional input value ids the child wants
      getGroupAttr()->addCharacteristicInputs(childPulledInputs);
      pulledNewInputs += childPulledInputs;
    }

  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  ValueIdSet availableValues;
  getInputAndPotentialOutputValues(availableValues);

  // Rewrite the selection predicates.
  NABoolean replicatePredicates = TRUE;
  selectionPred().replaceVEGExpressions
                     (availableValues,
		      getGroupAttr()->getCharacteristicInputs(),
		      FALSE, // no need to generate key predicates here
		      0 /* no need for idempotence here */,
		      replicatePredicates
		     );

  getGroupAttr()->resolveCharacteristicOutputs
                     (availableValues,
		      getGroupAttr()->getCharacteristicInputs());

  markAsPreCodeGenned();

  return this;
} // RelExpr::preCodeGen

//
// Recuvsively call the method on each RelExpr node, accumulating
// # of rows from each node.
//
void RelExpr::prepareDopReduction(Generator* generator)
{
  pcgEspFragment* currentEspFragmentPCG = generator->getCurrentEspFragmentPCG();

  if ( currentEspFragmentPCG )
     currentEspFragmentPCG->accumulateRows(getEstRowsUsed());

  Int32 nc = getArity();

  for (Lng32 i = 0; i < nc; i++)
  {
     child(i)->prepareDopReduction(generator);
  }
}

void Exchange::prepareDopReduction(Generator* generator)
{
   pcgEspFragment* parentEspFragPCG = generator->getCurrentEspFragmentPCG();

   //
   // Save the current pcg fragment and add myself as the child to it.
   //
   if ( parentEspFragPCG ) {
     parentEspFragPCG->accumulateRows(getEstRowsUsed());
     parentEspFragPCG->addChild(this);
   }

   //
   // Let the global pointer point at my pcg esp fragment (for the
   // fragment rooted at me). Do this only for above-DP2 Exchanges.
   // Note a PA is represented by an Exchange with "execute in Master or ESP"
   // as location. So a PA exchange with a SCAN as a child will have an empty
   // childPcgEsp array.
   //
   generator->setCurrentEspFragmentPCG
     (
       (getPhysicalProperty()->getPlanExecutionLocation() != EXECUTE_IN_DP2)
               ? getEspFragPCG() : NULL
     );

  child(0)->prepareDopReduction(generator);

  //
  // Restore the pcg esp fragment
  //
  generator->setCurrentEspFragmentPCG(parentEspFragPCG);

  // Try to reduce the dop and if it fails, invalidate any proposed
  // dop reductions for this.
  //
  if ( parentEspFragPCG &&
       parentEspFragPCG ->tryToReduceDoP() == FALSE )
     parentEspFragPCG->invalidate();
}

RelExpr * RelRoot::preCodeGen(Generator * generator,
			      const ValueIdSet & /* externalInputs */,
			      ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  // For all the inputVars, if it is with UNKNOWN data type, make it a
  // varchar type. This is from SQL/MP extension. Example query
  // select ?p1 from any-table;
  if (isTrueRoot()) {
    CollIndex i;
    ValueId vid;
    ValueIdList vidList = inputVars();
    for ( i=0; i < vidList.entries(); i++ )
      if ((vid=vidList[i]).getType().getTypeQualifier() == NA_UNKNOWN_TYPE) {
	vid.coerceType(NA_CHARACTER_TYPE);
      }
  }

  // if root has GET_N indication set, insert a FirstN node.
  // Usually this transformation is done in the binder, but in
  // some special cases it is not.
  // For example, if there is an 'order by' in the query, then
  // the Sort node is added by the optimizer. In this case, we
  // want to add the FirstN node on top of the Sort node and not
  // below it. If we add the FirstN node in the binder, the optimizer
  // will add the Sort node on top of the FirstN node. Maybe we
  // can teach optimizer to do this.
  if ((getFirstNRows() != -1) || (getFirstNRowsParam()))
    {
      // As of JIRA TRAFODION-2840, the binder always adds the FirstN,
      // except in the case of output rowsets. So, the only time we 
      // should now be going through this code is a SELECT query using
      // output rowsets + FirstN + ORDER BY. A follow-on JIRA,
      // TRAFODION-2924, will take care of that case and delete this code.
      // (As a matter of design, it is highly undesireable to sometimes
      // create the FirstN in the Binder and sometimes in the Generator;
      // that means that any FirstN-related semantic checks in the 
      // intervening passes will need two completely separate 
      // implementations.)

      RelExpr * firstn = new(generator->wHeap()) FirstN(child(0),
							getFirstNRows(),
							needFirstSortedRows(),   
                                                        getFirstNRowsParam());

      // move my child's attributes to the firstN node.
      // Estimated rows will be mine.
      firstn->setEstRowsUsed(getEstRowsUsed());
      firstn->setMaxCardEst(getMaxCardEst());
      firstn->setInputCardinality(child(0)->getInputCardinality());
      firstn->setPhysicalProperty(child(0)->getPhysicalProperty());
      firstn->setGroupAttr(child(0)->getGroupAttr());
      //10-060516-6532 -Begin
      //When FIRSTN node is created after optimization phase, the cost
      //of that node does not matter.But, display_explain and explain
      //show zero operator costs and rollup cost which confuses the user.
      //Also, the VQP crashes when cost tab for FIRSTN node is selected.
      //So, creating a cost object will fix this.
      //The operator cost is zero and rollup cost is same as it childs.
      Cost* firstnNodecost = new HEAP Cost();
      firstn->setOperatorCost(firstnNodecost);
      Cost* rollupcost = (Cost *)(child(0)->getRollUpCost());
      *rollupcost += *firstnNodecost;
      firstn->setRollUpCost(rollupcost);
      //10-060516-6532 -End

      setChild(0, firstn);

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

  if (isTrueRoot())
    {
      // Set the internal format to use for the plan being generated ...
      // Checks the CQD COMPRESSED_INTERNAL_FORMAT to decide whether to use
      // SQLARK_EXPLODED_FORMAT or SQLMX_ALIGNED_FORMAT as the internal
      // data format
      // When the CIF CQD is set to SYSTEM we decide whether to use aligned or exploded format
      // as the tuple format for the whole query. In precodeGEn we visit all the copy
      // operators (Hash join, hash group by, exchange and sort) in a query
      // tree and keep a count of the nodes that are in favor of aligned format and those
      // that are in favor of exploded format.
      // The final decision about the tuple format for the whole query will depend on those two
      // numbers. if the number of nodes in favor of aligned format is greater than those
      // in favor of exploded than aligned format is select otherwise exploded is selected
      // The function that determine the format for each of the copy operators + relroot
      // is determineInternalFormat(..) is is called in the precodeGen of the copy operators
      generator->initNNodes();
      isCIFOn_ = FALSE;

      if ((CmpCommon::getDefault(COMPRESSED_INTERNAL_FORMAT) == DF_ON )||
          generator->isFastExtract() ||
          generator->containsFastExtract())
      {
         isCIFOn_ = TRUE;
         generator->setCompressedInternalFormat();
      }
      else
      if ( CmpCommon::getDefault(COMPRESSED_INTERNAL_FORMAT) == DF_OFF )
      {
        generator->setExplodedInternalFormat();
      }
      else
      {
         NABoolean resize = FALSE;
         NABoolean considerBufferDefrag = FALSE;
         ValueIdSet vidSet = child(0)->getGroupAttr()->getCharacteristicOutputs();
         ExpTupleDesc::TupleDataFormat tupleFormat =
                                 generator->determineInternalFormat(
                                                   vidSet,
                                                   this,
                                                   resize,
                                                   RelExpr::CIF_SYSTEM,
                                                   FALSE,
                                                   considerBufferDefrag);

         if (tupleFormat == ExpTupleDesc::SQLMX_ALIGNED_FORMAT)
         {
           generator->incNCIFNodes();
         }
         else
         {
           generator->decNCIFNodes();
         }
      }
      //generator->setInternalFormat();

      // Some operators will revert the internal format back to exploded format
      // when they are directly under the root node - such as the top level ESPs,
      // Sort, and HJ operators.
      // This is so there is no bottleneck in the master flipping the data back
      // to exploded format (required for bulk move out).
      child(0)->setParentIsRoot( TRUE );

      // create a list of NATypes corresponding to each entry in the
      // userColumnList_ in RETDesc. Used by generator to convert to
      // this type during output expr code gen.
      // The value ids in userColumnList_ cannot be used as the type
      // corresponding to that value id may change due to VEG transformation
      // in the preCodeGen phase.
      if (getRETDesc()->createNATypeForUserColumnList(CmpCommon::statementHeap()))
	{
	  // error case.
	  GenAssert(FALSE, "error from createNATypeForUserColumnList.");
	}

      if ( (child(0)->getOperatorType() == REL_EXCHANGE) &&
	   (child(0)->child(0)->getOperatorType() == REL_COMPOUND_STMT) )
	{
	  ((Exchange *)((RelExpr *)child(0)))->setDP2TransactionIndicator( TRUE );
	}
    }

  unsigned short prevNumBMOs = 0;
  CostScalar prevBMOsMemoryUsage;

  if (isTrueRoot())
    {
      if (oltOptInfo().oltAnyOpt())
        {
          if (treeContainsEspExchange())
            {
              // turn off oltQueryOptimization if the query plan contains an
              // esp_exchange.
              // 10-070316-3325: childOperType_ = REL_UNARY_DELETE
              // 10-080118-9942: select query contains esp_exchange that is
              // not directly under root.
              oltOptInfo().setOltOpt(FALSE);
            }
          else if (childOperType() == REL_SCAN)
	    {
              // if this was a scan query to start with but is no longer
              // a scan query(which means it got transformed to join, etc),
              // then turn off oltQueryOptimization.
	      RelExpr *childExpr = child(0)->castToRelExpr();

	      if (childExpr->getOperatorType() == REL_FIRST_N)
		childExpr = childExpr->child(0)->castToRelExpr();

              if ((childExpr->getOperatorType() != REL_EXCHANGE) &&
		  (childExpr->getOperatorType() != REL_HBASE_ACCESS))
                oltOptInfo().setOltCliOpt(FALSE);
            }
        } // oltAnyOpt

      *generator->oltOptInfo() = oltOptInfo();
 
      if (generator->oltOptInfo()->oltAnyOpt())
	{
	  // Also, PubSub streams' STREAM_TIMEOUT not handled by opt'd root
          if (getGroupAttr()->isStream())
            {
	      generator->oltOptInfo()->setOltCliOpt(FALSE);
            }


	  if (CmpCommon::getDefault(EID_SPACE_USAGE_OPT) == DF_ON)
	    {
	      generator->setDoEidSpaceUsageOpt(TRUE);
	    }
	  else
	    {
	      generator->setDoEidSpaceUsageOpt(FALSE);
	    }

	  // olt opt not chosen if ALL stats are being collected.
	  // We may support this case later.
          // In case of operator stats, don't disable OLT optimization
          // But, when the query is OLT optimized, switch it to pertable stats
	  if ((generator->computeStats()) &&
	      ((generator->collectStatsType() == ComTdb::ALL_STATS)))
 	    generator->oltOptInfo()->setOltOpt(FALSE);
	  
	  if (CmpCommon::getDefault(OLT_QUERY_OPT) == DF_OFF)
	    generator->oltOptInfo()->setOltOpt(FALSE);

	  // In the case of an embedded insert,
	  // do not execute the query OLT optimized.
	  
	  if (getGroupAttr()->isEmbeddedInsert())
            generator->oltOptInfo()->setOltMsgOpt(FALSE);
	  
#ifdef _DEBUG
	  if (getenv("NO_OLT_QUERY_OPT"))
	    generator->oltOptInfo()->setOltOpt(FALSE);
#endif

	  if (generator->oltOptInfo()->oltEidOpt())
	    {
	      generator->oltOptInfo()->setOltEidLeanOpt(FALSE);

	      if (generator->doEidSpaceUsageOpt())
		{
		  generator->oltOptInfo()->setOltEidLeanOpt(TRUE);
		}
	    }

	  if (CmpCommon::getDefault(OLT_QUERY_OPT_LEAN) == DF_OFF)
	    generator->oltOptInfo()->setOltEidLeanOpt(FALSE);
	} // oltAnyOpt

      // mark exchange operator for maxOneRow optimization.
      RelExpr *childExpr = child(0)->castToRelExpr();
      NABoolean doMaxOneRowOpt = TRUE;
      NABoolean doMaxOneInputRowOpt = FALSE;
      NABoolean firstN = FALSE;
      RelExpr *exchExpr = NULL;
      if (NOT generator->doEidSpaceUsageOpt())
	{
	  doMaxOneRowOpt = FALSE;
	  doMaxOneInputRowOpt = FALSE;
	}
      else
	{
	  doMaxOneRowOpt = TRUE;
	  doMaxOneInputRowOpt = TRUE;
	}

      if (childExpr->getOperatorType() == REL_FIRST_N)
	{
	  firstN = TRUE;
	  if (((FirstN *)childExpr)->getFirstNRows() != 1)
	    doMaxOneRowOpt = FALSE;

	  childExpr = childExpr->child(0)->castToRelExpr();
	}

      if ((childExpr->getOperatorType() != REL_EXCHANGE) ||
	  (childExpr->child(0)->castToRelExpr()->
	   getPhysicalProperty()->getPlanExecutionLocation() != EXECUTE_IN_DP2))
	{
	  doMaxOneRowOpt = FALSE;
	  doMaxOneInputRowOpt = FALSE;
	}
      else
	{
	  exchExpr = childExpr;
	  childExpr = childExpr->child(0)->castToRelExpr();
          if (NOT childExpr->getOperator().match(REL_FORCE_ANY_SCAN))
	    {
	      doMaxOneInputRowOpt = FALSE;
	    }
	  else if (childExpr->getOperatorType() == REL_FILE_SCAN)
	    {
	      FileScan * s = (FileScan *)childExpr;
	      if (NOT firstN)
		doMaxOneRowOpt = FALSE;

	      if ((s->getGroupAttr()->isStream()) ||
		  (s->accessOptions().accessType() == TransMode::SKIP_CONFLICT_ACCESS_))
		{
		  //doMaxOneInputRowOpt = FALSE;
		  //doMaxOneRowOpt = FALSE;
		}
	    }
	}

      if (doMaxOneRowOpt)
	{
	  exchExpr->oltOptInfo().setMaxOneRowReturned(TRUE);
	}

      if (doMaxOneInputRowOpt)
	{
	  exchExpr->oltOptInfo().setMaxOneInputRow(TRUE);
	}

      generator->setUpdErrorInternalOnError(FALSE);

      if (rollbackOnError())
	generator->setUpdErrorOnError(FALSE);
      else
	generator->setUpdErrorOnError(TRUE);

      if (CmpCommon::getDefault(UPD_ABORT_ON_ERROR) == DF_ON)
	generator->setUpdAbortOnError(TRUE);
      else
	generator->setUpdAbortOnError(FALSE);

      if (CmpCommon::getDefault(UPD_PARTIAL_ON_ERROR) == DF_ON)
	generator->setUpdPartialOnError(TRUE);
      else
	generator->setUpdPartialOnError(FALSE);

      if (CmpCommon::getDefault(UPD_SAVEPOINT_ON_ERROR) == DF_ON)
	generator->setUpdSavepointOnError(TRUE);
      else
	generator->setUpdSavepointOnError(FALSE);

      generator->setSkipUnavailablePartition(FALSE);
      if ((childOperType() == REL_SCAN) &&
	  (CmpCommon::getDefault(SKIP_UNAVAILABLE_PARTITION) == DF_ON))
	generator->setSkipUnavailablePartition(TRUE);

      if (avoidHalloween_)
        { 
          // At beginning of preCodeGen, assume DP2Locks will be 
          // used.  The NestedJoin::preCodeGen will change this
          // if its left child is a sort.
          generator->setHalloweenProtection(Generator::DP2LOCKS);
        }

      if (generator->getBindWA()->getUdrStoiList().entries () > 0)
        generator->setAqrEnabled(FALSE);

      // Reset the accumulated # of BMOs for the fragment
      prevNumBMOs = generator->replaceNumBMOs(0);

    } // true root

  // propagate the need to return top sorted N rows to all sort
  // nodes in the query.
  if (needFirstSortedRows() == TRUE)
    {
      needSortedNRows(TRUE);
    }

  // Delete any VEGReference that appear in the Characteristic Inputs.
  // The Characteristic Inputs of the root of the execution plan MUST
  // only contain external dataflow inputs that are provided by the
  // user. The VEGReferences may have been introduced as a side-effect
  // of predicate pushdown. They are redundant in the Characteristic
  // Inputs of the root.
  ValueIdSet availableValues;
  for (ValueId exprId = getGroupAttr()->getCharacteristicInputs().init();
                        getGroupAttr()->getCharacteristicInputs().next(exprId);
                        getGroupAttr()->getCharacteristicInputs().advance(exprId) )
    {
      if (exprId.getItemExpr()->getOperatorType() != ITM_VEG_REFERENCE)
	availableValues += exprId;
    }

  getGroupAttr()->setCharacteristicInputs(availableValues);

  // If this is the root for a parallel extract producer query then
  // there should be an Exchange node immediately below and we need to
  // set a flag in that Exchange.
  if (numExtractStreams_ > 0)
  {
    if (child(0)->getOperatorType() == REL_EXCHANGE)
    {
      Exchange *e = (Exchange *) child(0)->castToRelExpr();
      e->setExtractProducerFlag();
    }
    // fix for soln 10-090506-1407: parallel extract for a union distinct 
    // can sometimes have root->mapvalueidsl->exchange. It should be OK.
    else if (child(0)->getOperatorType() == REL_MAP_VALUEIDS &&
             child(0)->child(0)->getOperatorType() == REL_EXCHANGE)
    {
      Exchange *e = (Exchange *) child(0)->child(0)->castToRelExpr();
      e->setExtractProducerFlag();
    }
  }

  //
  // If there is no hard requirement on #ESPs, reduce the dop based on 
  // the total # of rows processed per ESP. The reduction can modify
  // the number of partitions attribute of the partition function stored
  // in the synthesized physical property of an Exchange operator.
  // 
  // CQD DOP_REDUCTION_ROWCOUNT_THRESHOLD set to 0.0 will disable the 
  // feature.

   float threshold;
   ActiveSchemaDB()->
      getDefaults().getFloat(DOP_REDUCTION_ROWCOUNT_THRESHOLD, threshold);

  if ( threshold > 0.0 && CURRSTMT_OPTDEFAULTS->getRequiredESPs() <= 0 ) {

    generator->setCurrentEspFragmentPCG(NULL); // reset the 'global' 
                                               // to the current esp frag.

    RelExpr::prepareDopReduction(generator);
    RelExpr::doDopReduction();
  }

  // Now walk through the execution plan and initialize it for code generation.
  child(0) = child(0)->preCodeGen(generator,
				  getGroupAttr()->getCharacteristicInputs(),
				  pulledNewInputs);
  if (! child(0).getPtr())
    return NULL;

  if (! RelExpr::preCodeGen(
       generator,
       getGroupAttr()->getCharacteristicInputs(),
       pulledNewInputs))
      return NULL;

  if ( isTrueRoot() && CmpCommon::getDefault(COMPRESSED_INTERNAL_FORMAT) == DF_SYSTEM)
  {
    if (generator->getNCIFNodes()>0)
    {
      isCIFOn_ = TRUE;
      generator->setCompressedInternalFormat();
    }
    else
    {
      generator->setExplodedInternalFormat();
      isCIFOn_ = FALSE;
    }

  }


  // If the RelRoot is marked as a parallel extract producer then the
  // root's child must be an Exchange and the child must also be
  // marked for parallel extract. Even though we checked the type of
  // the child a few lines above, we do it again here because the call
  // to RelExpr::preCodeGen can potentially eliminate Exchange nodes.
  NABoolean extractPlanLooksOK = TRUE;
  if (numExtractStreams_ > 0)
  {
    if (child(0)->getOperatorType() == REL_EXCHANGE)
    {
      Exchange *e = (Exchange *) child(0)->castToRelExpr();
      if (!e->getExtractProducerFlag())
        extractPlanLooksOK = FALSE;
    }
    // fix for soln 10-090506-1407: parallel extract for a union distinct 
    // can sometimes have root->mapvalueidsl->exchange. It should be OK.
    else if (child(0)->getOperatorType() == REL_MAP_VALUEIDS &&
             child(0)->child(0)->getOperatorType() == REL_EXCHANGE)
    {
      Exchange *e = (Exchange *) child(0)->child(0)->castToRelExpr();
      if (!e->getExtractProducerFlag())
        extractPlanLooksOK = FALSE;
    }
    else
    {
      extractPlanLooksOK = FALSE;
    }
    if (!extractPlanLooksOK)
    {
      *CmpCommon::diags() << DgSqlCode(-7004);
      GenExit();
      return NULL;
    }
  }
  
  // Accumulate the values that are provided as inputs by my parent
  // together with the values that are produced as outputs by my
  // children. Use these values for rewriting the VEG expressions.
  getInputValuesFromParentAndChildren(availableValues);

  // Rebuild the computable expressions using a bridge value, if possible
  compExpr().replaceVEGExpressions
                (availableValues, getGroupAttr()->getCharacteristicInputs());
  // Rebuild the required order
  reqdOrder().replaceVEGExpressions
                 (availableValues, getGroupAttr()->getCharacteristicInputs());
  // Rebuild the pkey list
  pkeyList().replaceVEGExpressions
                 (availableValues, getGroupAttr()->getCharacteristicInputs());

  // add internally generated inputs to the input vars and make sure that
  // the root isn't left with "pulled" input values that aren't "internal"
  // inputs (the assert will most likely fire for leftover partition input
  // variables)
  inputVars().insertSet(generator->getInternalInputs());
  pulledNewInputs -= (ValueIdSet) inputVars();
  GenAssert(pulledNewInputs.isEmpty(),"root can't produce these values");

  // Do not rollback on error for INTERNAL REFRESH commands.
  if (isRootOfInternalRefresh())
    {
      generator->setUpdErrorInternalOnError(TRUE);
      generator->setUpdAbortOnError(FALSE);
      generator->setUpdPartialOnError(FALSE);
      generator->setUpdSavepointOnError(FALSE);
    }

  // do not abort transaction for internal compiles, even if abort
  // is needed for this statement.
  // Catman depends on no abort for individual IUD stmts.
  // It aborts the transaction when it gets an error from cli.
  if ( ( CmpCommon::context()->internalCompile() == CmpContext::INTERNAL_MODULENAME ) ||
       ( CmpCommon::statement()->isSMDRecompile() )
     )
    {
      generator->setUpdErrorInternalOnError(TRUE);
      generator->setUpdAbortOnError(FALSE);
      generator->setUpdPartialOnError(FALSE);
      generator->setUpdSavepointOnError(FALSE);
    }

  oltOptInfo().setOltCliOpt(generator->oltOptInfo()->oltCliOpt());

  if ((isTrueRoot()) &&
      (CmpCommon::getDefault(LAST0_MODE) == DF_ON) &&
      (child(0)))
      {
	OperatorTypeEnum op = child(0)->getOperatorType();
	if (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)
	  {
	    // do not return any rows at runtime.
	    // Setting of -2 tells executor to simulate [last 0]
	    // without having to put [last 0] in the query.
	    setFirstNRows(-2);
	  }
      }

  if (isTrueRoot())
    {
      // if warnings 6008 or 6011 were raised, set missingStats indication.
      if (CmpCommon::diags()->containsWarning(SINGLE_COLUMN_STATS_NEEDED) ||
	  CmpCommon::diags()->containsWarning(SINGLE_COLUMN_STATS_NEEDED_AUTO)) 
      {
	generator->compilerStatsInfo().setMissingStats(TRUE);
      }

      // change the following number(16) to whatever is considered 'large'.
      //#define LARGE_NUMBER_OF_JOINS 16      
      //if (generator->compilerStatsInfo().totalJoins() > LARGE_NUMBER_OF_JOINS)
      //generator->compilerStatsInfo().setLargeNumOfJoins(TRUE);

      // set mandatoryXP indication in generator.
      if (hasMandatoryXP()) 
      generator->compilerStatsInfo().setMandatoryCrossProduct(TRUE);

      // Remember # of BMOs that children's preCodeGen found for my fragment.
      setNumBMOs( generator->replaceNumBMOs(prevNumBMOs) );

      // Compute the total available memory quota for BMOs
      NADefaults &defs               = ActiveSchemaDB()->getDefaults();

      // total per node
      double m = defs.getAsDouble(BMO_MEMORY_LIMIT_PER_NODE_IN_MB) * (1024*1024);

      generator->setBMOsMemoryLimitPerNode(m);

    }


  if (isTrueRoot())
    {
      if (generator->isAqrWnrInsert())
        {
          ExeUtilWnrInsert * wi = new(generator->getBindWA()->wHeap())
            ExeUtilWnrInsert(generator->utilInsertTable(),
                             child(0)->castToRelExpr());
          child(0)->markAsBound();
          wi->bindNode(generator->getBindWA());
          if (generator->getBindWA()->errStatus())
            return NULL;

          // Use the same characteristic inputs and outputs as my child
          wi->setGroupAttr(new(generator->wHeap())
                           GroupAttributes(*(child(0)->getGroupAttr())));

          //pass along some of the  estimates
          wi->setEstRowsUsed(child(0)->getEstRowsUsed());
          wi->setMaxCardEst(child(0)->getMaxCardEst());
          wi->setInputCardinality(child(0)->getInputCardinality());
          wi->setPhysicalProperty(child(0)->getPhysicalProperty());
          wi->setOperatorCost(0);
          wi->setRollUpCost(child(0)->getRollUpCost());

          if (! wi->preCodeGen(generator,
                    getGroupAttr()->getCharacteristicInputs(),
                    pulledNewInputs))
            return NULL;

          child(0) = wi;
        }

    }

  
  // if blob values are being selected out, retrieve them and return them either in file
  // or as a stream
  if (isTrueRoot())
    {
      RETDesc * rd = getRETDesc();
      const ColumnDescList * cdl = rd->getColumnList();
      for (CollIndex i = 0; i < compExpr().entries(); i++)
	{
	  ValueId val_id = compExpr()[i];
	  ItemExpr * expr = val_id.getItemExpr();
	  if ((val_id.getType().isLob()))/* &&
	      ((expr->getOperatorType() == ITM_BASECOLUMN) ||
              (expr->getOperatorType() == ITM_INDEXCOLUMN)))*/
	    {
	      LOBconvertHandle * lc = new(generator->wHeap())
		LOBconvertHandle(val_id.getItemExpr(), LOBoper::STRING_);
	      
	      lc->bindNode(generator->getBindWA());
	      lc->preCodeGen(generator);
	      
	      compExpr().removeAt(i);
	      compExpr().insertAt(i, lc->getValueId());

	      ColumnDesc  *cd = (*cdl)[i];
	      
	      NAColumn * col = cd->getValueId().getNAColumn(TRUE);
              if (col)
                {
                  lc->lobNum() = col->lobNum();
                  lc->lobStorageType() = col->lobStorageType();
                  lc->lobStorageLocation() = col->lobStorageLocation();
                }
	      cd->setValueId(lc->getValueId());

	      rd->changeNATypeForUserColumnList(i, &lc->getValueId().getType());

	    }
	} // for

   
      if (getPredExprTree())
        {
          getPredExprTree()->preCodeGen(generator);
        }
    } // isTrueRoot
  
  setHdfsAccess(generator->hdfsAccess());

  generator->finetuneBMOEstimates();

  markAsPreCodeGenned();

#ifdef _DEBUG
  if(getenv("SHOW_PLAN"))
  {
    NAString plan;
    unparse(plan);
    printf("PLAN: %s\n",convertNAString(plan,generator->wHeap()));
  }
#endif

  return this;
} // RelRoot::preCodeGen

RelExpr * Join::preCodeGen(Generator * generator,
			   const ValueIdSet & externalInputs,
			   ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  // Check if the pivs of this operator and it's child are the same.
  // If they are not, make them the same.
  replacePivs();

  // In the case of an embedded insert,
  // and there is a selection predicate,
  // we need to retrieve the stored available outputs
  // from the GenericUpdate group attr.

  ValueIdSet availableGUOutputs;

  // clear any prefix sort key 
  generator->clearPrefixSortKey();

  if (getGroupAttr()->isEmbeddedInsert() &&
      !selectionPred().isEmpty()         &&
      getArity() > 1)
    {
      if (child(1)->getArity() > 0)
	child(1)->child(0)->getInputAndPotentialOutputValues(availableGUOutputs);
    }


  NABoolean isALeftJoin = (getOperator().match(REL_ANY_LEFT_JOIN));
  NABoolean isARightJoin = (getOperator().match(REL_ANY_RIGHT_JOIN));
  ValueIdSet availableValues;
  ValueIdSet childPulledInputs;

   if (isALeftJoin)
    {
      ValueId instNullId, exprId, vid;

      // Prune the nullInstatiatedOutputs list.Retain only those values
      // that are either:
      //   1) The external dataflow inputs to the Join.
      //   2) The Characteristic Outputs of the Join.
      //   3) The Characteristic Outputs of the first child of the Join.
      //   4) Values required for evaluating the selection expression
      //      on the Join.
      // Discard all other values.

      availableValues = getGroupAttr()->getCharacteristicInputs();
      availableValues += child(0)->getGroupAttr()->getCharacteristicOutputs();

      ValueIdSet discardSet;
      CollIndex ne = nullInstantiatedOutput().entries();
      for (CollIndex j = 0; j < ne; j++) 
	{
	  instNullId = nullInstantiatedOutput_[j];
	  GenAssert(instNullId.getItemExpr()->getOperatorType() == ITM_INSTANTIATE_NULL,"NOT instNullId.getItemExpr()->getOperatorType() == ITM_INSTANTIATE_NULL");
	  // Access the operand of the InstantiateNull
	  exprId = (((InstantiateNull *)(instNullId.getItemExpr()))
					    ->getExpr()->getValueId());
	  if ( (NOT availableValues.contains(exprId)) AND
	       (NOT getGroupAttr()->getCharacteristicOutputs()
		                      .referencesTheGivenValue(instNullId, vid)) AND
	       (NOT selectionPred().referencesTheGivenValue(instNullId, vid)) )
            {
	      discardSet += nullInstantiatedOutput_[j];
            }
	}
      // Delete all those elements that do not require null instantiation.
      for (exprId = discardSet.init(); discardSet.next(exprId);
	   discardSet.advance(exprId))
	{
	  nullInstantiatedOutput_.remove(exprId);
	}
    } // endif (getOperator().match(REL_ANY_LEFT_JOIN))
  else                                 // Null Instantiation will not be necessary.
    nullInstantiatedOutput().clear();  // clear in case a LJ was transformed to an IJ


  if (isARightJoin)
    {
      ValueId instNullIdForRightJoin, exprIdForRightJoin, vidForRightJoin;
      ValueIdSet discardSetForRightJoin;

      // Prune the nullInstatiatedOutputs list.Retain only those values
      // that are either:
      //   1) The external dataflow inputs to the Join.
      //   2) The Characteristic Outputs of the Join.
      //   3) The Characteristic Outputs of the second  child of the Join.
      //   4) Values required for evaluating the selection expression
      //      on the Join.
      // Discard all other values.

      availableValues = getGroupAttr()->getCharacteristicInputs();
      availableValues += child(1)->getGroupAttr()->getCharacteristicOutputs();

      CollIndex neR = nullInstantiatedForRightJoinOutput().entries();
      for (CollIndex j = 0; j < neR; j++) 
	{
	  instNullIdForRightJoin = nullInstantiatedForRightJoinOutput_[j];
	  GenAssert(instNullIdForRightJoin.getItemExpr()->getOperatorType() == ITM_INSTANTIATE_NULL,"NOT instNullId.getItemExpr()->getOperatorType() == ITM_INSTANTIATE_NULL");
	  // Access the operand of the InstantiateNull
	  exprIdForRightJoin  = (((InstantiateNull *)(instNullIdForRightJoin.getItemExpr()))
					    ->getExpr()->getValueId());
	  if ( (NOT availableValues.contains(exprIdForRightJoin)) AND
	       (NOT getGroupAttr()->getCharacteristicOutputs()
		                      .referencesTheGivenValue(instNullIdForRightJoin, 
							       vidForRightJoin)) AND
	       (NOT selectionPred().referencesTheGivenValue(instNullIdForRightJoin, 
							    vidForRightJoin)) )
            {
	      discardSetForRightJoin += nullInstantiatedForRightJoinOutput_[j];
            }
	}
      // Delete all those elements that do not require null instantiation.
      for (exprIdForRightJoin = discardSetForRightJoin.init(); 
	   discardSetForRightJoin.next(exprIdForRightJoin);
	   discardSetForRightJoin.advance(exprIdForRightJoin))
	{
	  nullInstantiatedForRightJoinOutput_.remove(exprIdForRightJoin);
	}
    } // endif (getOperator().match(REL_ANY_RIGHT_JOIN))
  else                                 // Null Instantiation will not be necessary.
    nullInstantiatedForRightJoinOutput().clear();  // clear in case a LJ was transformed to an IJ
  
  // Resolve the VEGReferences and VEGPredicates, if any, that appear
  // in the Characteristic Inputs, in terms of the externalInputs.
  getGroupAttr()->resolveCharacteristicInputs(externalInputs);
  availableValues = getGroupAttr()->getCharacteristicInputs();

  bool precodeHalloweenLHSofTSJ = false;
  bool savePrecodeHalloweenLHSofTSJ = false;
  if ((getHalloweenForceSort() != NO_SELF_REFERENCE) &&
      (generator->getR251HalloweenPrecode()))
  {
    savePrecodeHalloweenLHSofTSJ = 
          generator->setPrecodeHalloweenLHSofTSJ(true);
    precodeHalloweenLHSofTSJ  = true;
    
    if (getHalloweenForceSort() == FORCED)
      generator->setHalloweenSortForced();
  }
  
  NABoolean savedOltMsgOpt = generator->oltOptInfo()->oltMsgOpt();

  // My Characteristic Inputs become the external inputs for my left child.
  child(0) = child(0)->preCodeGen(generator,availableValues,childPulledInputs);
  if (! child(0).getPtr())
    return NULL;

  // For HashJoin Min/Max optimization 
  if (isHashJoin()) 
    {
      HashJoin *hj = (HashJoin *)this;

      for(CollIndex i = hj->getStartMinMaxIndex(); i < hj->getEndMinMaxIndex(); i++) 
        {
          // A scan may have decided to use the min/max values that
          // belongs to this join, remove them from the
          // childPulledInputs.  We do not need to pull them from the
          // parent as this Hash Join will generate them.
          if(generator->getWillUseMinMaxKeys()[i] != NULL_VALUE_ID) {
            childPulledInputs -= generator->getMinVals()[i];
            childPulledInputs -= generator->getMaxVals()[i];
          }

          // Clear the candidate values generated by this HashJoin, We
          // are done with the left child, so no one else can use
          // these values.
          generator->getMinMaxKeys()[i] = NULL_VALUE_ID;
          generator->getMinVals()[i] =  NULL_VALUE_ID;
          generator->getMaxVals()[i] = NULL_VALUE_ID;

        }

      // if we have both equi join preds and a beforejoin pred
      // Set a flag that will cause beforeJoinPred to be evaluated prior
      // join equi pred during execution. This helps with join explosion
      // if there are frequent matching values and the beforeJoinPred is
      // highly selective. There is no downside to evaluating beforeJoinPred
      // early, if it contains vids from outer only
      if (!(getEquiJoinPredicates().isEmpty() || getJoinPred().isEmpty() || 
	    isAntiSemiJoin()))
      {
	ValueIdSet coveredPreds, dummy2, dummy3, uncoveredPreds ;
	child(0)->getGroupAttr()->coverTest(getJoinPred(),
					    getGroupAttr()->getCharacteristicInputs(),
					    coveredPreds, dummy2, NULL,
					    &uncoveredPreds);
	// set the flag only if all the non-equi-join preds are covered
	if  ((getJoinPred().entries() == coveredPreds.entries()) &&
	      uncoveredPreds.isEmpty())
	  setBeforeJoinPredOnOuterOnly();
      }

    }

  if (precodeHalloweenLHSofTSJ)
  {
    generator->setPrecodeHalloweenLHSofTSJ(savePrecodeHalloweenLHSofTSJ);
    if (generator->getUnblockedHalloweenScans() == 0)
      {
        // Turn off DP2_LOCKS for codeGen, using either the FORCED_SORT
        // or PASSIVE values.
        if (getHalloweenForceSort() == FORCED)
          {
            generator->setHalloweenProtection(Generator::FORCED_SORT);
         }
        else
          generator->setHalloweenProtection(Generator::PASSIVE);
      }
    else if (updateSelectValueIdMap() && updateTableDesc() && 
	    (NOT updateTableDesc()->getNATable()->getClusteringIndex()->hasSyskey()))
      {
        // if the key columns of the table being inserted into are 
        // equal to constants or inputs then no sort is required 
        // to enforce Halloween blocking. Example statements are
        // update tt set a = 1  ;(a is the primary key for table tt)
        // insert into tt select * from tt where a = 1 ;
        ValueIdList reqdOrder ;
        updateSelectValueIdMap()->rewriteValueIdListDown(
            updateTableDesc()->getClusteringIndex()->getOrderOfKeyValues(),
            reqdOrder);
        reqdOrder.removeCoveredExprs(
            getGroupAttr()->getCharacteristicInputs());
        if (reqdOrder.isEmpty())
          {
            generator->setHalloweenProtection(Generator::PASSIVE);
          }
      }
  }

  NABoolean leftMultipleRowsReturned =
    generator->oltOptInfo()->multipleRowsReturned();

  // if nested join and left child could return multiple rows, then
  // disable olt msg opt for the right child. This is done since
  // olt msg opt can only handle input and output of max 1 row.
  if ((getOperatorType() == REL_NESTED_JOIN) ||
      (getOperatorType() == REL_LEFT_NESTED_JOIN) ||
      (getOperatorType() == REL_NESTED_SEMIJOIN) ||
      (getOperatorType() == REL_NESTED_ANTI_SEMIJOIN) ||
      (getOperatorType() == REL_NESTED_JOIN_FLOW))
    {
      if (generator->oltOptInfo()->multipleRowsReturned())
	{
	  generator->oltOptInfo()->setOltMsgOpt(FALSE);
	}
    }

  // process additional input value ids the child wants
  // (see RelExpr::preCodeGen())
  getGroupAttr()->addCharacteristicInputs(childPulledInputs);
  pulledNewInputs += childPulledInputs;
  availableValues += childPulledInputs;
  childPulledInputs.clear();

  // If this is a tuple substitution join that is implemented by the nested join
  // method, then the values produced as output by my left child can be used as
  // "external" inputs by my right child.
  NABoolean replicatePredicates = TRUE;
  
  ValueIdSet joinInputAndPotentialOutput;
  getInputAndPotentialOutputValues(joinInputAndPotentialOutput);

  if (isTSJ() || beforeJoinPredOnOuterOnly())
    {
      availableValues += child(0)->getGroupAttr()->getCharacteristicOutputs();

      // For a TSJ the joinPred() is a predicate between the inputs
      // and the first child that could not be pushed down to the first
      // child because it is either a left join or an anti-semi-join

      // if beforeJoinPredOnOuterOnly is true, then we have an outer join
      // and an other_join_predicate that has values from the outer side alone
      // We do not need the inner row to evaluate the other_join_predicate 
      // in this case.

      // Rebuild the join predicate tree now
      joinPred().replaceVEGExpressions
                    (availableValues,
                     getGroupAttr()->getCharacteristicInputs(),
                     FALSE, // no key predicates here
                     0 /* no need for idempotence here */,
                     replicatePredicates,
                     NULL /* not a groupByAgg */,
                     &joinInputAndPotentialOutput
                    );
    }

  bool didSetRHS = false;
  bool saveSetRHS = false;
  if (generator->getPrecodeHalloweenLHSofTSJ() &&
      isNestedJoin())
  {
    saveSetRHS = generator->setPrecodeRHSofNJ(true);
    didSetRHS = true;
  }

  // Process the right child
  child(1) = child(1)->preCodeGen(generator,availableValues,childPulledInputs);

  if (! child(1).getPtr())
    return NULL;

  if (didSetRHS)
    generator->setPrecodeRHSofNJ(saveSetRHS);

  NABoolean rightMultipleRowsReturned =
    generator->oltOptInfo()->multipleRowsReturned();

  if (leftMultipleRowsReturned || rightMultipleRowsReturned)
    generator->oltOptInfo()->setMultipleRowsReturned(TRUE);

  // process additional input value ids the child wants
  // (see RelExpr::preCodeGen())
  getGroupAttr()->addCharacteristicInputs(childPulledInputs);
  pulledNewInputs += childPulledInputs;

  // Accumulate the values that are provided as inputs by my parent
  // together with the values that are produced as outputs by my
  // children. Use these values for rewriting the VEG expressions.
  getInputValuesFromParentAndChildren(availableValues);

  // Rebuild the join predicate tree, for the general case where both inner
  // and outer row is needed to evaluate the predicate.
  if (! (isTSJ() || beforeJoinPredOnOuterOnly()))
    joinPred().replaceVEGExpressions
                  (availableValues,
		   getGroupAttr()->getCharacteristicInputs(),
		   FALSE, // no key predicates here
		   0 /* no need for idempotence here */,
		   replicatePredicates,
                   NULL /* not a groupByAgg */,
                   &joinInputAndPotentialOutput
                  );

  if (isALeftJoin)
    {

      // Replace the operands of the ITM_INSTANTIATE_NULL with values from
      // the Characteristic Outputs of the right child.
      // The following values are available for resolving the nullInstantiatedOuptut
      //   1) The external dataflow inputs to the Join.
      //   2) The Characteristic Outputs of the second (right) child of the Join.
      //   3) The Characteristic Outputs of the first(left)child of the Join.
      //      Needed when nested_join plan is chosen.

      availableValues = getGroupAttr()->getCharacteristicInputs();
      availableValues += child(1)->getGroupAttr()->getCharacteristicOutputs();
      availableValues += child(0)->getGroupAttr()->getCharacteristicOutputs();

      nullInstantiatedOutput_.replaceOperandsOfInstantiateNull
                                 (availableValues,
				  getGroupAttr()->getCharacteristicInputs());
    }

  if (isARightJoin)
    {

      // Replace the operands of the ITM_INSTANTIATE_NULL with values from
      // the Characteristic Outputs of the left child.
      // The following values are available for resolving the nullInstantiatedForRightJoinOutput
      //   1) The external dataflow inputs to the Join.
      //   2) The Characteristic Outputs of the first (left) child of the Join.

      availableValues = getGroupAttr()->getCharacteristicInputs();
      availableValues += child(0)->getGroupAttr()->getCharacteristicOutputs();

      nullInstantiatedForRightJoinOutput_.replaceOperandsOfInstantiateNull
	(availableValues,
	 getGroupAttr()->getCharacteristicInputs());
    }

  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  getInputAndPotentialOutputValues(availableValues);

  // If this is an embedded insert, with a selection predicate,
  // add in the characteristic outputs from the generic update RelExpr
  if (getGroupAttr()->isEmbeddedInsert() &&
      !selectionPred().isEmpty())
    {
      availableValues += availableGUOutputs;
    }

  // Rebuild the selection predicate tree.
  selectionPred().replaceVEGExpressions
                     (availableValues,
		      getGroupAttr()->getCharacteristicInputs(),
		      FALSE, // no need for key predicates here
		      0 /* no need for idempotence here */,
		      replicatePredicates
		     );

  //New code was added to avoid the following situation:
  //
  // Query: select max(t1.a) from t1,t2 where t1.a = t2.b;
  // Plan:         shortcut_groupby
  //                        |
  //                  esp_exchange
  //                        |
  //                    merge_join in parallel 4 ways on
  //                        |
  //                    |         |
  //                  scan t2    scan T1
  //
  //   By the time we get to precodegen merge_join has orderby
  //  on VEG(a,b) and characteristic output VEG(a,b)
  //  because scan T2 get precode gen'd first it resolves its
  //  orderby VEG(a,b) to t2.b this also changes orderby VEG
  //  in merge_join and thereafter to T2.b. Now when merge join
  // resolves it characteristic output it resolves it to T1.a because
  // T1 is first in the from clause and T1.a has a smaller value id and
  // so the combined set of T1. and T2's characteristic output has T1.a
  // in front of T2.b. Now esp_exchange during code gen time expects
  // T2.b to be characteristic output of the child because it needs to
  // do merge of sorted streams of its orderby value which is T2.b.
  // this causes an assertion failure because merge_join produces T1.a.
  // Following code counters that by making sure that if the sort key is
  // part of the available values then characteristic output first gets
  // resolved by sortkey then by rest of the available values.
  //

  ValueIdSet sortKey = getPhysicalProperty()->getSortKey();
  sortKey = sortKey.simplifyOrderExpr();
  sortKey.intersectSet(availableValues);

  if(sortKey.entries())
  {
    ValueIdSet reqOutput = getGroupAttr()->getCharacteristicOutputs();
    ValueIdSet copyOfSet(reqOutput);
    ValueIdSet inputValues;
    ValueIdSet newExpr;
    ItemExpr * iePtr;
  // ---------------------------------------------------------------------
  // Iterate over the predicate factors in the given predicate tree.
  // ---------------------------------------------------------------------
  for (ValueId exprId = copyOfSet.init();
        copyOfSet.next(exprId); copyOfSet.advance(exprId))
    {
      // -----------------------------------------------------------------
      // Walk through the item expression tree and replace any
      // VEGPredicates or VEGReferences that are found.
      // -----------------------------------------------------------------
      iePtr = exprId.getItemExpr()->replaceVEGExpressions(availableValues,
							  inputValues,
							  FALSE,
							  NULL,
							  FALSE);
      if (iePtr)			      // expression was not discarded
	{
	  iePtr->synthTypeAndValueId(TRUE);   // redrive type synthesis
          if (iePtr != exprId.getItemExpr())  // a replacement was done
	    {
	      reqOutput.subtractElement(exprId);        // remove existing ValueId
	      reqOutput += iePtr->getValueId(); // replace with a new one
	    }
	}

    } // loop over predTree



    getGroupAttr()->setCharacteristicOutputs(reqOutput);
  }
  // Rewrite the Characteristic Outputs.
  getGroupAttr()->resolveCharacteristicOutputs
                     (availableValues,
		      getGroupAttr()->getCharacteristicInputs());

  // propagate the children olt settings in case of a pushed down to dp2 NLJ
  if ( !getPhysicalProperty()->executeInDP2() OR
       !(generator->getBindWA()->getTopRoot()->getInliningInfo()).isUsedForMvLogging()
     )
  {

     generator->oltOptInfo()->setOltMsgOpt(savedOltMsgOpt);
  }

  // In the case of an embedded insert,
  // set the generator is embedded insert flag to TRUE.

  if (getGroupAttr()->isEmbeddedInsert())
    generator->setEmbeddedInsert(TRUE) ;
  
  markAsPreCodeGenned();

  // Done.
  return this;
} // Join::preCodeGen()

RelExpr * GenericUtilExpr::preCodeGen(Generator * generator,
				      const ValueIdSet & externalInputs,
				      ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! RelExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  if (xnNeeded())
    {
      generator->setUpdSavepointOnError(FALSE);
      generator->setUpdPartialOnError(FALSE);
    }

  markAsPreCodeGenned();

  // Done.
  return this;
}

RelExpr * ExeUtilExpr::preCodeGen(Generator * generator,
				  const ValueIdSet & externalInputs,
				  ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! GenericUtilExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  if (NOT aqrSupported())
    generator->setAqrEnabled(FALSE);

  markAsPreCodeGenned();

  // Done.
  return this;
}

// xnCanBeStarted is set to true if the whole ddl operation can run in one transaction
// It is set to false, then the DDL implementation methods manages the transaction
short DDLExpr::ddlXnsInfo(NABoolean &isDDLxn, NABoolean &xnCanBeStarted)
{
  ExprNode * ddlNode = getDDLNode();

  xnCanBeStarted = TRUE;
  // When the DDL transaction is not turned on via CQD
  if (NOT ddlXns()) 
  { 
     if ((dropHbase()) ||
       (purgedata()) ||
       (initHbase()) ||
       (createMDViews()) ||
       (dropMDViews()) ||
       (initAuth()) ||
       (dropAuth()) ||
       (createRepos()) ||
       (dropRepos()) ||
       (upgradeRepos()) ||
       (addSchemaObjects()) ||
       (updateVersion()))
     {
        // transaction will be started and commited in called methods.
         xnCanBeStarted = FALSE;
     }
  
     if (((ddlNode) && (ddlNode->castToStmtDDLNode()) &&
       (NOT ddlNode->castToStmtDDLNode()->ddlXns())) &&
      ((ddlNode->getOperatorType() == DDL_DROP_SCHEMA) ||
       (ddlNode->getOperatorType() == DDL_CLEANUP_OBJECTS) ||
       (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY) ||
       (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ALTER_COLUMN_SET_SG_OPTION) ||
       (ddlNode->getOperatorType() == DDL_CREATE_INDEX) ||
       (ddlNode->getOperatorType() == DDL_POPULATE_INDEX) ||
       (ddlNode->getOperatorType() == DDL_CREATE_TABLE) ||
       (ddlNode->getOperatorType() == DDL_ALTER_TABLE_DROP_COLUMN) ||
       (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ALTER_COLUMN_DATATYPE) ||
       (ddlNode->getOperatorType() == DDL_DROP_TABLE)))
     {
        // transaction will be started and commited in called methods.
        xnCanBeStarted = FALSE;
     }
     isDDLxn = FALSE;
  }
  else  // When the DDL transaction is turned on
  {
     isDDLxn = FALSE;
     if (ddlNode && ddlNode->castToStmtDDLNode() &&
        ddlNode->castToStmtDDLNode()->ddlXns())
     isDDLxn = TRUE;

     if (purgedata() || upgradeRepos())
        // transaction will be started and commited in called methods.
        xnCanBeStarted = FALSE;

     if (initHbase() && producesOutput())  // returns status
       xnCanBeStarted = FALSE;

     if ((ddlNode && ddlNode->castToStmtDDLNode() &&
          ddlNode->castToStmtDDLNode()->ddlXns()) &&
            ((ddlNode->getOperatorType() == DDL_CLEANUP_OBJECTS) ||
             (ddlNode->getOperatorType() == DDL_ALTER_TABLE_DROP_COLUMN) ||
             (ddlNode->getOperatorType() == DDL_ALTER_SCHEMA) ||
             (ddlNode->getOperatorType() == DDL_CREATE_INDEX) ||
             (ddlNode->getOperatorType() == DDL_POPULATE_INDEX) ||
             (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ALTER_COLUMN_DATATYPE) ||
             (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY) ||
             (ddlNode->getOperatorType() == DDL_ALTER_TABLE_ALTER_HBASE_OPTIONS) ||
             (ddlNode->getOperatorType() == DDL_ALTER_INDEX_ALTER_HBASE_OPTIONS) ||
             (ddlNode->getOperatorType() == DDL_ALTER_TABLE_RENAME) ||
             (ddlNode->getOperatorType() == DDL_ON_HIVE_OBJECTS)))
     {
        // transaction will be started and commited in called methods.
        xnCanBeStarted = FALSE;
     }
  } 
  return 0;
}

RelExpr * DDLExpr::preCodeGen(Generator * generator,
			      const ValueIdSet & externalInputs,
			      ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;
  
  if (! GenericUtilExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;
  
  if ((specialDDL()) ||
      (initHbase()))
    {
      generator->setAqrEnabled(FALSE);
    }
  
  NABoolean startXn = FALSE;
  NABoolean ddlXns = FALSE;
  if (ddlXnsInfo(ddlXns, startXn))
    return NULL;

  if (ddlXns && startXn)
    xnNeeded() = TRUE;
  else
    xnNeeded() = FALSE;

  markAsPreCodeGenned();
  
  // Done.
  return this;
}

RelExpr * NestedJoinFlow::preCodeGen(Generator * generator,
				     const ValueIdSet &externalInputs,
				     ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  /*  child(0) = child(0)->preCodeGen(
       generator,
       externalInputs,
       pulledNewInputs);
  if (! child(0).getPtr())
    return NULL;
  */

  RelExpr * nj =
    NestedJoin::preCodeGen(generator, externalInputs, pulledNewInputs);

  if (nj == NULL)
    return NULL;


  return nj;
}

RelExpr * NestedJoin::preCodeGen(Generator * generator,
                                 const ValueIdSet &externalInputs,
                                 ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  NABoolean espExchangeWithMerge = FALSE;
  NABoolean childIsBlocking = FALSE;

  if ((getHalloweenForceSort() != NO_SELF_REFERENCE) &&
      (!generator->getR251HalloweenPrecode()))
    {
      GenAssert(Generator::NOT_SELF_REF != generator->getHalloweenProtection(),
              "Inconsistency in Generator and NestedJoin.");

      // Look for either of two patterns on the left hand side:
      // sort or exchange+sort.  
      if (child(0)->getOperatorType() == REL_SORT) 
        childIsBlocking = TRUE;
      else
        if ((child(0)->getOperatorType() == REL_EXCHANGE) &&
            (child(0)->child(0)->getOperatorType() == REL_SORT))
          {
            childIsBlocking = TRUE;

            // The espExchangeWithMerge flag is used to conditionally
            // assert that the exchange will merge.  The assertion
            // is deferred until after preCodeGen on the left subtree,
            // because the Exchange::doesMerge() method should not be
            // called until Exchange::preCodeGen is finished.
            espExchangeWithMerge = TRUE;
          }

      if (childIsBlocking)
        {
          if (getHalloweenForceSort() == FORCED)
            {
              if (espExchangeWithMerge)
                ((Sort *)(child(0)->child(0).getPtr()))->
                        markAsHalloweenProtection();
              else
                ((Sort *)(child(0).getPtr()))->markAsHalloweenProtection();

              generator->setHalloweenProtection(Generator::FORCED_SORT);
           }
          else
            generator->setHalloweenProtection(Generator::PASSIVE);
        }
      else if (updateSelectValueIdMap() && updateTableDesc() && 
	      (NOT updateTableDesc()->getNATable()->getClusteringIndex()->hasSyskey()))
        {
          // if the key columns of the table being inserted into are 
          // equal to constants or inputs then no sort is required 
          // to enforce Halloween blocking. Example statements are
          // update tt set a = 1  ;(a is the primary key for table tt)
          // insert into tt select * from tt where a = 1 ;
          ValueIdList reqdOrder ;
          updateSelectValueIdMap()->rewriteValueIdListDown(
              updateTableDesc()->getClusteringIndex()->getOrderOfKeyValues(),
              reqdOrder);
          reqdOrder.removeCoveredExprs(
              getGroupAttr()->getCharacteristicInputs());
          if (reqdOrder.isEmpty())
            {
              generator->setHalloweenProtection(Generator::PASSIVE);
            }
        }
    }

  // Insert a probe cache above the inner table if applicable
  if ( isProbeCacheApplicable(
       castToRelExpr()->getPhysicalProperty()->getPlanExecutionLocation()
                             )
     )
    {
      ProbeCache *probeCache = 
        new (generator->wHeap()) ProbeCache( 
          child(1), getDefault(GEN_PROBE_CACHE_NUM_ENTRIES),
          generator->wHeap());

      // look for an aggregate right child node
      RelExpr     *rightChildExpr = child(1).getPtr();
      GroupByAgg  *rightChildGrby = NULL;
      RelExpr     *rightChildExch = NULL;
      MapValueIds *rightChildMvi  = NULL;
      ValueIdMap  *optionalMap    = NULL;
      NABoolean   done            = FALSE;

      while (!done)
        {
          if (rightChildExpr->getOperator().match(REL_ANY_GROUP))
            {
              rightChildGrby = (GroupByAgg *) rightChildExpr;
              done = TRUE;
            }
          else if (rightChildExpr->getOperator() == REL_EXCHANGE)
            {
              if (rightChildExch == NULL)
                rightChildExch = rightChildExpr;
              else
                done = TRUE; // can't handle more than one exchange
            }
          else if (rightChildExpr->getOperator() == REL_MAP_VALUEIDS)
            {
              if (rightChildMvi == NULL)
                {
                  rightChildMvi = (MapValueIds *) rightChildExpr;
                  optionalMap   = &rightChildMvi->getMap();
                }
              else
                done = TRUE; // can't handle more than one MVI
            }
          else
            done = TRUE;

          if (!done)
            rightChildExpr = rightChildExpr->child(0);
        }

      // Among other things, this will give the probeCache
      // the characteristic inputs and outputs of the 
      // inner table.
      probeCache->setGroupAttr(new(generator->wHeap())
			    GroupAttributes(*(child(1)->getGroupAttr())));

      // Try to pull up predicates from the child, if that reduces
      // the char. inputs sent to the child. We only try this right
      // now if the child is an aggregate or groupby.
      if (rightChildGrby && 
          CmpCommon::getDefault(NESTED_JOIN_CACHE_PREDS) != DF_OFF &&
          (// if right child exchange exists, it must have same char inputs
           rightChildExch == NULL ||
           rightChildExch->getGroupAttr()->getCharacteristicInputs() ==
           rightChildGrby->getGroupAttr()->getCharacteristicInputs()) &&
          (rightChildMvi == NULL ||
           rightChildMvi->getGroupAttr()->getCharacteristicInputs() ==
           rightChildGrby->getGroupAttr()->getCharacteristicInputs()))
        {
          ValueIdSet pcAvailableInputs(
               probeCache->getGroupAttr()->getCharacteristicInputs());

          // predicates can refer to both char. inputs and outputs
          pcAvailableInputs += 
            probeCache->getGroupAttr()->getCharacteristicOutputs();

          // note that this will overwrite the ProbeCache's selection preds
          rightChildGrby->tryToPullUpPredicatesInPreCodeGen(
               pcAvailableInputs,
               probeCache->selectionPred(),
               optionalMap);

          // adjust char. inputs of intervening nodes - this is not
          // exactly good style, just overwriting the char. inputs, but
          // hopefully we'll get away with it at this stage in the
          // processing
          if (rightChildExch)
            rightChildExch->getGroupAttr()->setCharacteristicInputs(
                 rightChildGrby->getGroupAttr()->getCharacteristicInputs());
          if (rightChildMvi)
            rightChildMvi->getGroupAttr()->setCharacteristicInputs(
                 rightChildGrby->getGroupAttr()->getCharacteristicInputs());
        }

      // propagate estimates, physical properties, and costings 
      // from the child to the ProbeCache:
      probeCache->setEstRowsUsed(child(1)->getEstRowsUsed());
      probeCache->setMaxCardEst(child(1)->getMaxCardEst());
      probeCache->setInputCardinality(child(1)->getInputCardinality());
      probeCache->setPhysicalProperty(child(1)->getPhysicalProperty());
      probeCache->setOperatorCost(0);
      probeCache->setRollUpCost(child(1)->getRollUpCost());

      // Glue the ProbeCache to the NestedJoin's right leg.
      child(1) = probeCache;
    }                     
  if (isTSJForUndo())
  {
  
    Sort *sortNode = new(generator->wHeap()) Sort(child(0));

      ItemExpr *sk = new (generator->wHeap()) SystemLiteral(1);
      sk->synthTypeAndValueId(TRUE);

      ValueIdList skey;
      skey.insert(sk->getValueId());

      sortNode->getSortKey() = skey;

    // Use the same characteristic inputs and outputs as the left child
    sortNode->setGroupAttr(new(generator->wHeap())
			   GroupAttributes(*(child(0)->getGroupAttr())));
    //pass along some of the  estimates 
    sortNode->setEstRowsUsed(child(0)->getEstRowsUsed());
    sortNode->setMaxCardEst(child(0)->getMaxCardEst());
    sortNode->setInputCardinality(child(0)->getInputCardinality());
    sortNode->setPhysicalProperty(child(0)->getPhysicalProperty());
    sortNode->setCollectNFErrors();
    sortNode->setOperatorCost(0);
    sortNode->setRollUpCost(child(0)->getRollUpCost());
    child(0) = sortNode;
  }

  if ( childIsBlocking && 
      generator->preCodeGenParallelOperator() )
  {
    if (espExchangeWithMerge == FALSE) 
    {
      // A "halloween sort" needs to ensure that if it is parallel, but executes
      // in the same ESP as the generic update's TSJ flow node, then the Sort
      // will block until all scans are finished.  
      ((Sort *)(child(0).getPtr()))->doCheckAccessToSelfRefTable();
    }
    else
    {
      // An ESP Exchange can be eliminated in its preCodeGen method if it is 
      // redundant.  If this happens, then the Sort will be executing in the 
      // same ESP as the TSJ after all.  So we set this flag now, so that the 
      // Exchange preCodeGen will call doCheckAccessToSelfRefTable() for the 
      // Sort before eliminating itself.  This is part of the fix for Sol 
      // 10-090310-9876.
      ((Exchange *)(child(0).getPtr()))->markHalloweenSortIsMyChild();
    }
  }
  RelExpr * re =
    Join::preCodeGen(generator, externalInputs, pulledNewInputs);

  if ( espExchangeWithMerge &&
      (child(0)->getOperatorType() == REL_EXCHANGE))
    GenAssert(((Exchange *)((RelExpr *)child(0)))->doesMerge(), 
      "Exchange operator does not block for Halloween problem.");

  generator->compilerStatsInfo().nj()++;

  return re;
}


RelExpr * MergeJoin::preCodeGen(Generator * generator,
				const ValueIdSet & externalInputs,
				ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! Join::preCodeGen(generator, externalInputs, pulledNewInputs))
    return 0;

  // Accumulate the values that are provided as inputs by my parent
  // together with the values that are produced as outputs by my
  // children. Use these values for rewriting the VEG expressions.
  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);

  // find if the left child and/or the right child will have atmost
  // one matching row. If so, an faster merge join implementation
  // will be used at runtime.
  ValueIdSet vidSet = getOrderedMJPreds();
  ValueIdSet valuesUsedForPredicates;

  computeValuesReqdForPredicates(vidSet,
				 valuesUsedForPredicates);
  leftUnique() =
    child(0)->getGroupAttr()->isUnique(valuesUsedForPredicates);

  rightUnique() =
    child(1)->getGroupAttr()->isUnique(valuesUsedForPredicates);


  ValueIdList mjp(getOrderedMJPreds());

  NABoolean replicatePredicates = TRUE;
  /* For merge join the characteristic outputs have already been resolved 
     by the time the equijoin preds are resolved below. The outputs are 
     resolved at the very end of Join::precodegen, which was called a few
     lines above. Therefore when we resolve the equijoin preds we have 
     only the actually resolved output values available. We do not have 
     all the potential output values available. 
  */
  ValueIdSet joinInputAndOutputValues;
  joinInputAndOutputValues = getGroupAttr()->getCharacteristicInputs();
  joinInputAndOutputValues += getGroupAttr()->getCharacteristicOutputs();

  // Pass in the children GAs so that the equipreds can have one side
  // resolved to one child and the other side resolved to the other child.
  // solution 10-100722-1962
  mjp.replaceVEGExpressions
         (availableValues,
	  getGroupAttr()->getCharacteristicInputs(),
	  FALSE, // no key predicates here
	  0 /* no need for idempotence here */,
	  replicatePredicates,
          NULL /* not a groupByAgg */,
          &joinInputAndOutputValues,
          NULL /* no indexDesc since we have no key preds*/,
          child(0)->getGroupAttr(),
          child(1)->getGroupAttr());

  // must have at least 1 merge join predicate
  GenAssert(!mjp.isEmpty(),"mjp.isEmpty()");

  // The generator expects the merge join predicates to be in the form
  // leftcol = rightcol where leftcol references a column from the left
  // table and rightcol references a column from the right table. Switch
  // the expression if it is the other way around. Also handle rare cases
  // where a VEGPred is resolved into two equalities connected by an AND.
  //
  ValueIdSet dummy1;
  ValueIdList newJoinPreds;
  ValueIdList newLeftOrder;
  ValueIdList newRightOrder;
  CollIndex ne = (CollIndex)(mjp.entries());
  NABoolean isANewJoinPred ;

  for (CollIndex i = 0; i < ne; i++)
  {
    // Will store all the conjuncts under the pred mjp[i] being considered.
    ValueIdSet conjuncts;
    conjuncts.clear();
    conjuncts.insert(mjp[i]);
    ValueIdSet finerConjuncts;

    do
    {
      finerConjuncts.clear();
      // Go through the set of conjuncts, breaking down any AND seen into
      // finer conjuncts.
      //
      for (ValueId vid = conjuncts.init();
                         conjuncts.next(vid);
                         conjuncts.advance(vid))
      {
        ItemExpr *pred = vid.getItemExpr();

        if (pred->getOperatorType() == ITM_AND)
        {
          // Found another AND, break it down into finer conjuncts. Store
          // them in finerConjuncts so that we can return to them later.
          //
          finerConjuncts.insert(pred->child(0)->getValueId());
          finerConjuncts.insert(pred->child(1)->getValueId());
        }
        else
        {
          // This is the "finest" conjunct - cannot be broken down further.
          // Make sure it's in the form of (leftCol = rightCol). Add the
          // equality predicate to the final list of MJ predicates. leftOrder
          // and rightOrder are set up correspondingly so that they match up
          // with the predicates.
          //
          GenAssert(pred->getOperatorType() == ITM_EQUAL,
                   "pred->getOperatorType() != ITM_EQUAL");

          ItemExpr *left = pred->child(0)->castToItemExpr();
          ItemExpr *right = pred->child(1)->castToItemExpr();
          isANewJoinPred = TRUE;

          NABoolean child0Covered = child(0).getGroupAttr()->covers(left->getValueId(),
					      getGroupAttr()->getCharacteristicInputs(),
					      dummy1) ;

          NABoolean child1Covered = child(1).getGroupAttr()->covers(right->getValueId(),
						  getGroupAttr()->getCharacteristicInputs(),
						  dummy1) ;

          if (NOT (child0Covered && child1Covered))
          {
	    //++MV - Irena
	    // save the pred's specialNulls_ flag before replacing the pred
 	    BiRelat *biRelat = new(generator->wHeap()) BiRelat(ITM_EQUAL, right, left);
	    // restore specialNulls_
	    biRelat->setSpecialNulls(((BiRelat*)pred)->getSpecialNulls());
	    biRelat->bindNode(generator->getBindWA());
	    pred = biRelat;
	    //--MV - Irena
	    
	    child0Covered = child(0).getGroupAttr()->covers(right->getValueId(),
						  getGroupAttr()->getCharacteristicInputs(),
						  dummy1) ;
	    
	    child1Covered = child(1).getGroupAttr()->covers(left->getValueId(),
						  getGroupAttr()->getCharacteristicInputs(),
						  dummy1) ;

            if(!(child0Covered && child1Covered))
            {
              if (isInnerNonSemiJoin())
              {
                selectionPred() += pred->getValueId();
              }
            else
              {
                // for an outer or semi join, the ON clause is stored in "joinPred"
                // while the WHERE clause is stored in "selectionPred".
                joinPred() += pred->getValueId();
              }
              isANewJoinPred = FALSE;
            }
          }

          if (isANewJoinPred)
          {
          // Store the finest conjuncts in the final list of MJ predicates.
          // Make sure the list is matched up with corresponding leftOrder
          // and rightOrder.
          //
          newJoinPreds.insert(pred->getValueId());
          newLeftOrder.insert(getLeftSortOrder()[i]);
          newRightOrder.insert(getRightSortOrder()[i]);
        }
        }
      } // for over conjuncts.

      // Come back to process the new set of broken-down conjuncts if the set
      // is non-empty.
      //
      conjuncts = finerConjuncts;
    } while (NOT conjuncts.isEmpty());
  } // for over mjp.
  if (ne > 0)
    GenAssert(NOT newJoinPreds.isEmpty(), "MergeJoin::PreCodeGen has no resolved join predicates");


  // Count merge join as a Big Memory Operator (BMO) if use of BMO quota
  // is enabled for merge join.
  if (CmpCommon::getDefaultLong(MJ_BMO_QUOTA_PERCENT) != 0)
  {
    generator->incrNumBMOs();
  }

  setOrderedMJPreds(newJoinPreds);
  setLeftSortOrder(newLeftOrder);
  setRightSortOrder(newRightOrder);

  generator->compilerStatsInfo().mj()++;

  markAsPreCodeGenned();
  return this;

} //  MergeJoin::preCodeGen()

RelExpr * HashJoin::preCodeGen(Generator * generator,
			       const ValueIdSet & externalInputs,
			       ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if ( CmpCommon::getDefault(COMPRESSED_INTERNAL_FORMAT) == DF_SYSTEM)
  {
    NABoolean resize = FALSE;
    NABoolean defrag = FALSE;
    ValueIdSet vidSet0 = child(0)->getGroupAttr()->getCharacteristicOutputs();
    ValueIdSet vidSet1 = child(1)->getGroupAttr()->getCharacteristicOutputs();

    ExpTupleDesc::TupleDataFormat tupleFormat =
                  determineInternalFormat( vidSet1,
                                           vidSet0,
                                           this,
                                           resize,
                                           generator,
                                           FALSE,
                                           defrag);

    cacheTupleFormatAndResizeFlag(tupleFormat, resize, defrag);

    if (tupleFormat == ExpTupleDesc::SQLMX_ALIGNED_FORMAT)
    {
      generator->incNCIFNodes();
    }
    else
    {
      generator->decNCIFNodes();
    }
	}	
  // Determine if we should attempt to use the HashJoin min/max optimization.
  NABoolean useMinMaxOpt = 
    ((CmpCommon::getDefault(GEN_HSHJ_MIN_MAX_OPT) == DF_ON) &&
     ! getEquiJoinPredicates().isEmpty() &&
     ! isLeftJoin() &&
     ! isRightJoin() &&
     ! isAntiSemiJoin());

  // These indexes define the subset of min max values which belong to this HashJoin.
  CollIndex startMinMaxIndex = 0;
  CollIndex endMinMaxIndex = 0;

  // If min/max opt is used, these lists are used to hold local copies of the
  // generators min and max values.  These are the min and max values
  // generated by HashJoins that may be used by scans.
  ValueIdList myMinVals;
  ValueIdList myMaxVals;

  // If min/max opt is used, this list are used to hold a local copy
  // of the generators minmaxKeys.  These are the values for which min
  // and max values are available
  ValueIdList myMinMaxKeys;

  if (useMinMaxOpt) {

    // This HashJoin will append to the end of the generator lists.
    //
    startMinMaxIndex = generator->getMinMaxKeys().entries();

    // Find the candidate values from the right hand side of the join.
    // For now, only consider VEGPreds.
    for (ValueId valId = getEquiJoinPredicates().init();
	 getEquiJoinPredicates().next(valId);
	 getEquiJoinPredicates().advance(valId)) {
      ItemExpr * itemExpr = valId.getItemExpr();

      NAType *mmType = NULL;
      if (itemExpr->getOperatorType() == ITM_VEG_PREDICATE) {

        VEGPredicate *vPred = (VEGPredicate *)itemExpr;
        VEGReference *vRef = vPred->getVEG()->getVEGReference();

        mmType = vRef->getValueId().getType().newCopy(generator->wHeap());

      }

      // mmType is the type of the VEGRef relating a left and right value.
      // We will compute the Min and Max using this type
      if(mmType) {

        // Min/Max are typed as nullable.
        mmType->setNullable(true);

        // Construct the host vars which will represent the min and
        // max values for this join key.

        char name[80];
        sprintf(name, "_sys_MinVal%d", generator->getMinMaxKeys().entries());

        ItemExpr *minVal = new(generator->wHeap()) 
          HostVar(name,
                  mmType,
                  TRUE);

        sprintf(name, "_sys_MaxVal%d", generator->getMinMaxKeys().entries());

        ItemExpr *maxVal = new(generator->wHeap())
          HostVar(name,
                  mmType,
                  TRUE);

        minVal->synthTypeAndValueId();
        maxVal->synthTypeAndValueId();

        // Insert the value and min and max into generator lists to
        // make the available to scans as key predicates.
        generator->getMinMaxKeys().insert(itemExpr->getValueId());
        generator->getMinVals().insert(minVal->getValueId());
        generator->getMaxVals().insert(maxVal->getValueId());
        
        // Initialize the 'will use' list to a NULL_VALUE_ID.  A scan
        // that decides to use the min max values will change this
        // entry to be the same as the corresponding entry in the
        // minMaxKeys list.
        generator->getWillUseMinMaxKeys().insert(NULL_VALUE_ID);

      }
    }
    
    // This is the end index (exclusive) for this HashJoin.
    endMinMaxIndex = generator->getMinMaxKeys().entries();

    // Keep local copies of the generators lists.
    myMinVals = generator->getMinVals();
    myMaxVals = generator->getMaxVals();
    myMinMaxKeys = generator->getMinMaxKeys();

  }

  // Register the start and end indexes for this Hash Join
  // (Join::preCodeGen() needs to have access to the indexes)
  setStartMinMaxIndex(startMinMaxIndex);
  setEndMinMaxIndex(endMinMaxIndex);

  if (! Join::preCodeGen(generator, externalInputs, pulledNewInputs))
    return NULL;

  // List for min and max values that will be used by a scan and which
  // will be generated by this HashJoin
  minMaxVals_.clear();
  minMaxCols_.clear();

  {

    // For each min/max value belonging to this HashJoin, check to see
    // if any scan decided to use it.  If so, add the min and max
    // values to the list.  Also, clear the 'will use' entry as no
    // other HashJoin can supply this value.
    for (CollIndex i = startMinMaxIndex; i < endMinMaxIndex; i++)
      {
        if (generator->getWillUseMinMaxKeys()[i] != NULL_VALUE_ID) 
          {

            minMaxVals_.insert(myMinVals[i]);
            minMaxVals_.insert(myMaxVals[i]);

            VEGPredicate *vPred = (VEGPredicate *)myMinMaxKeys[i].getItemExpr();
            VEGReference *vRef = vPred->getVEG()->getVEGReference();

            minMaxCols_.insert(vRef->getValueId());

            generator->getWillUseMinMaxKeys()[i] = NULL_VALUE_ID;
          }
      }

    // If we have some minMaxCols, then replace any VEGReferences.
    if (minMaxCols_.entries()) 
      {
        ValueIdSet availForMinMax;
        availForMinMax += child(1)->getGroupAttr()->getCharacteristicOutputs();
        availForMinMax += getGroupAttr()->getCharacteristicInputs();
        minMaxCols_.replaceVEGExpressions(availForMinMax,
                                          getGroupAttr()->getCharacteristicInputs());
      }
  }

  // Accumulate the values that are provided as inputs by my parent
  // together with the values that are produced as outputs by my
  // children. Use these values for rewriting the VEG expressions.
  ValueIdSet availableValues;


  getInputValuesFromParentAndChildren(availableValues);

  ValueIdSet hjp(getEquiJoinPredicates());

  NABoolean replicatePredicates = TRUE;

  /* For hash join the characteristic outputs have already been resolved 
     by the time the equijoin preds are resolved below. The outputs are 
     resolved at the very end of Join::precodegen, which was called a few
     lines above. Therefore when we resolve the equijoin preds we have 
     only the actually resolved output values available. We do not have 
     all the potential output values available. 
  */
  ValueIdSet joinInputAndOutputValues;
  joinInputAndOutputValues = getGroupAttr()->getCharacteristicInputs();
  joinInputAndOutputValues += getGroupAttr()->getCharacteristicOutputs();

  // Pass in the children GAs so that the equipreds can have one side
  // resolved to one child and the other side resolved to the other child.
  // solution 10-100722-1962
  hjp.replaceVEGExpressions
         (availableValues,
	  getGroupAttr()->getCharacteristicInputs(),
	  FALSE, // no key predicates here
	  0 /* no need for idempotence here */,
	  replicatePredicates,
          NULL /* not a groupByAgg */,
          &joinInputAndOutputValues,
          NULL /* no indexDesc since we have no key preds*/,
          child(0)->getGroupAttr(),
          child(1)->getGroupAttr());
  

  // Will store the rewritten hjp's which compile with the format of
  // leftCol= rightCol.
  //
  ValueIdSet newJoinPreds;

  if (hjp.isEmpty())
  {
  }
  else
  {
    // The generator expects the hash join predicates to be in the form
    // leftcol = rightcol where leftcol references a column from the left
    // table and rightcol references a column from the right table. Switch
    // the expression if it is the other way around. Also handle rare cases
    // where a VEGPred is resolved into two equalities connected by an AND.
    //
    ValueIdSet dummy1;
    NABoolean isANewJoinPred ;


    do
    {
      ValueIdSet finerConjuncts;
      finerConjuncts.clear();


      for (ValueId vid = hjp.init();
                         hjp.next(vid);
                         hjp.advance(vid))
      {
        ItemExpr *pred = vid.getItemExpr();

        // Break this up into the finer conjuncts. Store them in a separate
        // set so that we can return to it later.
        // of the set so that we could return
        if (pred->getOperatorType() == ITM_AND)
        {
          finerConjuncts.insert(pred->child(0)->getValueId());
          finerConjuncts.insert(pred->child(1)->getValueId());
        }
        else
        {
          GenAssert(pred->getOperatorType() == ITM_EQUAL,
                   "pred->getOperatorType() != ITM_EQUAL");

          ItemExpr *left = pred->child(0)->castToItemExpr();
          ItemExpr *right = pred->child(1)->castToItemExpr();
          isANewJoinPred = TRUE;

          NABoolean child0Covered = child(0).getGroupAttr()->covers(left->getValueId(),
					      getGroupAttr()->getCharacteristicInputs(),
					      dummy1) ;
	  
          NABoolean child1Covered = child(1).getGroupAttr()->covers(right->getValueId(),
						  getGroupAttr()->getCharacteristicInputs(),
						  dummy1) ;

          if (NOT (child0Covered && child1Covered))
          {
	    //++MV - Irena
	    // save the pred's specialNulls_ flag before replacing the pred
 	    BiRelat *biRelat = new(generator->wHeap()) BiRelat(ITM_EQUAL, right, left);
	    // restore specialNulls_
	    biRelat->setSpecialNulls(((BiRelat*)pred)->getSpecialNulls());
	    biRelat->bindNode(generator->getBindWA());
	    pred = biRelat;
	    //--MV - Irena
	    
	    child0Covered = child(0).getGroupAttr()->covers(right->getValueId(),
						  getGroupAttr()->getCharacteristicInputs(),
						  dummy1) ;
	    
	    child1Covered = child(1).getGroupAttr()->covers(left->getValueId(),
						  getGroupAttr()->getCharacteristicInputs(),
						  dummy1) ;

            if(!(child0Covered && child1Covered))
            {
              if (isInnerNonSemiJoin())
              {
                selectionPred() += pred->getValueId();
              }
            else
              {
                // for an outer or semi join, the ON clause is stored in "joinPred"
                // while the WHERE clause is stored in "selectionPred".
                joinPred() += pred->getValueId();
              }
              isANewJoinPred = FALSE;
            }
          }
          if (isANewJoinPred)
          newJoinPreds.insert(pred->getValueId());
	}
    } // for over hjp.
    
    // Come back to process the new set of broken-down conjuncts if the set
    // is non-empty.
    //
    hjp = finerConjuncts;
    } while (NOT hjp.isEmpty());
    GenAssert(NOT newJoinPreds.isEmpty(), "HashJoin::PreCodeGen has no resolved join predicates");
  }

  // Value IDs given to the right/inner child
  ValueIdSet valuesGivenToRightChild =
    child(1)->getGroupAttr()->getCharacteristicInputs();

  if ( ! valuesGivenToRightChild.isEmpty() )  {

    // Accumulate the values that are provided as inputs by my parent
    // together with the values that are produced as outputs by my
    // children. Use these values for rewriting the VEG expressions.
    ValueIdSet availableValues;
    const ValueIdSet & HJInputs = getGroupAttr()->getCharacteristicInputs();
    getInputValuesFromParentAndChildren(availableValues);

    valuesGivenToRightChild.replaceVEGExpressions(availableValues, HJInputs);
  }

  // before computing the move and check expressions, add one more
  // value to "valuesGivenToRightChild": a statement execution count
  // that will cause re-hashing each time the statement is
  // re-executed. It is not legal to keep a hash table across
  // statement executions (and possibly transactions).
  ValueId execCount = generator->getOrAddStatementExecutionCount();
  valuesGivenToRightChild += execCount;
  pulledNewInputs += execCount;
  getGroupAttr()->addCharacteristicInputs(pulledNewInputs);

  // add move and search expressions
  for (ValueId val_id = valuesGivenToRightChild.init();
       valuesGivenToRightChild.next(val_id);
       valuesGivenToRightChild.advance(val_id))  {

    ItemExpr * item_expr = val_id.getItemExpr();

    // add this converted value to the map table.
    Convert * conv_node = new(generator->wHeap()) Convert (item_expr);

    // bind/type propagate the new node
    conv_node->bindNode(generator->getBindWA());

    moveInputValues().insert(conv_node->getValueId());

    // add the search condition
    BiRelat * bi_relat = new(generator->wHeap())
      BiRelat(ITM_EQUAL, item_expr, conv_node);
    bi_relat->allocValueId();
    checkInputValues().insert(bi_relat->getValueId());

  }  // for val_id

  // Count this BMO and add its needed memory to the total needed
  generator->incrNumBMOs();

  if ((ActiveSchemaDB()->getDefaults()).getAsDouble(BMO_MEMORY_LIMIT_PER_NODE_IN_MB) > 0)
    generator->incrBMOsMemory(getEstimatedRunTimeMemoryUsage(generator, TRUE));


  // store the transformed predicates back into the hash join node
  storeEquiJoinPredicates(newJoinPreds);

  generator->compilerStatsInfo().hj()++;

  //
  // case of hash anti semi join optimization (NOT IN)
  // add/build expression to detect inner and outer null :
  // checkOuteNullexpr_ and checkInnerNullExpr_ 
  addCheckNullExpressions(generator->wHeap());

  markAsPreCodeGenned();
  return this;

} //  HashJoin::preCodeGen()

RelExpr * FileScan::preCodeGen(Generator * generator,
			       const ValueIdSet & externalInputs,
			       ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  const PartitioningFunction* myPartFunc = getPartFunc();

  NABoolean usePartKeyPreds =
    (isHbaseTable() &&
     myPartFunc &&
     myPartFunc->isPartitioned() &&
     !myPartFunc->isAReplicationPartitioningFunction());

  if (isRewrittenMV())
    generator->setNonCacheableMVQRplan(TRUE);

  if (usePartKeyPreds)
    {
      // partition key predicates will be applied to this file scan,
      // "pull" the partition input values from the parent
      pulledNewInputs += myPartFunc->getPartitionInputValues();
      getGroupAttr()->addCharacteristicInputs(myPartFunc->getPartitionInputValues());
    }

  // Resolve the VEGReferences and VEGPredicates, if any, that appear
  // in the Characteristic Inputs, in terms of the externalInputs.
  getGroupAttr()->resolveCharacteristicInputs(externalInputs);

  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  ValueIdSet availableValues;

  getInputAndPotentialOutputValues(availableValues);

  sampledColumns().replaceVEGExpressions
    (availableValues, getGroupAttr()->getCharacteristicInputs());

  // Rewrite the partitioning function in terms of the available values.
  if (getIndexDesc()->isPartitioned())
    getIndexDesc()->getPartitioningFunction()->preCodeGen(availableValues);

  // VEGPredicates that are key predicates but are also replicated in
  // the executor predicates must be replaced with the same expression
  // in both the places after they are rewritten.  The VEGRewritePairs
  // data structure, when passed to replaceVEGExpressions(), causes
  // replaceVEGExpressions() to be idempotent.

  VEGRewritePairs  vegPairs(generator->wHeap());
  ValueIdSet partKeyPredsHBase;

  if (usePartKeyPreds)
    {
      // add the partitioning key predicates to this scan node,
      // to make sure that each ESP reads only the part of the
      // data that it is supposed to process

      ValueId saltCol;

      if (myPartFunc->isATableHashPartitioningFunction())
        {
          // find the _SALT_ column and make a partitioning key
          // predicate for it
          const ValueIdList &keyCols = getIndexDesc()->getIndexKey();

          // the first salt column we find in the key is the one
          // we are looking for
          for (CollIndex i=0; i<keyCols.entries(); i++)
            if (keyCols[i].isSaltColumn())
              {
                saltCol = keyCols[i];
                break;
              }

          if (saltCol != NULL_VALUE_ID)
            ((TableHashPartitioningFunction *) myPartFunc)->
              createPartitioningKeyPredicatesForSaltedTable(saltCol);
        }

      partKeyPredsHBase = myPartFunc->getPartitioningKeyPredicates();
    }

  if (getMdamKeyPtr() != NULL)
    {

      NABoolean replicatePredicates = TRUE;

      //      mdamKeyPtr()->print(); // for debugging purposes

      ValueIdSet executorPredicates;

      ValueIdSet augmentedPreds = getSelectionPredicates();

      const LogPhysPartitioningFunction *logPhysPartFunc =
	getPartFunc()->castToLogPhysPartitioningFunction();

      if (!partKeyPredsHBase.isEmpty())
        {
          augmentedPreds += partKeyPredsHBase;
          mdamKeyPtr()->setNoExePred(FALSE);
        }

      augmentedPreds += getComputedPredicates();

      if ( logPhysPartFunc != NULL )
      {
	LogPhysPartitioningFunction::logPartType logPartType =
	  logPhysPartFunc->getLogPartType();
	if ( logPartType == LogPhysPartitioningFunction::LOGICAL_SUBPARTITIONING
	  OR logPartType == LogPhysPartitioningFunction::HORIZONTAL_PARTITION_SLICING
	  )
	  augmentedPreds += logPhysPartFunc->getPartitioningKeyPredicates();
      }

      mdamKeyPtr()->preCodeGen(executorPredicates,
			       augmentedPreds,
			       availableValues,
			       getGroupAttr()->getCharacteristicInputs(),
			       &vegPairs,
			       replicatePredicates,
                               !partKeyPredsHBase.isEmpty());
      setExecutorPredicates(executorPredicates);

      //      mdamKeyPtr()->print(); // for debugging purposes


    }
  else if (! isHiveTable() &&
           (getSearchKey() || !partKeyPredsHBase.isEmpty()))
    {
      // ---------------------------------------------------
      // --------------------- Rewrite preds for search key:
      // ---------------------------------------------------

      if (!partKeyPredsHBase.isEmpty())
        {
          // These predicates can compete with other key predicates;
          // decide which of them to use as key preds and which as
          // executor preds:

          // - No search key: Use part key preds as search key
          // - Search key with non-unique preds: Replace it with
          //   a new search key with part key preds
          // - Search key with unique preds (unlikely, this shouldn't
          //   have been a parallel query): add part key preds as
          //   executor preds

          ValueIdSet combinedInputs(externalInputs);
          combinedInputs += pulledNewInputs;
          ValueIdSet existingKeyPreds;

          if (getSearchKey()) 
            existingKeyPreds += getSearchKey()->getKeyPredicates();
   
          // create a new search key that has the partitioning key preds
          SearchKey * partKeySearchKey = 
            myPartFunc->createSearchKey(getIndexDesc(),
                                        combinedInputs,
                                        existingKeyPreds);
          ValueIdSet exePreds(partKeySearchKey->getExecutorPredicates());
          NABoolean replaceSearchKey = !(getSearchKey() &&
                                         getSearchKey()->isUnique());

          if (getSearchKey()) 
            exePreds += getSearchKey()->getExecutorPredicates();

          ValueId falseConst = NULL_VALUE_ID;
          if (exePreds.containsFalseConstant(falseConst))
            replaceSearchKey = FALSE;

          // pick one search key and add the remaining
          // predicates (if any) to exePreds
          if (replaceSearchKey)
            setSearchKey(partKeySearchKey);
          else
            exePreds += partKeySearchKey->getKeyPredicates();
          searchKey()->setExecutorPredicates(exePreds);
        }

      NABoolean replicatePredicates = TRUE;

      setExecutorPredicates(searchKey()->getExecutorPredicates());

      // Rebuild the search key expressions
      ValueIdSet& keyPred = searchKey()->keyPredicates();
      keyPred.replaceVEGExpressions
	(availableValues,
	 getGroupAttr()->getCharacteristicInputs(),
	 FALSE, // no need for key predicate generation here
	 &vegPairs,
	 replicatePredicates);

      // Rebuild the executor  predicate tree
      executorPred().replaceVEGExpressions
	(availableValues,
	 getGroupAttr()->getCharacteristicInputs(),
	 FALSE, // no need for key predicate generation here
	 &vegPairs,
	 replicatePredicates
	 );

      // Generate the begin and end keys.

      if ( getDoUseSearchKey() ) {
     
      generateKeyExpr(getGroupAttr()->getCharacteristicInputs(),
		      getIndexDesc()->getIndexKey(),
		      getSearchKey()->getBeginKeyValues(),
		      beginKeyPred_,
		      generator,
                      replicatePredicates);
      generateKeyExpr(getGroupAttr()->getCharacteristicInputs(),
		      getIndexDesc()->getIndexKey(),
		      getSearchKey()->getEndKeyValues(),
		      endKeyPred_,
		      generator,
                      replicatePredicates);
      }

      // Check to see if there are any MIN/MAX values coming from a
      // HashJoin which could be used as begin/end key values for the
      // leading key of this scan.  Don't consider doing this if this
      // is a unique scan (can't improve on that) or if the leading
      // key is already unique or if both the begin and end key are
      // exclusive (min max are inclusive and no easy way to mix
      // them).
      if (generator->getMinMaxKeys().entries() &&
         (getSearchKey()->getBeginKeyValues()[0] !=
          getSearchKey()->getEndKeyValues()[0]) &&
         (!getSearchKey()->isBeginKeyExclusive() ||
          !getSearchKey()->isEndKeyExclusive())) {

        // The keys of the scan.
        const ValueIdList &keys = getIndexDesc()->getIndexKey();
        ValueId      minMaxKeyCol = keys[0];
        IndexColumn *ixCol = (IndexColumn *) (minMaxKeyCol.getItemExpr());
        BaseColumn  *baseCol = NULL;
        ValueId      underlyingCol;
        NABoolean    needToComputeActualMinMax = FALSE;
        ItemExpr    *computedColExpr = NULL;
        
        // The candidate values for min and max.
        const ValueIdList &minMaxKeys = generator->getMinMaxKeys();
    
        CollIndex keyIdx = NULL_COLL_INDEX;

        // Determine how min/max is related to begin/end.  depends
        // on ordering (ASC vs DESC) and scan direction (forward vs
        // reverse)
        NABoolean ascKey = 
          getIndexDesc()->getNAFileSet()->getIndexKeyColumns().isAscending(0);

        if(getReverseScan())
          ascKey = !ascKey;

        // If the leading key column is a divisioning column, then
        // look for min/max values of an underlying column
        GenAssert(ixCol->getOperatorType() == ITM_INDEXCOLUMN,
                  "unexpected object type");
        baseCol = 
          (BaseColumn *) (((IndexColumn *) ixCol)->getDefinition().getItemExpr());
        GenAssert(baseCol->getOperatorType() == ITM_BASECOLUMN,
                  "unexpected object type");
        if (baseCol->getNAColumn()->isDivisioningColumn()) {
          ValueIdSet underlyingCols;
          baseCol->getUnderlyingColumnsForCC(underlyingCols);

          if (underlyingCols.entries() == 1) {
            // We have a leading division column that's computed from
            // 1 base column, now get the underlying column and the
            // divisioning expression
            needToComputeActualMinMax = TRUE;
            underlyingCols.getFirst(minMaxKeyCol);
            computedColExpr = baseCol->getComputedColumnExpr().getItemExpr();
            BaseColumn  *underlyingBaseCol =
              (BaseColumn *) minMaxKeyCol.getItemExpr();
            GenAssert(underlyingBaseCol->getOperatorType() == ITM_BASECOLUMN,
                      "unexpected object type");
            // the computed column expression has been rewritten to use
            // VEGRefs, so get the corresponding VEGRef for the underlying column
            underlyingCol = underlyingBaseCol->getTableDesc()->
              getColumnVEGList()[underlyingBaseCol->getColNumber()];
          }
        }

        // Check all the candidate values.  If any one of them matches
        // the leading key of this scan, then select it for use in the
        // begin/end key value of the leading key.

        // Scalar min/max functions cause an exponential growth when
        // combined with each other, see ItmScalarMinMax::codeGen()
        Int32 limitItems = 3 ; // use at most 3

        for(CollIndex i = 0; i < minMaxKeys.entries() && limitItems; i++) {
          ValueId mmKeyId = minMaxKeys[i];
          if(mmKeyId != NULL_VALUE_ID) {
            ItemExpr *mmItem = mmKeyId.getItemExpr();
      
            if (mmItem->getOperatorType() == ITM_VEG_PREDICATE) {
              VEGPredicate *vPred = (VEGPredicate *)mmItem;
              const ValueIdSet &members = vPred->getVEG()->getAllValues();

              if (members.contains(minMaxKeyCol)) {

                // some other operator is producing min/max values
                // for our leading key column, now check whether we
                // can use them

                keyIdx = i;

                // Indicate in the 'will use' list that we will use these
                // min/max values.  This will indicate to the HashJoin that
                // it should produce these values.
                generator->getWillUseMinMaxKeys()[keyIdx] =
                  generator->getMinMaxKeys()[keyIdx];
                addMinMaxHJColumn(baseCol->getValueId());

                limitItems-- ; // one more is used

                // If we can use a min/max value for the begin key, do so...
                if(!getSearchKey()->isBeginKeyExclusive()) {
                  ItemExpr *keyPred = getBeginKeyPred()[0].getItemExpr();
                  ItemExpr *currentBeg = keyPred->child(1);

                  // Get the proper begin key (min or max) that came from
                  // the HashJoin
                  ValueId hashJoinBeg = (ascKey ?
                                         generator->getMinVals()[keyIdx] :
                                         generator->getMaxVals()[keyIdx]);

                  // Construct an expression which determines at runtime
                  // which BK to use.  Either the existing one or the one
                  // coming from HashJoin whichever is larger (smaller).
                  // 
                  ItemExpr *newBeg = hashJoinBeg.getItemExpr();

                  if (needToComputeActualMinMax) {
                    ValueIdMap divExprMap;
                    ValueId computedBeg;

                    // If hashJoinBeg is :sysHV1 and the computed column
                    // expression is A/100, then the begin value for
                    // the computed column is :sysHV1/100. Do this
                    // rewrite by using a ValueIdMap
                    divExprMap.addMapEntry(underlyingCol, hashJoinBeg);
                    divExprMap.rewriteValueIdDown(computedColExpr->getValueId(),
                                                  computedBeg);
                    newBeg = computedBeg.getItemExpr();
                  }

                  newBeg = new (generator->wHeap())
                    ItmScalarMinMax((ascKey ? ITM_SCALAR_MAX : ITM_SCALAR_MIN),
                                    currentBeg, 
                                    newBeg);
                  newBeg->synthTypeAndValueId();
                  // Replace the RHS of the key pred.
                  keyPred->child(1) = newBeg->getValueId();

                  // The value coming from the HashJoin must be in out inputs.
                  getGroupAttr()->addCharacteristicInputs(hashJoinBeg);

                  // And we must pull those values from the HashJoin.
                  pulledNewInputs += hashJoinBeg;
                  availableValues += hashJoinBeg;
                }

                // If we can use a min/max value for the end key, do so...
                if(!getSearchKey()->isEndKeyExclusive()) {
                  ItemExpr *keyPred = getEndKeyPred()[0].getItemExpr();
                  ItemExpr *currentEnd = keyPred->child(1);

                  // Get the proper end key (max or min) that came from
                  // the HashJoin
                  ValueId hashJoinEnd = (ascKey ?
                                         generator->getMaxVals()[keyIdx] :
                                         generator->getMinVals()[keyIdx]);

                  // Construct an expression which determines at runtime
                  // which EK to use.  Either the existing one or the one
                  // coming from HashJoin whichever is smaller (larger).
                  // 
                  ItemExpr *newEnd = hashJoinEnd.getItemExpr();

                  if (needToComputeActualMinMax) {
                    ValueIdMap divExprMap;
                    ValueId computedEnd;

                    divExprMap.addMapEntry(underlyingCol, hashJoinEnd);
                    divExprMap.rewriteValueIdDown(computedColExpr->getValueId(),
                                                  computedEnd);
                    newEnd = computedEnd.getItemExpr();
                  }

                  newEnd = new (generator->wHeap())
                    ItmScalarMinMax((ascKey ? ITM_SCALAR_MIN : ITM_SCALAR_MAX),
                                    currentEnd, 
                                    newEnd);
                  newEnd->synthTypeAndValueId();

                  // Replace the RHS of the key pred.
                  keyPred->child(1) = newEnd->getValueId();

                  // The value coming from the HashJoin must be in out inputs.
                  getGroupAttr()->addCharacteristicInputs(hashJoinEnd);

                  // And we must pull those values from the HashJoin.
                  pulledNewInputs += hashJoinEnd;
                  availableValues += hashJoinEnd;
                }
              }
            }
          }
        }
      }
    }
  else
    {
      // Hive table scan (HBase scan has executor preds set up already)
      if (isHiveTable())
        setExecutorPredicates(selectionPred());

      // Rebuild the executor  predicate tree
      executorPred().replaceVEGExpressions
	(availableValues,
	 getGroupAttr()->getCharacteristicInputs(),
	 FALSE, // no need for key predicate generation here
	 &vegPairs,
	 TRUE);

      if (isHiveTable())
        {
          // assign individual files and blocks to each ESPs
          ((NodeMap *) getPartFunc()->getNodeMap())->assignScanInfos(hiveSearchKey_);
          if (CmpCommon::getDefault(USE_LIBHDFS) == DF_ON)
             generator->setProcessLOB(TRUE);
	  
	  // flag set for HBase scan in HbaseAccess::preCodeGen
	  // unique scan unlikely for hive scans except 
	  // with predicate on virtual cols.
	  if (!(searchKey() && searchKey()->isUnique()))
	    generator->oltOptInfo()->setMultipleRowsReturned(TRUE);
        }
    }

  
  // Selection predicates are not needed anymore:
  selectionPred().clear();

  // Add the sampled columns to the set of available values. This is
  // basically a kluge to get the GroupAttributes right.

  availableValues += sampledColumns();

  // This call also rewrites predicates
  // $$$ Does it need vegPairs too? $$$
  getGroupAttr()->resolveCharacteristicOutputs
    (availableValues,
     getGroupAttr()->getCharacteristicInputs());

  generator->oltOptInfo()->mayDisableOperStats(&oltOptInfo());
  markAsPreCodeGenned();
  return this;
} // FileScan::preCodeGen()


RelExpr * GenericUpdate::preCodeGen(Generator * generator,
				    const ValueIdSet & externalInputs,
				    ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! RelExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  // Determine whether OLT optimization must be avoided.
  if (getGroupAttr()->isEmbeddedUpdateOrDelete())
    {
      generator->oltOptInfo()->setOltMsgOpt(FALSE);

      generator->setUpdAbortOnError(TRUE);
      generator->setUpdSavepointOnError(FALSE);
      generator->setUpdPartialOnError(FALSE);
      generator->setUpdErrorOnError(FALSE);
    }

  if ((accessOptions().accessType() == TransMode::SKIP_CONFLICT_ACCESS_) ||
      (getGroupAttr()->isStream()) ||
      (newRecBeforeExprArray().entries() > 0)) // set on rollback
    {
      generator->oltOptInfo()->setOltEidOpt(FALSE);
      oltOptInfo().setOltEidOpt(FALSE);
      setExpandShortRows(FALSE);

      generator->setUpdAbortOnError(TRUE);
      generator->setUpdSavepointOnError(FALSE);
      generator->setUpdPartialOnError(FALSE);
      generator->setUpdErrorOnError(FALSE);
    }

  // If RI, IM, MV or triggers are being used, abort on error.
  // This is because internal data consistency
  // cannot be guaranteed for these cases.
  if ((getInliningInfo().hasInlinedActions()) ||
      (getInliningInfo().isEffectiveGU()))
    {
      // cannot do partial updates.
      generator->setUpdPartialOnError(FALSE);

      if (CmpCommon::getDefault(COMP_BOOL_206) == DF_ON)
	{
	  if (NOT ((getInliningInfo().hasTriggers()) ||
		   (getInliningInfo().hasRI()) ||
		   (getInliningInfo().hasIM()) ||
		   (getInliningInfo().isMVLoggingInlined())))
	    {
	      generator->setUpdAbortOnError(TRUE);
	      generator->setUpdSavepointOnError(FALSE);
	      generator->setUpdErrorOnError(FALSE);
	    }
	  else
	    generator->setUpdErrorOnError(FALSE);
	}
      else
	{
	  // abort on error for non-IM cases(RI,MV,Trig).
	  if ((NOT getInliningInfo().hasIM()) ||
	      (getInliningInfo().hasRI()))
	    {
	      generator->setUpdAbortOnError(TRUE);
	      generator->setUpdSavepointOnError(FALSE);
	      generator->setUpdErrorOnError(FALSE);
	    }
	  else
	    generator->setUpdErrorOnError(FALSE);
	}
    }

  // If RI, MV or triggers are being used, turn off the lean optimization for
  // the complete plan; all other optimizations will still apply.
  if ( generator->oltOptInfo()->oltEidLeanOpt() &&
       ( getInliningInfo().hasTriggers()  ||
         getInliningInfo().hasRI()        ||
         getInliningInfo().isMVLoggingInlined() ) )
  {
    generator->oltOptInfo()->setOltEidLeanOpt(FALSE);
    oltOptInfo().setOltEidLeanOpt(FALSE);
  }

  // Accumulate the values that are provided as inputs by my parent
  // together with the values that are produced as outputs by my
  // children. Use these values for rewriting the VEG expressions.
  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);

  newRecExpr_.replaceVEGExpressions
                 (availableValues,
		  getGroupAttr()->getCharacteristicInputs());

  newRecBeforeExpr_.replaceVEGExpressions
                 (availableValues,
		  getGroupAttr()->getCharacteristicInputs());

  executorPred().replaceVEGExpressions
	          (availableValues,
		    getGroupAttr()->getCharacteristicInputs());

  // VEGPredicates that are key predicates but are also replicated
  // in the executor predicates must be replaced with the same
  // expression in both places after they are rewritten.
  // Therefore, we want replaceVEGExpressions() processing to be
  // idempotent.  By passing the VEGRewritePairs data structure
  // to replaceVEGExpressions(), we get idempotence.

  VEGRewritePairs lookup(generator->wHeap());   // so replaceVEGExpressions will be idempotent

  if (getSearchKey() == NULL)
    {
      // Begin and end key preds may already be available.
      beginKeyPred_.replaceVEGExpressions
                       (availableValues,
			getGroupAttr()->getCharacteristicInputs(),
			FALSE, // no need for key predicate generation here
			&lookup);
      endKeyPred_.replaceVEGExpressions
                     (availableValues,
		      getGroupAttr()->getCharacteristicInputs(),
		      FALSE,  // no need for key predicate generation here
		      &lookup);

      // In the case of an embedded insert from VALUES,
      // any predicates need to have their VEGreferences resolved.
      if (getGroupAttr()->isEmbeddedInsert())
	{

          NABoolean replicatePredicates = TRUE;

	  // Rebuild the executor predicate tree
	  executorPred().replaceVEGExpressions
			    (availableValues,
			     getGroupAttr()->getCharacteristicInputs(),
			     FALSE,  // no need for key predicate generation
			     &lookup,
			     replicatePredicates
			    );
	}
    }
  else
    {
      // Build begin and end key predicates from the search key structure.

      //## It *might* be a good idea to add here:
      //##   CMPASSERT(beginKeyPred_.isEmpty() && endKeyPred_.isEmpty());
      //## as that *seems* to be the assumption here.
      //## (But I haven't the time to make the change and test it.)

      ValueIdSet& keyPred = getSearchKey()->keyPredicates();

      NABoolean replicatePredicates = TRUE;

      // Rebuild the search key expressions
      keyPred.replaceVEGExpressions
                 (availableValues,
		  getGroupAttr()->getCharacteristicInputs(),
		  FALSE, // no need for key predicate generation
		  &lookup,
		  replicatePredicates);

      // Rebuild the executor  predicate tree
      executorPred().replaceVEGExpressions
	                (availableValues,
			 getGroupAttr()->getCharacteristicInputs(),
			 FALSE,  // no need for key predicate generation
			 &lookup,
			 replicatePredicates
			);

      // Generate the begin and end keys.
      generateKeyExpr(getGroupAttr()->getCharacteristicInputs(),
		      getIndexDesc()->getIndexKey(),
		      getSearchKey()->getBeginKeyValues(),
		      beginKeyPred_,
		      generator);
      generateKeyExpr(getGroupAttr()->getCharacteristicInputs(),
		      getIndexDesc()->getIndexKey(),
		      getSearchKey()->getEndKeyValues(),
		      endKeyPred_,
		      generator);
    }

  // ---------------------------------------------------------------------
  // Rewrite the check constraint expressions.
  // ---------------------------------------------------------------------
  checkConstraints().replaceVEGExpressions
                        (availableValues,
			 getGroupAttr()->getCharacteristicInputs());

  generator->setFoundAnUpdate(TRUE);
  generator->setPartnAccessChildIUD();

#ifdef _DEBUG
  // Compile in the index maintenance ... just for testing
  //
  if(getenv("IM_COMPILE"))
    generator->imUpdateRel() = this;
#endif

  if (oltOptLean() &&
      ((isinBlockStmt()) ||
       (getTableDesc()->getNATable()->hasAddedColumn()) ||
       (getTableDesc()->getNATable()->hasVarcharColumn())))
  {
    oltOptInfo().setOltEidLeanOpt(FALSE);
  }

  generator->setSkipUnavailablePartition(FALSE);

  if (isMtsStatement())
    generator->setEmbeddedIUDWithLast1(TRUE) ;

  if (isMerge())
    {
      // Accumulate the values that are provided as inputs by my parent
      // together with the values that are produced as outputs by my
      // children. Use these values for rewriting the VEG expressions.
      ValueIdSet availableValues;
      getInputValuesFromParentAndChildren(availableValues);
      
      mergeInsertRecExpr().replaceVEGExpressions
	(availableValues,
	 getGroupAttr()->getCharacteristicInputs());

      mergeUpdatePred().replaceVEGExpressions
	(availableValues,
	 getGroupAttr()->getCharacteristicInputs());

      ValueIdList tempVIDlist;
      getTableDesc()->getIdentityColumn(tempVIDlist);
      NAColumn *identityCol = NULL;
      if (tempVIDlist.entries() > 0)
	{
	  ValueId valId = tempVIDlist[0];
	  identityCol = valId.getNAColumn();
	}

      if (((getOperatorType() == REL_HBASE_DELETE) ||
           (getOperatorType() == REL_HBASE_UPDATE)) &&
          (getTableDesc()->getNATable()->getClusteringIndex()->hasSyskey()))
	{
	  *CmpCommon::diags() << DgSqlCode(-3241) 
			      << DgString0(" SYSKEY not allowed.");
	  GenExit();
	}

      if ((getOperatorType() != REL_HBASE_UPDATE) &&
          (mergeInsertRecExpr().entries() > 0) &&
          (CmpCommon::getDefault(COMP_BOOL_175) == DF_OFF))
	{
          // MERGE with INSERT is limited to HBase updates unless
          // the CQD is on
	  *CmpCommon::diags() << DgSqlCode(-3241)
			      << DgString0(" This MERGE is not allowed with INSERT.");
	  GenExit();
	}

      if (oltOpt())
	{
	  // if no update expr and only insert expr is specified for 
	  // this MERGE stmt, turn off olt opt.
	  // 
	  if (newRecExprArray().entries() == 0)
	    oltOptInfo().setOltEidOpt(FALSE);

	  oltOptInfo().setOltEidLeanOpt(FALSE);
	}

      generator->setUpdErrorOnError(FALSE);
      generator->setUpdSavepointOnError(FALSE);
    } // isMerge

  generator->oltOptInfo()->mayDisableOperStats(&oltOptInfo());

  // Part of the fix for Soln 10-100425-9755.  Don't AQR a 
  // positioned update/delete because part of the recovery
  // for the error that triggers the AQR is rollback transaction
  // and this causes the referenced cursor to be closed.  The other
  // part of the fix is in compiler cache: positioned update/deletes
  // will not be cached, and this should reduce the need to handle
  // errors with AQR, e.g., timestamp mismatch errors.
  if (updateCurrentOf())
    generator->setAqrEnabled(FALSE);

  if (getTableDesc()->getNATable()->hasLobColumn())
    {
      oltOptInfo().setOltOpt(FALSE);
      generator->oltOptInfo()->setOltOpt(FALSE);
      //enabling AQR to take care of the lock conflict error 8558 that
      // should be retried.
      //      generator->setAqrEnabled(FALSE);
      generator->setUpdAbortOnError(TRUE);
      generator->setUpdSavepointOnError(FALSE);
    }

  if ((isNoRollback()) ||
      (generator->getTransMode()->getRollbackMode() == TransMode::NO_ROLLBACK_))
    {
      generator->setWithNoRollbackUsed(isNoRollback());
      if (CmpCommon::getDefault(AQR_WNR) == DF_OFF)
        generator->setAqrEnabled(FALSE);
    }

  if (((getInliningInfo().hasInlinedActions()) ||
       (getInliningInfo().isEffectiveGU())) &&
      (getInliningInfo().hasRI()))
    {
      generator->setRIinliningForTrafIUD(TRUE);
    }

  if (precondition_.entries() > 0)
  {
    ValueIdSet availableValues;
    getInputValuesFromParentAndChildren(availableValues);  
    precondition_.
      replaceVEGExpressions(availableValues,
			    getGroupAttr()->getCharacteristicInputs());
  }

  markAsPreCodeGenned();

  return this;
} // GenericUpdate::preCodeGen()

RelExpr * Update::preCodeGen(Generator * generator,
			     const ValueIdSet & externalInputs,
			     ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;
  
  if (! GenericUpdate::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  markAsPreCodeGenned();

  return this;
}

RelExpr * MergeUpdate::preCodeGen(Generator * generator,
				  const ValueIdSet & externalInputs,
				  ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;
  
  if (! Update::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  markAsPreCodeGenned();

  return this;
}

RelExpr * UpdateCursor::preCodeGen(Generator * generator,
				   const ValueIdSet & externalInputs,
				   ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! Update::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  // primary key columns cannot be updated, yet. After RI support
  // is in, they could be updated.
   const NAColumnArray & key_column_array =
     getTableDesc()->getNATable()->getClusteringIndex()->getIndexKeyColumns();

  ValueIdSet& val_id_set = newRecExpr();
  ValueId val_id;
  for (val_id = val_id_set.init(); val_id_set.next(val_id); val_id_set.advance(val_id))
    {
      ItemExpr * item_expr = val_id.getItemExpr();

      for (short i = 0; i < getTableDesc()->getNATable()->getKeyCount(); i++)
	{
	  const char * key_colname = key_column_array[i]->getColName();
	  const char * upd_colname = ((BaseColumn *)
	  			      (item_expr->child(0)->castToItemExpr()))->
				      getColName();

	  if ((strcmp(key_colname, upd_colname) == 0) &&
              (item_expr->getOperatorType() == ITM_ASSIGN) &&
              (((Assign*)item_expr)->isUserSpecified()))
	    {
	      *CmpCommon::diags() << DgSqlCode(-4033) 
				  << DgColumnName(key_colname);

	      GenExit();
	    }
	}
    }
  generator->oltOptInfo()->mayDisableOperStats(&oltOptInfo());
  markAsPreCodeGenned();

  return this;
} // UpdateCursor::preCodeGen()

RelExpr * Delete::preCodeGen(Generator * generator,
                             const ValueIdSet & externalInputs,
                             ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;
  
  if (! GenericUpdate::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  markAsPreCodeGenned();

  return this;
}

RelExpr * MergeDelete::preCodeGen(Generator * generator,
				  const ValueIdSet & externalInputs,
				  ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;
  
  if (! Delete::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  markAsPreCodeGenned();

  return this;
}

static NABoolean hasColReference(ItemExpr * ie)
{
  if (! ie)
    return FALSE;

  if ((ie->getOperatorType() == ITM_BASECOLUMN) ||
      (ie->getOperatorType() == ITM_INDEXCOLUMN) ||
      (ie->getOperatorType() == ITM_REFERENCE))
    return TRUE;

  for (Lng32 i = 0; i < ie->getArity(); i++)
    {
      if (hasColReference(ie->child(i)))
	return TRUE;
    }
  
  return FALSE;
}

void HbaseAccess::addReferenceFromItemExprTree(ItemExpr * ie,
                                               NABoolean addCol, NABoolean addHBF,
                                               ValueIdSet &colRefVIDset)
{
  if (! ie)
    return;
  
  if ((ie->getOperatorType() == ITM_BASECOLUMN) ||
      (ie->getOperatorType() == ITM_INDEXCOLUMN) ||
      (ie->getOperatorType() == ITM_REFERENCE))
    {
      if (addCol)
        colRefVIDset.insert(ie->getValueId());

      return;
    }

  if (ie->getOperatorType() == ITM_HBASE_TIMESTAMP)
    {
      if (addHBF)
        {
          colRefVIDset.insert(ie->getValueId());
        }

      return;
    }

  if (ie->getOperatorType() == ITM_HBASE_VERSION)
    {
      if (addHBF)
        {
          colRefVIDset.insert(ie->getValueId());
        }

      return;
    }

  for (Lng32 i = 0; i < ie->getArity(); i++)
    {
      addReferenceFromItemExprTree(ie->child(i), addCol, addHBF, colRefVIDset);
    }
  
  return;
}

void HbaseAccess::addColReferenceFromVIDlist(const ValueIdList &exprList,
					     ValueIdSet  &colRefVIDset)
{
  for (CollIndex i = 0; i < exprList.entries(); i++)
    {
      addReferenceFromItemExprTree(exprList[i].getItemExpr(), 
                                   TRUE, FALSE, colRefVIDset);
    }
}

void HbaseAccess::addReferenceFromVIDset(const ValueIdSet &exprList,
                                         NABoolean addCol, NABoolean addHBF,
                                         ValueIdSet  &colRefVIDset)
{
  for (ValueId v = exprList.init(); exprList.next(v); exprList.advance(v))
    {
      addReferenceFromItemExprTree(v.getItemExpr(), addCol, addHBF, colRefVIDset);
    }
}

void HbaseAccess::addColReferenceFromRightChildOfVIDarray(ValueIdArray &exprList,
							  ValueIdSet &colRefVIDset)
{

  for (CollIndex i = 0; i < exprList.entries(); i++)
    {
      addReferenceFromItemExprTree(exprList[i].getItemExpr()->child(1), 
                                   TRUE, FALSE, colRefVIDset);
    }
}

static NABoolean isEqGetExpr(ItemExpr * ie, ValueId &vid, NABoolean &isConstParam,
			     const char * colName)
{
  NABoolean found = FALSE;
  isConstParam = FALSE;

  if (ie && ie->getOperatorType() == ITM_EQUAL)
    {
      ItemExpr * child0 = ie->child(0)->castToItemExpr();
      ItemExpr * child1 = ie->child(1)->castToItemExpr();
      
      if ((ie->child(0)->getOperatorType() == ITM_BASECOLUMN) &&
	  (((BaseColumn*)ie->child(0)->castToItemExpr())->getNAColumn()->getColName() == colName) &&
	  (NOT hasColReference(ie->child(1))))
	{
	  if (ie->child(1)->getOperatorType() == ITM_CONSTANT)
	    {
	      found = TRUE;
	      vid = ie->child(1)->getValueId();
	    }
	  else if (ie->child(1)->getOperatorType() == ITM_CACHE_PARAM)
	    {
	      found = TRUE;
	      isConstParam = TRUE;
	      vid = ie->child(1)->getValueId();
	    }
	}
      else if ((ie->child(1)->getOperatorType() == ITM_BASECOLUMN) &&
	       (((BaseColumn*)ie->child(1)->castToItemExpr())->getNAColumn()->getColName() == colName) &&
	       (NOT hasColReference(ie->child(0))))
	{
	  if (ie->child(0)->getOperatorType() == ITM_CONSTANT)
	    {
	      found = TRUE;
	      vid = ie->child(0)->getValueId();
	    }
	  else if (ie->child(0)->getOperatorType() == ITM_CACHE_PARAM)
	    {
	      found = TRUE;
	      isConstParam = TRUE;
	      vid = ie->child(0)->getValueId();
	    }
	}
      else if ((ie->child(0)->getOperatorType() == ITM_INDEXCOLUMN) &&
	       (((IndexColumn*)ie->child(0)->castToItemExpr())->getNAColumn()->getColName() == colName) &&
	       (NOT hasColReference(ie->child(1))))
	{
	  if (ie->child(1)->getOperatorType() == ITM_CONSTANT)
	    {
	      found = TRUE;
	      vid = ie->child(1)->getValueId();
	    }
	  else if (ie->child(1)->getOperatorType() == ITM_CACHE_PARAM)
	    {
	      found = TRUE;
	      isConstParam = TRUE;
	      vid = ie->child(1)->getValueId();
	    }
	}
      else if ((ie->child(1)->getOperatorType() == ITM_INDEXCOLUMN) &&
	       (((IndexColumn*)ie->child(1)->castToItemExpr())->getNAColumn()->getColName() == colName) &&
	       (NOT hasColReference(ie->child(0))))
	{
	  if (ie->child(0)->getOperatorType() == ITM_CONSTANT)
	    {
	      found = TRUE;
	      vid = ie->child(0)->getValueId();
	    }
	  else if (ie->child(0)->getOperatorType() == ITM_CACHE_PARAM)
	    {
	      found = TRUE;
	      isConstParam = TRUE;
	      vid = ie->child(0)->getValueId();
	    }
	}
      else if ((ie->child(0)->getOperatorType() == ITM_REFERENCE) &&
	       (((ColReference*)ie->child(0)->castToItemExpr())->getCorrNameObj().getQualifiedNameObj().getObjectName() == colName)  &&
	       (NOT hasColReference(ie->child(1))))
	{
	  if (ie->child(1)->getOperatorType() == ITM_CONSTANT)
	    {
	      found = TRUE;
	      vid = ie->child(1)->getValueId();
	    }
	  else if (ie->child(1)->getOperatorType() == ITM_CACHE_PARAM)
	    {
	      found = TRUE;
	      isConstParam = TRUE;
	      vid = ie->child(1)->getValueId();
	    }
	}
      else if ((ie->child(1)->getOperatorType() == ITM_REFERENCE) &&
	       (((ColReference*)ie->child(1)->castToItemExpr())->getCorrNameObj().getQualifiedNameObj().getObjectName() == colName)  &&
	       (NOT hasColReference(ie->child(0))))
	{
	  if (ie->child(0)->getOperatorType() == ITM_CONSTANT)
	    {
	      found = TRUE;
	      vid = ie->child(0)->getValueId();
	    }
	  else if (ie->child(0)->getOperatorType() == ITM_CACHE_PARAM)
	    {
	      found = TRUE;
	      isConstParam = TRUE;
	      vid = ie->child(0)->getValueId();
	    }
	}
    }

  return found;
}

RelExpr * HbaseDelete::preCodeGen(Generator * generator,
				  const ValueIdSet & externalInputs,
				  ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  // if a column list is specified, make sure all column names are of valid hbase
  // column name format ("ColFam:ColNam")
  if (csl())
    {
      for (Lng32 i = 0; i < csl()->entries(); i++)
	{
	  const NAString * nas = (*csl())[i];

	  std::string colFam;
	  std::string colName;
	  if (nas)
	    {
	      ExFunctionHbaseColumnLookup::extractColFamilyAndName(
								   nas->data(), -1, FALSE, colFam, colName);
	    }
	  
	  if (colFam.empty())
	    {
	      *CmpCommon::diags() << DgSqlCode(-1426)
				  << DgString0(nas->data());
	      GenExit();
	    }
	  
	} // for
    } // if

  if (!processConstHBaseKeys(
           generator,
           this,
           getSearchKey(),
           getIndexDesc(),
           executorPred(),
           getHbaseSearchKeys(),
           listOfDelUniqueRows_,
           listOfDelSubsetRows_))
    return NULL;

  if (! Delete::preCodeGen(generator, externalInputs, pulledNewInputs))
    return NULL;

  if (((getTableDesc()->getNATable()->isHbaseRowTable()) ||
       (getTableDesc()->getNATable()->isHbaseCellTable())) &&
      (producesOutputs()))
    {
      *CmpCommon::diags() << DgSqlCode(-1425)
			  << DgTableName(getTableDesc()->getNATable()->getTableName().
					 getQualifiedNameAsAnsiString())
                          << DgString0("Reason: Cannot return values from an hbase insert, update or delete.");
      GenExit();
    }

   NABoolean isAlignedFormat = getTableDesc()->getNATable()->isAlignedFormat(getIndexDesc());

  if  (producesOutputs()) 
    {
      retColRefSet_ = getIndexDesc()->getIndexColumns();
    }
  else
    {
      ValueIdSet colRefSet;

      // create the list of columns that need to be retrieved from hbase .
      // first add all columns referenced in the executor pred.
      HbaseAccess::addReferenceFromVIDset(executorPred(), TRUE, TRUE, colRefSet);

      if ((getTableDesc()->getNATable()->getExtendedQualName().getSpecialType() == ExtendedQualName::INDEX_TABLE))
        {
	  for (ValueId valId = executorPred().init();
	       executorPred().next(valId);
	       executorPred().advance(valId))
            {
              ItemExpr * ie = valId.getItemExpr();
              if (ie->getOperatorType() == ITM_EQUAL)
                {
                  BiRelat * br = (BiRelat*)ie;
                  br->setSpecialNulls(TRUE);
                }
            }
        } // index_table


      if ((getTableDesc()->getNATable()->isHbaseRowTable()) ||
	  (getTableDesc()->getNATable()->isHbaseCellTable()) ||
           isAlignedFormat)
	{
	  for (Lng32 i = 0; i < getIndexDesc()->getIndexColumns().entries(); i++)
	    {
	      retColRefSet_.insert(getIndexDesc()->getIndexColumns()[i]);
	    }
        }

      for (ValueId valId = colRefSet.init();
           colRefSet.next(valId);
           colRefSet.advance(valId))
        {
          ValueId dummyValId;
          if (NOT getGroupAttr()->getCharacteristicInputs().referencesTheGivenValue(valId, dummyValId))
            {
              if ((valId.getItemExpr()->getOperatorType() == ITM_HBASE_TIMESTAMP) ||
                  (valId.getItemExpr()->getOperatorType() == ITM_HBASE_VERSION))
                {
                  *CmpCommon::diags() << DgSqlCode(-3242)
                                      << DgString0("Illegal use of Hbase Timestamp or Hbase Version function.");

                  GenExit();
                }

              retColRefSet_.insert(valId);
            }
        }

      if (NOT ((getTableDesc()->getNATable()->isHbaseRowTable()) ||
               (getTableDesc()->getNATable()->isHbaseCellTable()) ||
               (isAlignedFormat)))
        {
          // add all the key columns. If values are missing in hbase, then atleast the key
          // value is needed to retrieve a row. 
          HbaseAccess::addColReferenceFromVIDlist(getIndexDesc()->getIndexKey(), retColRefSet_);
        }

      if (getTableDesc()->getNATable()->hasLobColumn())
        {
          for (Lng32 i = 0; i < getIndexDesc()->getIndexColumns().entries(); i++)
            {
              const ValueId vid = getIndexDesc()->getIndexColumns()[i];
              retColRefSet_.insert(vid);
            }
        }
    }

  NABoolean inlinedActions = FALSE;
  if ((getInliningInfo().hasInlinedActions()) ||
      (getInliningInfo().isEffectiveGU()))
    inlinedActions = TRUE;
 
  NABoolean isUnique = FALSE;
  if (listOfDelSubsetRows_.entries() == 0)
    {
      if ((getSearchKey() && getSearchKey()->isUnique()) &&
	  (listOfDelUniqueRows_.entries() == 0))
	isUnique = TRUE;
      else if ((NOT (getSearchKey() && getSearchKey()->isUnique())) &&
	       (listOfDelUniqueRows_.entries() == 1) &&
	       (listOfDelUniqueRows_[0].rowIds_.entries() == 1))
	isUnique = TRUE;
    }
 
  NABoolean hbaseRowsetVSBBopt = 
    (CmpCommon::getDefault(HBASE_ROWSET_VSBB_OPT) == DF_ON);
  if ((getTableDesc()->getNATable()->isHbaseMapTable()) ||
      (getTableDesc()->getNATable()->isHbaseRowTable()) ||
      (getTableDesc()->getNATable()->isHbaseCellTable()))
    hbaseRowsetVSBBopt = FALSE;

  if (getInliningInfo().isIMGU()) {
     // There is no need to do checkAndDelete for IM
     canDoCheckAndUpdel() = FALSE;
     uniqueHbaseOper() = FALSE;
     if ((generator->oltOptInfo()->multipleRowsReturned()) &&
	  (hbaseRowsetVSBBopt) &&
         (NOT generator->isRIinliningForTrafIUD()) &&
         (NOT getTableDesc()->getNATable()->hasLobColumn()))
       uniqueRowsetHbaseOper() = TRUE;
  }
  else
  if (isUnique)
    {
      //If this unique delete is not part of a rowset operation , 
      //don't allow it to be cancelled. 
      if (!generator->oltOptInfo()->multipleRowsReturned())
	generator->setMayNotCancel(TRUE);
      uniqueHbaseOper() = TRUE;
      canDoCheckAndUpdel() = FALSE;
      if ((NOT producesOutputs()) &&
	  (NOT  inlinedActions) &&
          (executorPred().isEmpty()))
	{
	  if ((generator->oltOptInfo()->multipleRowsReturned()) &&
	      (hbaseRowsetVSBBopt) &&
	      (NOT generator->isRIinliningForTrafIUD()) &&
              (NOT getTableDesc()->getNATable()->hasLobColumn()))
	    uniqueRowsetHbaseOper() = TRUE;
	  else if ((NOT generator->oltOptInfo()->multipleRowsReturned()) &&
		   (listOfDelUniqueRows_.entries() == 0))
	    {
	      if ((CmpCommon::getDefault(HBASE_CHECK_AND_UPDEL_OPT) == DF_ON) &&
		  (CmpCommon::getDefault(HBASE_SQL_IUD_SEMANTICS) == DF_ON) &&
                  (NOT isAlignedFormat))
	      canDoCheckAndUpdel() = TRUE;
	    }
	}
    }

  if ((producesOutputs()) &&
      ((NOT isUnique) || (getUpdateCKorUniqueIndexKey())))
    {
      // Cannot do olt msg opt if:
      //   -- values are to be returned and unique operation is not being used.
      //   -- or this delete was transformed from an update of pkey/index key
      // set an indication that multiple rows will be returned.
      generator->oltOptInfo()->setMultipleRowsReturned(TRUE);
      generator->oltOptInfo()->setOltCliOpt(FALSE);
    }

  if (getTableDesc()->getNATable()->hasLobColumn())
    {
      canDoCheckAndUpdel() = FALSE;
      uniqueRowsetHbaseOper() = FALSE;
    }

  generator->setUpdSavepointOnError(FALSE);
  generator->setUpdPartialOnError(FALSE);
  
  // if unique oper with no index maintanence and autocommit is on, then
  // do not require a trnsaction. 
  // Use hbase or region transactions. 
  // Hbase guarantees single row consistency.
  Int64 transId = -1;
  if (CmpCommon::getDefault(TRAF_NO_DTM_XN) == DF_ON)
    {
      // no transaction needed
      noDTMxn() = TRUE;
    }
  else if ((uniqueHbaseOper()) &&
           (NOT cursorHbaseOper()) &&
           (NOT uniqueRowsetHbaseOper()) &&
           (NOT inlinedActions) &&
           (generator->getTransMode()->getAutoCommit() == TransMode::ON_) &&
           (! NAExecTrans(0, transId)) &&
           (NOT generator->oltOptInfo()->multipleRowsReturned()))
    {
      // no DTM transaction needed
      useRegionXn() = FALSE;
      if (CmpCommon::getDefault(TRAF_USE_REGION_XN) == DF_ON)
        useRegionXn() = TRUE;
    }
  else
    {
      generator->setTransactionFlag(TRUE);

      if ((NOT uniqueHbaseOper()) ||
	  (cursorHbaseOper()) ||
	  (uniqueRowsetHbaseOper()) ||
	  (inlinedActions) ||
	  (generator->oltOptInfo()->multipleRowsReturned()))
	generator->setUpdAbortOnError(TRUE);
    }

  // flag for hbase tables
  generator->setHdfsAccess(TRUE);
  
  markAsPreCodeGenned();

  return this;  
}

RelExpr * HbaseUpdate::preCodeGen(Generator * generator,
				  const ValueIdSet & externalInputs,
				  ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (getTableDesc()->getNATable()->isHbaseMapTable())
    {
      *CmpCommon::diags() << DgSqlCode(-1425)
			  << DgTableName(getTableDesc()->getNATable()->getTableName().
					 getQualifiedNameAsAnsiString())
                          << DgString0("Reason: update not yet supported.");
      GenExit();
    }

  if (!processConstHBaseKeys(
           generator,
           this,
           getSearchKey(),
           getIndexDesc(),
           executorPred(),
           getHbaseSearchKeys(),
           listOfUpdUniqueRows_,
           listOfUpdSubsetRows_))
    return NULL;

  //  if (! GenericUpdate::preCodeGen(generator, externalInputs, pulledNewInputs))
  //    return NULL;
  if (! UpdateCursor::preCodeGen(generator, externalInputs, pulledNewInputs))
    return NULL;

  CollIndex totalColCount = getTableDesc()->getColumnList().entries();
  NABoolean isAlignedFormat = getTableDesc()->getNATable()->isAlignedFormat(getIndexDesc());

  if (isAlignedFormat &&
      (newRecExprArray().entries() > 0) &&
      (newRecExprArray().entries() <  totalColCount))
    {
      ValueIdArray holeyArray(totalColCount);
      
      Lng32 i;
      for (i = 0; i < newRecExprArray().entries(); i++)
        {
          ItemExpr * assign = newRecExprArray()[i].getItemExpr();
          const NAColumn *nacol = assign->child(0).getNAColumn();
          Lng32 colPos = nacol->getPosition();
          holeyArray.insertAt(colPos, assign->getValueId());
        } // for
      
      for (i = 0; i < totalColCount; i++)
       {
         if (! (holeyArray.used(i)))
           {
             BaseColumn * bc = (BaseColumn*)getTableDesc()->getColumnList()[i].getItemExpr();
             CMPASSERT(bc->getOperatorType() == ITM_BASECOLUMN);

             ValueId srcId = getIndexDesc()->getIndexColumns()[i];
             
             ItemExpr * an = 
               new(generator->wHeap()) Assign(bc, srcId.getItemExpr(), FALSE);
             an->bindNode(generator->getBindWA());
             holeyArray.insertAt(i, an->getValueId());
           } // if
       } // for
      
      newRecExprArray().clear();
      newRecExprArray() = holeyArray;
    } // if aligned

  if ((isMerge()) &&
      (mergeInsertRecExpr().entries() > 0))
    {
      if ((listOfUpdSubsetRows_.entries() > 0) ||
	  (getSearchKey() && (NOT getSearchKey()->isUnique())))
	{
	  *CmpCommon::diags() << DgSqlCode(-3241)
			      << DgString0(" Non-unique ON clause not allowed with INSERT.");
	  GenExit();
	}
    }

  if (((getTableDesc()->getNATable()->isHbaseRowTable()) ||
       (getTableDesc()->getNATable()->isHbaseCellTable())) &&
      (producesOutputs()))
    {
      *CmpCommon::diags() << DgSqlCode(-1425)
			  << DgTableName(getTableDesc()->getNATable()->getTableName().
					 getQualifiedNameAsAnsiString())
                          << DgString0("Reason: Cannot return values from an hbase insert, update or delete.");
      GenExit();
    }

  NABoolean canDoRowsetOper = TRUE;
  NABoolean canDoCheckAndUpdate = TRUE;
  NABoolean needToGetCols = FALSE;
  if (producesOutputs())
    {
      retColRefSet_ = getIndexDesc()->getIndexColumns();
    }
  else
    {
      ValueIdSet colRefSet;

      // create the list of columns that need to be retrieved from hbase .
      // first add all columns referenced in the executor pred.
      HbaseAccess::addReferenceFromVIDset(executorPred(), TRUE, TRUE, colRefSet);

      if ((getTableDesc()->getNATable()->getExtendedQualName().getSpecialType() == ExtendedQualName::INDEX_TABLE))
        {
	  for (ValueId valId = executorPred().init();
	       executorPred().next(valId);
	       executorPred().advance(valId))
            {
              ItemExpr * ie = valId.getItemExpr();
              if (ie->getOperatorType() == ITM_EQUAL)
                {
                  BiRelat * br = (BiRelat*)ie;
                  br->setSpecialNulls(TRUE);
                }
            }
        }

      // add all columns referenced in the right side of the update expr.
      HbaseAccess::addColReferenceFromRightChildOfVIDarray(newRecExprArray(), colRefSet);

      if (isMerge())
	HbaseAccess::addReferenceFromVIDset(mergeUpdatePred(), TRUE, FALSE, colRefSet);

      if ((getTableDesc()->getNATable()->isHbaseRowTable()) ||
	  (getTableDesc()->getNATable()->isHbaseCellTable()) ||
          (isAlignedFormat))
	{
	  for (Lng32 i = 0; i < getIndexDesc()->getIndexColumns().entries(); i++)
	    {
	      retColRefSet_.insert(getIndexDesc()->getIndexColumns()[i]);
	    }
	}
      else
	{
	  for (ValueId valId = colRefSet.init();
	       colRefSet.next(valId);
	       colRefSet.advance(valId))
	    {
	      ValueId dummyValId;
	      if (NOT getGroupAttr()->getCharacteristicInputs().referencesTheGivenValue(valId, dummyValId))
                {
                  if ((valId.getItemExpr()->getOperatorType() == ITM_HBASE_TIMESTAMP) ||
                      (valId.getItemExpr()->getOperatorType() == ITM_HBASE_VERSION))
                    {
                      *CmpCommon::diags() << DgSqlCode(-3242)
                                          << DgString0("Illegal use of Hbase Timestamp or Hbase Version function.");
                      
                      GenExit();
                    }
                  
                  retColRefSet_.insert(valId);
                }
	    }
	}

      if (retColRefSet_.entries() > 0)
	{
	  needToGetCols = TRUE;
	  canDoRowsetOper = FALSE;
	  canDoCheckAndUpdate = FALSE;
	}

      // nullable and added columns in the row may be missing. That will cause
      // a row to not be returned if those are the only columns that are being
      // retrieved. 
      // To make sure that a row is always returned, add the key columns. These are
      // guaranteed to be present in an hbase row.
      HbaseAccess::addColReferenceFromVIDlist(getIndexDesc()->getIndexKey(), retColRefSet_);
    }

  NABoolean inlinedActions = FALSE;
  if ((getInliningInfo().hasInlinedActions()) ||
      (getInliningInfo().isEffectiveGU()))
    inlinedActions = TRUE;
  
  NABoolean isUnique = FALSE;
  if (listOfUpdSubsetRows_.entries() == 0)
    {
      if ((getSearchKey() && getSearchKey()->isUnique()) &&
	  (listOfUpdUniqueRows_.entries() == 0))
	isUnique = TRUE;
      else if ((NOT (getSearchKey() && getSearchKey()->isUnique())) &&
	       (listOfUpdUniqueRows_.entries() == 1) &&
	       (listOfUpdUniqueRows_[0].rowIds_.entries() == 1))
	isUnique = TRUE;
    }
  if (getInliningInfo().isIMGU()) {
     // There is no need to checkAndPut for IM
     canDoCheckAndUpdel() = FALSE;
     uniqueHbaseOper() = FALSE;
     if ((generator->oltOptInfo()->multipleRowsReturned()) &&
	      (CmpCommon::getDefault(HBASE_ROWSET_VSBB_OPT) == DF_ON) &&
	      (NOT generator->isRIinliningForTrafIUD()))
	 uniqueRowsetHbaseOper() = TRUE;
  }
  else
  if (isUnique)
    {
      //If this unique delete is not part of a rowset operation , 
      //don't allow it to be cancelled.
      if (!generator->oltOptInfo()->multipleRowsReturned())
	generator->setMayNotCancel(TRUE);
      uniqueHbaseOper() = TRUE;

      canDoCheckAndUpdel() = FALSE;

      if ((NOT isMerge()) &&
	  (NOT producesOutputs()) &&
	  (executorPred().isEmpty()) &&
	  (NOT needToGetCols) &&
	  (NOT inlinedActions))
	{
	  if ((generator->oltOptInfo()->multipleRowsReturned()) &&
	      (CmpCommon::getDefault(HBASE_ROWSET_VSBB_OPT) == DF_ON) &&
	      (NOT generator->isRIinliningForTrafIUD()))
	    uniqueRowsetHbaseOper() = TRUE;
	  else if ((NOT generator->oltOptInfo()->multipleRowsReturned()) &&
		   (listOfUpdUniqueRows_.entries() == 0))
	    {
	      if ((CmpCommon::getDefault(HBASE_CHECK_AND_UPDEL_OPT) == DF_ON) &&
                  (NOT isAlignedFormat))
		canDoCheckAndUpdel() = TRUE;
	    }
	}
    }
  else if (producesOutputs())
    {
      // Cannot do olt msg opt if:
      //   -- values are to be returned and unique operation is not being used.
      // set an indication that multiple rows will be returned.
      generator->oltOptInfo()->setMultipleRowsReturned(TRUE);
      generator->oltOptInfo()->setOltCliOpt(FALSE);
    }

  generator->setUpdSavepointOnError(FALSE);
  generator->setUpdPartialOnError(FALSE);

  // if unique oper with no index maintanence and autocommit is on, then
  // do not require a transaction. 
  // Use hbase or region transactions. 
  // Hbase guarantees single row consistency.
  Int64 transId = -1;
  if (CmpCommon::getDefault(TRAF_NO_DTM_XN) == DF_ON)
    {
      // no transaction needed
      noDTMxn() = TRUE;
    }
  else if ((uniqueHbaseOper()) &&
           (NOT isMerge()) &&
           (NOT cursorHbaseOper()) &&
           (NOT uniqueRowsetHbaseOper()) &&
           (NOT inlinedActions) &&
           (generator->getTransMode()->getAutoCommit() == TransMode::ON_) &&
           (! NAExecTrans(0, transId)) &&
           (NOT generator->oltOptInfo()->multipleRowsReturned()))
    {
      // no DTM transaction needed
      useRegionXn() = FALSE;
      if (CmpCommon::getDefault(TRAF_USE_REGION_XN) == DF_ON)
        useRegionXn() = TRUE;
    }
  else
    {
      generator->setTransactionFlag(TRUE);

      if ((NOT uniqueHbaseOper()) ||
	  (isMerge()) ||
	  (cursorHbaseOper()) ||
	  (uniqueRowsetHbaseOper()) ||
	  (inlinedActions) ||
	  (generator->oltOptInfo()->multipleRowsReturned()))
	generator->setUpdAbortOnError(TRUE);
    }

  // flag for hbase tables
  generator->setHdfsAccess(TRUE);
  if (getTableDesc()->getNATable()->hasLobColumn())
    {
      for (CollIndex i = 0; i < newRecExprArray().entries(); i++)
	{
	  NAColumn * col = 
	    newRecExprArray()[i].getItemExpr()->child(0)->castToItemExpr()->
	    getValueId().getNAColumn(TRUE);

	  ItemExpr * val = 
	    newRecExprArray()[i].getItemExpr()->child(1)->castToItemExpr();
	  
	  if ((col->getType()->isLob()) &&
	      (val->getOperatorType() == ITM_LOBUPDATE))
	    {
	      LOBupdate * lu = (LOBupdate*)val;

	      lu->updatedTableObjectUID() = 
		getIndexDesc()->getPrimaryTableDesc()->
		getNATable()->objectUid().castToInt64();
	      
	      lu->updatedTableSchemaName() = "\"";
	      lu->updatedTableSchemaName() += 
		getTableDesc()->getNATable()->
		getTableName().getCatalogName();
	      lu->updatedTableSchemaName().append("\".\"");
	      lu->updatedTableSchemaName().
		append(getTableDesc()->getNATable()->
		       getTableName().getSchemaName());
	      lu->updatedTableSchemaName() += "\"";
              lu->lobSize() = col->getType()->getPrecision();
	      lu->lobNum() = col->lobNum();
	     
              if (lu->lobStorageType() == Lob_Empty)
                    {
                      lu->lobStorageType() = col->lobStorageType();
                    }
              if (lu->lobStorageType() != col->lobStorageType())
                    {
                      *CmpCommon::diags() << DgSqlCode(-1432)
                                          << DgInt0((Int32)lu->lobStorageType())
                                          << DgInt1((Int32)col->lobStorageType())
                                          << DgString0(col->getColName());
                      GenExit();
                    }
	      lu->lobStorageLocation() = col->lobStorageLocation();
	    }
	} // for
    } // if
 
  markAsPreCodeGenned();

  return this;  
}

RelExpr * HiveInsert::preCodeGen(Generator * generator,
                              const ValueIdSet & externalInputs,
                              ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  generator->setHiveAccess(TRUE);
  return GenericUpdate::preCodeGen(generator, externalInputs, pulledNewInputs);
}


RelExpr * HbaseInsert::preCodeGen(Generator * generator,
                              const ValueIdSet & externalInputs,
                              ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  // char. outputs are set to empty after in RelExpr::genPreCode sometimes,
  // after a call to resolveCharOutputs. We need to remember if a returnRow
  // tdb flag should be set, even if no output columns are required
  if (getIsTrafLoadPrep() && !getGroupAttr()->getCharacteristicOutputs().isEmpty())
    setReturnRow(TRUE);

  if (! GenericUpdate::preCodeGen(generator, externalInputs, pulledNewInputs))
    return NULL;

  NABoolean inlinedActions = FALSE;
  if ((getInliningInfo().hasInlinedActions()) ||
      (getInliningInfo().isEffectiveGU()))
    inlinedActions = TRUE;

  // Allow projecting rows if the upsert has IM. 
  if (inlinedActions && isUpsert())
    setReturnRow(TRUE);

  if (((getTableDesc()->getNATable()->isHbaseRowTable()) ||
       (getTableDesc()->getNATable()->isHbaseCellTable())) &&
      (producesOutputs()))
    {
      *CmpCommon::diags() << DgSqlCode(-1425)
			  << DgTableName(getTableDesc()->getNATable()->getTableName().
					 getQualifiedNameAsAnsiString())
                          << DgString0("Reason: Cannot return values from an hbase insert, update or delete.");
      GenExit();
    }

  if ((isUpsert()) &&
      ((getInsertType() == Insert::VSBB_INSERT_USER) ||
       (getInsertType() == Insert::UPSERT_LOAD)))
    {
      // Remove this restriction
      /* if ((inlinedActions || producesOutputs())&& !getIsTrafLoadPrep())
         setInsertType(Insert::SIMPLE_INSERT);*/
      
    }

  

  
  // if there are blob columns, use simple inserts.
  if ( getTableDesc()->getNATable()->hasLobColumn())
    {
      setInsertType(Insert::SIMPLE_INSERT);

      NAColumnArray colArray;
      NAColumn *tgtCol, *srcCol;

      for (CollIndex ii = 0;
           ii < newRecExprArray().entries(); ii++)
	{
	  ItemExpr *assignExpr =
	    newRecExprArray()[ii].getItemExpr();
	  
	  ValueId tgtValueId =
	    assignExpr->child(0)->castToItemExpr()->getValueId();

	  ValueId srcValueId =
	    assignExpr->child(1)->castToItemExpr()->getValueId();

	  tgtCol = tgtValueId.getNAColumn( TRUE );
	  srcCol = srcValueId.getNAColumn( TRUE );
	  ItemExpr * child1Expr = assignExpr->child(1);
	  if (srcValueId.getType().isLob())
	    {
	      LOBinsert * li = NULL;
	      if ((child1Expr->getOperatorType() != ITM_LOBINSERT) &&
		  (child1Expr->getOperatorType() != ITM_LOBUPDATE))
		{
		  li = new(generator->wHeap())
		    LOBinsert(child1Expr, NULL, LOBoper::LOB_);
                  
		  li->insertedTableObjectUID() = 
		    getIndexDesc()->getPrimaryTableDesc()->
		    getNATable()->objectUid().castToInt64();

		  li->insertedTableSchemaName() = "\"";
		  li->insertedTableSchemaName() += 
		    getTableDesc()->getNATable()->
		    getTableName().getCatalogName();
		  li->insertedTableSchemaName().append("\".\"");
		  li->insertedTableSchemaName().
		    append(getTableDesc()->getNATable()->
			   getTableName().getSchemaName());
		  li->insertedTableSchemaName() += "\"";
		  
		
                  li->lobSize() = tgtValueId.getType().getPrecision();
		  li->lobFsType() = tgtValueId.getType().getFSDatatype();

		  li->lobNum() = tgtCol->lobNum();
                  if ((child1Expr->getOperatorType() == ITM_CONSTANT) && 
                      !(((ConstValue *)child1Expr)->isNull()))
                    {
                    if (srcCol->lobStorageType() != tgtCol->lobStorageType())
                      {
                        *CmpCommon::diags() << DgSqlCode(-1432)
                                            << DgInt0((Int32)srcCol->lobStorageType())
                                            << DgInt1((Int32)tgtCol->lobStorageType())
                                            << DgString0(tgtCol->getColName());
                        GenExit();
                      }
                    }
                    else
                      if ((child1Expr->getOperatorType() == ITM_BASECOLUMN)||
                          (child1Expr->getOperatorType() == ITM_INDEXCOLUMN))
                        {
                          if (srcCol->lobStorageType() != tgtCol->lobStorageType())
                            {
                              *CmpCommon::diags() << DgSqlCode(-1432)
                                                  << DgInt0((Int32)srcCol->lobStorageType())
                                                  << DgInt1((Int32)tgtCol->lobStorageType())
                                                  << DgString0(tgtCol->getColName());
                              GenExit();
                            }
                          
                        }
                  li->lobStorageType() = tgtCol->lobStorageType();

		  li->lobStorageLocation() = tgtCol->lobStorageLocation();

		  li->bindNode(generator->getBindWA());

		  child1Expr = li;

		  assignExpr->child(1) = child1Expr;
		}
	      else if (child1Expr->getOperatorType() == ITM_LOBINSERT)
		{
		  li = (LOBinsert*)child1Expr;
		  li->insertedTableObjectUID() = 
		    getIndexDesc()->getPrimaryTableDesc()->
		    getNATable()->objectUid().castToInt64();

		  li->insertedTableSchemaName() = "\"";
		  li->insertedTableSchemaName() += 
		    getTableDesc()->getNATable()->
		    getTableName().getCatalogName();
		  li->insertedTableSchemaName().append("\".\"");
		  li->insertedTableSchemaName().
		    append(getTableDesc()->getNATable()->
			   getTableName().getSchemaName());
		  li->insertedTableSchemaName() += "\"";
		  
		  li->lobNum() = tgtCol->lobNum();
                  //If we are initializing an empty_lob, assume the storage 
                  //type of the underlying column
                  if (li->lobStorageType() == Lob_Empty)
                    {
                      li->lobStorageType() = tgtCol->lobStorageType();
                    }
                  if (li->lobStorageType() != tgtCol->lobStorageType())
                    {
                      *CmpCommon::diags() << DgSqlCode(-1432)
                                          << DgInt0((Int32)li->lobStorageType())
                                          << DgInt1((Int32)tgtCol->lobStorageType())
                                          << DgString0(tgtCol->getColName());
                        GenExit();
                      }
		  li->lobStorageLocation() = tgtCol->lobStorageLocation();
		  
		  li->lobSize() = tgtValueId.getType().getPrecision();

		  if (li->lobFsType() != tgtValueId.getType().getFSDatatype())
		    {
		      // create a new LOBinsert node since fsType has changed.
		      ItemExpr * liChild = li->child(0);
		      ItemExpr * liChild1 = li->child(1);
		      li = new(generator->wHeap())
			LOBinsert(liChild, liChild1, li->getObj(),FALSE, 
                                  li->lobAsVarchar());
		      
		      li->insertedTableObjectUID() = 
			getIndexDesc()->getPrimaryTableDesc()->
			getNATable()->objectUid().castToInt64();
		      
		      li->insertedTableSchemaName() = "\"";
		      li->insertedTableSchemaName() += 
			getTableDesc()->getNATable()->
			getTableName().getCatalogName();
		      li->insertedTableSchemaName().append("\".\"");
		      li->insertedTableSchemaName().
			append(getTableDesc()->getNATable()->
			       getTableName().getSchemaName());
		      li->insertedTableSchemaName() += "\"";
		      
		      //li->lobSize() = srcValueId.getType().getPrecision();
                      li->lobSize() = tgtValueId.getType().getPrecision();
		      li->lobFsType() = tgtValueId.getType().getFSDatatype();

		      li->lobNum() = tgtCol->lobNum();
		     
		      li->lobStorageLocation() = tgtCol->lobStorageLocation();
		      
		      li->bindNode(generator->getBindWA());

		      assignExpr->child(1) = li;
		    }
		} // lobinsert

	      GenAssert(li, "must have a LobInsert node");
	    } // lob
	}
    }


  if ((getInsertType() == Insert::SIMPLE_INSERT)  &&
      (NOT getTableDesc()->getNATable()->hasLobColumn()))
    uniqueHbaseOper() = TRUE;

  generator->setUpdSavepointOnError(FALSE);
  generator->setUpdPartialOnError(FALSE);

  // if unique oper with no index maintanence and autocommit is on, then
  // do not require a trnsaction. 
  // Use hbase or region transactions. 
  // Hbase guarantees single row consistency.
  Int64 transId = -1;
  if ((CmpCommon::getDefault(TRAF_NO_DTM_XN) == DF_ON) ||
      (isNoRollback()) ||
      ((isUpsert()) && (insertType_ == UPSERT_LOAD)))
    {
      // no transaction needed
      noDTMxn() = TRUE;
    }
  else if ((uniqueHbaseOper()) &&
           (NOT uniqueRowsetHbaseOper()) &&
           (NOT inlinedActions) &&
           (generator->getTransMode()->getAutoCommit() == TransMode::ON_) &&
           (! NAExecTrans(0, transId)) &&
           (NOT generator->oltOptInfo()->multipleRowsReturned()))
    {
      // no DTM transaction needed
      useRegionXn() = FALSE;
      if (CmpCommon::getDefault(TRAF_USE_REGION_XN) == DF_ON)
        useRegionXn() = TRUE;
    }
  else
    {
      generator->setTransactionFlag(TRUE);

      if ((NOT uniqueHbaseOper()) ||
	  (uniqueRowsetHbaseOper()) ||
	  (inlinedActions) ||
	  (generator->oltOptInfo()->multipleRowsReturned()))
	generator->setUpdAbortOnError(TRUE);
    }

  return this;
}

RelExpr * ExeUtilHiveTruncateLegacy::preCodeGen(Generator * generator,
                                                const ValueIdSet & externalInputs,
                                                ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  return ExeUtilExpr::preCodeGen(generator,externalInputs,pulledNewInputs);
}

RelExpr * ExeUtilLobExtract::preCodeGen(Generator * generator,
                                       const ValueIdSet & externalInputs,
                                       ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! ExeUtilExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  ValueIdSet availableValues;
  for (ValueId exprId = getGroupAttr()->getCharacteristicInputs().init();
       getGroupAttr()->getCharacteristicInputs().next(exprId);
       getGroupAttr()->getCharacteristicInputs().advance(exprId) )
    {
      if (exprId.getItemExpr()->getOperatorType() != ITM_VEG_REFERENCE)
       availableValues += exprId;
    }
  
  getGroupAttr()->setCharacteristicInputs(availableValues);
  getInputValuesFromParentAndChildren(availableValues);

  if (handle_)
    handle_->replaceVEGExpressions
      (availableValues, getGroupAttr()->getCharacteristicInputs());
  
  markAsPreCodeGenned();

   // Done.
   return this;
 }

RelExpr * ExeUtilLobUpdate::preCodeGen(Generator * generator,
                                       const ValueIdSet & externalInputs,
                                       ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! ExeUtilExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  ValueIdSet availableValues;
  for (ValueId exprId = getGroupAttr()->getCharacteristicInputs().init();
       getGroupAttr()->getCharacteristicInputs().next(exprId);
       getGroupAttr()->getCharacteristicInputs().advance(exprId) )
    {
      if (exprId.getItemExpr()->getOperatorType() != ITM_VEG_REFERENCE)
       availableValues += exprId;
    }
  
  getGroupAttr()->setCharacteristicInputs(availableValues);
  getInputValuesFromParentAndChildren(availableValues);

  if (handle_)
    handle_->replaceVEGExpressions
      (availableValues, getGroupAttr()->getCharacteristicInputs());
  xnNeeded() = TRUE;
  markAsPreCodeGenned();

   // Done.
   return this;
 }

RelExpr * HashGroupBy::preCodeGen(Generator * generator,
                                 const ValueIdSet & externalInputs,
                                 ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;


  if ( CmpCommon::getDefault(COMPRESSED_INTERNAL_FORMAT) == DF_SYSTEM)
  {
    NABoolean resize = FALSE;
    NABoolean defrag = FALSE;
    ValueIdSet vidSet = child(0)->getGroupAttr()->getCharacteristicOutputs();

    ExpTupleDesc::TupleDataFormat tupleFormat =
                  determineInternalFormat( vidSet,
                                           this,
                                           resize,
                                           generator,
                                           FALSE,
                                           defrag);

    cacheTupleFormatAndResizeFlag(tupleFormat, resize, defrag);

    if (tupleFormat == ExpTupleDesc::SQLMX_ALIGNED_FORMAT)
    {
      generator->incNCIFNodes();
    }
    else
    {
      generator->decNCIFNodes();
    }
  }


  return GroupByAgg::preCodeGen(generator, externalInputs, pulledNewInputs);

}
RelExpr * GroupByAgg::preCodeGen(Generator * generator,
				 const ValueIdSet & externalInputs,
				 ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  // Check if the pivs of this operator and it's child are the same.
  // If they are not, make them the same.
  replacePivs();

  generator->clearPrefixSortKey();
  // Resolve the VEGReferences and VEGPredicates, if any, that appear
  // in the Characteristic Inputs, in terms of the externalInputs.
  getGroupAttr()->resolveCharacteristicInputs(externalInputs);
  // My Characteristic Inputs become the external inputs for my child.
  child(0) = child(0)->preCodeGen(generator,
				  getGroupAttr()->getCharacteristicInputs(),
				  pulledNewInputs);
  if (! child(0).getPtr())
    return NULL;

  if ((getOperatorType() == REL_SHORTCUT_GROUPBY)
      && (getFirstNRows() == 1))
    {
      RelExpr * firstnNode = new(generator->wHeap()) FirstN(child(0),
							    getFirstNRows(),
							    FALSE /* [any n] is good enough */);
      firstnNode->setEstRowsUsed(getEstRowsUsed());
      firstnNode->setMaxCardEst(getMaxCardEst());
      firstnNode->setInputCardinality(child(0)->getInputCardinality());
      firstnNode->setPhysicalProperty(child(0)->getPhysicalProperty());
      firstnNode->setGroupAttr(child(0)->getGroupAttr());
      //10-060516-6532 -Begin
      //When FIRSTN node is created after optimization phase, the cost
      //of that node does not matter.But, display_explain and explain
      //show zero operator costs and rollup cost which confuses the user.
      //Also, the VQP crashes when cost tab for FIRSTN node is selected.
      //So, creating a cost object will fix this.
      //The operator cost is zero and rollup cost is same as it childs.
      Cost* firstnNodecost = new HEAP Cost();
      firstnNode->setOperatorCost(firstnNodecost);
      Cost* rollupcost = (Cost *)(child(0)->getRollUpCost());
      *rollupcost += *firstnNodecost;
      firstnNode->setRollUpCost(rollupcost);
      //10-060516-6532 -End

      firstnNode =
	firstnNode->preCodeGen(generator,
			       getGroupAttr()->getCharacteristicInputs(),
			       pulledNewInputs);
      if (! firstnNode)
	return NULL;

      setChild(0, firstnNode);
    }

  getGroupAttr()->addCharacteristicInputs(pulledNewInputs);

  // Accumulate the values that are provided as inputs by my parent
  // together with the values that are produced as outputs by my
  // children. Use these values for rewriting the VEG expressions.
  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);
  NABoolean replicatePredicates = TRUE;

  // Rebuild the grouping expressions tree. Use bridge values, if possible
  groupExpr().replaceVEGExpressions
                 (availableValues,
		  getGroupAttr()->getCharacteristicInputs(),
                  FALSE, // No key predicates need to be generated here
		  NULL,
		  replicatePredicates,
                  &getGroupAttr()->getCharacteristicOutputs());

  // Rebuild the rollup grouping expressions tree. Use bridge values, if possible
  rollupGroupExprList().replaceVEGExpressions
                 (availableValues,
		  getGroupAttr()->getCharacteristicInputs(),
                  FALSE, // No key predicates need to be generated here
		  NULL,
		  replicatePredicates,
                  &getGroupAttr()->getCharacteristicOutputs());

  // Rebuild the aggregate expressions tree
  aggregateExpr().replaceVEGExpressions
                     (availableValues,
  	 	      getGroupAttr()->getCharacteristicInputs());

  if (CmpCommon::getDefault(COMP_BOOL_211) == DF_ON) 
  {
    ValueIdSet constantsInGroupExpr ;
    groupExpr().getConstantExprs(constantsInGroupExpr,FALSE);
    if (constantsInGroupExpr.entries() > 0)
    {
      if (constantsInGroupExpr.entries() == groupExpr().entries())
      {
        ValueId vid ;
        constantsInGroupExpr.getFirst(vid);
        constantsInGroupExpr.remove(vid);
      }
      groupExpr() -= constantsInGroupExpr ;
    }
  }

  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  getInputAndPotentialOutputValues(availableValues);

  selectionPred().replaceVEGExpressions
                     (availableValues,
		      getGroupAttr()->getCharacteristicInputs(),
		      FALSE, // No key predicates need to be generated here
		      NULL,
		      replicatePredicates);

  getGroupAttr()->resolveCharacteristicOutputs
                      (availableValues,
		       getGroupAttr()->getCharacteristicInputs());

  // if the grouping is executed in DP2, we don't do overflow
  // handling. This also means, that it is a partial group by
  // Do not do overflow handling for any partial groupby.
  //
  NABoolean isPartialGroupBy = (isAPartialGroupByNonLeaf() ||
                                isAPartialGroupByLeaf());

  // The old way, only groupbys in DP2 are considered partial
  //
  if (CmpCommon::getDefault(COMP_BOOL_152) == DF_ON) {
    isPartialGroupBy = executeInDP2();
  }
  
  if ((getOperatorType() == REL_HASHED_GROUPBY) && !isPartialGroupBy) {
    // Count this BMO and add its needed memory to the total needed
    generator->incrNumBMOs();

  if ((ActiveSchemaDB()->getDefaults()).getAsDouble(BMO_MEMORY_LIMIT_PER_NODE_IN_MB) > 0)
      generator->incrBMOsMemory(getEstimatedRunTimeMemoryUsage(generator, TRUE));

  }

  markAsPreCodeGenned();

  // Done.
  return this;
} // GroupByAgg::preCodeGen()

RelExpr * MergeUnion::preCodeGen(Generator * generator,
                                 const ValueIdSet & externalInputs,
                                 ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  // A temporary union (blocked union introduced for inlining after trigger)
  // should not get here. Should be removed in optimization phase.
  GenAssert(!getIsTemporary(), "Expecting this blocked union to be removed by this phase");

  // Check if the pivs of this operator and it's child are the same.
  // If they are not, make them the same.
  replacePivs();

  // clear any prefix sort key in generator work area
  generator->clearPrefixSortKey();

  // Resolve the VEGReferences and VEGPredicates, if any, that appear
  // in the Characteristic Inputs, in terms of the externalInputs.
  getGroupAttr()->resolveCharacteristicInputs(externalInputs);

  // Predicate pushdown causes the Characteristic Inputs and Outputs
  // of the union to be set precisely to those values that are
  // required by one of its descendants or by one of its ancestors,
  // respectively. However, the colMapTable_ contains all the values
  // that the MergeUnion is capable of producing. The colMapTable_
  // is rebuilt here to contain exactly those values that appear in
  // the Characteristic Outputs.
  //
  // The output of the union is defined by the ValueIdUnion
  // expressions that are maintained in the colMapTable_.
  //

  ValueIdSet charOutputs = getGroupAttr()->getCharacteristicOutputs();
  colMapTable().clear();

  for (ValueId v = charOutputs.init();
       charOutputs.next(v); charOutputs.advance(v))
  {
    if (v.getItemExpr()->getOperatorType() != ITM_VALUEIDUNION)
    {
      // "other" available values besides the value being considered.
      ValueIdSet availableValues = charOutputs;
      availableValues -= v;

      // -------------------------------------------------------------------
      // see whether the value being considered is covered by the remaining
      // values. that is, whether it is an expression in termes of the
      // other vid union's.
      // -------------------------------------------------------------------
      ValueIdSet outputId;
      outputId.insert(v);
      outputId.removeUnCoveredExprs(availableValues);

      // -------------------------------------------------------------------
      // v removed from outputId. that means it's not covered by remaining
      // vid union's. add the vid union's v is in terms of to colMapTable.
      // the node needs to produce it. Instead of producing the expression,
      // change the node to produce just the vid union, the expression can
      // be evaluatated at the parent.
      // -------------------------------------------------------------------
      if (outputId.isEmpty())
      {
        Int32 leftIndex = getLeftMap().getTopValues().index(v);
        Int32 rightIndex = getRightMap().getTopValues().index(v);

        CMPASSERT((leftIndex != NULL_COLL_INDEX) &&
                  (rightIndex != NULL_COLL_INDEX));

        ItemExpr *ptr = new(CmpCommon::statementHeap())
          ValueIdUnion(getLeftMap().getBottomValues()[leftIndex],
                       getRightMap().getBottomValues()[rightIndex],v);
        v.replaceItemExpr(ptr);
	colMapTable().insert(v);
      }
    }
    else
      colMapTable().insert(v);
  }

  // My Characteristic Inputs become the external inputs for my children.
  Lng32 nc = (Lng32)getArity();
  const ValueIdSet & inputs = getGroupAttr()->getCharacteristicInputs();
  for (Lng32 index = 0; index < nc; index++)
  {
    ValueIdSet pulledInputs;
    child(index) = child(index)->preCodeGen(generator,inputs,pulledInputs);
    if (child(index).getPtr() == NULL) return NULL;
    pulledNewInputs += pulledInputs;
  }

  // Accumulate the values that are provided as inputs by my parent
  // together with the values that are produced as outputs by my
  // children. Use these values for rewriting the VEG expressions.
  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);

  // Rebuild the colMapTable
  colMapTable().replaceVEGExpressions(availableValues,inputs);

  // Rebuild the sortOrder.
  sortOrder_.replaceVEGExpressions(availableValues,inputs);

  // Rebuild the merge expression
  if (mergeExpr_)
  {
    mergeExpr_ = mergeExpr_->replaceVEGExpressions(availableValues,inputs);
    //10-061219-1283:Set the second arugment to TRUE to redrive typesynthesis of children.
    mergeExpr_->synthTypeAndValueId(TRUE,TRUE);
  }

  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  getInputAndPotentialOutputValues(availableValues);

  // Rebuild the selection predicate tree.
  selectionPred().replaceVEGExpressions(availableValues,inputs);
  getGroupAttr()->resolveCharacteristicOutputs(availableValues,inputs);
  // Rebuild the conditional expression.
  condExpr().replaceVEGExpressions(availableValues,
				   getGroupAttr()->getCharacteristicInputs());

  if (!getUnionForIF() && !getInliningInfo().isIMUnion())
    generator->oltOptInfo()->setMultipleRowsReturned(TRUE);

  markAsPreCodeGenned();

  return this;
} // MergeUnion::preCodeGen()

RelExpr * MapValueIds::preCodeGen(Generator * generator,
				  const ValueIdSet & externalInputs,
				  ValueIdSet &pulledNewInputs)
{
  const ValueIdList &upperValues = map_.getTopValues();
  const ValueIdList &lowerValues = map_.getBottomValues();

  if (nodeIsPreCodeGenned())
    return this;

  // Check if the pivs of this operator and it's child are the same.
  // If they are not, make them the same.
  replacePivs();

  // Resolve the VEGReferences and VEGPredicates, if any, that appear
  // in the Characteristic Inputs, in terms of the externalInputs.
  getGroupAttr()->resolveCharacteristicInputs(externalInputs);

  // My Characteristic Inputs become the external inputs for my children.
  child(0) = child(0)->preCodeGen(
       generator,
       getGroupAttr()->getCharacteristicInputs(),
       pulledNewInputs);
  if (child(0).getPtr() == NULL)
    return NULL;

  getGroupAttr()->addCharacteristicInputs(pulledNewInputs);

  if (cseRef_)
    {
      // -------------------------------------------------------------
      // This MapValueIds represents a common subexpression.
      //
      // We need to take some actions here to help with VEG rewrite,
      // since we eliminated some nodes from the tree, while the
      // VEGies still contain all equated values, including those that
      // got eliminated. Furthermore, the one tree that was chosen for
      // materialization got moved and we need to make sure that the
      // place where we scan the temp table produces the same ValueIds
      // that were marked as "Bridge Values" when we processed the
      // insert into temp statement.
      // -------------------------------------------------------------

      ValueIdSet cseVEGPreds;
      const ValueIdList &vegCols(cseRef_->getColumnList());
      ValueIdSet nonVegCols(cseRef_->getNonVEGColumns());
      NABoolean isAnalyzingConsumer =
        (CmpCommon::statement()->getCSEInfo(cseRef_->getName())->
           getIdOfAnalyzingConsumer() == cseRef_->getId());
      ValueIdSet availableValues(
           getGroupAttr()->getCharacteristicInputs());

      valuesNeededForVEGRewrite_ += cseRef_->getNonVEGColumns();
      availableValues += valuesNeededForVEGRewrite_;

      // find all the VEG predicates of the original columns that this
      // common subexpression represents...
      for (CollIndex v=0; v<vegCols.entries(); v++)
        if (vegCols[v].getItemExpr()->getOperatorType() == ITM_VEG_REFERENCE)
          {
            // look at one particular VEG that is produced by this
            // query tree
            VEG *veg =
              static_cast<VEGReference *>(vegCols[v].getItemExpr())->getVEG();

            if (isAnalyzingConsumer && veg->getBridgeValues().entries() > 0)
              {
                // If we are looking at the analyzing consumer, then
                // its child tree "C" got transformed into an
                // "insert overwrite table "temp" select * from "C".

                // This insert into temp statement chose some VEG
                // member(s) as the "bridge value(s)". Find these bridge
                // values and choose one to represent the VEG here.
                const ValueIdSet &vegMembers(veg->getAllValues());

                // collect all VEG members produced and subtract them
                // from the values to be used for VEG rewrite
                ValueIdSet subtractions(cseRef_->getNonVEGColumns());
                // then add back only the bridge value
                ValueIdSet additions;

                // get the VEG members produced by child C
                subtractions.intersectSet(vegMembers);

                // augment the base columns with their index columns,
                // the bridge value is likely an index column
                for (ValueId v=subtractions.init();
                     subtractions.next(v);
                     subtractions.advance(v))
                  if (v.getItemExpr()->getOperatorType() == ITM_BASECOLUMN)
                    {
                      subtractions +=
                        static_cast<BaseColumn *>(v.getItemExpr())->getEIC();
                    }

                // now find a bridge value (or values) that we can
                // produce
                additions = subtractions;
                additions.intersectSet(veg->getBridgeValues());

                // if we found it, then adjust availableValues
                if (additions.entries() > 0)
                  {
                    availableValues -= subtractions;
                    availableValues += additions;
                    // do the same for valuesNeededForVEGRewrite_,
                    // which will be used for rewriting the char.
                    // outputs
                    valuesNeededForVEGRewrite_ -= subtractions;
                    valuesNeededForVEGRewrite_ += additions;
                  }
              }

            cseVEGPreds += veg->getVEGPredicate()->getValueId();
          } // a VEGRef

      // Replace the VEGPredicates, pretending that we still have
      // the original tree below us, not the materialized temp
      // table. This will hopefully keep the bookkeeping in the
      // VEGies correct by setting the right referenced values
      // and choosing the right bridge values.
      cseVEGPreds.replaceVEGExpressions(
           availableValues,
           getGroupAttr()->getCharacteristicInputs());

    } // this MapValueIds is for a common subexpression

  // ---------------------------------------------------------------------
  // The MapValueIds node describes a mapping between expressions used
  // by its child tree and expressions used by its parent tree. The
  // generator will make sure that the output values of the child tree
  // and the input values from the parent get passed in the correct
  // buffers.
  // ---------------------------------------------------------------------

  // ---------------------------------------------------------------------
  // Replacing VEGReferences in those mapped expressions is not possible
  // in all cases; we have to restrict the kind of mappings that can
  // be done for expressions involving VEGs. This method assumes that
  // references to VEGs do not get altered during the rewrite, in other
  // words it assumes mappings of the kind
  //
  //     a)          sum(VEGRef(a,b,c))    <---->    VEGRef(a,b,c)
  //
  // and it disallows mappings of the kind
  //
  //     b)          count(VEGRef(a,b,c))  <----->   1
  //     c)          VEGRef(a,b,c)         <----->   VEGRef(d,e,f)
  //
  // Mappings of type b) will still work, as long as the VEGRef is contained
  // in some other mapped expression. A possible extension is to store
  // in the MapValueIds node which element(s) of which VEGRef should
  // be replaced in this step, but this information is hard to get
  // during optimization, unless we are looking at a scan node.
  // ---------------------------------------------------------------------

  // ---------------------------------------------------------------------
  // The map contains many mappings, not all of which will have to
  // be evaluated by the generator. Only those values that are either
  // characteristic output values or are referenced by characteristic
  // output values will actually be mapped at execution time. Therefore
  // we first determine the actually needed mappings with the coverTest
  // method.
  // ---------------------------------------------------------------------

  GroupAttributes emptyGA;
  ValueIdSet coveredExpr;
  ValueIdSet referencedUpperValues;
  ValueIdMap newMap;

  emptyGA.setCharacteristicInputs(getGroupAttr()->getCharacteristicInputs());

  emptyGA.coverTest(
       getGroupAttr()->getCharacteristicOutputs(), // the expressions needed
       upperValues,            // offer the upper values as extra inputs
       coveredExpr,            // doesn't matter which outputs are covered
       referencedUpperValues); // get those upper values needed by the outputs

  // Compute the values that are available here.
  ValueIdSet lowerAvailableValues;
  getOutputValuesOfMyChildren(lowerAvailableValues);
  lowerAvailableValues += getGroupAttr()->getCharacteristicInputs();

  // The VEGReferences that are resolved can appear as leaves of the
  // expressions contained in lowerAvailableValues. These values are
  // required for remapping the upperValues.
  ValueIdSet leafValues;

  ValueId x;
  for (x = lowerAvailableValues.init();
       lowerAvailableValues.next(x);
       lowerAvailableValues.advance(x))
    x.getItemExpr()->getLeafValueIds(leafValues);
  lowerAvailableValues += leafValues;

  ValueIdSet upperAvailableValues(valuesNeededForVEGRewrite_);
  // The addition of the lower available values is only necessary to
  // avoid an assertion failure in VEGReference::replaceVEGReference().
  upperAvailableValues += lowerAvailableValues;

  // ---------------------------------------------------------------------
  // now walk through each needed mapping and replace wildcards in both its
  // upper and lower expressions
  // ---------------------------------------------------------------------
  for (CollIndex i = 0; i < upperValues.entries(); i++)
    {
      if (referencedUpperValues.contains(upperValues[i]))
	{
	  ItemExpr *newUpper;
	  ItemExpr *newLower;
	  // This mapping is actually required, expand wild cards for it

          // We used to resolve the upper values using the
          // upperAvailableValues.  Note that these available values
          // might not actually be available to this node.  This could
          // sometimes cause problems if the VEGRef was resolved to the
          // 'wrong' value and the value is in a VEGPRed above.  This
          // would cause VEGPRed to be resolved incorrectly and
          // possibly drop some join predicates.

          // Don't need to replace the VEGgies in the upper since they
          // will never be codeGen'ed.  Just need to replace them with
          // a suitable substitute.

          // If it is a VEG_REF, then replace it with a surrogate
          // (NATypeToItem) otherwise leave it as is.  (Don't use the
          // surrogate for all upper values because there are some
          // MVIds that have BaseColumns in the upper values. These
          // MVIds are introduced by Triggers.  And these BaseColumns
          // are used in other operators in other parts of the tree
          // where they are expected to always be BaseColumns. So
          // mapping them here will cause problems elsewhere).  In any
          // case, all we need to do here is to get rid of the
          // VEGRefs.
          //

	  newLower = lowerValues[i]
                       .getItemExpr()
                           ->replaceVEGExpressions
                                (lowerAvailableValues,
				 getGroupAttr()->getCharacteristicInputs());

          newUpper = upperValues[i].getItemExpr();

          if (upperValues[i] != lowerValues[i]) 
          {
             if (newUpper->getOperatorType() == ITM_VEG_REFERENCE) 
             {
               if (valuesNeededForVEGRewrite_.entries() > 0)
                 // If this node is used to map the outputs of one
                 // table to those of another, upperAvailableValues
                 // has been constructed to contain the base column a
                 // vegref should map to, so we use that instead of a
                 // created surrogate.
                 newUpper = newUpper->replaceVEGExpressions
                                (upperAvailableValues,
				 getGroupAttr()->getCharacteristicInputs());
               else {
                 NAType *mapType =
                   upperValues[i].getType().newCopy(generator->wHeap());
       
                 // Create replacement for VEGRef
                 //
                 ItemExpr *mapping =
                   new(generator->wHeap()) NATypeToItem(mapType);
       
                 ValueId id = upperValues[i];
       
                 // Replace in ValueDescArray.  All instances of this ID
                 // will now map to the surrogate.
                 //
                 id.replaceItemExpr(mapping);
       
                 newUpper = upperValues[i].getItemExpr();
               }
             }
          } else {
                // since they are the same, make upper equal to lower..
             newUpper = newLower;
          }


	  // add the mapping that may have been rewritten to the new map
	  newMap.addMapEntry(newUpper->getValueId(),newLower->getValueId());
	}
    }


  // now replace the map with the recomputed mappings
  map_ = newMap;

  // The selectionPred() on a MapValueId should have been pushed down
  // by the optimizer.
  GenAssert(selectionPred().isEmpty(),"NOT selectionPred().isEmpty()");

  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  // Be thrifty. Reuse coveredExpr for gathering the input and output values.
  getInputAndPotentialOutputValues(coveredExpr);

  // Add the value that is being fabricated by the MapValueIds to the values
  // that are produced by its child and flow throught the MapValueIds.
  lowerAvailableValues += coveredExpr;

  getGroupAttr()->resolveCharacteristicOutputs
                     (lowerAvailableValues,
		      getGroupAttr()->getCharacteristicInputs());

  markAsPreCodeGenned();

  return this;
} // MapValueIds::preCodeGen()

RelExpr * Sort::preCodeGen(Generator * generator,
			   const ValueIdSet & externalInputs,
			   ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
      return this;
    //else
    //  cerr << "Possible error..."

  // Check if the pivs of this operator and it's child are the same.
  // If they are not, make them the same.
  replacePivs();

  // Resolve the VEGReferences and VEGPredicates, if any, that appear
  // in the Characteristic Inputs, in terms of the externalInputs.
  getGroupAttr()->resolveCharacteristicInputs(externalInputs);

  // if doing Partial Sorting, store partial sort key in generator work area
  // if the split-top node is providing this underneath, protect the order
  // else clear the partial sort key
  ValueIdList prefixSortKey = getPrefixSortKey();

  generator->clearPrefixSortKey();

  if (!prefixSortKey.isEmpty())
    generator->setPrefixSortKey(prefixSortKey);

  PhysicalProperty* unPreCodeGendPP = NULL;

  // Protect against scan of self-referencing table partitions 
  // completing asynchronously, thus allowing the various instances
  // of SORT to start returning rows before all scans are complete.
  // Let the PartitionAccess::preCodeGen and Exchange::preCodeGen
  // work together to detect this.  Part of the fix for solution 
  // 10-071204-9253.

  bool doCheckUnsycHalloweenScans = false;
  
  // solution 10-100310-8659
  bool fixSolution8659 = false;   
  int numUnblockedHalloweenScansBefore = 
    generator->getUnblockedHalloweenScans();
  bool needToRestoreLSH = false;
  bool saveLSH = generator->getPrecodeHalloweenLHSofTSJ();
  
  // This is the pre-R2.5.1 test that triggers the check unblocked access.
  // Note that it indirectly depends on COMP_BOOL_166 OFF.
  if (checkAccessToSelfRefTable_)
    doCheckUnsycHalloweenScans = true;

  // This is the R2.5.1 way -- see solution 10-100310-8659.
  if ((generator->getPrecodeHalloweenLHSofTSJ()) &&
      (!generator->getPrecodeRHSofNJ()))
  {
    if (generator->getHalloweenSortForced())
      markAsHalloweenProtection();

    if (generator->preCodeGenParallelOperator() &&
        !generator->getHalloweenESPonLHS())
    {
      doCheckUnsycHalloweenScans = true;
      fixSolution8659 = true;
    }
    else
    {
      // This serial sort is enough to block the 
      // scan of the target table.  No need for further
      // checking.  Notice this serial vs. parallel sort test
      // was made in NestedJoin::preCodeGen before the fix
      // for 10-100310-8659.
      doCheckUnsycHalloweenScans  = false;

      // More for 10-100310-8659 - don't call incUnblockedHalloweenScans
      // below this node. 
      generator->setPrecodeHalloweenLHSofTSJ(false);
      needToRestoreLSH = true;

      GenAssert(generator->unsyncdSortFound() == FALSE, 
        "Unknown operator set unsyncdSortFound.");
    }
  }

  if (doCheckUnsycHalloweenScans)
  {
    generator->setCheckUnsyncdSort(TRUE);

    // Preserve a copy of the child's physical properties
    // as it is before preCodeGen is called for the child.  
    // Also, in this copy of the physical properties, use 
    // a copy of the child's partitioning function.  This 
    // will be used in case we need to insert an ESP for 
    // halloween protection.
    unPreCodeGendPP = new (CmpCommon::statementHeap()) 
        PhysicalProperty(*child(0)->getPhysicalProperty(),
		     child(0)->getPhysicalProperty()->getSortKey(),
                     child(0)->getPhysicalProperty()->getSortOrderType(), 
                     child(0)->getPhysicalProperty()->getDp2SortOrderPartFunc(),
		     child(0)->getPhysicalProperty()->
                            getPartitioningFunction()->copy()
                    );
  }

  if ( CmpCommon::getDefault(COMPRESSED_INTERNAL_FORMAT) == DF_SYSTEM)
  {
    NABoolean resize = FALSE;
    NABoolean defrag = FALSE;
    // get the char outputs and not  the child's
    ValueIdSet vidSet = getGroupAttr()->getCharacteristicOutputs();

    ExpTupleDesc::TupleDataFormat tupleFormat =
                  determineInternalFormat( vidSet,
                                           this,
                                           resize,
                                           generator,
                                           FALSE,
                                           defrag);

    cacheTupleFormatAndResizeFlag(tupleFormat, resize, defrag);

    if (tupleFormat == ExpTupleDesc::SQLMX_ALIGNED_FORMAT)
    {
      generator->incNCIFNodes();
    }
    else
    {
      generator->decNCIFNodes();
    }
  }

  // My Characteristic Inputs become the external inputs for my child.
  child(0) = child(0)->preCodeGen(generator,
				  getGroupAttr()->getCharacteristicInputs(),
				  pulledNewInputs);

  generator->clearPrefixSortKey();
  
  if (! child(0).getPtr())
    return NULL;

  if (needToRestoreLSH)
    generator->setPrecodeHalloweenLHSofTSJ(saveLSH);

  getGroupAttr()->addCharacteristicInputs(pulledNewInputs);

  // Accumulate the values that are provided as inputs by my parent
  // together with the values that are produced as outputs by my
  // children. Use these values for rewriting the VEG expressions.
  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);

  // ----------------------------------------------------------------------
  // Replace VEGReferences in the order by list
  // Bugfix: sol# 10-020909-1555/56: the last argument, if not explicitly
  // stated, defaults to FALSE, and causes a shallow copy of the tree.
  // ----------------------------------------------------------------------
  sortKey_.replaceVEGExpressions
              (availableValues,
	       getGroupAttr()->getCharacteristicInputs(),
	       FALSE, // default
	       NULL,  // default
	       TRUE); // bugfix

  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  getInputAndPotentialOutputValues(availableValues);

  getGroupAttr()->resolveCharacteristicOutputs
                     (availableValues,
		      getGroupAttr()->getCharacteristicInputs());

  //Consider Sort as part of BMO memory participant if not partial sort.
  if (prefixSortKey.entries() == 0 ||
     CmpCommon::getDefault(COMP_BOOL_84) == DF_ON)
    {
      if (CmpCommon::getDefault(SORT_MEMORY_QUOTA_SYSTEM) != DF_OFF) {
        generator->incrNumBMOs();

        if ((ActiveSchemaDB()->getDefaults()).getAsDouble(BMO_MEMORY_LIMIT_PER_NODE_IN_MB) > 0)
          generator->incrBMOsMemory(getEstimatedRunTimeMemoryUsage(generator, TRUE));
      }
    }


  markAsPreCodeGenned();  

  // Part of the fix for solution 10-071204-9253.
  // Modified for 10-100310-8659
  if (doCheckUnsycHalloweenScans && generator->unsyncdSortFound())
    {
      RelExpr *newChild = generator->insertEspExchange(child(0), 
						       unPreCodeGendPP);
      
      ((Exchange *)newChild)->markAsHalloweenProtection();
      
      newChild = 
	newChild->preCodeGen(generator, externalInputs, pulledNewInputs);
      
      GenAssert(newChild->getOperatorType() == REL_EXCHANGE, 
		"Exchange eliminated despite our best efforts.");

      child(0) = newChild;
          
      // Now that an ESP is inserted above the scans, this sort operator
      // does block the scans, so we can discount them.
      if (fixSolution8659)
	{
	  generator->setUnsyncdSortFound(FALSE);
	  generator->setUnblockedHalloweenScans(
				       numUnblockedHalloweenScansBefore);
	}
    }
  topNRows_ = generator->getTopNRows();
  return this;

} // Sort::preCodeGen()

RelExpr * SortFromTop::preCodeGen(Generator * generator,
				  const ValueIdSet & externalInputs,
				  ValueIdSet &pulledNewInputs)
{
  return Sort::preCodeGen(generator, externalInputs, pulledNewInputs);
}

RelExpr *ProbeCache::preCodeGen(Generator * generator,
			   const ValueIdSet & externalInputs,
			   ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  // Check if the pivs of this operator and it's child are the same.
  // If they are not, make them the same.
  replacePivs();

  // Resolve the VEGReferences and VEGPredicates, if any, that appear
  // in the Characteristic Inputs, in terms of the externalInputs.
  getGroupAttr()->resolveCharacteristicInputs(externalInputs);

  // My Characteristic Inputs become the external inputs for my child.
  child(0) = child(0)->preCodeGen(generator,
				  getGroupAttr()->getCharacteristicInputs(),
				  pulledNewInputs);
  if (! child(0).getPtr())
    return NULL;

  // add one more value to "valuesGivenToChild_": a statement execution 
  // count that will invalidate cache each time the statement is 
  // re-executed. It would be incorrect to cache across
  // statement executions (and possibly transactions).
  ValueId execCount = generator->getOrAddStatementExecutionCount();
  pulledNewInputs += execCount;
  
  getGroupAttr()->addCharacteristicInputs(pulledNewInputs);

  // Accumulate the values that are provided as inputs by my parent
  // together with the values that are produced as outputs by my
  // children. Use these values for rewriting the VEG expressions.
  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);

  // Rewrite the selection predicates.
  NABoolean replicatePredicates = TRUE;
  selectionPred().replaceVEGExpressions
                     (availableValues,
		      getGroupAttr()->getCharacteristicInputs(),
		      FALSE, // no need to generate key predicates here
		      0 /* no need for idempotence here */,
		      replicatePredicates
		     );

  getGroupAttr()->resolveCharacteristicOutputs
                     (availableValues,
		      getGroupAttr()->getCharacteristicInputs());

/*
  TBD - maybe ProbeCache as BMO memory participant??
  if(CmpCommon::getDefault(PROBE_CACHE_MEMORY_QUOTA_SYSTEM) != DF_OFF)
    generator->incrNumBMOs();

  if ((ActiveSchemaDB()->getDefaults()).getAsDouble(BMO_MEMORY_LIMIT_PER_NODE_IN_MB) > 0)
    generator->incrNBMOsMemoryPerNode(getEstimatedRunTimeMemoryUsage(generator, TRUE));
*/
  markAsPreCodeGenned();
  return this;
    
} // ProbeCache::preCodeGen()


RelExpr * Exchange::preCodeGen(Generator * generator,
			       const ValueIdSet & externalInputs,
			       ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  // Set a flag if this is a parallel extract consumer. The flag for
  // extract producer queries gets set earlier in RelRoot::codeGen()
  if (child(0)->getOperatorType() == REL_EXTRACT_SOURCE)
  {
    isExtractConsumer_ = TRUE;
    GenAssert(!isExtractProducer_,
              "One extact query cannot be both producer and consumer");
  }

  const PhysicalProperty* sppOfChild = child(0)->getPhysicalProperty();

  NABoolean PivsReplaced = FALSE;

  if (sppOfChild->getPlanExecutionLocation() == EXECUTE_IN_DP2) {
    // If this is not an ESP exchange, then check if the pivs of this op
    // and it's child are the same. If they are not, make them the same.
    // We don't do this for an ESP exchange because an ESP exchange
    // denotes an ESP process boundary and the child's pivs
    // do not have to be the same as the parent and in fact should
    // not be the same.
    replacePivs();
    PivsReplaced = TRUE;
  }

  RelExpr *result = this;

  // ---------------------------------------------------------------------
  // copy important info from the properties into data members
  // ---------------------------------------------------------------------
   
  storePhysPropertiesInNode(generator->getPrefixSortKey());

  // If this is a parallel extract producer query:
  // - do a few checks to make sure the plan is valid
  // - store a copy of the root's select list
  if (isExtractProducer_)
  {
    RelRoot *root = generator->getBindWA()->getTopRoot();

    // The plan is valid if this is an ESP exchange the number of
    // bottom partitions matches the number of requested streams.
    ComUInt32 numRequestedStreams = root->getNumExtractStreams();
    ComUInt32 numBottomEsps = (ComUInt32)
      getBottomPartitioningFunction()->getCountOfPartitions();
    if (!isEspExchange() || (numRequestedStreams != numBottomEsps))
    {
      *CmpCommon::diags() << DgSqlCode(-7004);
      GenExit();
      return NULL;
    }

    // Make a copy of the root's select list
    extractSelectList_ = new (generator->wHeap())
      ValueIdList(root->compExpr());

    // Do a coverage test to see find values in the select list that
    // this operator cannot already provide
    ValueIdSet valuesIDontHave(*extractSelectList_);
    ValueIdSet coveredExpr;
    ValueIdSet referencedUpperValues;
    getGroupAttr()->coverTest(valuesIDontHave,        // expressions needed
                              externalInputs,         // extra inputs
                              coveredExpr,            // covered exprs
                              referencedUpperValues); // new values needed

    // Add the needed values to characteristic inputs
    pulledNewInputs += referencedUpperValues;
    getGroupAttr()->addCharacteristicInputs(referencedUpperValues);
  }

  // ---------------------------------------------------------------------
  // Resolve the VEGReferences and VEGPredicates, if any, that appear
  // in the Characteristic Inputs, in terms of the externalInputs.
  // ---------------------------------------------------------------------
  ValueIdSet saveCharInputs = getGroupAttr()->getCharacteristicInputs();
  getGroupAttr()->resolveCharacteristicInputs(externalInputs);

  // variables that store the result of the major decisions:
  //
  // makeThisExchangeAPapa: if this is a PAPA node, then make this
  //                        node the PAPA (and add a PA below it)
  // eliminateThisExchange: get rid of this node either because
  //                        it represents a sole PA or because it is
  //                        a redundant ESP exchange
  // topPartFunc_:          the partitioning function produced by
  //                        this node after we're done with preCodeGen
  // bottomPartFunc_:       the partitioning function produced by
  //                        the child of this node
  // paPartFunc:            the partitioning function produced by the
  //                        PA node inserted below
  // lbpf                   LogPhysPartitioningFunction of the child,
  //                        if the child has such a part. function
  NABoolean makeThisExchangeAPapa            = FALSE;
  NABoolean eliminateThisExchange            = FALSE;
  const PartitioningFunction *paPartFunc     = topPartFunc_;
  const LogPhysPartitioningFunction *lppf    = NULL;


  if (isDP2Exchange() AND
      bottomPartFunc_->isALogPhysPartitioningFunction())
  {
    lppf = bottomPartFunc_->castToLogPhysPartitioningFunction();

    if (lppf->getUsePapa() || getGroupAttr()->isEmbeddedUpdateOrDelete())
    {

      // Will a merge of sorted streams need to be done?
      if (NOT sortKeyForMyOutput_.isEmpty())
      {
        Lng32 maxPartsPerGroup;

        // Since a merge of sorted streams is needed, we must
        // ensure that there is one PA for every partition in every
        // process. The optimizer should already have set this up
        // correctly, but sometimes, due to plan stealing, the value
        // can be wrong. This code is really a patch for the plan
        // stealing problem. We could try to fix the plan stealing
        // problem, but that would adversely affect compile time.
        // To set the number of clients (i.e. PAs) we must cast away
        // the const-ness, sorry.
        if (topPartFunc_->isAGroupingOf(*bottomPartFunc_,
                                        &maxPartsPerGroup))
        {
          ((LogPhysPartitioningFunction*)lppf)->setNumOfClients(
            maxPartsPerGroup * topPartFunc_->getCountOfPartitions());
        }
        else
        {
          ((LogPhysPartitioningFunction*)lppf)->setNumOfClients(
            bottomPartFunc_->getCountOfPartitions() *
            topPartFunc_->getCountOfPartitions());
        }
      }


      // Keep this exchange and make it the PAPA node. The PA
      // nodes below the PAPA will actually produce a partitioning
      // scheme that is identical to that of the DP2 operator below,
      // since the PAPA splits its requests into smaller ones that
      // do not span DP2 partition boundaries.
      makeThisExchangeAPapa = TRUE;
      paPartFunc = bottomPartFunc_;
    }
  }

  if  (!PivsReplaced && isRedundant_)
    replacePivs();

  // flag to decide whether to use the characteristic inputs or outputs
  // as input the to the CIF determineInternalFormatFunction
  // if the the child is an insert or update then we consider the chars input
  // otherwise we use the chars outputs
  NABoolean useCharInputs = FALSE;

  // ---------------------------------------------------------------------
  // If the child of this Exchange executes in DP2, then allocate a
  // PartitionAccess operator. It should have the same Group Attributes
  // as its child.
  // ---------------------------------------------------------------------
  NABoolean savedOltMsgOpt = generator->oltOptInfo()->oltMsgOpt();

  NABoolean inputOltMsgOpt = generator->oltOptInfo()->oltMsgOpt();

  unsigned short prevNumBMOs = generator->replaceNumBMOs(0);

  // These are used to fix solution 10-071204-9253 and for 
  // solution 10-100310-8659.
  bool needToRestoreParallel = false;
  NABoolean savedParallelSetting = FALSE;
  bool needToRestoreCheckUnsync = false;
  NABoolean savedCheckUnsyncdSort = FALSE;
  bool needToRestoreLHS = false;
  bool halloweenLHSofTSJ = generator->getPrecodeHalloweenLHSofTSJ();
  bool needToRestoreESP = false;
  bool halloweenESPonLHS = generator->getHalloweenESPonLHS();

  if (isEspExchange() && getBottomPartitioningFunction()->isPartitioned())
    {
      // Tell any child NJ that its Halloween blocking operator (SORT)
      // is operating in parallel.
      savedParallelSetting = generator->preCodeGenParallelOperator();
      generator->setPreCodeGenParallelOperator(TRUE);
      needToRestoreParallel = true;
    }

  if (isEspExchange() && halloweenLHSofTSJ)
    {
      if ( !isRedundant_ )
        {
          // Tell any parallel SORT below that it doesn't have to check
          // unsyncd access.
          needToRestoreESP = true;
          generator->setHalloweenESPonLHS(true);
        }

      savedCheckUnsyncdSort = generator->checkUnsyncdSort();
      if (savedCheckUnsyncdSort == TRUE)
        {
          // savedCheckUnsyncdSort tells me there is a parallel SORT above this 
          // exchange.  This ESP guarantees that all instances of the SORT will
          // block until all instances of this ESP finish. So tell any child 
          // PARTITION ACCESS that its scan of a self-referencing is sync'd.
          generator->setCheckUnsyncdSort(FALSE);
          needToRestoreCheckUnsync = true;

          // More for 10-100310-8659 - don't call incUnblockedHalloweenScans
          // below this node. 
          halloweenLHSofTSJ = generator->setPrecodeHalloweenLHSofTSJ(false);
          needToRestoreLHS = true;
        }
    }
  else if (isEspExchange() && 
           // this isPartitioned() condition is probably a bug, but 
           // to be safe I am not fixing it now.
           getBottomPartitioningFunction()->isPartitioned())
    {

      // Tell any child PARTITION ACCESS that its scan of a self-referencing
      // table is synchronized by an ESP exchange.  That is, any blocking
      // SORT operator above this exchange will not get any rows until all
      // scans have finished.
      savedCheckUnsyncdSort = generator->checkUnsyncdSort();
      generator->setCheckUnsyncdSort(FALSE);

      needToRestoreCheckUnsync = true;
    }

  if (halloweenSortIsMyChild_ && isRedundant_)
  {
    // Before eliminating itself, and before preCodeGen'ing the child
    // tree, this Exchange will tell its child (a Sort) that it needs to 
    // check for unsynchronized access to the target table of a 
    // self-referencing update.  This is part of the fix for 
    // solution 10-090310-9876.
    ((Sort *)(child(0).getPtr()))->doCheckAccessToSelfRefTable();

    // Note for solution 10-100310-8659 -- the halloweenSortIsMyChild_
    // flag will only be set when the COMP_BOOL_166 is used to revert
    // to pre-bugfix behavior.  With the fix for 10-100310-8659, the 
    // Sort uses the Generator's flags (precodeHalloweenLHSofTSJ and
    // precodeRHSofNJ) to know if it needs check access to the target 
    // table.  In other words, unless COMP_BOOL_166 is used, this
    // is dead code.
  }
  if ( CmpCommon::getDefault(COMPRESSED_INTERNAL_FORMAT) == DF_SYSTEM)
  {
    NABoolean resize = FALSE;
    NABoolean defrag = FALSE;
    ValueIdSet vidSet;
    if (!useCharInputs)
    {
      vidSet = child(0)->getGroupAttr()->getCharacteristicOutputs();
    }
    else
    {
      vidSet = saveCharInputs;
    }

    ExpTupleDesc::TupleDataFormat tupleFormat =
                  determineInternalFormat( vidSet,
                                           this,
                                           resize,
                                           generator,
                                           FALSE,
                                           defrag);

    cacheTupleFormatAndResizeFlag(tupleFormat, resize, defrag);

    if (tupleFormat == ExpTupleDesc::SQLMX_ALIGNED_FORMAT)
    {
      generator->incNCIFNodes();
    }
    else
    {
      generator->decNCIFNodes();
    }
  }

  // For HashJoin MIN/MAX optimization.  If this is an ESP Exchange,
  // block all candidate values for min/max optimization from going
  // below this Exchange.  Restore them upon return from
  // preCodeGen'ing the child.
  ValueIdList minMaxKeys, minVals, maxVals, willUseMinMaxKeys;
  if(isEspExchange()) {

    // Save the current values.
    minMaxKeys = generator->getMinMaxKeys();
    minVals = generator->getMinVals();
    maxVals = generator->getMaxVals();
    willUseMinMaxKeys = generator->getWillUseMinMaxKeys();

    
    // Clear the current values.
    generator->getMinMaxKeys().clear();
    generator->getMinVals().clear();
    generator->getMaxVals().clear();
    generator->getWillUseMinMaxKeys().clear();
  }

  // ---------------------------------------------------------------------
  // Perform preCodeGen on the child (including PA node if we created it)
  // ---------------------------------------------------------------------
  child(0) = child(0)->preCodeGen(
       generator,
       getGroupAttr()->getCharacteristicInputs(),
       pulledNewInputs);

  // For HashJoin MIN/MAX optimization.
  if(isEspExchange()) {
    // Restore the saved values.
    generator->getMinMaxKeys() = minMaxKeys;
    generator->getMinVals() = minVals;
    generator->getMaxVals() = maxVals;
    generator->getWillUseMinMaxKeys() = willUseMinMaxKeys;
  }

  if (needToRestoreParallel)
    generator->setPreCodeGenParallelOperator(savedParallelSetting);
  if (needToRestoreCheckUnsync)
    generator->setCheckUnsyncdSort(savedCheckUnsyncdSort);
  if (needToRestoreLHS)
    generator->setPrecodeHalloweenLHSofTSJ(halloweenLHSofTSJ);
  if (needToRestoreESP)
    generator->setHalloweenESPonLHS(halloweenESPonLHS);

  setNumBMOs( generator->replaceNumBMOs(prevNumBMOs) );

  if (! child(0).getPtr())
    return NULL;

  generator->oltOptInfo()->setOltMsgOpt(savedOltMsgOpt);

  // Decide whether this Exchange should try to eliminate itself.
  if (child(0)->castToRelExpr()->getOperatorType() == REL_EXE_UTIL)
    {
      // No, the REL_EXE_UTIL must execute in an ESP.
    }
  else if (skipRedundancyCheck_)
    {
      // No, the ESP was inserted just to force blocking of 
      // data from SORT instances, to help prevent Halloween
      // problem -- see Soln 10-071204-9253.
    }
  else
    {
      // Yes, perform the redundancy check.
      eliminateThisExchange = (isRedundant_ OR
          (isDP2Exchange() AND NOT makeThisExchangeAPapa));
    }

  // ---------------------------------------------------------------------
  // Determine which partition input values need to be supplied by our
  // parent and which are produced by this exchange node.  PA or PAPA
  // exchange nodes (DP2 exchange nodes) do not produce any partition
  // input values themselves, just ask the parent to produce the PIVs
  // needed by the child. ESP exchanges produce the PIVs for their bottom
  // partition function, and this is also true for added repartitioning
  // exchanges.
  // ---------------------------------------------------------------------
  if (isEspExchange())
    {
      pulledNewInputs -= bottomPartFunc_->getPartitionInputValues();
      setBottomPartitionInputValues(
	   bottomPartFunc_->getPartitionInputValuesLayout());
    }

  getGroupAttr()->addCharacteristicInputs(pulledNewInputs);

  // ---------------------------------------------------------------------
  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  // ---------------------------------------------------------------------
  ValueIdSet availableValues;

  getInputAndPotentialOutputValues(availableValues);

  // Accumulate the values that are provided as inputs by my parent
  // together with the values that are produced as outputs by my
  // children. Use these values for rewriting the VEG expressions.

  // ---------------------------------------------------------------------
  // Rewrite the copy of the sort key which will be used for merging
  // rows. The VEGRef on the column being sorted may be preceeded by 
  // an InverseOrder itemExpr (in case the shortcut_grby rule has fired)
  // The InverseOrder itemExpr will not perform a copy of the sortKey
  // before replacing VEGExpressions unless replicateExpression is set 
  // to TRUE below. This avoids inverse(VEGRef_60(T1.a = T2.a)) being 
  // resolved to T1.a in two different exchange nodes, even though T1.a 
  // is not available at the second exchange node.
  // ---------------------------------------------------------------------
  NABoolean replicateExpression = TRUE;
  sortKeyForMyOutput_.replaceVEGExpressions
    (availableValues,
     getGroupAttr()->getCharacteristicInputs(),
     FALSE, // no key predicates here
     0 /* no need for idempotence here */,
     replicateExpression
     );

  // ---------------------------------------------------------------------
  // Rewrite the partitioning expression, if the repartitioning function
  // contains one. A ReplicationPartitioningFunction does not contain
  // a partititioning expression because it uses a broadcast for
  // replicating rows to its consumers.
  // ---------------------------------------------------------------------
  if (isEspExchange())
  {
    PartitioningFunction * rpf;

    // need to cast away const-ness to create partitioning expr, sorry
    rpf = (PartitioningFunction *) topPartFunc_;

    rpf->createPartitioningExpression();
    rpf->preCodeGen(availableValues);
  }

  // ---------------------------------------------------------------------
  // For a parallel extract producer query, rewrite our copy of the
  // root's select list
  // ---------------------------------------------------------------------
  if (isExtractProducer_)
  {
    extractSelectList_->
      replaceVEGExpressions(availableValues,
                            getGroupAttr()->getCharacteristicInputs());
  }

  // ---------------------------------------------------------------------
  // Resolve characteristic outputs.
  // ---------------------------------------------------------------------
  getGroupAttr()->resolveCharacteristicOutputs
                      (availableValues,
		       getGroupAttr()->getCharacteristicInputs());

  generator->oltOptInfo()->mayDisableOperStats(&oltOptInfo());

  // ---------------------------------------------------------------------
  // From here on we add or remove exchange nodes, but this node is
  // ready and does not need to be processed again should we call
  // preCodeGen for it again.
  // ---------------------------------------------------------------------
  markAsPreCodeGenned();

  // ---------------------------------------------------------------------
  // Eliminate this exchange if it simply represented the PA node or
  // if it is redundant. Do not eliminate the exchange if it is a
  // parallel extract producer or consumer.
  // ---------------------------------------------------------------------
  if (isExtractProducer_ || isExtractConsumer_)
    eliminateThisExchange = FALSE;

  if (eliminateThisExchange)
  {
    result = child(0).getPtr();

    // transfer the # of BMOs to generator as
    // this exchange node is to be discarded.
    generator->incrNumBMOsPerFrag(getNumBMOs());
  }

  if ((isEspExchange()) &&
      (NOT eliminateThisExchange))
    {
      //      generator->setUpdAbortOnError(TRUE);
      generator->setUpdSavepointOnError(FALSE);
      generator->setUpdErrorOnError(FALSE);
      
      generator->compilerStatsInfo().exchangeOps()++;
      
      generator->compilerStatsInfo().dop() =
	(UInt16)MAXOF(generator->compilerStatsInfo().dop(),
		      getBottomPartitioningFunction()->getCountOfPartitions());
      
      
      if ( getNumBMOs() > 0 )
	generator->incTotalESPs();
      
      // If the exchange uses SeaMonster, set a flag in the generator
      // to indicate that some part of the query does use SeaMonster
      if (thisExchangeCanUseSM(generator->getBindWA()))
        generator->setQueryUsesSM(TRUE);
      
    } // isEspExchange() && !eliminateThisExchange
  

  
  return result;
  
} // Exchange::preCodeGen()

RelExpr * Tuple::preCodeGen(Generator * generator,
		       const ValueIdSet & externalInputs,
		       ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! RelExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  // Accumulate the values that are provided as inputs by my parent
  // together with the values that are produced as outputs by my
  // children. Use these values for rewriting the VEG expressions.
  ValueIdSet availableValues = getGroupAttr()->getCharacteristicInputs();
  tupleExpr().replaceVEGExpressions
                 (availableValues,
		  getGroupAttr()->getCharacteristicInputs());

  return this;
}

ItemExpr * BuiltinFunction::preCodeGen(Generator * generator)
{
  ItemExpr * retExpr = NULL;

  if (nodeIsPreCodeGenned())
    return getReplacementExpr();
	
  if (CmpCommon::getDefault(OR_PRED_KEEP_CAST_VC_UCS2) == DF_ON) {
    // part of temporary workaround to yotta dp2 killer problem:
    // keep cast for upper(cast name as varchar(n) char set ucs2)
    switch (getOperatorType()) {
    case ITM_UPPER:
    case ITM_LOWER:
    case ITM_SUBSTR:
    case ITM_TRIM:
      if (child(0)->getOperatorType() == ITM_CAST) {
        Cast *arg = (Cast*)child(0)->castToItemExpr();
        const NAType& typ = arg->getValueId().getType();
        if (arg->matchChildType() &&
            arg->child(0)->getValueId().getType() == typ &&
            typ.getTypeQualifier() == NA_CHARACTER_TYPE && 
            typ.isVaryingLen() &&
            ((CharType*)(&typ))->getCharSet() == CharInfo::UCS2) {
          // don't skip codegen for the cast of 
          // "upper(cast name as varchar(n) char set ucs2) IN <inlist>"
          arg->setMatchChildType(FALSE);
        }
      }
    }
  }

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  switch (getOperatorType())
    {
    case ITM_QUERYID_EXTRACT:
      {
        // convert arguments to ISO88591 character set

        if (child(0)->castToItemExpr()->getValueId().getType().getTypeQualifier() ==
            NA_CHARACTER_TYPE)
          {
            const CharType &typ0 =
              (const CharType &) (child(0)->castToItemExpr()->getValueId().getType());
            if (typ0.getCharSet() != CharInfo::ISO88591)
              {
                // the executor method assumes an ASCII string for the query id, so
                // convert the value to a fixed char type in the ISO88591 char set
                SQLChar * newTyp0 = new(generator->wHeap())
                  SQLChar(generator->wHeap(), typ0.getCharLimitInUCS2or4chars(),
                          typ0.supportsSQLnullLogical(),
                          typ0.isUpshifted(),
                          typ0.isCaseinsensitive(),
                          typ0.isVaryingLen(),
                          CharInfo::ISO88591);
                
                child(0) = new (generator->wHeap()) Cast(child(0), newTyp0);
                child(0)->bindNode(generator->getBindWA());
                child(0) = child(0)->preCodeGen(generator);
              }
          }

        if (child(1)->castToItemExpr()->getValueId().getType().getTypeQualifier() ==
            NA_CHARACTER_TYPE)
          {
            const CharType &typ1 =
              (const CharType &) (child(1)->castToItemExpr()->getValueId().getType());
            if (typ1.getCharSet() != CharInfo::ISO88591)
              {
                // the executor method assumes an ASCII string for the query id, so
                // convert the value to a fixed char type in the ISO88591 char set
                SQLChar * newTyp1 = new(generator->wHeap())
                  SQLChar(generator->wHeap(), typ1.getCharLimitInUCS2or4chars(),
                          typ1.supportsSQLnullLogical(),
                          typ1.isUpshifted(),
                          typ1.isCaseinsensitive(),
                          typ1.isVaryingLen(),
                          CharInfo::ISO88591);
                
                child(1) = new (generator->wHeap()) Cast(child(1), newTyp1);
                child(1)->bindNode(generator->getBindWA());
                child(1) = child(1)->preCodeGen(generator);
              }
          }
      }
      retExpr = this;
      break;


    default:
      {
	retExpr = this;
      }
      break;
    } // switch

  setReplacementExpr(retExpr);

  markAsPreCodeGenned();
  return retExpr;
}

/*
ItemExpr * Abs::preCodeGen(Generator * generator)
{
  // The ABS function has the distinction of being the sole BuiltinFunction
  // that a) generates a new replacementExpr tree
  // and b) can appear in the select-list (compExpr).
  //
  // What happens is that code is generated for the ABS replacement CASE
  // TWICE, once in PartitionAccess eid, once in RelRoot generateOutputExpr:
  // the latter fails with a GenMapTable assert failing to find info for
  // the column in "SELECT ABS(col) FROM t;"
  // ("SELECT ABS(-1) FROM t;" and "SELECT ABS(col),col FROM T;" work fine --
  // but of course they generate twice as much code as necessary,
  // however harmless/idempotent it may be...)
  //
  // We therefore cannot handle this one discrepant case neatly in
  // preCodeGen/codeGen -- it is fixed instead by having the Binder
  // upstream rewrite an ABS as the equivalent CASE.
  //
  // Genesis 10-980112-5942.
  //
  GenAssert(FALSE, "Abs::preCodeGen should be unreachable code!");
  return NULL;

//if (nodeIsPreCodeGenned())
//  return getReplacementExpr();
//
//ItemExpr * newExpr =
//  generator->getExpGenerator()->createExprTree(
//    "CASE WHEN @A1 < 0 THEN - @A1 ELSE @A1 END", 0, 1, child(0));
//
//newExpr->bindNode(generator->getBindWA());
//setReplacementExpr(newExpr->preCodeGen(generator));
//markAsPreCodeGenned();
//return getReplacementExpr();

}
*/

ItemExpr * Abs::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return getReplacementExpr();

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  NAType * result_type = (NAType *)(&(getValueId().getType()));
  NAType * type_op1 = (NAType *)(&(child(0)->castToItemExpr()->getValueId().getType()));

  if (! (*result_type == *type_op1))
    {
      // Insert a cast node to convert child to a result type.
      child(0) = new (generator->wHeap())
	Cast(child(0), result_type);

      child(0)->bindNode(generator->getBindWA());

      child(0) = child(0)->preCodeGen(generator);
      if (! child(0).getPtr())
	return NULL;
    }

  markAsPreCodeGenned();
  return this;
} // Abs::preCodeGen()

ItemExpr * AggrMinMax::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return getReplacementExpr();

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  // if my child's attributes EXCEPT for nullability are not the
  // same as mine, do a conversion.
  NABoolean doConversion = FALSE;
  const NAType &myType = getValueId().getType();
  const NAType &childType = child(0)->castToItemExpr()->getValueId().getType();
  if (NOT (myType == childType)) // something is different
    {
      if ((myType.supportsSQLnull() &&
	   childType.supportsSQLnull()) ||
	  ((NOT myType.supportsSQLnull()) &&
	   (NOT childType.supportsSQLnull())))
	doConversion = TRUE; // both nullable or not nullable,
                             // something else is different
      else if (myType.supportsSQLnull() &&
	       NOT childType.supportsSQLnull())
	{
	  // create a new my type with the same null attr as child.
	  NAType * newType = myType.newCopy(generator->wHeap());
	  newType->resetSQLnullFlag();

	  if (NOT(*newType == childType))
	    doConversion = TRUE;

	  delete newType;
	}
      else
	{
	  // Fix for solution ID 10-031121-1505)
	  // I dont think we the following assert is correct
	  // During VEG resolution a MIN/MAX() function can have a
	  // NON-NULLABLE child replaced by a nullable child, consider
	  // as an example the following query where i2 is not null:
	  //
	  // SELECT MIN(T0.i2)
          // FROM D12 T0
          // WHERE
          //  ?pa2  =  T0.i2
          // GROUP BY T0.i1;
          //
          // In the above case i2 will be replaced by ?pa2 when the VEG
          // (i2, ?pa2) is resolved. Therefore it is possible to get a
          // nullable child for a non-nullable aggregate. In the above
          // case the aggregate is non-nullable because i2 is non-nullable.
          // In such a case MIN(?pa2) would never be executed if ?pa2 is NULL
          // because predicate '?pa2 = T0.i2' will not select any rows when
          // ?pa2 is NULL (I am not sure how a parameter is set to NULL, for host
          // vars we can use the NULL indicator, not sure how we pass in NULL using
          // parameters).
          //
          // Assert on the following condition
	  // The condition where I am not nullable and my child is nullable,
	  // is an error case.
	  //GenAssert(0, "AggrMinMax::preCodeGen::Should not reach here.");
	  doConversion = TRUE;
	}
    }

  if (doConversion)
    {
      // Insert a cast node to convert child to a result type.
      child(0) = new (generator->wHeap()) Cast(child(0), &myType);

      child(0)->bindNode(generator->getBindWA());

      child(0) = child(0)->preCodeGen(generator);
      if (! child(0).getPtr())
	return NULL;
    }

  markAsPreCodeGenned();
  return this;
} // AggrMinMax::preCodeGen()

ItemExpr * Between::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return getReplacementExpr();

  // transform "A BETWEEN B AND C" to "A >= B AND A <= C"
  ItemExpr * newExpr =
    generator->getExpGenerator()->createExprTree(
      "@A1 >= @A2 AND @A1 <= @A3", 0, 3, child(0), child(1), child(2));

  newExpr->bindNode(generator->getBindWA());
  setReplacementExpr(newExpr->preCodeGen(generator));
  markAsPreCodeGenned();
  return getReplacementExpr();
}

// BiArithCount::preCodeGen
//
// The BiArithCount executor clause requires that all of the operands
// be of the same type. preCodeGen introduces cast operators on the
// input operands if necessary to enforce this requirement.
//
ItemExpr * BiArithCount::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  // Get a local handle on common generator objects.
  //
  CollHeap *wHeap = generator->wHeap();

  const NAType &resultType = getValueId().getType();
  const NAType &op1Type = child(0)->castToItemExpr()->getValueId().getType();
  const NAType &op2Type = child(1)->castToItemExpr()->getValueId().getType();

  // If the first operand type does not match that of the result,
  // cast it to the result type.
  //
  if(!(op1Type == resultType))
    {
      child(0) = new(wHeap) Cast(child(0)->castToItemExpr(),
				resultType.newCopy(wHeap),
				ITM_CAST);
      child(0)->synthTypeAndValueId();
    }

  // Ditto for the second operand.
  //
  if(!(op2Type == resultType))
    {
      child(1) = new(wHeap) Cast(child(1)->castToItemExpr(),
				 resultType.newCopy(wHeap),
				 ITM_CAST);
      child(1)->synthTypeAndValueId();
    }

  return BiArith::preCodeGen(generator);
}

// BiArithSum::preCodeGen
//
// The BiArithSum executor clause requires that all of the operands
// be of the same type. preCodeGen introduces cast operators on the
// input operands if necessary to enforce this requirement.
//
ItemExpr * BiArithSum::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  // Get a local handle on common generator objects.
  //
  CollHeap *wHeap = generator->wHeap();

  // Get a handle on the operand types.
  //
  const NAType &resultType = getValueId().getType();
  const NAType &op1Type = child(0)->castToItemExpr()->getValueId().getType();
  const NAType &op2Type = child(1)->castToItemExpr()->getValueId().getType();

  // If the first operand type does not match that of the result,
  // cast it to the result type.
  //
  if(!(op1Type == resultType))
    {
      child(0) = new(wHeap) Cast(child(0)->castToItemExpr(),
				resultType.newCopy(wHeap),
				ITM_CAST);
      child(0)->synthTypeAndValueId();
    }

  // Ditto for the second operand.
  //
  if(!(op2Type == resultType))
    {
      child(1) = new(wHeap) Cast(child(1)->castToItemExpr(),
				 resultType.newCopy(wHeap),
				 ITM_CAST);
      child(1)->synthTypeAndValueId();
    }

  ItemExpr *result = BiArith::preCodeGen(generator);
  if (! result)
    return NULL;

  ItemExpr *outExpr = NULL;
  Lng32 rc = generator->getExpGenerator()->foldConstants(child(0), &outExpr);
  if ((rc == 0) &&
      (outExpr))
    {
      child(0) = outExpr->preCodeGen(generator);
    }

  rc = generator->getExpGenerator()->foldConstants(child(1), &outExpr);
  if ((rc == 0) &&
      (outExpr))
    {
      child(1) = outExpr->preCodeGen(generator);
    }

  return this;
}

ItemExpr * BiArith::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  NAType * result_type = (NAType *)(&(getValueId().getType()));
  NAType * type_op1 = (NAType *)(&(child(0)->castToItemExpr()->getValueId().getType()));
  NAType * type_op2 = (NAType *)(&(child(1)->castToItemExpr()->getValueId().getType()));

  if (result_type->isComplexType())
    {
      if ((getOperatorType() == ITM_PLUS) ||
	  (getOperatorType() == ITM_MINUS))
	{
	  child(0) = generator->getExpGenerator()->matchScales(child(0)->getValueId(),
							       *result_type);

	  child(1) = generator->getExpGenerator()->matchScales(child(1)->getValueId(),
							       *result_type);
	}
      else
	if (getOperatorType() == ITM_DIVIDE)
	  {
	    // before doing the division, the numerator has to be upscaled.
	    // Lets find out how much.
	    // NS = numerator scale
	    // DS = denominator scale
	    // RS = result scale
	    // Upscale = (RS - NS) + DS
	    // Newscale = NS + Upscale = RS + DS

	    Lng32 newscale
	      = ((NumericType *)result_type)->getScale() +
		((NumericType *)type_op2)->getScale();

	    if (newscale != ((NumericType *)type_op1)->getScale()) {
	      NAType * new_type = result_type->newCopy(generator->wHeap());
	      ((NumericType *)new_type)->setScale(newscale);
	      child(0) = generator->getExpGenerator()->matchScales(
							 child(0)->getValueId(),
							 *new_type);
	    }
	  }

      type_op1 = (NAType *)(&(child(0)->getValueId().getType()));
      type_op2 = (NAType *)(&(child(1)->getValueId().getType()));

      if (result_type->getFSDatatype() == type_op1->getFSDatatype())
	{
	  if (((getOperatorType() == ITM_PLUS) ||
	       (getOperatorType() == ITM_MINUS) ||
	       (getOperatorType() == ITM_DIVIDE)) &&
	      (result_type->getNominalSize() != type_op1->getNominalSize()))
	    {
	      child(0) = new(generator->wHeap()) Cast(child(0), result_type);
	    }
	}
      else
	{
	  if ((getOperatorType() == ITM_PLUS) ||
	      (getOperatorType() == ITM_MINUS) ||
	      (getOperatorType() == ITM_DIVIDE))
	    {
	      child(0) = new(generator->wHeap()) Cast(child(0), result_type);
	    }
	  else
	    {
	      child(0) =
	        new(generator->wHeap()) Cast(child(0),
	                 result_type->synthesizeType(SYNTH_RULE_PASS_THRU_NUM,
                                                     *type_op1,
	                                             *result_type,
						     generator->wHeap()));
	    }
	}

      if (result_type->getFSDatatype() == type_op2->getFSDatatype())
	{
	  if (((getOperatorType() == ITM_PLUS) ||
	       (getOperatorType() == ITM_MINUS)) &&
	      (result_type->getNominalSize() != type_op2->getNominalSize()))
	    {
	      child(1) = new(generator->wHeap()) Cast(child(1), result_type);
	    }
	}
      else
	{
	  if ((getOperatorType() == ITM_PLUS) ||
	      (getOperatorType() == ITM_MINUS))
	    {
	      child(1) = new(generator->wHeap()) Cast(child(1), result_type);
	    }
	  else
	    {
	      child(1) =
	        new(generator->wHeap()) Cast(child(1),
	                 result_type->synthesizeType(SYNTH_RULE_PASS_THRU_NUM,
                                                     *type_op2,
	                                             *result_type,
						     generator->wHeap()));
	    }
	}

      child(0)->bindNode(generator->getBindWA());
      child(1)->bindNode(generator->getBindWA());

      child(0) = child(0)->preCodeGen(generator);
      if (! child(0).getPtr())
	return NULL;

      child(1) = child(1)->preCodeGen(generator);
      if (! child(1).getPtr())
	return NULL;

      markAsPreCodeGenned();

      return this;
    }

  // following is for simple types.
  SimpleType * attr_result = (SimpleType *)
    (ExpGenerator::convertNATypeToAttributes
     (getValueId().getType(), generator->wHeap()));
  SimpleType * attr_op1 = (SimpleType *)
    (ExpGenerator::convertNATypeToAttributes
     (child(0)->getValueId().getType(), generator->wHeap()));
  SimpleType * attr_op2 = (SimpleType *)
    (ExpGenerator::convertNATypeToAttributes
     (child(1)->getValueId().getType(), generator->wHeap()));

  // see if conversion needed before arithmetic operation could be done.

  Int32 matchScale = 0;
  if (result_type->getTypeQualifier() == NA_NUMERIC_TYPE)
    {
      // match scales
      if ((getOperatorType() == ITM_PLUS) ||
	  (getOperatorType() == ITM_MINUS))
	{
	  child(0) = generator->getExpGenerator()->matchScales(child(0)->getValueId(),
							       *result_type);

	  child(1) = generator->getExpGenerator()->matchScales(child(1)->getValueId(),
							       *result_type);
	}
      else
	if (getOperatorType() == ITM_DIVIDE)
	  {
	    // before doing the division, the numerator has to be upscaled.
	    // Lets find out how much.
	    // NS = numerator scale
	    // DS = denominator scale
	    // RS = result scale
	    // Upscale = (RS - NS) + DS
	    // Newscale = NS + Upscale = RS + DS

	    Lng32 newscale
	      = ((NumericType *)result_type)->getScale() +
		((NumericType *)type_op2)->getScale();

	    if (newscale != ((NumericType *)type_op1)->getScale()) {
	      NAType * new_type = result_type->newCopy(generator->wHeap());
	      ((NumericType *)new_type)->setScale(newscale);
	      child(0) = generator->getExpGenerator()->matchScales(
							 child(0)->getValueId(),
							 *new_type);
              matchScale = 1;
	    }
	  }
    }

  else if (result_type->getTypeQualifier() == NA_INTERVAL_TYPE) {
    switch (getOperatorType()) {
    case ITM_PLUS:
    case ITM_MINUS:
      if (type_op1->getTypeQualifier() == NA_DATETIME_TYPE) {
        Lng32 fp1 = ((DatetimeType *) type_op1)->getFractionPrecision();
        Lng32 fp2 = ((DatetimeType *) type_op2)->getFractionPrecision();
        if (fp1 < fp2) {
          child(0) = new(generator->wHeap()) Cast(child(0), type_op2);
          child(0)->bindNode(generator->getBindWA());
        } else if (fp1 > fp2) {
          child(1) = new(generator->wHeap()) Cast(child(1), type_op1);
          child(1)->bindNode(generator->getBindWA());
        }
      } else {
        child(0) = generator->getExpGenerator()->matchIntervalEndFields(
                                                   child(0)->getValueId(),
                                                   *result_type);
        child(1) = generator->getExpGenerator()->matchIntervalEndFields(
                                                   child(1)->getValueId(),
                                                   *result_type);
        child(0) = generator->getExpGenerator()->matchScales(
                                                   child(0)->getValueId(),
                                                   *result_type);
        child(1) = generator->getExpGenerator()->matchScales(
                                                   child(1)->getValueId(),
                                                   *result_type);
        type_op1 = (NAType *)(&(child(0)->getValueId().getType()));
        type_op2 = (NAType *)(&(child(1)->getValueId().getType()));
        if (result_type->getNominalSize() != type_op1->getNominalSize()) {
          child(0) = new(generator->wHeap()) Cast(child(0), result_type);
          child(0)->bindNode(generator->getBindWA());
        }
        if (result_type->getNominalSize() != type_op2->getNominalSize()) {
          child(1) = new(generator->wHeap()) Cast(child(1), result_type);
          child(1)->bindNode(generator->getBindWA());
        }
      }
      break;
    case ITM_TIMES: {
      //
      // Unfortunately, the multiply node may be the root ItemExpr node, and
      // we can't change the root ItemExpr node since its ValueId has already
      // been stored away in the parent RelExpr's ValueIdLists.  We'll have to
      // move the expression down, e.g.
      //
      //   *   <-- same root -->   *
      //  / \                     / \
      // I   N      becomes      I   1
      //                         |
      //                         *
      //                        / \
      //                       N   N
      //                       |
      //                       I
      //
      if (type_op1->getTypeQualifier() == NA_INTERVAL_TYPE)
        child(0) = generator->getExpGenerator()->convertIntervalToNumeric(
                                                   child(0)->getValueId());
      else
        child(1) = generator->getExpGenerator()->convertIntervalToNumeric(
                                                   child(1)->getValueId());
      char str[20];
      strcpy(str, "@A1 * @A2");
      child(0) = generator->getExpGenerator()->createExprTree(str, 0,
                                                              2,
                                                              child(0),
                                                              child(1));
      child(0)->bindNode(generator->getBindWA());
      child(0) = generator->getExpGenerator()->convertNumericToInterval(
                                                 child(0)->getValueId(),
                                                 *result_type);
      strcpy(str, "001"); // to make sure it is not a tinyint
      child(1) = generator->getExpGenerator()->createExprTree(str, CharInfo::ISO88591);
      child(1)->bindNode(generator->getBindWA());
      type_op2 = (NAType *)(&(child(1)->getValueId().getType()));
      if ((result_type->getNominalSize() != type_op2->getNominalSize()) ||
          (type_op2->getFSDatatype() != REC_BIN16_SIGNED)) {
        IntervalType *interval = (IntervalType *) result_type;
        const Int16 DisAmbiguate = 0;
        child(1) = new(generator->wHeap()) Cast(child(1),
                            new(generator->wHeap()) SQLNumeric(generator->wHeap(), TRUE, /* signed */
                                           interval->getTotalPrecision(),
                                           0,
                                           DisAmbiguate, // added for 64bit proj.
                                           interval->supportsSQLnull()));
        child(1)->bindNode(generator->getBindWA());
      }
      break;
    }
    case ITM_DIVIDE: {
      //
      // Unfortunately, the divide node may be the root ItemExpr node, and
      // we can't change the root ItemExpr node since its ValueId has already
      // been stored away in the parent RelExpr's ValueIdLists.  We'll have to
      // move the expression down, e.g.
      //
      //  div  <-- same root -->  div
      //  / \                     / \
      // I   N      becomes      I   1
      //                         |
      //                        div
      //                        / \
      //                       N   N
      //                       |
      //                       I
      //
      child(0) = generator->getExpGenerator()->convertIntervalToNumeric(
                                                 child(0)->getValueId());
      char str[20];
      strcpy(str, "@A1 / @A2");
      child(0) = generator->getExpGenerator()->createExprTree(str, 0,
                                                              2,
                                                              child(0),
                                                              child(1));
      child(0)->bindNode(generator->getBindWA());
      child(0) = generator->getExpGenerator()->convertNumericToInterval(
                                                 child(0)->getValueId(),
                                                 *result_type);
      strcpy(str, "001"); // to make sure it is not a tinyint
      child(1) = generator->getExpGenerator()->createExprTree(str, CharInfo::ISO88591);
      child(1)->bindNode(generator->getBindWA());
      type_op2 = (NAType *)(&(child(1)->getValueId().getType()));
      if ((result_type->getNominalSize() != type_op2->getNominalSize()) ||
          (type_op2->getFSDatatype() != REC_BIN16_SIGNED)) {
        IntervalType *interval = (IntervalType *) result_type;
        const Int16 DisAmbiguate = 0;
        child(1) = new(generator->wHeap()) Cast(child(1),
                            new(generator->wHeap()) SQLNumeric(generator->wHeap(), TRUE, /* signed */
                                           interval->getTotalPrecision(),
                                           0,
                                           DisAmbiguate, // added for 64bit proj.
                                           interval->supportsSQLnull()));
        child(1)->bindNode(generator->getBindWA());
      }
      break;
    }
    default:
      break;
    }
  } else if (result_type->getTypeQualifier() == NA_DATETIME_TYPE) {
    switch (getOperatorType()) {
    case ITM_PLUS:
    case ITM_MINUS: {
      if ((type_op1->getTypeQualifier() == NA_INTERVAL_TYPE) &&
          (((IntervalType*) type_op1)->getEndField() == REC_DATE_SECOND)) {
        Lng32 sourceScale = ((IntervalType *) type_op1)->getFractionPrecision();
        Lng32 targetScale = ((DatetimeType *) type_op2)->getFractionPrecision();
        child(0) = generator->getExpGenerator()->scaleBy10x(
                                                   child(0)->getValueId(),
                                                   targetScale - sourceScale);
      } else if ((type_op2->getTypeQualifier() == NA_INTERVAL_TYPE) &&
                 (((IntervalType*) type_op2)->getEndField() == REC_DATE_SECOND)) {
        Lng32 targetScale = ((DatetimeType *) type_op1)->getFractionPrecision();
        Lng32 sourceScale = ((IntervalType *) type_op2)->getFractionPrecision();
        child(1) = generator->getExpGenerator()->scaleBy10x(
                                                   child(1)->getValueId(),
                                                   targetScale - sourceScale);
      }

      // Extend the datetime to contain a YEAR field if needed.  The
      // value will need to be extended if it contains a DAY field but
      // does not already contain a YEAR field.  This is necessary
      // since with the introduction of non-standard SQL/MP datetime
      // types, it is possible to have a datetime value which has a
      // DAY field but not a YEAR or not a MONTH field.  In this
      // situation, it is not possible to define a meaningful way to
      // do the operation.  Does the DAY field wrap at 30, 31, 28, or
      // 29.  So to make this operation meaningful, the value is
      // extended to the current timestamp.
      //
      if (type_op1->getTypeQualifier() == NA_DATETIME_TYPE) {
        if(((DatetimeType *) type_op1)->containsField(REC_DATE_DAY) &&
           ! ((DatetimeType *) type_op1)->containsField(REC_DATE_YEAR)) {

          // Need to extend the given datetime value in order to be
          // able to do the operation.  Extend the value out to the
          // YEAR field.
          //
          DatetimeType *extendedType =
            DatetimeType::constructSubtype(type_op1->supportsSQLnull(),
                                           REC_DATE_YEAR,
                                           ((DatetimeType *)type_op1)->getEndField(),
                                           ((DatetimeType *)type_op1)->getFractionPrecision(),
                                           generator->wHeap());

          // Cast the given value to the extended type.
          //
          child(0) = new (generator->wHeap()) Cast(child(0), extendedType);
          child(0)->bindNode(generator->getBindWA());
        }
      } else {
        if(((DatetimeType *) type_op2)->containsField(REC_DATE_DAY) &&
           ! ((DatetimeType *) type_op2)->containsField(REC_DATE_YEAR)) {

          // Need to extend the given datetime value in order to be
          // able to do the operation.  Extend the value out to the
          // YEAR field.
          //
          DatetimeType *extendedType =
            DatetimeType::constructSubtype(type_op2->supportsSQLnull(),
                                           REC_DATE_YEAR,
                                           ((DatetimeType *)type_op2)->getEndField(),
                                           ((DatetimeType *)type_op2)->getFractionPrecision(),
                                           generator->wHeap());

          // Cast the given value to the extended type.
          //
          child(1) = new (generator->wHeap()) Cast(child(1), extendedType);
          child(1)->bindNode(generator->getBindWA());
        }
      }

      break;
    }
    default:
      break;
    }
  }

  // NABoolean convertRoundedDivResult = FALSE;

  // If this arith operation is supported at runtime, then no
  // conversion is needed. Done for result numeric type only.
  if (result_type->getTypeQualifier() == NA_NUMERIC_TYPE)
    {
      child(0) = child(0)->preCodeGen(generator);
      if (! child(0).getPtr())
	return NULL;

      child(1) = child(1)->preCodeGen(generator);
      if (! child(1).getPtr())
	return NULL;

      attr_result = (SimpleType *)
	(ExpGenerator::convertNATypeToAttributes
	 (getValueId().getType(), generator->wHeap()));
      attr_op1 = (SimpleType *)
	(ExpGenerator::convertNATypeToAttributes
	 (child(0)->getValueId().getType(), generator->wHeap()));
      attr_op2 = (SimpleType *)
	(ExpGenerator::convertNATypeToAttributes
	 (child(1)->getValueId().getType(), generator->wHeap()));

      ex_arith_clause temp_clause(getOperatorType(), NULL, NULL, 
				  getRoundingMode(), getDivToDownscale());
      if (temp_clause.isArithSupported(getOperatorType(),
				       attr_op1,
				       attr_op2,
				       attr_result
				       ))
	{
	  markAsPreCodeGenned();

	  return this;
	}
    }

  // if the datatype or lengths of child and this don't match, then
  // conversion is needed.
  type_op1 = (NAType *)(&(child(0)->getValueId().getType()));
  type_op2 = (NAType *)(&(child(1)->getValueId().getType()));
  if ((result_type->getTypeQualifier() != NA_INTERVAL_TYPE) &&
      (result_type->getTypeQualifier() != NA_DATETIME_TYPE) &&
      ((result_type->getFSDatatype() != type_op1->getFSDatatype()) ||
       (result_type->getNominalSize() != type_op1->getNominalSize())))
    {
      // If the result type is not a float, make sure that the following
      // Cast does not scale (for floats we have do do scaling). This is
      // done by using the result type but changing the scale to the scale
      // of the operand
      NAType * new_type = result_type->newCopy(generator->wHeap());
      if ((result_type->getFSDatatype() < REC_MIN_FLOAT) ||
	  (result_type->getFSDatatype() > REC_MAX_FLOAT)) {
	((NumericType *)new_type)->
	  setScale(((NumericType *)type_op1)->getScale());
      };
      child(0) = new(generator->wHeap()) Cast(child(0), new_type,
					      ITM_CAST, FALSE);
    }

  if ((result_type->getTypeQualifier() != NA_INTERVAL_TYPE) &&
      (result_type->getTypeQualifier() != NA_DATETIME_TYPE) &&
      ((result_type->getFSDatatype() != type_op2->getFSDatatype()) ||
       (result_type->getNominalSize() != type_op2->getNominalSize())))
    {
      NAType * new_type = result_type->newCopy(generator->wHeap());
      if ((result_type->getFSDatatype() < REC_MIN_FLOAT) ||
	  (result_type->getFSDatatype() > REC_MAX_FLOAT) ||
           matchScale)
      {
	((NumericType *)new_type)->
	  setScale(((NumericType *)type_op2)->getScale());
      };
      child(1) = new(generator->wHeap()) Cast(child(1), new_type,
					      ITM_CAST, FALSE);
    }

  child(0)->bindNode(generator->getBindWA());
  child(1)->bindNode(generator->getBindWA());

  child(0) = child(0)->preCodeGen(generator);
  if (! child(0).getPtr())
     return NULL;

  child(1) = child(1)->preCodeGen(generator);
  if (! child(1).getPtr())
     return NULL;

  markAsPreCodeGenned();

  return this;
} // BiArith::preCodeGen()

ItemExpr * UnArith::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  return this;
}

ItemExpr * BiLogic::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  ItemExpr *result = this;
  ItemExpr *INlhs = NULL;
  if (CmpCommon::getDefault(OR_PRED_ADD_BLOCK_TO_IN_LIST) == DF_ON 
      && createdFromINlist() && (INlhs=getINlhs())!=NULL)
    {
      // ItmBlockFunction serves like the "C/C++ comma" expression that
      // 1) evaluates its 1st operand, 2nd operand, and
      // 2) returns its 2nd operand as value of that expression.
      // ItmBlockFunction also has the codegen property that
      //   its 1st operand is evaluated (codegen'ed) only once
      //   even if 1st operand occurs multiple times in 2nd operand.
      // So, given "UPPER(n) IN ('a', 'b')" that has been converted to
      //     ItmBlockFunction
      //     /               \
      //    U                 OR
      //                    /    \
      //                  =        =
      //                /   \    /   \
      //               U     a  U     b
      // "UPPER(n)", represented as U, is evaluated once even if 
      // it's used multiple times in the OR expression.

      // Trying to add ItmBlockFunction early in the parser (ie, in
      // sqlparseraux.cpp convertINvaluesToOR() causes a lot of grief
      // especially in cardinality estimation code. So, we resort to
      // doing it late, here in precodegen.
      result = new(generator->wHeap()) ItmBlockFunction(INlhs, result);
      result->synthTypeAndValueId();
      result->markAsPreCodeGenned();
      return result;
    }

  markAsPreCodeGenned();
  return result;
}

ItemExpr * BiRelat::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  // transform multivalue predicates to single-value comparisons.
  ItemExpr * newNode = transformMultiValuePredicate();
  if (newNode)
    {
      #ifdef _DEBUG
      // NAString unp;
      // unparse(unp);
      // cerr << "BiRelat::preCodeGen - " << unp << " needed to be transformed!"
      //    << endl;
      // I don't think we should ever have an untransformed MVP at this stage!
      #endif

      // transformMultiValuePredicate() cannot do synthTypeAndValue()
      // because it is also called from the normalizer in places
      // where it needs to postpone it.
      newNode->synthTypeAndValueId();
      return newNode->preCodeGen(generator);
    }

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  NAType * type_op1 = (NAType *)(&(child(0)->getValueId().getType()));
  NAType * type_op2 = (NAType *)(&(child(1)->getValueId().getType()));

  if ((type_op1->isComplexType()) || (type_op2->isComplexType()))
    {
      // find the 'super' type
      const NAType *result_type = type_op1->synthesizeType(SYNTH_RULE_UNION,
                                                           *type_op1,
                                                           *type_op2,
							   generator->wHeap());
      CMPASSERT(result_type);
      if (result_type->getTypeQualifier() == NA_NUMERIC_TYPE)
	{
	  // match scales
	  child(0) = generator->getExpGenerator()->matchScales(child(0)->getValueId(),
							       *result_type);

	  child(1) = generator->getExpGenerator()->matchScales(child(1)->getValueId(),
							       *result_type);
	}

      type_op1 = (NAType *)(&(child(0)->getValueId().getType()));
      type_op2 = (NAType *)(&(child(1)->getValueId().getType()));

      if ((result_type->getFSDatatype() != type_op1->getFSDatatype()) ||
	  (result_type->getNominalSize() != type_op1->getNominalSize()))
	{
	  child(0) = new(generator->wHeap()) Cast(child(0), result_type);
	}

      if ((result_type->getFSDatatype() != type_op2->getFSDatatype()) ||
	  (result_type->getNominalSize() != type_op2->getNominalSize()))
	{
	  child(1) = new(generator->wHeap()) Cast(child(1), result_type);
	}

      child(0)->bindNode(generator->getBindWA());
      child(1)->bindNode(generator->getBindWA());

      child(0) = child(0)->preCodeGen(generator);
      if (! child(0).getPtr())
	return NULL;

      child(1) = child(1)->preCodeGen(generator);
      if (! child(1).getPtr())
	return NULL;

      markAsPreCodeGenned();

      return this;
    }

  const NAType &type1A =
    child(0)->castToItemExpr()->getValueId().getType();
  const NAType &type2A =
    child(1)->castToItemExpr()->getValueId().getType();

  if ((type1A.getTypeQualifier() == NA_CHARACTER_TYPE) &&
      (type2A.getTypeQualifier() == NA_CHARACTER_TYPE))
    {
      const CharType &cType1A = (CharType&)type1A;
      const CharType &cType2A = (CharType&)type2A;
      
      CharInfo::Collation cType1A_coll = cType1A.getCollation();
      CharInfo::Collation cType2A_coll = cType2A.getCollation();

      //
      // When Implicit Casting And Translation feature is enabled, it is
      // possible for the binder to allow a comparision between an ISO88591-type
      // value and a UCS2-type value to be passed through to the generator.
      // If that happens, we throw in a Translate node at this point.
      //
      CharInfo::CharSet cType1A_CS  = cType1A.getCharSet() ;
      CharInfo::CharSet cType2A_CS = cType2A.getCharSet() ;

      if ( ( cType1A_CS  != cType2A_CS )               &&
           ( cType1A_CS  != CharInfo::UnknownCharSet ) &&
           ( cType2A_CS != CharInfo::UnknownCharSet ) )
      {
         Int32 chld_to_trans = 0;
         if ( cType1A_CS != CharInfo::ISO88591 )
         {
            if ( (cType1A_CS == CharInfo::UNICODE) ) chld_to_trans = 1;
            if ( (cType1A_CS == CharInfo::UTF8) && (cType2A_CS != CharInfo::UNICODE) ) chld_to_trans = 1;
            if ( (cType1A_CS == CharInfo::SJIS) && (cType2A_CS == CharInfo::ISO88591) ) chld_to_trans = 1;
         }
         Int32 tran_type = Translate::UNKNOWN_TRANSLATION;
         if ( chld_to_trans == 0 )
             tran_type = find_translate_type( cType1A_CS, cType2A_CS );
         else
             tran_type = find_translate_type( cType2A_CS, cType1A_CS );

	 ItemExpr * newChild = NULL;
         newChild = new (generator->wHeap()) Translate(child(chld_to_trans), tran_type);
         newChild = newChild->bindNode(generator->getBindWA());
         newChild = newChild->preCodeGen(generator);
         if (! newChild)
            return NULL;
         setChild(chld_to_trans, newChild);
      }
      else if ( cType1A_coll != cType2A_coll &&
                cType1A_CS == CharInfo::ISO88591 &&
                cType1A_CS == cType2A_CS &&
                child(1)->getOperatorType() == ITM_CONSTANT &&
                CollationInfo::isSystemCollation(cType1A_coll))
      {
         ItemExpr * pNewChild2 = NULL;
         NAType * pNewType2 = cType2A.newCopy(generator->wHeap());
         CharType * pNewCType2 = NULL;
         if (pNewType2 != NULL)
           pNewCType2 = (CharType*)pNewType2;
         if (pNewCType2 != NULL)
           pNewCType2->setCollation(cType1A_coll);
         pNewChild2 = new (generator->wHeap()) Cast(child(1), pNewCType2);
         pNewChild2 = pNewChild2->bindNode(generator->getBindWA());
         pNewChild2 = pNewChild2->preCodeGen(generator);
         if (pNewChild2 == NULL)
            return NULL;
         setChild(1, pNewChild2);
      }
      // Regenerate the types...before we continue with rest of code
      type_op1 = (NAType *)(&(child(0)->getValueId().getType()));
      type_op2 = (NAType *)(&(child(1)->getValueId().getType()));

      ItemExpr * pChild1 = child(1)->castToItemExpr();
      const NAType &type1 = pChild1->getValueId().getType();
      const CharType &cType1 = (CharType&)type1;

      ItemExpr * pChild2 = child(1)->castToItemExpr();
      const NAType &type2 = pChild2->getValueId().getType();
      const CharType &cType2 = (CharType&)type2;

      CharInfo::Collation coll1 = cType1.getCollation();
      CharInfo::Collation coll2 = cType2.getCollation();

      CMPASSERT(coll1==coll2);

	  if (CollationInfo::isSystemCollation(coll1))
	  {
	    setCollationEncodeComp(TRUE);

	    {

	      ItemExpr * newIe1 = child(0);
	      ItemExpr * newIe2 = child(1);
	      
	      if (! (cType1 == cType2)) 
	      {

		NAType *resultType ;
		Lng32 len = MAXOF(cType1.getMaxLenInBytesOrNAWChars(), cType2.getMaxLenInBytesOrNAWChars());
		Lng32 Prec= MAXOF(cType1.getStrCharLimit(), cType2.getStrCharLimit());
        	     
		if (len != cType1.getMaxLenInBytesOrNAWChars()) 
		{
		  if (DFS2REC::isAnyVarChar(cType1.getFSDatatype()))
		  {
		    resultType = new (generator->wHeap())
		      SQLVarChar(generator->wHeap(), CharLenInfo(Prec, len),
				  cType1.supportsSQLnull(), 
				  cType1.isUpshifted(),
				  cType1.isCaseinsensitive(),
				  cType1.getCharSet(),
				  cType1.getCollation(),
				  cType1.getCoercibility()
				 );
		  }
		  else
		  {
		    resultType = new (generator->wHeap())
		      SQLChar(generator->wHeap(), CharLenInfo(Prec, len),
				  cType1.supportsSQLnull(), 
				  cType1.isUpshifted(),
				  cType1.isCaseinsensitive(),
				  FALSE,
				  cType1.getCharSet(),
				  cType1.getCollation(),
				  cType1.getCoercibility()
				 );
		  }

		  newIe1 = new(generator->wHeap()) Cast(newIe1,resultType);
		}

		if (len != cType2.getMaxLenInBytesOrNAWChars()) 
		{
		  if (DFS2REC::isAnyVarChar(cType2.getFSDatatype()))
		  {
		    resultType = new (generator->wHeap())
		      SQLVarChar(generator->wHeap(), CharLenInfo(Prec, len),
				  cType2.supportsSQLnull(), 
				  cType2.isUpshifted(),
				  cType2.isCaseinsensitive(),
				  cType2.getCharSet(),
				  cType2.getCollation(),
				  cType2.getCoercibility()
				 );
		  }
		  else
		  {
		    resultType = new (generator->wHeap())
		      SQLChar(generator->wHeap(), CharLenInfo(Prec, len),
				  cType2.supportsSQLnull(), 
				  cType2.isUpshifted(),
				  cType2.isCaseinsensitive(),
				  FALSE,
				  cType2.getCharSet(),
				  cType2.getCollation(),
				  cType2.getCoercibility()
				 );
		  }

		  newIe2 = new(generator->wHeap()) Cast(newIe2,resultType);
		}
	      }

	      ItemExpr * newEncode;
	      
	      newEncode = 
		    new(generator->wHeap()) 
		    CompEncode(newIe1,FALSE, -1, CollationInfo::Compare);

	      newEncode->bindNode(generator->getBindWA());
	      newEncode = newEncode->preCodeGen(generator);
	      if (!newEncode)
		return NULL;
	      setChild(0, newEncode);


	      newEncode = 
		    new(generator->wHeap()) 
		    CompEncode(newIe2, FALSE, -1,CollationInfo::Compare);

	      newEncode->bindNode(generator->getBindWA());
	      newEncode = newEncode->preCodeGen(generator);
	      if (!newEncode)
		return NULL;
	      setChild(1, newEncode);
	    }

	  }
	  else
	  {
	     // update both operands if case insensitive comparions
	     // are to be done.

	    NABoolean doCIcomp =
	      ((cType1.isCaseinsensitive()) && (cType2.isCaseinsensitive()));

	    ItemExpr * newChild = NULL;
	    if ((doCIcomp) &&
		(NOT cType1.isUpshifted()))
	      {
		newChild = child(0);

		// Add UPPER except if it is NULL constant value.
		if (newChild->getOperatorType() != ITM_CONSTANT || !((ConstValue *)newChild)->isNull())
		    newChild = new (generator->wHeap()) Upper(newChild);

		newChild = newChild->bindNode(generator->getBindWA());
		if (! newChild || generator->getBindWA()->errStatus())
		  return NULL;

		newChild = newChild->preCodeGen(generator);
		if (! newChild)
		  return NULL;

		setChild(0, newChild);
	      }

	    if ((doCIcomp) &&
		(NOT cType2.isUpshifted()))
	      {
		newChild = child(1);

		// Add UPPER except if it is NULL constant value.
		if (newChild->getOperatorType() != ITM_CONSTANT || !((ConstValue *)newChild)->isNull())
		    newChild = new (generator->wHeap()) Upper(newChild);

		newChild = newChild->bindNode(generator->getBindWA());
		if (! newChild || generator->getBindWA()->errStatus())
		  return NULL;

		newChild = newChild->preCodeGen(generator);
		if (! newChild)
		  return NULL;

		setChild(1, newChild);
	      }
	    }
	  }


  // following is for simple types.
  const NAType &type1B =
    child(0)->castToItemExpr()->getValueId().getType();
  const NAType &type2B =
    child(1)->castToItemExpr()->getValueId().getType();

  SimpleType * attr_op1 = (SimpleType *)
    (ExpGenerator::convertNATypeToAttributes(type1B, generator->wHeap()));
  SimpleType * attr_op2 = (SimpleType *)
    (ExpGenerator::convertNATypeToAttributes(type2B, generator->wHeap()));

  ex_comp_clause temp_clause;

  temp_clause.setInstruction(getOperatorType(),
			     attr_op1,
			     attr_op2
			     );

  if ((temp_clause.getInstruction() == COMP_NOT_SUPPORTED) &&
      (type1B.getTypeQualifier() == NA_NUMERIC_TYPE) &&
      (type2B.getTypeQualifier() == NA_NUMERIC_TYPE))
    {
      const NumericType &numOp1 = (NumericType&)type1B;
      const NumericType &numOp2 = (NumericType&)type2B;

      if ((numOp1.isExact() && numOp2.isExact()) &&
          ((numOp1.getFSDatatype() == REC_BIN64_UNSIGNED) ||
           (numOp2.getFSDatatype() == REC_BIN64_UNSIGNED)))
        {
          if (numOp1.getFSDatatype() == REC_BIN64_UNSIGNED)
            {
              // add a Cast node to convert op2 to sqllargeint.
              ItemExpr * newOp2 =
                new (generator->wHeap())
                Cast(child(1),
                     new (generator->wHeap())
                     SQLLargeInt(generator->wHeap(), numOp2.isSigned(),
                                 numOp2.supportsSQLnull()));
              
              newOp2 = newOp2->bindNode(generator->getBindWA());
              newOp2 = newOp2->preCodeGen(generator);
              if (! newOp2)
                return NULL;
              
              setChild(1, newOp2);

              attr_op2 = (SimpleType *)
                (ExpGenerator::convertNATypeToAttributes(
                     newOp2->getValueId().getType(), generator->wHeap()));
            }
          else 
           {
              // add a Cast node to convert op1 to sqllargeint.
              ItemExpr * newOp1 =
                new (generator->wHeap())
                Cast(child(0),
                     new (generator->wHeap())
                     SQLLargeInt(generator->wHeap(), numOp1.isSigned(),
                                 numOp1.supportsSQLnull()));
              
              newOp1 = newOp1->bindNode(generator->getBindWA());
              newOp1 = newOp1->preCodeGen(generator);
              if (! newOp1)
                return NULL;
              
              setChild(0, newOp1);

              attr_op1 = (SimpleType *)
                (ExpGenerator::convertNATypeToAttributes(
                     newOp1->getValueId().getType(), generator->wHeap()));
           }

          temp_clause.setInstruction(getOperatorType(),
                                     attr_op1,
                                     attr_op2
                                     );
        } // convert
    }
  
  if (temp_clause.getInstruction() != COMP_NOT_SUPPORTED)
    {
      NABoolean doConstFolding = FALSE;
      if ((temp_clause.getInstruction() == ASCII_COMP) &&
	  (CmpCommon::getDefault(CONSTANT_FOLDING) == DF_ON))
	{
	  if (((child(0)->getOperatorType() == ITM_CONSTANT) &&
	       (child(1)->getOperatorType() != ITM_CONSTANT)) ||
	      ((child(1)->getOperatorType() == ITM_CONSTANT) &&
	       (child(0)->getOperatorType() != ITM_CONSTANT)) &&
	      (type_op1->getFSDatatype() == REC_BYTE_F_ASCII) &&
	      (type_op2->getFSDatatype() == REC_BYTE_F_ASCII))
	    {
	      if (((child(0)->getOperatorType() == ITM_CONSTANT) &&
		   (type_op1->getNominalSize() < type_op2->getNominalSize())) ||
		  ((child(1)->getOperatorType() == ITM_CONSTANT) &&
		   (type_op2->getNominalSize() < type_op1->getNominalSize())))
		{
		  doConstFolding = TRUE;
		}
	    }
	}

      if (NOT doConstFolding)
	{
	  markAsPreCodeGenned();

	  return this;
	}
    }

  // conversion needed before comparison could be done.

  // find the 'super' type
  UInt32 flags =
            ((CmpCommon::getDefault(LIMIT_MAX_NUMERIC_PRECISION) == DF_ON)
            ? NAType::LIMIT_MAX_NUMERIC_PRECISION : 0);
  if (CmpCommon::getDefault(ALLOW_INCOMPATIBLE_OPERATIONS) == DF_ON)
    {
      flags |= NAType::ALLOW_INCOMP_OPER;
    }
  
  const NAType *result_type = type_op1->synthesizeType(SYNTH_RULE_UNION,
                                                       *type_op1,
                                                       *type_op2,
						       generator->wHeap(),
                                                       &flags);
  CMPASSERT(result_type);
  if (result_type->getTypeQualifier() == NA_NUMERIC_TYPE)
    {
      // match scales
      child(0) = generator->getExpGenerator()->matchScales(child(0)->getValueId(),
							   *result_type);
      child(1) = generator->getExpGenerator()->matchScales(child(1)->getValueId(),
							   *result_type);
    }
  else if (result_type->getTypeQualifier() == NA_DATETIME_TYPE) {
    Lng32 fp1 = ((DatetimeType *) type_op1)->getFractionPrecision();
    Lng32 fp2 = ((DatetimeType *) type_op2)->getFractionPrecision();
    Lng32 fpResult = ((DatetimeType *) result_type)->getFractionPrecision();
    if (fp1 != fpResult) {
      child(0) = new(generator->wHeap()) Cast(child(0), result_type,
					      ITM_CAST, FALSE);
      child(0)->bindNode(generator->getBindWA());
    }
    if (fp2 != fpResult) {
      child(1) = new(generator->wHeap()) Cast(child(1), result_type,
					      ITM_CAST, FALSE);
      child(1)->bindNode(generator->getBindWA());
    }
  } else if (result_type->getTypeQualifier() == NA_INTERVAL_TYPE) {
    child(0) = generator->getExpGenerator()->matchIntervalEndFields(
                                               child(0)->getValueId(),
                                               *result_type);
    child(1) = generator->getExpGenerator()->matchIntervalEndFields(
                                               child(1)->getValueId(),
                                               *result_type);
    child(0) = generator->getExpGenerator()->matchScales(
                                               child(0)->getValueId(),
                                               *result_type);
    child(1) = generator->getExpGenerator()->matchScales(
                                               child(1)->getValueId(),
                                               *result_type);
    type_op1 = (NAType *)(&(child(0)->getValueId().getType()));
    type_op2 = (NAType *)(&(child(1)->getValueId().getType()));
    if (result_type->getNominalSize() != type_op1->getNominalSize()) {
      child(0) = new(generator->wHeap()) Cast(child(0), result_type,
					      ITM_CAST, FALSE);
      child(0)->bindNode(generator->getBindWA());
    }
    if (result_type->getNominalSize() != type_op2->getNominalSize()) {
      child(1) = new(generator->wHeap()) Cast(child(1), result_type,
					      ITM_CAST, FALSE);
      child(1)->bindNode(generator->getBindWA());
    }
  }

  // if the datatype or lengths of child and this don't match, then
  // conversion is needed.
  type_op1 = (NAType *)(&(child(0)->getValueId().getType()));
  type_op2 = (NAType *)(&(child(1)->getValueId().getType()));
  if ((result_type->getTypeQualifier() != NA_INTERVAL_TYPE) &&
      ((result_type->getFSDatatype() != type_op1->getFSDatatype()) ||
       (result_type->getNominalSize() != type_op1->getNominalSize())))
    {
      child(0) = new(generator->wHeap()) Cast(child(0), result_type,
					      ITM_CAST, FALSE);
    }

  if ((result_type->getTypeQualifier() != NA_INTERVAL_TYPE) &&
      ((result_type->getFSDatatype() != type_op2->getFSDatatype()) ||
       (result_type->getNominalSize() != type_op2->getNominalSize())))
    {
      child(1) = new(generator->wHeap()) Cast(child(1), result_type,
					      ITM_CAST, FALSE);
    }

  // bind/type propagate the new nodes
  child(0)->bindNode(generator->getBindWA());
  child(1)->bindNode(generator->getBindWA());

  child(0) = child(0)->preCodeGen(generator);
  if (! child(0).getPtr())
     return NULL;

  child(1) = child(1)->preCodeGen(generator);
  if (! child(1).getPtr())
     return NULL;

  ItemExpr *outExpr = NULL;
  Lng32 rc = generator->getExpGenerator()->foldConstants(child(0), &outExpr);
  if ((rc == 0) &&
      (outExpr))
    {
      child(0) = outExpr->preCodeGen(generator);
    }

  rc = generator->getExpGenerator()->foldConstants(child(1), &outExpr);
  if ((rc == 0) &&
      (outExpr))
    {
      child(1) = outExpr->preCodeGen(generator);
    }

  markAsPreCodeGenned();

  return this;
} // BiRelat::preCodeGen()

ItemExpr * Assign::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  child(1) = generator->getExpGenerator()->matchIntervalEndFields(
                                             child(1)->getValueId(),
                                             getValueId().getType());
  child(1) = generator->getExpGenerator()->matchScales(child(1)->getValueId(),
					     getValueId().getType());
  child(1)->bindNode(generator->getBindWA());
  child(1) =  child(1)->preCodeGen(generator);
  if (! child(1).getPtr())
    return NULL;

  markAsPreCodeGenned();

  return this;
} // Assign::preCodeGen()

ItemExpr * BaseColumn::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  ItemExpr * i = convertExternalType(generator);
  if (i == NULL)
    return NULL;

  return i;
}

ItemExpr * BitOperFunc::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (getOperatorType() == ITM_BITEXTRACT)
    {
      // convert 2nd and 3rd operands to Int32 signed.
      for (Int32 i = 1; i < getArity(); i++)
	{
	  const NAType &typ = child(i)->getValueId().getType();
       
	  if (typ.getFSDatatype() != REC_BIN32_UNSIGNED)
	    {
	      ItemExpr * newChild =
		new (generator->wHeap()) 
		Cast(child(i), 
		     new (generator->wHeap()) SQLInt(generator->wHeap(), FALSE,
						 typ.supportsSQLnullLogical()));
	      setChild(i, newChild);	

	      child(i)->bindNode(generator->getBindWA());
	      
	      child(i) = child(i)->preCodeGen(generator);
	      if (! child(i).getPtr())
		return NULL;  
	    } // if
	} // for
    }
  else
    {
      for (Int32 i = 0; i < getArity(); i++)
	{
	  const NAType &typ = child(i)->getValueId().getType();
	  
	  if (NOT (getValueId().getType() == typ))
	    {
	      NAType *resultType = 
		getValueId().getType().newCopy(generator->wHeap());
	      
	      ItemExpr * newChild =
		new (generator->wHeap()) Cast(child(i), resultType);
	      setChild(i, newChild);
	    }
	  
	  child(i)->bindNode(generator->getBindWA());
	  
	  child(i) = child(i)->preCodeGen(generator);
	  if (! child(i).getPtr())
	    return NULL;
	}
    }

  markAsPreCodeGenned();
  return this;
} // BitOperFunc::preCodeGen()

ItemExpr * Cast::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  child(0)->bindNode(generator->getBindWA());
  child(0) = child(0)->preCodeGen(generator);

  if (! child(0).getPtr())
    return NULL;

  // if a special cast node, see if my child's data attributes are
  // the same as my data attributes. If they are, return pointer to
  // my child.
  if ((matchChildType()) &&
      (child(0)->getValueId().getType() == getValueId().getType()))
    {
      markAsPreCodeGenned();
      return child(0);
    }

  NABuiltInTypeEnum sourceTypeQual =
    child(0)->getValueId().getType().getTypeQualifier();
  NABuiltInTypeEnum targetTypeQual =
    getValueId().getType().getTypeQualifier();

  // If this is a NARROW operation, but it is not possible to result
  // in an error, no reason to use NARROW.  Convert the NARROW to the
  // equivalent CAST.
  if (getOperatorType() == ITM_NARROW)
    {
      const NAType * sourceType = &(child(0)->getValueId().getType());

      const NAType * targetType = &(getValueId().getType());

      if (!sourceType->errorsCanOccur(*targetType))
        {

          ItemExpr *c = new(generator->wHeap()) Cast(child(0), targetType);
          c->bindNode(generator->getBindWA());
          return c->preCodeGen(generator);
        
        }
    }

  if (generator->getExpGenerator()->handleUnsupportedCast(this))
    return NULL;

  const NAType &srcNAType = child(0)->getValueId().getType();
  const NAType &tgtNAType = getValueId().getType();
  short srcFsType = srcNAType.getFSDatatype();
  short tgtFsType = tgtNAType.getFSDatatype();

  if ((sourceTypeQual == NA_NUMERIC_TYPE) &&
      (targetTypeQual == NA_DATETIME_TYPE))
    {
      // binder has already verified that this is a valid conversion
      // in special1 mode.
      NumericType &sourceType =
      (NumericType &)(child(0)->getValueId().getType());
      DatetimeType &targetType =
	(DatetimeType &)(getValueId().getType());

      if (sourceType.getFSDatatype() != REC_BIN64_SIGNED)
	{
	  // doing a numeric to date conversion
	  // convert source to largeint.
	  ItemExpr * newChild =
	    new (generator->wHeap())
	    Cast(child(0),
		 new (generator->wHeap())
		 SQLLargeInt(generator->wHeap(), TRUE,
			     child(0)->castToItemExpr()->
			     getValueId().getType().supportsSQLnull()));
	  newChild = newChild->bindNode(generator->getBindWA());
	  newChild = newChild->preCodeGen(generator);
	  if (! newChild)
	    return NULL;

	  setChild(0, newChild);
	}
    }

  if ((sourceTypeQual == NA_DATETIME_TYPE) &&
      (targetTypeQual == NA_NUMERIC_TYPE))
    {
      // binder has already verified that this is a valid conversion
      // in special1 mode.
      DatetimeType &sourceType =
      (DatetimeType &)(child(0)->getValueId().getType());
      NumericType &targetType =
	(NumericType &)(getValueId().getType());

      if (targetType.getFSDatatype() != REC_BIN64_SIGNED)
	{
	  // doing a date to numeric conversion.
	  // convert source to largeint.
	  ItemExpr * newChild =
	    new (generator->wHeap())
	    Cast(child(0),
		 new (generator->wHeap())
		 SQLLargeInt(generator->wHeap(), TRUE,
			     child(0)->castToItemExpr()->
			     getValueId().getType().supportsSQLnull()));
	  newChild = newChild->bindNode(generator->getBindWA());
	  newChild = newChild->preCodeGen(generator);
	  if (! newChild)
	    return NULL;

	  setChild(0, newChild);
	}

    } // numeric to date conversion

  if ((CmpCommon::getDefault(ALLOW_INCOMPATIBLE_OPERATIONS) == DF_ON) &&
      (sourceTypeQual == NA_NUMERIC_TYPE) &&
      (targetTypeQual == NA_INTERVAL_TYPE))
    { 
      NumericType &sourceType =
	(NumericType &)(child(0)->getValueId().getType());

      if (NOT sourceType.isExact())
        {
	  // doing a float numeric to interval conversion.
	  // convert source to corresponding exact numeric (largeint).
          // This is the largest interval type that is supported.
	  ItemExpr * newChild =
	    new (generator->wHeap())
	    Cast(child(0),
		 new (generator->wHeap())
		 SQLLargeInt(generator->wHeap(), TRUE,
                             child(0)->castToItemExpr()->
                             getValueId().getType().supportsSQLnull()));
	  newChild = newChild->bindNode(generator->getBindWA());
	  newChild = newChild->preCodeGen(generator);
	  if (! newChild)
	    return NULL;
          
	  setChild(0, newChild);
	}
      
    } // numeric to date conversion

  if ((sourceTypeQual == NA_DATETIME_TYPE) &&
      (targetTypeQual == NA_DATETIME_TYPE)) {
    DatetimeType &sourceType =
      (DatetimeType &)(child(0)->getValueId().getType());
    DatetimeType &targetType =
      (DatetimeType &)(getValueId().getType());

    if (targetType.getStartField() < sourceType.getStartField()) {
      // Must provide some fields from the current time stamp
      //

      // The following code generates the current timestamp as a
      // string and extracts the needed leading fields and appends to
      // this the given value (child(0)) as a string. The result is a
      // string which contains the given datetime value extended to
      // the YEAR field with the current timestamp.
      //
      // Buffer to hold new expression string.
      //
      char str[200];

      // Offset (in bytes) from the start of the current timestamp
      // (represented as a char. string) to the first field needed in
      // the extension.
      //
      // - Subtract 1 from the start field to make the value zero based.
      //
      // - Each field has a least 3 bytes (2 for the value and 1 for the
      //   delimiter)
      //
      // - Add 1, since the substring function is 1 based.
      //
      Int32 leadFieldsOffset = ((targetType.getStartField() - 1) * 3) + 1;

      // - Add 2 extra for the year field if it is being skiped over
      //   since it has 4 bytes of value.
      //
      if (leadFieldsOffset > 1)
        leadFieldsOffset += 2;

      // Size (in bytes) of the leading fields represented as a
      // character string taken from the current timestamp
      //
      // - Subtract 1 from the start field to make the value zero based.
      //
      // - Each field has a least 3 bytes (2 for the value and 1 for the
      //   delimiter)
      //
      // - Add 2 extra for the year field (which will always be one of
      //   the extended fields) since it has 4 bytes of value.
      //
      // - Subtract the leadFieldsOffset ( - 1 to make it zero based).
      //
      Int32 leadFieldsSize = ((((sourceType.getStartField() - 1) * 3) + 2)
                            - (leadFieldsOffset - 1));

      // Size (in bytes) of the source value represented as a
      // character string.
      //
      Int32 sourceFieldsSize = sourceType.getDisplayLength();

      // Construct an expression (string) to concatinate the given
      // value with the required fields from the current timestamp as
      // a string, then cast this string as a datetime value, that can
      // be cast to the desired result.
      //
      // Example :
      //
      // cast(DATETIME 'dd hh:mm:ss' DAY TO SECOND as DATETIME MONTH to MINUTE)
      //
      // current timestamp (as string)       | "YYYY-MM-DD HH:MM:SS.FFFFFF"
      //                                     |
      // leadFieldsOffset = ((2-1)*3)+1 +2 = |  --6--^
      //                                     |
      // leadFieldsSize = (((3-1)*3)+2) - 5 =|       ^3^
      //                                     |
      // result of substring(cts from 1 to 8)|      "MM-"
      //                                     |
      // value to be extended (as string)    |         "dd hh:mm:ss"
      //                                     |
      // result of string concat. (as string)|      "MM-dd hh:mm:ss"
      //                                     |
      // Cast to a datetime MONTH TO SECOND  |    Mdhms
      //                                     |
      // Original (this) cast to result      |    Mdhm
      //
      str_sprintf(str,
                  "CAST((SUBSTRING(CAST(CURRENT AS CHAR(19)) "
                  "FROM %d FOR %d) || CAST(@A1 AS CHAR(%d))) "
                  "AS DATETIME %s TO %s)",
                  leadFieldsOffset,
                  leadFieldsSize,
                  sourceFieldsSize,
                  targetType.getFieldName(targetType.getStartField()),
                  ((sourceType.getEndField() == REC_DATE_SECOND)
                   ? "FRACTION(6)"
                   : sourceType.getFieldName(sourceType.getEndField())));

      GenAssert(str_len(str) < 199,"Internal Datetime Error Cast::preCodeGen");

      ItemExpr * newExpr =
        generator->getExpGenerator()->createExprTree(str, 0,
                                                     1, child(0));
      newExpr->bindNode(generator->getBindWA());
      child(0) = newExpr->preCodeGen(generator);

    }

  }

  // Call matchScales only if both datatypes aren't intervals.
  // (We make the exception for intervals because Cast is able
  // to match the scales of intervals itself.)
  // Also, we suppress the call to matchScales() for a narrow.
  // This is because narrow will handle the scaling differently.
  // Conversions from float to bignum are also not scaled here. Scaling
  // is done in BigNum::castFrom method.
  if (NOT ((getOperatorType() == ITM_NARROW) ||
	   ((sourceTypeQual == NA_INTERVAL_TYPE) &&
	    (targetTypeQual == NA_INTERVAL_TYPE)) ||
	   ((DFS2REC::isFloat(srcFsType)) &&
	    (DFS2REC::isBigNum(tgtFsType)))))
    {
      child(0) = generator->getExpGenerator()->matchScales(
					    child(0)->getValueId(),
				            getValueId().getType());
      child(0) = child(0)->preCodeGen(generator);
      if (! child(0).getPtr())
	return NULL;
    }

  //  For a numeric NARROW, check if scaling is needed.
  if (targetTypeQual == NA_NUMERIC_TYPE &&
      getOperatorType() == ITM_NARROW)
    {
      GenAssert(sourceTypeQual == NA_NUMERIC_TYPE,
        "source type and target type incompatible in NARROW");

      const NumericType * sourceNumType
	= (const NumericType *)(&child(0)->getValueId().getType());
      const NumericType * targetNumType
	= (const NumericType *)(&getValueId().getType());

      if (sourceNumType->getScale() != targetNumType->getScale())
        {
          // We need to scale the value.  We don't want to use the
	  // usual scaling method of simply multiplying or dividing
	  // the result because we need to capture truncations
	  // and overflows at run time.  The Narrow operator supports
	  // scaling for the BigNum-to-any-numeric type case.
	  // Therefore, we first cast the value to BigNum,
	  // then narrow it down.
	  // Soln 10-041105-1519
          // Dont introduce the CAST operator if the target is already a BigNum
          // because NARROW does not support scaling for the BigNum-to-BigNum
          // case. Use the usual scaling method instead.
          if (targetNumType->isBigNum())
          {
            child(0) = generator->getExpGenerator()->matchScales(
              child(0)->getValueId(), *targetNumType);
          }
          else
          {
	    Lng32 intermediatePrecision = sourceNumType->getPrecision();
	    Lng32 intermediateScale = sourceNumType->getScale();

	    // SQLBigNum takes decimal precision, so if the source
	    // has binary precision, we need to adjust.

	    if (sourceNumType->binaryPrecision())
	      {

		// Can fit three binary digits in the space of one
		// decimal digit. The '+5' in the precision calculation
		// allows for an extra digit before and after the
		// radix point.

		intermediatePrecision = (intermediatePrecision+5)/3;
	      }

	    // If we need to cast an approximate, increase the length
	    // and scale so that the number can be represented now that
	    // it won't have an exponent.

	    // In each of the cases below, the formula used to calculate
	    // precision is:
	    //
	    // intermediatePrecision = 2 * <max exponent>
	    //    + <# significant digits in mantissa> + 1
	    //
	    // We use 2 * <max exponent> to take into account the
	    // maximum positive exponent as well as the maximum
	    // negative exponent.
	    //
	    // The formula used to calculate scale is:
	    //
	    // intermediateScale = <max exponent> +
	    //   <# significant digits in mantissa> - 1
	    //
	    // Here the exponent and digits are understood to be decimal,
	    // not binary.
	    //
	    // For the various kinds of floats we have:
	    //
	    // Kind         Max exponent   Decimal digits in Mantissa
	    // -----------  ------------   --------------------------
	    // IEEE 32 bit            38        7
	    // IEEE 64 bit           308       17

	    if (sourceNumType->getFSDatatype() == REC_IEEE_FLOAT32)
	      {
		intermediatePrecision = 84;  // (2 x 38) + 7 + 1 = 84
		intermediateScale = 44;   // 38 + 7 - 1 = 44
	      }

	    else if (sourceNumType->getFSDatatype() == REC_IEEE_FLOAT64)
	      {
		intermediatePrecision = 634; // (2 x 308) + 17 + 1 = 634
		intermediateScale = 324;  // 308 + 17 - 1 = 324
	      }

	    NAType * intermediateType =
	      new(generator->wHeap())
		SQLBigNum(generator->wHeap(), intermediatePrecision,
			  intermediateScale,
			  (sourceNumType->isBigNum() &&
			   ((SQLBigNum*)sourceNumType)->isARealBigNum()),
			  TRUE, // make it signed
			  sourceNumType->supportsSQLnull());

	    child(0) = new(generator->wHeap()) Cast(child(0),intermediateType);

	    child(0)->bindNode(generator->getBindWA());

            if (generator->getExpGenerator()->handleUnsupportedCast((Cast*)child(0)->castToItemExpr()))
              return NULL;

	    // To suppress insertion of multiplying/dividing, mark Cast as
	    // already pre-code-genned.

	    child(0)->markAsPreCodeGenned();
	  }
	}
    }

 
  if ((sourceTypeQual == NA_CHARACTER_TYPE) &&
      ((tgtFsType == REC_BLOB) ||
       (tgtFsType == REC_CLOB)))
    {
      LOBconvertHandle * lc = new(generator->wHeap())
	LOBconvertHandle(child(0), LOBoper::LOB_);

      lc->bindNode(generator->getBindWA());
      lc->preCodeGen(generator);
      
      child(0) = lc;
    }

  if (getArity() > 1)
    {
      child(1)->bindNode(generator->getBindWA());
      child(1) = child(1)->preCodeGen(generator);
      if (! child(1).getPtr())
	return NULL;
    }

  ItemExpr *result = this;

  markAsPreCodeGenned();
  return result;
} // Cast::preCodeGen()

ItemExpr * CharFunc::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  const NAType &typ1 = child(0)->getValueId().getType();

  // Insert a cast node to convert child to an INT.
  child(0) = new (generator->wHeap())
    Cast(child(0), new (generator->wHeap()) SQLInt(generator->wHeap(), FALSE,
						   typ1.supportsSQLnullLogical()));

  child(0)->bindNode(generator->getBindWA());

  child(0) = child(0)->preCodeGen(generator);
  if (! child(0).getPtr())
    return NULL;

  markAsPreCodeGenned();
  return this;
} // CharFunc::preCodeGen()

ItemExpr * CompEncode::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  // during key encode expr generation, no need to convert external
  // column types(like tandem floats) to their internal
  // equivalent(ieee floats). Avoid doing preCodeGen in these cases.
  // Do this only for child leaf nodes (columns, hostvar, params, literals).
  //
  if (NOT (child(0)->getValueId().getType().isExternalType() &&
	   child(0)->getArity() == 0)) {
    child(0) = child(0)->preCodeGen(generator);
  }

  markAsPreCodeGenned();

  return this;
} // CompEncode::preCodeGen()

ItemExpr * CompDecode::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  return CompEncode::preCodeGen(generator);

} // CompDecode::preCodeGen()

ItemExpr * Convert::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  // Since this CONVERT will convert its child to the original
  // ExternalType, no need to ask it to first be cast to an internal
  // type.  So, do not call precodegen in these cases.
  // Do this only for child leaf nodes (columns, hostvar, params, literals).
  //
  if (NOT (child(0)->getValueId().getType().isExternalType() &&
	   child(0)->getArity() == 0)) {
    child(0) = child(0)->preCodeGen(generator);
  }

  markAsPreCodeGenned();

  return this;
} // Convert::preCodeGen()

ItemExpr * ConvertTimestamp::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;
  //
  // If the operand is not a largeint with a scale of 0, convert it to one.
  //
  NumericType *numeric = (NumericType *)(&(child(0)->getValueId().getType()));
  if ((numeric->getFSDatatype() != REC_BIN64_SIGNED) ||
      (numeric->getScale() != 0)) {
    child(0) = new(generator->wHeap())
                 Cast(child(0),
                      new(generator->wHeap())
                        SQLLargeInt(generator->wHeap(), TRUE, numeric->supportsSQLnull()));
    child(0)->bindNode(generator->getBindWA());
  }
  child(0) = child(0)->preCodeGen(generator);
  if (! child(0).getPtr())
    return NULL;

  markAsPreCodeGenned();
  return this;
} // ConvertTimestamp::preCodeGen()

ItemExpr * Extract::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;
  //
  // If the operand is an interval and the extract field is not the end field,
  // convert the interval to the units of the extract field.
  // Set the dataconversionerror param to Cast so conversion error
  // (truncation) could be ignored at runtime.
  //
  NAType * type_op1 = (NAType *)(&(child(0)->getValueId().getType()));
  if ((type_op1->getTypeQualifier() == NA_INTERVAL_TYPE) &&
      (getExtractField() < ((IntervalType *) type_op1)->getEndField())) {
    IntervalType *interval = (IntervalType *) type_op1;
    ItemExpr *dataConvError = new(generator->wHeap()) ConstValue(1234567890);
    child(0) = new(generator->wHeap())
                 Cast(child(0), dataConvError,
                      new(generator->wHeap())
                        SQLInterval(generator->wHeap(), interval->supportsSQLnull(),
                                    interval->getStartField(),
                                    interval->getLeadingPrecision(),
                                    getExtractField()),
		      ITM_NARROW);
    child(0)->bindNode(generator->getBindWA());
  }
  child(0) = child(0)->preCodeGen(generator);
  if (! child(0).getPtr())
    return NULL;

  markAsPreCodeGenned();
  return this;
} // Extract::preCodeGen()

ItemExpr * Format::preCodeGen(Generator * generator)
{
  return BuiltinFunction::preCodeGen(generator);
}

ItemExpr * JulianTimestamp::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;
  //
  // If the operand is not a timestamp with a fractional precision of 6,
  // convert it to one.
  //
  DatetimeType *dt = (DatetimeType *)(&(child(0)->getValueId().getType()));
  if ((dt->getSubtype() != DatetimeType::SUBTYPE_SQLTimestamp) ||
      (dt->getFractionPrecision() != 6)) {
    child(0) = new(generator->wHeap())
                 Cast(child(0),
                      new(generator->wHeap())
                        SQLTimestamp(generator->wHeap(), dt->supportsSQLnull(), 6));
    child(0)->bindNode(generator->getBindWA());
  }
  child(0) = child(0)->preCodeGen(generator);
  if (! child(0).getPtr())
    return NULL;
  markAsPreCodeGenned();
  return this;
} // JulianTimestamp::preCodeGen()

ItemExpr * Hash::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return getReplacementExpr();

  ItemExpr *result = this;

  // ---------------------------------------------------------------------
  // In the optimizer, a hash function accepts a comma-separated list
  // of columns. In the executor, replace this with the HashComb of the hash
  // functions of the individual list elements. NOTE: once error handling
  // is in place we need to make sure that no errors are generated from
  // this.
  // ---------------------------------------------------------------------
  if (child(0)->getOperatorType() == ITM_ITEM_LIST)
    {
      // child is a multi-valued expression, transform into multiple
      // hash expressions
      ExprValueId treePtr = child(0);

      ItemExprTreeAsList hashValues(&treePtr,
				    ITM_ITEM_LIST,
				    LEFT_LINEAR_TREE);

      // this expression becomes the hash operator for the first
      // hash value
      child(0) = hashValues[0];

      const NAType &childType = child(0)->getValueId().getType();

      if(childType.getTypeQualifier() == NA_CHARACTER_TYPE) {

	const CharType &chType = (CharType&)childType;
	CharInfo::Collation coll = chType.getCollation();
	
	if (CollationInfo::isSystemCollation(coll))
	    {
	      child(0) = new(generator->wHeap()) 
		CompEncode(child(0),FALSE, -1, CollationInfo::Compare);
	      child(0) = child(0)->bindNode(generator->getBindWA());
	    }
	  else
	    {
	      //--------------------------
	      if ((chType.isCaseinsensitive()) &&
		  (NOT casesensitiveHash()) &&
		  (NOT chType.isUpshifted())) {
		child(0) = new (generator->wHeap()) Upper(child(0));
		child(0) = child(0)->bindNode(generator->getBindWA());
	      }
	    }
	  }

      // add hash expressions for all other hash values and HashComb
      // them together
      CollIndex nc = hashValues.entries();
      for (CollIndex i = 1; i < nc; i++)
	{
          ItemExpr *hi = hashValues[i];

	  const NAType &childType = hi->getValueId().getType();

	  if(childType.getTypeQualifier() == NA_CHARACTER_TYPE) {

	    const CharType &chType = (CharType&)childType;
	    CharInfo::Collation coll = chType.getCollation();
	    
            if (CollationInfo::isSystemCollation(coll))
	      {
		hi = new(generator->wHeap()) 
		    CompEncode(hi,FALSE, -1, CollationInfo::Compare);

		hi = hi->bindNode(generator->getBindWA());
	      }
	      else
	      {
		//-----------------------------
		if ((chType.isCaseinsensitive()) &&
		    (NOT casesensitiveHash()) &&
		    (NOT chType.isUpshifted())) {
		  hi = new (generator->wHeap()) Upper(hi);
		  hi = hi->bindNode(generator->getBindWA());
		}
		  //-----------------------
	      }
	  }

	  ItemExpr *hv = new(generator->wHeap()) Hash(hi);
	  result = new(generator->wHeap()) HashComb(result,hv);
	}

      result->bindNode(generator->getBindWA());
    } else {
      const NAType &childType = child(0)->getValueId().getType();

      if(childType.getTypeQualifier() == NA_CHARACTER_TYPE) {

	const CharType &chType = (CharType&)childType;
	CharInfo::Collation coll = chType.getCollation();
	
        if (CollationInfo::isSystemCollation(coll))
	  {
	    child(0) = new (generator->wHeap()) 
	      CompEncode(child(0), FALSE, -1, CollationInfo::Compare);
	    
	    child(0) = child(0)->bindNode(generator->getBindWA());
          }
	  else
	  {
	    if ((chType.isCaseinsensitive()) &&
		(NOT casesensitiveHash()) &&
		(NOT chType.isUpshifted())) {
	      child(0) = new (generator->wHeap()) Upper(child(0));
	      child(0) = child(0)->bindNode(generator->getBindWA());
	    }
          }

      }
    }

  // do generic tasks for pre-code generation (e.g. recurse to the children)
  setReplacementExpr(result->ItemExpr::preCodeGen(generator));
  markAsPreCodeGenned();
  return getReplacementExpr();
} // Hash::preCodeGen()

ItemExpr * HiveHash::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return getReplacementExpr();

  ItemExpr *result = this;

  // ---------------------------------------------------------------------
  // In the optimizer, a hash function accepts a comma-separated list
  // of columns. In the executor, replace this with the HashComb of the hash
  // functions of the individual list elements. NOTE: once error handling
  // is in place we need to make sure that no errors are generated from
  // this.
  // ---------------------------------------------------------------------
  if (child(0)->getOperatorType() == ITM_ITEM_LIST)
    {
      // child is a multi-valued expression, transform into multiple
      // hash expressions
      ExprValueId treePtr = child(0);

      ItemExprTreeAsList hivehashValues(&treePtr,
				    ITM_ITEM_LIST,
				    LEFT_LINEAR_TREE);

      // this expression becomes the hash operator for the first
      // hash value
      child(0) = hivehashValues[0];

      const NAType &childType = child(0)->getValueId().getType();

      if(childType.getTypeQualifier() == NA_CHARACTER_TYPE) {

	const CharType &chType = (CharType&)childType;
	CharInfo::Collation coll = chType.getCollation();
	
	if (CollationInfo::isSystemCollation(coll))
	    {
	      child(0) = new(generator->wHeap()) 
		CompEncode(child(0),FALSE, -1, CollationInfo::Compare);
	      child(0) = child(0)->bindNode(generator->getBindWA());
	    }
	  else
	    {
	      //--------------------------
	      if ((chType.isCaseinsensitive()) &&
		  (NOT casesensitiveHash()) &&
		  (NOT chType.isUpshifted())) {
		child(0) = new (generator->wHeap()) Upper(child(0));
		child(0) = child(0)->bindNode(generator->getBindWA());
	      }
	    }
	  }

      // add hash expressions for all other hash values and HiveHashComb
      // them together
      CollIndex nc = hivehashValues.entries();
      for (CollIndex i = 1; i < nc; i++)
	{
          ItemExpr *hi = hivehashValues[i];

	  const NAType &childType = hi->getValueId().getType();

	  if(childType.getTypeQualifier() == NA_CHARACTER_TYPE) {

	    const CharType &chType = (CharType&)childType;
	    CharInfo::Collation coll = chType.getCollation();
	    
            if (CollationInfo::isSystemCollation(coll))
	      {
		hi = new(generator->wHeap()) 
		    CompEncode(hi,FALSE, -1, CollationInfo::Compare);

		hi = hi->bindNode(generator->getBindWA());
	      }
	      else
	      {
		//-----------------------------
		if ((chType.isCaseinsensitive()) &&
		    (NOT casesensitiveHash()) &&
		    (NOT chType.isUpshifted())) {
		  hi = new (generator->wHeap()) Upper(hi);
		  hi = hi->bindNode(generator->getBindWA());
		}
		  //-----------------------
	      }
	  }

	  ItemExpr *hv = new(generator->wHeap()) HiveHash(hi);
	  result = new(generator->wHeap()) HiveHashComb(result,hv);
	}

      result->bindNode(generator->getBindWA());
    } else {
      const NAType &childType = child(0)->getValueId().getType();

      if(childType.getTypeQualifier() == NA_CHARACTER_TYPE) {

	const CharType &chType = (CharType&)childType;
	CharInfo::Collation coll = chType.getCollation();
	
        if (CollationInfo::isSystemCollation(coll))
	  {
	    child(0) = new (generator->wHeap()) 
	      CompEncode(child(0), FALSE, -1, CollationInfo::Compare);
	    
	    child(0) = child(0)->bindNode(generator->getBindWA());
          }
	  else
	  {
	    if ((chType.isCaseinsensitive()) &&
		(NOT casesensitiveHash()) &&
		(NOT chType.isUpshifted())) {
	      child(0) = new (generator->wHeap()) Upper(child(0));
	      child(0) = child(0)->bindNode(generator->getBindWA());
	    }
          }

      }
    }

  // do generic tasks for pre-code generation (e.g. recurse to the children)
  setReplacementExpr(result->ItemExpr::preCodeGen(generator));
  markAsPreCodeGenned();
  return getReplacementExpr();
} // Hash::preCodeGen()

// --------------------------------------------------------------
// member functions for HashDistPartHash operator
// Hash Function used by Hash Partitioning. This function cannot change
// once Hash Partitioning is released!  Defined for all data types,
// returns a 32 bit non-nullable hash value for the data item.
//--------------------------------------------------------------


ItemExpr * HashDistPartHash::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return getReplacementExpr();

  ItemExpr *result = this;

  // ---------------------------------------------------------------------
  // In the optimizer, a hash function accepts a comma-separated list
  // of columns. Replace this with the HashComb of the hash functions
  // of the individual list elements.
  // ---------------------------------------------------------------------
  if (child(0)->getOperatorType() == ITM_ITEM_LIST)
    {
      // child is a multi-valued expression, transform into multiple
      // hash expressions
      ExprValueId treePtr = child(0);

      ItemExprTreeAsList hashValues(&treePtr,
				    ITM_ITEM_LIST,
				    LEFT_LINEAR_TREE);

      // this expression becomes the hash operator for the first
      // hash value
      child(0) = hashValues[0];

      const NAType &childType = child(0)->getValueId().getType();

      if(childType.getTypeQualifier() == NA_CHARACTER_TYPE) {

	const CharType &chType = (CharType&)childType;
	
	CharInfo::Collation coll = chType.getCollation();

        if (CollationInfo::isSystemCollation(coll))
	  {
	    if (child(0)->getOperatorType() == ITM_NARROW)
	    {
	      ItemExpr* narrowsChild = child(0)->child(0);
	      const NAType &narrowsChildType= narrowsChild->getValueId().getType();
	      CMPASSERT(narrowsChildType.getTypeQualifier() == NA_CHARACTER_TYPE);
	      NAType *newType= narrowsChildType.newCopy(generator->wHeap());
	      CharType * newCharType = (CharType *) newType;
	      newCharType->setDataStorageSize(chType.getDataStorageSize());
  	    
	      child(0)->getValueId().changeType(newCharType);

	    }

	    child(0) = new(generator->wHeap()) 
			CompEncode(child(0),FALSE, -1, CollationInfo::Compare);

	    child(0) = child(0)->bindNode(generator->getBindWA());
	  }
	  else
	  {
	    if ((chType.isCaseinsensitive()) &&
		(NOT chType.isUpshifted())) {
	      child(0) = new (generator->wHeap()) Upper(child(0));
	      child(0) = child(0)->bindNode(generator->getBindWA());
	    }
	  }
      }

      // add hash expressions for all other hash values and HashComb
      // them together
      CollIndex nc = hashValues.entries();
      for (CollIndex i = 1; i < nc; i++)
	{
          ItemExpr *hi = hashValues[i];

	  const NAType &childType = hi->getValueId().getType();

	  if(childType.getTypeQualifier() == NA_CHARACTER_TYPE) {

	    const CharType &chType = (CharType&)childType;

	    CharInfo::Collation coll = chType.getCollation();

            if (CollationInfo::isSystemCollation(coll))
	    {
	      //Solution 10-081216-8006
	      if (hi->getOperatorType() == ITM_NARROW)
	      {
		ItemExpr* narrowsChild = hi->child(0);
		const NAType &narrowsChildType= narrowsChild->getValueId().getType();
		CMPASSERT(narrowsChildType.getTypeQualifier() == NA_CHARACTER_TYPE);
		NAType *newType= narrowsChildType.newCopy(generator->wHeap());
		CharType * newCharType = (CharType *) newType;
		newCharType->setDataStorageSize(chType.getDataStorageSize());
    	    
		hi->getValueId().changeType(newCharType);

	      }

		hi = new(generator->wHeap()) 
		      CompEncode(hi,FALSE, -1, CollationInfo::Compare);

		hi = hi->bindNode(generator->getBindWA());
	    }
	    else
	    {
  		if ((chType.isCaseinsensitive()) &&
		    (NOT chType.isUpshifted())) {
		  hi = new (generator->wHeap()) Upper(hi);
		  hi = hi->bindNode(generator->getBindWA());
		}
	      }
          }

	  ItemExpr *hv =
            new(generator->wHeap()) HashDistPartHash(hi);
	  result = new(generator->wHeap())
            HashDistPartHashComb(result,hv);
	}

      result->bindNode(generator->getBindWA());
    } else {
      const NAType &childType = child(0)->getValueId().getType();

      if(childType.getTypeQualifier() == NA_CHARACTER_TYPE) {

	const CharType &chType = (CharType&)childType;

	CharInfo::Collation coll = chType.getCollation();

        if (CollationInfo::isSystemCollation(coll))
	{
	  //Solution 10-081216-8006
	  if (child(0)->getOperatorType() == ITM_NARROW)
	  {
	    ItemExpr* narrowsChild = child(0)->child(0);
	    const NAType &narrowsChildType= narrowsChild->getValueId().getType();
	    CMPASSERT(narrowsChildType.getTypeQualifier() == NA_CHARACTER_TYPE);
	    NAType *newType= narrowsChildType.newCopy(generator->wHeap());
	    CharType * newCharType = (CharType *) newType;
	    newCharType->setDataStorageSize(chType.getDataStorageSize());
	    
	    child(0)->getValueId().changeType(newCharType);

	  }

	  child(0) = new(generator->wHeap()) 
			CompEncode(child(0),FALSE, -1, CollationInfo::Compare);

	  child(0) = child(0)->bindNode(generator->getBindWA());
	}
	else
	{
	    if ((chType.isCaseinsensitive()) &&
		(NOT chType.isUpshifted())) {
	      child(0) = new (generator->wHeap()) Upper(child(0));
	      child(0) = child(0)->bindNode(generator->getBindWA());
	    }
	  }
      }
    }

  // do generic tasks for pre-code generation (e.g. recurse to the children)
  setReplacementExpr(result->ItemExpr::preCodeGen(generator));
  markAsPreCodeGenned();
  return getReplacementExpr();
} // HashDistPartHash::preCodeGen()


ItemExpr * HostVar::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  ItemExpr * i = convertExternalType(generator);
  if (i == NULL)
    return NULL;

  return i;
}

ItemExpr * IndexColumn::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  ItemExpr * i = convertExternalType(generator);
  if (i == NULL)
    return NULL;

  return i;
}

ItemExpr * Generator::addCompDecodeForDerialization(ItemExpr * ie, NABoolean isAlignedFormat)
{
  if (!ie)
    return NULL;

  if ((ie->getOperatorType() == ITM_BASECOLUMN) ||
      (ie->getOperatorType() == ITM_INDEXCOLUMN))
    {
      if (! isAlignedFormat && HbaseAccess::isEncodingNeededForSerialization(ie))
	{
	  ItemExpr * newNode = new(wHeap()) CompDecode
	    (ie, &ie->getValueId().getType(), FALSE, TRUE);

	  newNode->bindNode(getBindWA());
	  if (getBindWA()->errStatus())
	    return NULL;

	  newNode = newNode->preCodeGen(this);
	  if (! newNode)
	    return NULL;  
	  return newNode;
	}
      else
	return ie;
    }

  for (Lng32 i = 0; i < ie->getArity(); i++)
    {
      ItemExpr * nie = addCompDecodeForDerialization(ie->child(i), isAlignedFormat);
      if (nie)
	ie->setChild(i, nie);
    }

  return ie;
}

ItemExpr * HbaseTimestamp::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return getReplacementExpr();

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  markAsPreCodeGenned();

  return this;
}

ItemExpr * HbaseVersion::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return getReplacementExpr();

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  markAsPreCodeGenned();

  return this;
}

ItemExpr * LOBoper::preCodeGen(Generator * generator)
{
  generator->setProcessLOB(TRUE);

  return BuiltinFunction::preCodeGen(generator);
}

ItemExpr * LOBconvert::preCodeGen(Generator * generator)
{
  NAColumn * col = child(0)->getValueId().getNAColumn(TRUE);
  if (col)
    {
      lobNum() = col->lobNum();
      lobStorageType() = col->lobStorageType();
      lobStorageLocation() = col->lobStorageLocation();
    }
  
  return LOBoper::preCodeGen(generator);
}


ItemExpr * LOBupdate::preCodeGen(Generator * generator)
{
  return LOBoper::preCodeGen(generator);
}

ItemExpr * MathFunc::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  for (Int32 i = 0; i < getArity(); i++)
    {
      const NAType &typ = child(i)->getValueId().getType();

      // Insert a cast node to convert child to a double precision.
      child(i) = new (generator->wHeap())
	Cast(child(i),
	     new (generator->wHeap()) SQLDoublePrecision(
		  generator->wHeap(), typ.supportsSQLnullLogical()));

      child(i)->bindNode(generator->getBindWA());

      child(i) = child(i)->preCodeGen(generator);
      if (! child(i).getPtr())
	return NULL;
    }

  markAsPreCodeGenned();
  return this;
} // MathFunc::preCodeGen()

ItemExpr * Modulus::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  for (Int32 i = 0; i < 2; i++)
    {
      const NumericType &typ
	= (NumericType&)child(i)->getValueId().getType();

      if (typ.isDecimal())
	{
	  // Insert a cast node to convert child to an LARGEINT.
	  child(i) = new (generator->wHeap())
	    Cast(child(i), new (generator->wHeap()) SQLLargeInt(generator->wHeap(), TRUE,
								typ.supportsSQLnullLogical()));
	}

      child(i)->bindNode(generator->getBindWA());

      child(i) = child(i)->preCodeGen(generator);
      if (! child(i).getPtr())
	return NULL;
    }

  markAsPreCodeGenned();
  return this;
} // Modulus::preCodeGen()

ItemExpr * ItemExpr::convertExternalType(Generator * generator)
{
  BindWA * bindWA = generator->getBindWA();

  if (getValueId().getType().isExternalType())
    {
      // this type is not supported internally.
      // Convert it to an equivalent internal type.
      ItemExpr * c = new (bindWA->wHeap())
	Cast(this, getValueId().getType().equivalentType(bindWA->wHeap()));

      c->synthTypeAndValueId();

      // mark 'this' as precodegenned so we don't go thru
      // this path again.
      markAsPreCodeGenned();
      c = c->preCodeGen(generator);
      unmarkAsPreCodeGenned();

      return c;
    }
  else
    return this;
}

ItemExpr * Parameter::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  ItemExpr * i = convertExternalType(generator);
  if (i == NULL)
    return NULL;

  return i;
}

ItemExpr * PivotGroup::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return getReplacementExpr();

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  ItemExpr * childExpr = child(0)->castToItemExpr();

  const NAType &type1 = 
    childExpr->getValueId().getType();
 
  if (type1.getTypeQualifier() != NA_CHARACTER_TYPE) 
    {
      Lng32 displayLen = type1.getDisplayLength(
                                                type1.getFSDatatype(),
                                                type1.getNominalSize(),
                                                type1.getPrecision(),
                                                type1.getScale(),
                                                0);

      NAType * newType = new(generator->getBindWA()->wHeap()) 
        SQLVarChar(generator->getBindWA()->wHeap(), displayLen, type1.supportsSQLnull());

      childExpr = new (generator->getBindWA()->wHeap()) Cast(childExpr, newType);
      
      childExpr = childExpr->bindNode(generator->getBindWA());
      if (! childExpr || generator->getBindWA()->errStatus())
        return NULL;

      childExpr = childExpr->preCodeGen(generator);
      if (! childExpr)
	return NULL;

      child(0) = childExpr;
    }

  markAsPreCodeGenned();

  return this;
}

ItemExpr * RandomNum::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (child(0))
    {
      const NAType &typ1 = child(0)->getValueId().getType();

      // Insert a cast node to convert child to an INT.
      child(0) = new (generator->wHeap())
	Cast(child(0), new (generator->wHeap()) SQLInt(generator->wHeap(), FALSE,
						       typ1.supportsSQLnullLogical()));

      child(0)->bindNode(generator->getBindWA());

      child(0) = child(0)->preCodeGen(generator);
      if (! child(0).getPtr())
	return NULL;
    }

  markAsPreCodeGenned();
  return this;
} // RandomNum::preCodeGen()

ItemExpr * Repeat::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  const NAType &typ2 = child(1)->getValueId().getType();

  // Insert a cast node to convert child 2 to an INT.
  child(1) = new (generator->wHeap())
    Cast(child(1), new (generator->wHeap()) SQLInt(generator->wHeap(), FALSE,
						   typ2.supportsSQLnullLogical()));

  child(1)->bindNode(generator->getBindWA());

  for (Int32 i = 0; i < getArity(); i++)
    {
      if (child(i))
	{
	  child(i) = child(i)->preCodeGen(generator);
	  if (! child(i).getPtr())
	    return NULL;
	}
    }

  markAsPreCodeGenned();
  return this;
} // Repeat::preCodeGen()

ItemExpr *ReplaceNull::preCodeGen(Generator *generator)
{
  if (nodeIsPreCodeGenned())
    return getReplacementExpr();

  NAType *dstAType = getValueId().getType().newCopy(generator->wHeap());
  const NAType& dstBType = getValueId().getType();

  if(child(0) == child(1))
    {
      dstAType->setNullable(TRUE);
    }

  child(1) = new(generator->wHeap()) Cast(child(1), dstAType);
  child(2) = new(generator->wHeap()) Cast(child(2), &dstBType);

  child(1)->bindNode(generator->getBindWA());
  child(2)->bindNode(generator->getBindWA());

  setReplacementExpr(ItemExpr::preCodeGen(generator));
  markAsPreCodeGenned();
  return getReplacementExpr();
}

ItemExpr * TriRelational::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return getReplacementExpr();

  // ---------------------------------------------------------------------
  // The executor does not handle tri-relational operators. It either
  // handles key exclusion expressions if the operator is part or a key
  // predicate, or the tri-relational operator gets converted into
  // a case statement (see comment in file ItemFunc.h).
  // ---------------------------------------------------------------------
  NABoolean lessOrLe = (getOperatorType() == ITM_LESS_OR_LE);
  BiRelat *exclusive = new(generator->wHeap()) BiRelat(
       (IFX lessOrLe THENX ITM_LESS ELSEX ITM_GREATER),
       child(0),
       child(1));
  BiRelat *inclusive = new(generator->wHeap()) BiRelat(
       (IFX lessOrLe THENX ITM_LESS_EQ ELSEX ITM_GREATER_EQ),
       child(0),
       child(1));
  exclusive->setSpecialNulls(getSpecialNulls());
  inclusive->setSpecialNulls(getSpecialNulls());

  ItemExpr * result = new(generator->wHeap()) Case(
       NULL,
       new(generator->wHeap()) IfThenElse(
	    child(2),
	    exclusive,
	    inclusive));

  result->bindNode(generator->getBindWA());

  // do generic tasks for pre-code generation (e.g. recurse to the children)
  setReplacementExpr(result->preCodeGen(generator));
  markAsPreCodeGenned();
  return getReplacementExpr();
} // TriRelational::preCodeGen()

ItemExpr *
HashDistrib::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  // Assert that the operands are unsigned int.
  //
  NumericType *numeric = (NumericType *)(&(child(0)->getValueId().getType()));
  GenAssert(numeric->getFSDatatype()==REC_BIN32_UNSIGNED &&
	    numeric->getScale()==0,
	    "invalid first operand type to function HashDistrib");

  numeric = (NumericType *)(&(child(1)->getValueId().getType()));
  GenAssert(numeric->getFSDatatype()==REC_BIN32_UNSIGNED &&
	    numeric->getScale()==0,
	    "invalid second operand type to function HashDistrib");

  markAsPreCodeGenned();
  return this;
}

ItemExpr * ProgDistribKey::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  // Assert that all operands are of type unsigned int.
  //
  for (Int32 i=0; i<3; i++)
    {
      NumericType *numeric =
        (NumericType *)(&(child(i)->getValueId().getType()));

      GenAssert(numeric->getFSDatatype()==REC_BIN32_UNSIGNED &&
		numeric->getScale()==0,
		"invalid operand type to function ProgDistribKey");
    }

  markAsPreCodeGenned();
  return this;
}

ItemExpr *
PAGroup::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  // Assert that the operands are unsigned int.
  //
  NumericType *numeric = (NumericType *)(&(child(0)->getValueId().getType()));
  GenAssert(numeric->getFSDatatype()==REC_BIN32_UNSIGNED &&
	    numeric->getScale()==0,
	    "invalid first operand type to function PAGroup");

  numeric = (NumericType *)(&(child(1)->getValueId().getType()));
  GenAssert(numeric->getFSDatatype()==REC_BIN32_UNSIGNED &&
	    numeric->getScale()==0,
	    "invalid second operand type to function PAGroup");

  numeric = (NumericType *)(&(child(2)->getValueId().getType()));
  GenAssert(numeric->getFSDatatype()==REC_BIN32_UNSIGNED &&
	    numeric->getScale()==0,
	    "invalid third operand type to function PAGroup");

  markAsPreCodeGenned();
  return this;
}

ItemExpr *
ScalarVariance::preCodeGen(Generator *generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! ItemExpr::preCodeGen(generator))
    return NULL;

  NumericType *result_type =
    (NumericType *)(&(getValueId().getType()));

  NumericType *type_op1 =
    (NumericType *)(&(child(0)->castToItemExpr()->getValueId().getType()));

  NumericType *type_op2 =
    (NumericType *)(&(child(1)->castToItemExpr()->getValueId().getType()));

  NumericType *type_op3 =
    (NumericType *)(&(child(1)->castToItemExpr()->getValueId().getType()));

  GenAssert(result_type->getTypeQualifier() == NA_NUMERIC_TYPE &&
	    type_op1->getTypeQualifier() == NA_NUMERIC_TYPE &&
	    type_op2->getTypeQualifier() == NA_NUMERIC_TYPE &&
	    type_op3->getTypeQualifier() == NA_NUMERIC_TYPE &&
	    !result_type->isExact() &&
	    !type_op1->isExact() &&
	    !type_op2->isExact() &&
	    !type_op3->isExact() &&
	    result_type->getBinaryPrecision() == SQL_DOUBLE_PRECISION &&
	    type_op1->getBinaryPrecision() == SQL_DOUBLE_PRECISION &&
	    type_op2->getBinaryPrecision() == SQL_DOUBLE_PRECISION &&
	    type_op3->getBinaryPrecision() == SQL_DOUBLE_PRECISION,
	    "ScalarVariance: Invalid Inputs");

  markAsPreCodeGenned();
  return this;
}

ItemExpr * Substring::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  child(0) = child(0)->preCodeGen(generator);
  if (! child(0).getPtr())
    return NULL;

  for (Int32 i = 1; i < getArity(); i++)
    {
      if (child(i))
	{
	  const NAType &typ1 = child(i)->getValueId().getType();

	  // Insert a cast node to convert child to an INT.
	  child(i) = new (generator->wHeap())
	    Cast(child(i), new (generator->wHeap()) SQLInt(generator->wHeap(), TRUE,
							   typ1.supportsSQLnullLogical()));

	  child(i)->bindNode(generator->getBindWA());

	  child(i) = child(i)->preCodeGen(generator);
	  if (! child(i).getPtr())
	    return NULL;
	}
    }

  markAsPreCodeGenned();
  return this;
} // Substring::preCodeGen()


ItemExpr * ItemExpr::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  Lng32 nc = (Lng32)getArity();

  for (Lng32 index = 0; index < nc; index++)
    {
      child(index) = child(index)->preCodeGen(generator);
      if (! child(index).getPtr())
	return NULL;
    }

  markAsPreCodeGenned();

  return this;
} // ItemExpr::preCodeGen()

// ---------------------------------------------------------
// Methods for class VEGRewritePairs
// ---------------------------------------------------------
VEGRewritePairs::VEGRewritePairs(CollHeap* heap)
  : heap_(heap),
    vegRewritePairs_(&valueIdHashFunc, 1009, TRUE, heap)
{
} 

ULng32 VEGRewritePairs::valueIdHashFunc(const CollIndex & v) 
{
  return (ULng32)v;
}

const VEGRewritePairs::VEGRewritePair *
VEGRewritePairs::getPair( const ValueId& original) const
{
  CollIndex k(original);
  return vegRewritePairs_.getFirstValue(&k);

} // getPair(..)


NABoolean VEGRewritePairs::
getRewritten(ValueId& rewritten, const ValueId& original) const
{
  NABoolean found = FALSE;
  const VEGRewritePairs::VEGRewritePair * vrPairPtr = NULL;
  if (vrPairPtr = getPair(original)){
      rewritten = vrPairPtr->getRewritten();
      found = TRUE;
  }

  return found;
} // getRewritten

VEGRewritePairs::~VEGRewritePairs()
{
  clear();

} // VEGRewritePairs::~VEGRewritePairs()

void
VEGRewritePairs::insert(const ValueId& original,
			const ValueId& rewritten)
{
  // Precondition:
  // original must have not been rewritten before:
  CMPASSERT(getPair(original) == NULL);

  VEGRewritePairs::VEGRewritePair * vrPairPtr =
    new (heap_) VEGRewritePairs::VEGRewritePair(original,rewritten);
  CMPASSERT(vrPairPtr != NULL);

  CollIndex* key = (CollIndex*) new (heap_) CollIndex(original);


  vegRewritePairs_.insert(key, vrPairPtr);
}


void VEGRewritePairs::VEGRewritePair::print(FILE *ofd) const
{
  Lng32 orId = CollIndex(original_),
    reId = CollIndex(rewritten_);
  fprintf(ofd,"<%d, %d>",orId,reId);
}


void VEGRewritePairs::print( FILE* ofd,
			     const char* indent,
			     const char* title) const
{
  BUMP_INDENT(indent);
  fprintf(ofd,"%s %s\n%s",NEW_INDENT,title,NEW_INDENT);

  CollIndex *key;
  VEGRewritePair *value;
  NAHashDictionaryIterator<CollIndex, VEGRewritePair> iter(vegRewritePairs_);

  for (CollIndex i=0; i < iter.entries(); i++)
    {
      iter.getNext(key, value);
      value->print(ofd);
    }
}

// PhysTranspose::preCodeGen() -------------------------------------------
// Perform local query rewrites such as for the creation and
// population of intermediate tables, for accessing partitioned
// data. Rewrite the value expressions after minimizing the dataflow
// using the transitive closure of equality predicates.
//
// PhysTranspose::preCodeGen() - is basically the same as the RelExpr::
// preCodeGen() except that here we replace the VEG references in the
// transUnionVals() as well as the selectionPred().
//
// Parameters:
//
// Generator *generator
//    IN/OUT : A pointer to the generator object which contains the state,
//             and tools (e.g. expression generator) to generate code for
//             this node.
//
// ValueIdSet &externalInputs
//    IN    : The set of external Inputs available to this node.
//
//
RelExpr * PhysTranspose::preCodeGen(Generator * generator,
				    const ValueIdSet &externalInputs,
				    ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  // Check if the pivs of this operator and it's child are the same.
  // If they are not, make them the same.
  replacePivs();

  // Resolve the VEGReferences and VEGPredicates, if any, that appear
  // in the Characteristic Inputs, in terms of the externalInputs.
  //
  getGroupAttr()->resolveCharacteristicInputs(externalInputs);

  // My Characteristic Inputs become the external inputs for my children.
  //
  Int32 nc = getArity();
  for (Int32 index = 0; index < nc; index++)
    {
      ValueIdSet childPulledInputs;

      child(index) = child(index)->preCodeGen(generator,
					      externalInputs,
					      pulledNewInputs);
      if (! child(index).getPtr())
	return NULL;

      // process additional input value ids the child wants
      getGroupAttr()->addCharacteristicInputs(childPulledInputs);
      pulledNewInputs += childPulledInputs;
    }

  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  //
  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);

  // The transUnionVals have access to only the Input Values.
  // These can come from the parent of be the outputs of the child.
  //
  for(CollIndex v = 0; v < transUnionVectorSize(); v++) {
    ValueIdList valIdList = transUnionVector()[v];

    valIdList.replaceVEGExpressions
      (availableValues,
       getGroupAttr()->getCharacteristicInputs());
  }

  // The selectionPred has access to the output values generated by transpose.
  // as well as any input values from the parent or child.
  //
  getInputAndPotentialOutputValues(availableValues);


  // Rewrite the selection predicates.
  //
  NABoolean replicatePredicates = TRUE;
  selectionPred().replaceVEGExpressions
    (availableValues,
     getGroupAttr()->getCharacteristicInputs(),
     FALSE, // no key predicates here
     0 /* no need for idempotence here */,
     replicatePredicates
     );

  // Replace VEG references in the outputs and remove redundant
  // outputs.
  //
  getGroupAttr()->resolveCharacteristicOutputs
    (availableValues,
     getGroupAttr()->getCharacteristicInputs());
  generator->oltOptInfo()->setMultipleRowsReturned(TRUE);
  markAsPreCodeGenned();

  return this;
} // PhysTranspose::preCodeGen

// -----------------------------------------------------------------------
// PhyPack::preCodeGen() is basically the same as RelExpr::preCodeGen().
// It replaces the VEG's in its packingExpr_ as well as selectionPred_.
// -----------------------------------------------------------------------
RelExpr* PhyPack::preCodeGen(Generator* generator,
                             const ValueIdSet& externalInputs,
			     ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  // Check if the pivs of this operator and it's child are the same.
  // If they are not, make them the same.
  replacePivs();

  // Resolve the VEGReferences and VEGPredicates, if any, that appear
  // in the Characteristic Inputs, in terms of the externalInputs.
  //
  getGroupAttr()->resolveCharacteristicInputs(externalInputs);

  // My Characteristic Inputs become the external inputs for my children.
  //
  Int32 nc = getArity();
  for(Int32 index = 0; index < nc; index++)
  {
    ValueIdSet childPulledInputs;

    child(index) = child(index)->preCodeGen(generator,
					    externalInputs,
					    pulledNewInputs);
    if(! child(index).getPtr()) return NULL;

    // process additional input value ids the child wants
    getGroupAttr()->addCharacteristicInputs(childPulledInputs);
    pulledNewInputs += childPulledInputs;
  }

  if (getFirstNRows() != -1)
    {
      RelExpr * firstn = new(generator->wHeap()) FirstN(child(0),
                                                        getFirstNRows(),
                                                        FALSE /* [any n] is good enough */);

      // move my child's attributes to the firstN node.
      // Estimated rows will be mine.
      firstn->setEstRowsUsed(getEstRowsUsed());
      firstn->setMaxCardEst(getMaxCardEst());
      firstn->setInputCardinality(child(0)->getInputCardinality());
      firstn->setPhysicalProperty(child(0)->getPhysicalProperty());
      firstn->setGroupAttr(child(0)->getGroupAttr());
      //10-060516-6532 -Begin
      //When FIRSTN node is created after optimization phase, the cost
      //of that node does not matter.But, display_explain and explain
      //show zero operator costs and rollup cost which confuses the user.
      //Also, the VQP crashes when cost tab for FIRSTN node is selected.
      //So, creating a cost object will fix this.
      //The operator cost is zero and rollup cost is same as it childs.
      Cost* firstnNodecost = new HEAP Cost();
      firstn->setOperatorCost(firstnNodecost);
      Cost* rollupcost = (Cost *)(child(0)->getRollUpCost());
      *rollupcost += *firstnNodecost;
      firstn->setRollUpCost(rollupcost);
      //10-060516-6532 -End

      firstn =
        firstn->preCodeGen(generator,
                           getGroupAttr()->getCharacteristicInputs(),
                           pulledNewInputs);
      if (! firstn)
        return NULL;

      setChild(0, firstn);
    }

  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  //
  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);
  const ValueIdSet& inputValues = getGroupAttr()->getCharacteristicInputs();

  // Replace VEG's in both the packing expression and the packing factor.
  //
  packingFactor().replaceVEGExpressions(availableValues,inputValues);
  packingExpr().replaceVEGExpressions(availableValues,inputValues);

  // The selectionPred has access to the output values generated by Pack.
  //
  getInputAndPotentialOutputValues(availableValues);

  // Rewrite the selection predicates.
  //
  NABoolean replicatePredicates = TRUE;
  selectionPred().replaceVEGExpressions(availableValues,
                                        inputValues,
                                        FALSE, // no key predicates here
                                        0 /* no need for idempotence here */,
                                        replicatePredicates
                                        );

  // Replace VEG references in the outputs and remove redundant outputs.
  //
  getGroupAttr()->resolveCharacteristicOutputs(availableValues,inputValues);

  markAsPreCodeGenned();
  return this;

} // PhyPack::preCodeGen()


//
//PrecodeGen method for class PhysicalTuple list
//This was put in as a fix for cr 10-010327-1947.
//Before the fix the RelExpr was getting to the generator
//with a VEGRef still in it, because the VEGRef from the
//tupleExpr had not be removed and resolved correctly.
RelExpr * PhysicalTuple::preCodeGen(Generator * generator,
                              const ValueIdSet& externalInputs,
                              ValueIdSet& pulledNewInputs_)
{
  ValueIdSet availableValues = externalInputs;
  tupleExpr().replaceVEGExpressions
                (availableValues, externalInputs);

  return (RelExpr::preCodeGen(generator, availableValues, pulledNewInputs_));
} // PhysicalTuple::preCodeGen()
//

RelExpr * PhysicalTupleList::preCodeGen(Generator * generator,
                              const ValueIdSet& externalInputs,
                              ValueIdSet& pulledNewInputs_)
{
  ValueIdSet availableValues = externalInputs;
  tupleExpr().replaceVEGExpressions
                (availableValues, externalInputs);

  generator->oltOptInfo()->setMultipleRowsReturned(TRUE);

  return (RelExpr::preCodeGen(generator, availableValues, pulledNewInputs_));
} // PhysicalTupleList::preCodeGen()

RelExpr * CompoundStmt::preCodeGen(Generator * generator,
			           const ValueIdSet & externalInputs,
			           ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  // Check if the pivs of this operator and it's child are the same.
  // If they are not, make them the same.
  replacePivs();

  ValueIdSet availableValues;
  ValueIdSet childPulledInputs;

  // Resolve the VEGReferences and VEGPredicates, if any, that appear
  // in the Characteristic Inputs, in terms of the externalInputs.
  getGroupAttr()->resolveCharacteristicInputs(externalInputs);
  availableValues = getGroupAttr()->getCharacteristicInputs();

  // This is similar to what is done in Join::precodeGen when we have a TSJ.
  // A compound statement node behaves in a similar way to a TSJ node since
  // it flows values from left to right.

  // My Characteristic Inputs become the external inputs for my left child.
  child(0) = child(0)->preCodeGen(generator,availableValues,childPulledInputs);
  if (! child(0).getPtr())
    return NULL;

   // process additional input value ids the child wants
  // (see RelExpr::preCodeGen())
  getGroupAttr()->addCharacteristicInputs(childPulledInputs);
  pulledNewInputs += childPulledInputs;
  availableValues += childPulledInputs;
  childPulledInputs.clear();

  // The values produced as output by my left child can be used as
  // "external" inputs by my right child.
  availableValues += child(0)->getGroupAttr()->getCharacteristicOutputs();

  // Process the right child
  child(1) = child(1)->preCodeGen(generator,availableValues,childPulledInputs);
  if (! child(1).getPtr())
    return NULL;

  // process additional input value ids the child wants
  // (see RelExpr::preCodeGen())
  getGroupAttr()->addCharacteristicInputs(childPulledInputs);
  pulledNewInputs += childPulledInputs;

  // Accumulate the values that are provided as inputs by my parent
  // together with the values that are produced as outputs by my
  // children. Use these values for rewriting the VEG expressions.
  getInputValuesFromParentAndChildren(availableValues);

  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  getInputAndPotentialOutputValues(availableValues);

  // Rewrite the selection predicates.
  NABoolean replicatePredicates = TRUE;
  selectionPred().replaceVEGExpressions
                     (availableValues,
		      getGroupAttr()->getCharacteristicInputs(),
		      FALSE, // no need to generate key predicates here
		      0 /* no need for idempotence here */,
		      replicatePredicates
		     );

  getGroupAttr()->resolveCharacteristicOutputs
                     (availableValues,
		      getGroupAttr()->getCharacteristicInputs());

  // Xn will be aborted if there is any IUD stmt within this CS and
  // an error occurs at runtime.
  if (generator->foundAnUpdate())
    {
      //generator->setUpdAbortOnError(TRUE);
      generator->setUpdSavepointOnError(FALSE);
      generator->setUpdErrorOnError(FALSE);
      //generator->setUpdPartialOnError(FALSE);
    }

  generator->setAqrEnabled(FALSE);

  markAsPreCodeGenned();

  return this;
} // CompoundStmt::preCodeGen

RelExpr * FirstN::preCodeGen(Generator * generator,
			     const ValueIdSet & externalInputs,
			     ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;


  if (getFirstNRows() > 0)
     generator->setTopNRows(getFirstNRows());
  else
     generator->setTopNRows(ActiveSchemaDB()->getDefaults().getAsULong(GEN_SORT_TOPN_THRESHOLD));

  if (! RelExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  markAsPreCodeGenned();

  return this;
} // FirstN::preCodeGen

RelExpr * RelRoutine::preCodeGen (Generator * generator,
					     const ValueIdSet &externalInputs,
					     ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;
  
  if (!RelExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;
  
  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  //
  ValueIdSet availableValues;
  availableValues = getGroupAttr()->getCharacteristicInputs();

  const ValueIdSet &inputValues = getGroupAttr()->getCharacteristicInputs();
  getProcInputParamsVids().replaceVEGExpressions(availableValues, inputValues);
  generator->setAqrEnabled(FALSE);

  markAsPreCodeGenned();
  
  return this;
}

RelExpr * IsolatedNonTableUDR::preCodeGen (Generator * generator,
					     const ValueIdSet &externalInputs,
					     ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;
  
  if (!RelRoutine::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  // The VEG expressions in the selection predicates and the characteristic
  // outputs can reference any expression that is either a potential output
  // or a characteristic input for this RelExpr. Supply these values for
  // rewriting the VEG expressions.
  //
  ValueIdSet availableValues;
  availableValues = getGroupAttr()->getCharacteristicInputs();

  const ValueIdSet &inputValues = getGroupAttr()->getCharacteristicInputs();
  getNeededValueIds().replaceVEGExpressions(availableValues, inputValues);
  
  markAsPreCodeGenned();
  
  return this;
}

RelExpr * PhysicalTableMappingUDF::preCodeGen(Generator * generator,
                                              const ValueIdSet &externalInputs,
                                              ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;
  
  if (!RelRoutine::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);

  for(Int32 i = 0; i < getArity(); i++)
  {
    ValueIdList &childOutputs(getChildInfo(i)->getOutputIds());
    ValueIdList origChildOutputs(childOutputs);

    childOutputs.replaceVEGExpressions(
         availableValues,
         getGroupAttr()->getCharacteristicInputs());

    for (CollIndex j=0; j<childOutputs.entries(); j++)
      if (NOT(childOutputs[j].getType() == origChildOutputs[j].getType()))
        {
          // VEG rewrite changed the type.
          // Since we recorded the original type of the input
          // column and exposed this type to the UDF writer, don't
          // change the type now. Instead, add a cast back to the
          // original type.
          ItemExpr *castToOrigType = new(CmpCommon::statementHeap())
            Cast(childOutputs[j].getItemExpr(),
                 origChildOutputs[j].getType().newCopy());

          castToOrigType->synthTypeAndValueId();
          childOutputs[j] = castToOrigType->getValueId();
        }
  }

  planInfo_ = getPhysicalProperty()->getUDRPlanInfo();
  if (!getDllInteraction()->finalizePlan(this, planInfo_))
    return NULL;
  
  markAsPreCodeGenned();
  
  return this;
}

RelExpr * PhysicalFastExtract::preCodeGen (Generator * generator,
					     const ValueIdSet &externalInputs,
					     ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (getIsMainQueryOperator())
    generator->setIsFastExtract(TRUE);
  else
    generator->setContainsFastExtract(TRUE);

  if (!RelExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);

  getSelectListIds().replaceVEGExpressions(availableValues, externalInputs);

  if (isAppend())
    generator->setAqrEnabled(FALSE);

  // This relation is a linear fit to cpu consumption data observed during a 
  // performance run, while extracting data from the LINEITEM table. CPU Usage
  // can go from 0% to 50% according to this relation. CPU Usage is determined
  // by 2 factors (a) bytes of data extracted and (b) % non-character 
  // (termed numeric below) columns in each row (computed based on total max 
  // row size and tol non-char column size). Both factors have equal weigth, 
  // i.e. they can contribute at most 25% towards Cpu usage. For upto 50 GB
  // extracted data the bytes of extracted data increases linearly from 0% to
  // 25%. After 50 GB (total volume across all partitions), the contribution to
  // cpu usage from bytes extracted does not increase. Similarly the a table
  // all non-char columns can contribute upto 25% towards cpu usage. The numeric
  // factor is also weighted by the volume of data extracted.

  const Int32  plateauTabSizeInGB = 50;
  const float  weightOfBaseExtract = 0.5;
  const float  weightOfNumericExpressionEval = 0.5;
  const Int32  maxPossibleCpuUsage = 50 ; // in percentage units
  Int32 rowLength = child(0).getGroupAttr()->getCharacteristicOutputs().getRowLength();
  Int32 numericRowLength = child(0).getGroupAttr()->
			getCharacteristicOutputs().getRowLengthOfNumericCols();
  float numericRowLengthRatio = ((float) numericRowLength)/rowLength ;

  double bytesExtractedInGB = (getEstRowsUsed().value()*rowLength)/(1024*1024*1024);
  double bytesExtractedRatio = bytesExtractedInGB/plateauTabSizeInGB ;
  if (bytesExtractedRatio > 1)
	bytesExtractedRatio = 1;

  Int32 maxCpuUsage = (Int32) (maxPossibleCpuUsage*bytesExtractedRatio*(weightOfBaseExtract + 
                        (weightOfNumericExpressionEval*numericRowLengthRatio)));
  generator->setMaxCpuUsage(maxCpuUsage);

  markAsPreCodeGenned();

  return this;
}

RelExpr * RelLock::preCodeGen (Generator * generator,
			       const ValueIdSet &externalInputs,
			       ValueIdSet &pulledNewInputs)
{

  if (nodeIsPreCodeGenned())
    return this;

  // Since the newExch node is added as the parent
  // to SequenceGenerator node, this method gets
  // called again during the preCodeGen of t
  // newExch.
  if(parallelExecution_) 
    {
      // Add an exchange node here so this could be executed in ESP.
      RelExpr * exchange = new(generator->wHeap()) Exchange (this);
      exchange->setPhysicalProperty(this->getPhysicalProperty());
      exchange->setGroupAttr(this->getGroupAttr());
      
      markAsPreCodeGenned();

      exchange = exchange->preCodeGen(generator, externalInputs, pulledNewInputs);

      // Done.
      return exchange;

      /*
      RelExpr *newExch = 
	generator->insertEspExchange(this, getPhysicalProperty());
      
      ((Exchange *)newExch)->makeAnESPAccess();
      
      markAsPreCodeGenned();

      RelExpr * exch = 
	newExch->preCodeGen(generator, externalInputs, pulledNewInputs);
      
      return exch;
      */
    }
  
  if (!RelExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  markAsPreCodeGenned();

  return this;
}

RelExpr * StatisticsFunc::preCodeGen(Generator * generator,
				     const ValueIdSet & externalInputs,
				     ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! RelExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  // don't collect stats for stats func itself
  generator->setComputeStats(FALSE);

  markAsPreCodeGenned();

  // Done.
  return this;
}

RelExpr * ExeUtilGetStatistics::preCodeGen(Generator * generator,
					   const ValueIdSet & externalInputs,
					   ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! ExeUtilExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  // don't collect stats for stats func itself
  generator->setComputeStats(FALSE);

  markAsPreCodeGenned();

  // Done.
  return this;
}

RelExpr * ExeUtilWnrInsert::preCodeGen(Generator * generator,
                                   const ValueIdSet & externalInputs,
                                   ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! ExeUtilExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  markAsPreCodeGenned();

  return this;
}



ItemExpr * PositionFunc::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! BuiltinFunction::preCodeGen(generator))
    return NULL;

  const NAType &type1 =
    child(0)->castToItemExpr()->getValueId().getType();
  const NAType &type2 =
    child(1)->castToItemExpr()->getValueId().getType();
  
  CMPASSERT(
      (type1.getTypeQualifier() == NA_CHARACTER_TYPE) &&
      (type2.getTypeQualifier() == NA_CHARACTER_TYPE))
  
  const CharType &cType1 = (CharType&)type1;
  const CharType &cType2 = (CharType&)type2;

  CharInfo::Collation coll1 = cType1.getCollation();
  CharInfo::Collation coll2 = cType2.getCollation();

  CMPASSERT(coll1==coll2);

  setCollation(coll1);

  if (CollationInfo::isSystemCollation(coll1))
  {
    
    {
      ItemExpr * newEncode = 
	new(generator->wHeap()) 
	CompEncode(child(0),FALSE, -1, CollationInfo::Search);

      newEncode = newEncode->bindNode(generator->getBindWA());
      newEncode = newEncode->preCodeGen(generator);
      if (!newEncode)
	return NULL;
      setChild(0, newEncode);


      newEncode = 
	new(generator->wHeap()) 
	CompEncode(child(1), FALSE, -1,CollationInfo::Search);

      newEncode->bindNode(generator->getBindWA());
      newEncode = newEncode->preCodeGen(generator);
      if (!newEncode)
	return NULL;
      setChild(1, newEncode);
    }

  }

  markAsPreCodeGenned();
  return this;

} // PositionFunc::preCodeGen()


ItemExpr * Trim::preCodeGen(Generator * generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! BuiltinFunction::preCodeGen(generator))
    return NULL;

  const NAType &type1 =
    child(0)->castToItemExpr()->getValueId().getType();
  const NAType &type2 =
    child(1)->castToItemExpr()->getValueId().getType();
  
  CMPASSERT(
      (type1.getTypeQualifier() == NA_CHARACTER_TYPE) &&
      (type2.getTypeQualifier() == NA_CHARACTER_TYPE))
  
  const CharType &cType1 = (CharType&)type1;
  const CharType &cType2 = (CharType&)type2;

  CharInfo::Collation coll1 = cType1.getCollation();
  CharInfo::Collation coll2 = cType2.getCollation();

  CMPASSERT(coll1==coll2);

  setCollation(coll1);

  markAsPreCodeGenned();
  return this;

} // Trim::preCodeGen()

ItemExpr * NotIn::preCodeGen(Generator * generator)
{
  if (child(0)->getOperatorType() == ITM_ITEM_LIST)
  {//Multicolumn NotIn should not reach this far
    GenAssert(FALSE,"Multicolumn NotIn should not have reached this far");
    return NULL;
  }

  if (nodeIsPreCodeGenned())
  {
    return getReplacementExpr();
  }
  // if single column NOT IN reaches pre-code generation, then replace it with 
  // non equi-predicate form (NE)
  // An example of cases where NotIn reaches this far is a aquery like
  // select * from ta where (select sum(a2) from ta) not in (select b2 from tb);
  // where the NotIn predicate gets pushed down and is not caught at optimization 
  // time

  ValueId vid = createEquivNonEquiPredicate();

  ItemExpr * newPred = vid.getItemExpr();

  setReplacementExpr(newPred->preCodeGen(generator));
  markAsPreCodeGenned();

  return getReplacementExpr();


} // NotIn::preCodeGen()

short HbaseAccess::processSQHbaseKeyPreds(Generator * generator,
					  NAList<HbaseSearchKey*>& searchKeys,
					  ListOfUniqueRows &listOfUniqueRows,
					  ListOfRangeRows &listOfRangeRows)
{
  Int32 ct = 0;
  HbaseUniqueRows getSpec;
  getSpec.rowTS_ = -1;
  
  for (CollIndex i = 0; i<searchKeys.entries(); i++ ) 
    {
      HbaseSearchKey* searchKey = searchKeys[i];

      ValueIdSet newSelectionPreds;
      
      if ( searchKey->isUnique() ) 
	{
	  // Since we fill one rowId per entry, we will be using getRow() form of Get.
	  if ( (ct=searchKey->getCoveredLeadingKeys()) > 0 )
	    {
	      NAString result;
	      ValueIdList keyValues = searchKey->getBeginKeyValues();
	      
	      keyValues.convertToTextKey(searchKey->getKeyColumns(), result);
	      getSpec.rowIds_.insert(result);
	    } 
	  
	  //	  getSpec.addColumnNames(searchKey->getRequiredOutputColumns());
	} 
      else 
	{
	  // Multiple rows. Do Scan
	  HbaseRangeRows scanSpec;
	  scanSpec.beginKeyExclusive_ = FALSE;
	  scanSpec.endKeyExclusive_ = FALSE;
	  scanSpec.rowTS_ = -1;
	  
          if ((( !searchKey->areAllBeginKeysMissing() ) && 
	       ((ct=searchKey->getCoveredLeadingKeys()) > 0 )) ||
	      searchKey->isFalsePred())
	  {
	    ValueIdList beginKeyValues = searchKey->getBeginKeyValues();
	    beginKeyValues.convertToTextKey(searchKey->getKeyColumns(), 
					    scanSpec.beginRowId_);
	    scanSpec.beginKeyExclusive_ = 
              searchKey->isBeginKeyExclusive();
	  } 
	  
	  if ((( !searchKey->areAllEndKeysMissing() ) && 
	       (ct=searchKey->getCoveredLeadingKeys())) ||
	      searchKey->isFalsePred())
	  {
	    ValueIdList endKeyValues = searchKey->getEndKeyValues();
	    endKeyValues.convertToTextKey(searchKey->getKeyColumns(), 
					  scanSpec.endRowId_);
	    scanSpec.endKeyExclusive_ = searchKey->isEndKeyExclusive();
	  }  
	 
	  listOfRangeRows.insertAt(listOfRangeRows.entries(), scanSpec);
	}
    } // for
  
  if (getSpec.rowIds_.entries() > 0)
    listOfUniqueRows.insert(getSpec);
  
  return 0;
}

short HbaseAccess::processNonSQHbaseKeyPreds(Generator * generator,
				       ValueIdSet &preds,
				       ListOfUniqueRows &listOfUniqueRows,
				       ListOfRangeRows &listOfRangeRows)
{
  ValueId vid;
  ValueId eqRowIdValVid;
  ValueId eqColNameValVid;
  ItemExpr * ie = NULL;
  NABoolean rowIdFound = FALSE;
  NABoolean colNameFound = FALSE;
  NABoolean isConstParam = FALSE;

  ValueIdList newPredList;
  NABoolean addToNewPredList;
 
  HbaseUniqueRows hg;
  HbaseRangeRows hs;
 
  for (vid = preds.init(); 
       (preds.next(vid)); 
       preds.advance(vid))
    {
      ie = vid.getItemExpr();
      
      addToNewPredList = TRUE;
      ConstValue * constVal = NULL;
      if ((NOT rowIdFound) && (isEqGetExpr(ie, eqRowIdValVid, isConstParam, 
					   "ROW_ID")))
	{
	  rowIdFound = TRUE;
	  
	  if (isConstParam)
	    {
	      ConstantParameter*cp = (ConstantParameter*)eqRowIdValVid.getItemExpr();
	      constVal = cp->getConstVal();
	    }
	  else
	    constVal = (ConstValue*)eqRowIdValVid.getItemExpr();
	  NAString rid = *constVal->getRawText();
	  hg.rowIds_.insert(rid); 
	  
	  hg.rowTS_ = -1;
	  
	  addToNewPredList = FALSE;
	}
      
      if (isEqGetExpr(ie, eqColNameValVid, isConstParam, "COL_NAME"))
	{
	  colNameFound = TRUE;
	  
	  if (isConstParam)
	    {
	      ConstantParameter*cp = (ConstantParameter*)eqColNameValVid.getItemExpr();
	      constVal = cp->getConstVal();
	    }
	  else
	    constVal = (ConstValue*)eqColNameValVid.getItemExpr();
	  NAString col = *constVal->getRawText();
	  hg.colNames_.insert(col); 
	  hs.colNames_.insert(col);
	  
	  addToNewPredList = FALSE;
	}
      
      if (addToNewPredList)
	newPredList.insert(vid);
    } // for
  
  if ((rowIdFound) || (colNameFound))
    {
      preds.clear();
      preds.insertList(newPredList);
    }
  
  if (rowIdFound)
    {
      listOfUniqueRows.insert(hg);
    }
  else
    {
      hs.rowTS_ = -1;
      listOfRangeRows.insert(hs);
    }

  //  markAsPreCodeGenned();
  
  // Done.
  return 0;
}

////////////////////////////////////////////////////////////////////////////
// To push down, the predicate must have the following form:
//    <column>  <op>  <value-expr>
//
// and all of the following conditions must be met:
//
//      <column>:       a base table or index column which can be serialized.
//                            serialized: either the column doesn't need encoding, like
//                                            an unsigned integer,  or the column
//                                            was declared with the SERIALIZED option.
//      <op>:              eq, ne, gt, ge, lt, le
//      <value-expr>:  an expression that only contains const or param values, and
//                            <value-expr>'s datatype is not a superset of <column>'s datatype.
//
/////////////////////////////////////////////////////////////////////////////
NABoolean HbaseAccess::isHbaseFilterPred(Generator * generator, ItemExpr * ie,
					 ValueId &colVID, ValueId &valueVID,
					 NAString &op,
					 NABoolean &removeFromOrigList)
{
  NABoolean found = FALSE;
  removeFromOrigList = FALSE;
  NABoolean hbaseLookupPred = FALSE;
  NABoolean flipOp = FALSE;  // set to TRUE when column is child(1)

  if (ie && 
      ((ie->getOperatorType() >= ITM_EQUAL) &&
       (ie->getOperatorType() <= ITM_GREATER_EQ)))
    {
      ItemExpr * child0 = ie->child(0)->castToItemExpr();
      ItemExpr * child1 = ie->child(1)->castToItemExpr();
      
      if ((ie->child(0)->getOperatorType() == ITM_BASECOLUMN) &&
	  (NOT hasColReference(ie->child(1))))
	{
	  found = TRUE;
	  colVID = ie->child(0)->getValueId();
	  valueVID = ie->child(1)->getValueId();
	}
      else if ((ie->child(1)->getOperatorType() == ITM_BASECOLUMN) &&
	       (NOT hasColReference(ie->child(0))))
	{
	  found = TRUE;
          flipOp = TRUE;
	  colVID = ie->child(1)->getValueId();
	  valueVID = ie->child(0)->getValueId();
	}
      else if ((ie->child(0)->getOperatorType() == ITM_INDEXCOLUMN) &&
	       (NOT hasColReference(ie->child(1))))
	{
	  found = TRUE;
	  colVID = ie->child(0)->getValueId();
	  valueVID = ie->child(1)->getValueId();
	}
      else if ((ie->child(1)->getOperatorType() == ITM_INDEXCOLUMN) &&
	       (NOT hasColReference(ie->child(0))))
	{
	  found = TRUE;
          flipOp = TRUE;
	  colVID = ie->child(1)->getValueId();
	  valueVID = ie->child(0)->getValueId();
	}
      else if ((ie->child(0)->getOperatorType() == ITM_REFERENCE) &&
	       (NOT hasColReference(ie->child(1))))
	{
	  found = TRUE;
	  colVID = ie->child(0)->getValueId();
	  valueVID = ie->child(1)->getValueId();
	}
      else if ((ie->child(1)->getOperatorType() == ITM_REFERENCE) &&
	       (NOT hasColReference(ie->child(0))))
	{
	  found = TRUE;
          flipOp = TRUE;
	  colVID = ie->child(1)->getValueId();
	  valueVID = ie->child(0)->getValueId();
	}
      else if ((ie->child(0)->getOperatorType() == ITM_HBASE_COLUMN_LOOKUP) &&
	       (NOT hasColReference(ie->child(1))))
	{
	  HbaseColumnLookup * hcl = (HbaseColumnLookup*)ie->child(0)->castToItemExpr();
	  if (hcl->getValueId().getType().getTypeQualifier() == NA_CHARACTER_TYPE)
	    {
	      hbaseLookupPred = TRUE;

	      ItemExpr * newCV = new(generator->wHeap()) ConstValue(hcl->hbaseCol());
	      newCV = newCV->bindNode(generator->getBindWA());
	      newCV = newCV->preCodeGen(generator);
	      
	      found = TRUE;
	      colVID = newCV->getValueId();
	      valueVID = ie->child(1)->getValueId();
	    }
	}
      else if ((ie->child(1)->getOperatorType() == ITM_HBASE_COLUMN_LOOKUP) &&
	       (NOT hasColReference(ie->child(0))))
	{
	  HbaseColumnLookup * hcl = (HbaseColumnLookup*)ie->child(1)->castToItemExpr();
	  if (hcl->getValueId().getType().getTypeQualifier() == NA_CHARACTER_TYPE)
	    {
	      hbaseLookupPred = TRUE;

	      ItemExpr * newCV = new(generator->wHeap()) ConstValue(hcl->hbaseCol());
	      newCV = newCV->bindNode(generator->getBindWA());
	      newCV = newCV->preCodeGen(generator);
	      
	      found = TRUE;
              flipOp = TRUE;
	      colVID = newCV->getValueId();
	      valueVID = ie->child(0)->getValueId();
	    }
	}
    }

  if (found)
    {
      const NAType &colType = colVID.getType();
      const NAType &valueType = valueVID.getType();

      NABoolean generateNarrow = FALSE;
      if (NOT hbaseLookupPred)
	{
	  generateNarrow = valueType.errorsCanOccur(colType);
	  if ((generateNarrow)  || // value not a superset of column
	      (NOT columnEnabledForSerialization(colVID.getItemExpr())))
	    found = FALSE;
	}

      if (found)
	{
	  if (colType.getTypeQualifier() == NA_CHARACTER_TYPE)
	    {
	      const CharType &charColType = (CharType&)colType;
	      const CharType &charValType = (CharType&)valueType;
	      
	      if ((charColType.isCaseinsensitive() || charValType.isCaseinsensitive()) ||
		  (charColType.isUpshifted() || charValType.isUpshifted()))
		found = FALSE;
	    }
	  else if (colType.getTypeQualifier() == NA_NUMERIC_TYPE)
	    {
	      const NumericType &numType = (NumericType&)colType;
	      const NumericType &valType = (NumericType&)valueType;
	      if (numType.isBigNum() || valType.isBigNum())
		found = FALSE;
	    }
	}

      if (found)
	{
	  if ((ie) && (((BiRelat*)ie)->addedForLikePred()) &&
	      (valueVID.getItemExpr()->getOperatorType() == ITM_CONSTANT))
	    {
	      // remove trailing '\0' characters since this is being pushed down to hbase.
	      ConstValue * cv = (ConstValue*)(valueVID.getItemExpr());
	      char * cvv = (char*)cv->getConstValue();
	      Lng32 len = cv->getStorageSize() - 1;
	      while ((len > 0) && (cvv[len] == '\0'))
		len--;

	      NAString newCVV(cvv, len+1);

	      ItemExpr * newCV = new(generator->wHeap()) ConstValue(newCVV);
	      newCV = newCV->bindNode(generator->getBindWA());
	      newCV = newCV->preCodeGen(generator);
	      valueVID = newCV->getValueId();
	    }

	  ItemExpr * castValue = NULL;
          if (NOT hbaseLookupPred)
            castValue = new(generator->wHeap()) Cast(valueVID.getItemExpr(), &colType);
          else
            {
              castValue = new(generator->wHeap()) Cast(valueVID.getItemExpr(), &valueVID.getType());
            }

	  if ((NOT hbaseLookupPred) &&
	      (isEncodingNeededForSerialization(colVID.getItemExpr())))
	    {
	      castValue = new(generator->wHeap()) CompEncode
		(castValue, FALSE, -1, CollationInfo::Sort, TRUE, FALSE);
	    }

	  castValue = castValue->bindNode(generator->getBindWA());
	  castValue = castValue->preCodeGen(generator);
	  
	  valueVID = castValue->getValueId();

	  // hbase pred evaluation compares the column byte string with the
	  // value byte string. It doesn't have a notion of nullability.
	  // For a nullable value stored in database, the first byte represents
	  // if the value is a null value.
	  // During pred evaluation in hbase, a null value could either get filtered
	  // out due to byte string comparison, or it may get returned back.
	  // For ex,   <col>  <gt>  <value>
	  //      will return TRUE if the first byte of <col> is a null value.
	  //      Similary, <col> <lt> <value> 
	  //      will return FALSE if the first byte of <col> is a null value.
	  // If the a null value gets filtered out, then that is correct semantics.
	  // But if the null value gets returned to executor, then it still need to be
	  // filtered out. To do that, the predicate need to be evaluated in executor
	  // with proper null semantics.
	  //
	  // Long story short, do not remove the original pred if the col or value is
	  // nullable.
	  //   
	  if ((colType.supportsSQLnull()) ||
	      (valueType.supportsSQLnull()))
	    {
	      removeFromOrigList = FALSE;
	    }
	  else
	    {
	      removeFromOrigList = TRUE;
	    }

	  if (ie->getOperatorType() == ITM_EQUAL)
	    op = "EQUAL";
	  else  if (ie->getOperatorType() == ITM_NOT_EQUAL)
	    op = "NOT_EQUAL";
	  else  if (ie->getOperatorType() == ITM_LESS)
            {
            if (flipOp)
              op = "GREATER";
            else
	      op = "LESS";
            }
	  else  if (ie->getOperatorType() == ITM_LESS_EQ)
            {
            if (flipOp)
              op = "GREATER_OR_EQUAL";
            else
	      op = "LESS_OR_EQUAL";
            }
	  else  if (ie->getOperatorType() == ITM_GREATER)
            {
            if (flipOp)
              op = "LESS";
            else
	      op = "GREATER";
            }
	  else  if (ie->getOperatorType() == ITM_GREATER_EQ)
            {
            if (flipOp)
              op = "LESS_OR_EQUAL";
            else
	      op = "GREATER_OR_EQUAL";
            }
	  else
	    op = "NO_OP";
	}
    }

  return found;
}

short HbaseAccess::extractHbaseFilterPreds(Generator * generator, 
					   ValueIdSet &preds, ValueIdSet &newExePreds)
{
   if (CmpCommon::getDefault(HBASE_FILTER_PREDS) == DF_OFF)
       return 0;
   // cannot push preds for aligned format row
   NABoolean isAlignedFormat = getTableDesc()->getNATable()->isAlignedFormat(getIndexDesc());

   if (isAlignedFormat)
     return 0;
  
   for (ValueId vid = preds.init(); 
       (preds.next(vid)); 
       preds.advance(vid))
    {
      ItemExpr * ie = vid.getItemExpr();
      ValueId colVID;
      ValueId valueVID;
      NABoolean removeFromOrigList = FALSE;
      NAString op;
      NABoolean isHFP =
        isHbaseFilterPred(generator, ie, colVID, valueVID, op, removeFromOrigList);
      
      if (isHFP) 
        {
          hbaseFilterColVIDlist_.insert(colVID);
          hbaseFilterValueVIDlist_.insert(valueVID);
          
          opList_.insert(op);
          
          if (NOT removeFromOrigList)
            newExePreds.insert(vid);
        }
      else 
        {
          newExePreds.insert(vid);
        }
      
    } // end for
  
  return 0;
}

////////////////////////////////////////////////////////////////////////////
// To push down, the predicate must have the following form:
//  xp:=  <column>  <op>  <value-expr>
//  xp:=  <column> is not null (no support for hbase lookup)
//  xp:=  <column> is null (no support for hbase lookup)
//    (xp:=<column> like <value-expr> not yet implemented)
//  xp:=<xp> OR <xp> (not evaluated in isHbaseFilterPredV2, but by extractHbaseFilterPredV2)
//  xp:=<xp> AND <xp>(not evaluated in isHbaseFilterPredV2, but by extractHbaseFilterPredV2)
//
// and all of the following conditions must be met:
//
//      <column>:       a base table or index column which can be serialized and belong to the table being scanned.
//                            serialized: either the column doesn't need encoding, like
//                                            an unsigned integer,  or the column
//                                            was declared with the SERIALIZED option.
//                      it also must not be an added column with default non null.
//      <op>:              eq, ne, gt, ge, lt, le
//      <value-expr>:  an expression that only contains const or param values, and
//                     <value-expr>'s datatype is not a superset of <column>'s datatype.
//
// colVID, valueID and op are output parameters.
/////////////////////////////////////////////////////////////////////////////
NABoolean HbaseAccess::isHbaseFilterPredV2(Generator * generator, ItemExpr * ie,
                     ValueId &colVID, ValueId &valueVID,
                     NAString &op)
{
  NABoolean foundBinary = FALSE;
  NABoolean foundUnary = FALSE;
  NABoolean hbaseLookupPred = FALSE;
  NABoolean flipOp = FALSE;  // set to TRUE when column is child(1)

  if (ie &&
      ((ie->getOperatorType() >= ITM_EQUAL) &&
       (ie->getOperatorType() <= ITM_GREATER_EQ))) //binary operator case
    {//begin expression
      ItemExpr * child0 = ie->child(0)->castToItemExpr();
      ItemExpr * child1 = ie->child(1)->castToItemExpr();

      if ((ie->child(0)->getOperatorType() == ITM_BASECOLUMN) &&
      (NOT hasColReference(ie->child(1))))
    {
      foundBinary = TRUE;
      colVID = ie->child(0)->getValueId();
      valueVID = ie->child(1)->getValueId();
    }
      else if ((ie->child(1)->getOperatorType() == ITM_BASECOLUMN) &&
           (NOT hasColReference(ie->child(0))))
    {
      foundBinary = TRUE;
      flipOp = TRUE;
      colVID = ie->child(1)->getValueId();
      valueVID = ie->child(0)->getValueId();
    }
      else if ((ie->child(0)->getOperatorType() == ITM_INDEXCOLUMN) &&
           (NOT hasColReference(ie->child(1))))
    {
      foundBinary = TRUE;
      colVID = ie->child(0)->getValueId();
      valueVID = ie->child(1)->getValueId();
    }
      else if ((ie->child(1)->getOperatorType() == ITM_INDEXCOLUMN) &&
           (NOT hasColReference(ie->child(0))))
    {
      foundBinary = TRUE;
      flipOp = TRUE;
      colVID = ie->child(1)->getValueId();
      valueVID = ie->child(0)->getValueId();
    }
      else if ((ie->child(0)->getOperatorType() == ITM_HBASE_COLUMN_LOOKUP) &&
           (NOT hasColReference(ie->child(1))))
    {
      HbaseColumnLookup * hcl = (HbaseColumnLookup*)ie->child(0)->castToItemExpr();
      if (hcl->getValueId().getType().getTypeQualifier() == NA_CHARACTER_TYPE)
        {
          hbaseLookupPred = TRUE;

          ItemExpr * newCV = new(generator->wHeap()) ConstValue(hcl->hbaseCol());
          newCV = newCV->bindNode(generator->getBindWA());
          newCV = newCV->preCodeGen(generator);

          foundBinary = TRUE;
          colVID = newCV->getValueId();
          valueVID = ie->child(1)->getValueId();
        }
    }
      else if ((ie->child(1)->getOperatorType() == ITM_HBASE_COLUMN_LOOKUP) &&
           (NOT hasColReference(ie->child(0))))
    {
      HbaseColumnLookup * hcl = (HbaseColumnLookup*)ie->child(1)->castToItemExpr();
      if (hcl->getValueId().getType().getTypeQualifier() == NA_CHARACTER_TYPE)
        {
          hbaseLookupPred = TRUE;

          ItemExpr * newCV = new(generator->wHeap()) ConstValue(hcl->hbaseCol());
          newCV = newCV->bindNode(generator->getBindWA());
          newCV = newCV->preCodeGen(generator);

          foundBinary = TRUE;
          flipOp = TRUE;
          colVID = newCV->getValueId();
          valueVID = ie->child(0)->getValueId();
        }
    }
    }//end binary operators
  else if (ie && ((ie->getOperatorType() == ITM_IS_NULL)||(ie->getOperatorType() == ITM_IS_NOT_NULL))){//check for unary operators
      ItemExpr * child0 = ie->child(0)->castToItemExpr();
      if ((ie->child(0)->getOperatorType() == ITM_BASECOLUMN) ||
          (ie->child(0)->getOperatorType() == ITM_INDEXCOLUMN)){
          foundUnary = TRUE;
          colVID = ie->child(0)->getValueId();
          valueVID = NULL_VALUE_ID;
      }

  }//end unary operators

  //check if found columns belong to table being scanned (so is not an input to the scan node)
  if (foundBinary || foundUnary){
    ValueId dummyValueId;
    if (getGroupAttr()->getCharacteristicInputs().referencesTheGivenValue(colVID,dummyValueId)){
        foundBinary=FALSE;
        foundUnary=FALSE;
    }
  }
  //check if not an added column with default non null
  if ((foundBinary || foundUnary)&& (NOT hbaseLookupPred)){
        if (colVID.isColumnWithNonNullNonCurrentDefault()){
            foundBinary=FALSE;
            foundUnary=FALSE;
        }
  }

  if (foundBinary)
    {
      const NAType &colType = colVID.getType();
      const NAType &valueType = valueVID.getType();

      NABoolean generateNarrow = FALSE;
      if (NOT hbaseLookupPred)
    {
      generateNarrow = valueType.errorsCanOccur(colType);
      if ((generateNarrow)  || // value not a superset of column
          (NOT columnEnabledForSerialization(colVID.getItemExpr())))
          foundBinary = FALSE;
    }

      if (foundBinary)
    {
      if (colType.getTypeQualifier() == NA_CHARACTER_TYPE)
        {
          const CharType &charColType = (CharType&)colType;
          const CharType &charValType = (CharType&)valueType;

          if ((charColType.isCaseinsensitive() || charValType.isCaseinsensitive()) ||
          (charColType.isUpshifted() || charValType.isUpshifted()))
         foundBinary = FALSE;
        }
      else if (colType.getTypeQualifier() == NA_NUMERIC_TYPE)
        {
          const NumericType &numType = (NumericType&)colType;
          const NumericType &valType = (NumericType&)valueType;
          if (numType.isBigNum() || valType.isBigNum())
         foundBinary = FALSE;
        }
    }

      if (foundBinary)
    {
      if ((ie) && (((BiRelat*)ie)->addedForLikePred()) &&
          (valueVID.getItemExpr()->getOperatorType() == ITM_CONSTANT))
        {
          // remove trailing '\0' characters since this is being pushed down to hbase.
          ConstValue * cv = (ConstValue*)(valueVID.getItemExpr());
          char * cvv = (char*)cv->getConstValue();
          Lng32 len = cv->getStorageSize() - 1;
          while ((len > 0) && (cvv[len] == '\0'))
            len--;

          NAString newCVV(cvv, len+1);

          ItemExpr * newCV = new(generator->wHeap()) ConstValue(newCVV);
          newCV = newCV->bindNode(generator->getBindWA());
          newCV = newCV->preCodeGen(generator);
          valueVID = newCV->getValueId();
        }

      ItemExpr * castValue = NULL;
          if (NOT hbaseLookupPred)
            castValue = new(generator->wHeap()) Cast(valueVID.getItemExpr(), &colType);
          else
            {
              castValue = new(generator->wHeap()) Cast(valueVID.getItemExpr(), &valueVID.getType());
            }

      if ((NOT hbaseLookupPred) &&
          (isEncodingNeededForSerialization(colVID.getItemExpr())))
        {
          castValue = new(generator->wHeap()) CompEncode
        (castValue, FALSE, -1, CollationInfo::Sort, TRUE, FALSE);
        }

      castValue = castValue->bindNode(generator->getBindWA());
      castValue = castValue->preCodeGen(generator);

      valueVID = castValue->getValueId();

      NAString nullType;

      if ((colType.supportsSQLnull()) ||
          (valueType.supportsSQLnull()))
        {
          nullType = "_NULL";
        }
      else
        {
          nullType = "";
        }

      // append -NULL to the operator to signify the java code generating pushdown filters to handle NULL semantic logic
      if (ie->getOperatorType() == ITM_EQUAL)
          op = "EQUAL"+nullType;
      else  if (ie->getOperatorType() == ITM_NOT_EQUAL)
        op = "NOT_EQUAL"+nullType;
      else  if (ie->getOperatorType() == ITM_LESS){
          if (flipOp)
              op = "GREATER"+nullType;
          else
              op = "LESS"+nullType;
      }
      else  if (ie->getOperatorType() == ITM_LESS_EQ){
          if (flipOp)
              op = "GREATER_OR_EQUAL"+nullType;
          else
              op = "LESS_OR_EQUAL"+nullType;
      }else  if (ie->getOperatorType() == ITM_GREATER){
          if (flipOp)
              op = "LESS"+nullType;
          else
              op = "GREATER"+nullType;
      }else  if (ie->getOperatorType() == ITM_GREATER_EQ){
          if (flipOp)
              op = "LESS_OR_EQUAL"+nullType;
          else
              op = "GREATER_OR_EQUAL"+nullType;
      }else
        op = "NO_OP"+nullType;
    }
    }
  if (foundUnary){
      const NAType &colType = colVID.getType();
      NAString nullType;

      if (colType.supportsSQLnull())
        {
          nullType = "_NULL";
        }
      else
        {
          nullType = "";
        }
      if (ie->getOperatorType() == ITM_IS_NULL)
              op = "IS_NULL"+nullType;
      else if (ie->getOperatorType() == ITM_IS_NOT_NULL)
              op = "IS_NOT_NULL"+nullType;
  }

  return foundBinary || foundUnary;
}
short HbaseAccess::extractHbaseFilterPredsVX(Generator * generator,
           ValueIdSet &preds, ValueIdSet &newExePreds){
    //separate the code that should not belong in the recursive function
       if (CmpCommon::getDefault(HBASE_FILTER_PREDS) == DF_OFF)
        return 0;
       // check if initial (version 1) implementation
       if (CmpCommon::getDefault(HBASE_FILTER_PREDS) == DF_MINIMUM)
        return extractHbaseFilterPreds(generator,preds,newExePreds);

       // if here, we are DF_MEDIUM
       // cannot push preds for aligned format row
       NABoolean isAlignedFormat = getTableDesc()->getNATable()->isAlignedFormat(getIndexDesc());

       if (isAlignedFormat)
         return 0;
       //recursive function call
       opList_.insert("V2");//to instruct the java side that we are dealing with predicate pushdown V2 semantic, add "V2" marker
       extractHbaseFilterPredsV2(generator,preds,newExePreds,FALSE);
       return 0;

}

// return true if successfull push down of node
NABoolean HbaseAccess::extractHbaseFilterPredsV2(Generator * generator,
                       ValueIdSet &preds, ValueIdSet &newExePreds, NABoolean checkOnly)
{

    // the isFirstAndLayer is used to allow detecting top level predicate that can still be pushed to executor
    int addedNode=0;
    for (ValueId vid = preds.init();
       (preds.next(vid));
       preds.advance(vid))
    {
      ItemExpr * ie = vid.getItemExpr();

      // if it is AND operation, recurse through left and right children
      if (ie->getOperatorType() == ITM_AND){
          ValueIdSet leftPreds;
          ValueIdSet rightPreds;
          leftPreds += ie->child(0)->castToItemExpr()->getValueId();
          rightPreds += ie->child(1)->castToItemExpr()->getValueId();
          //cannot be first AND layer, both left and right must be pushable to get anything pushed
          if(extractHbaseFilterPredsV2(generator, leftPreds, newExePreds, TRUE)&&
             extractHbaseFilterPredsV2(generator, rightPreds, newExePreds, TRUE)){// both left and right child must match
              if(!checkOnly){
                  extractHbaseFilterPredsV2(generator, leftPreds, newExePreds, FALSE);//generate tree
                  extractHbaseFilterPredsV2(generator, rightPreds, newExePreds, FALSE);//generate tree
                  opList_.insert("AND");
              }
            if (preds.entries()==1)
                return TRUE;
          }
          else{
              if(!checkOnly){
                  newExePreds.insert(vid);
              }
              if (preds.entries()==1)
                    return FALSE;
          }
          continue;
          // the OR case is easier, as we don t have the case of top level expression that can still be pushed to executor
      }//end if AND
      else if(ie->getOperatorType() == ITM_OR){
          ValueIdSet leftPreds;
          ValueIdSet rightPreds;
          leftPreds += ie->child(0)->castToItemExpr()->getValueId();
          rightPreds += ie->child(1)->castToItemExpr()->getValueId();
          //both left and right must be pushable to get anything pushed
          if(extractHbaseFilterPredsV2(generator, leftPreds, newExePreds, TRUE)&&
             extractHbaseFilterPredsV2(generator, rightPreds, newExePreds, TRUE)){// both left and right child must match
              if(!checkOnly){
                  extractHbaseFilterPredsV2(generator, leftPreds, newExePreds, FALSE);//generate tree
                  extractHbaseFilterPredsV2(generator, rightPreds, newExePreds, FALSE);//generate tree
                  opList_.insert("OR");
                  if (addedNode>0)opList_.insert("AND"); // if it is not the first node add to the push down, AND it with the rest
                  addedNode++; // we just pushed it down, so increase the node count pushed down.
              }
              if (preds.entries()==1)
               return TRUE;
          }
          else{// if predicate cannot be pushed down
              if(!checkOnly){
                  newExePreds.insert(vid);
              }
              if (preds.entries()==1)
                    return FALSE;
          }
          continue;
      }//end if OR

      ValueId colVID;
      ValueId valueVID;

      NAString op;
      NABoolean isHFP =
        isHbaseFilterPredV2(generator, ie, colVID, valueVID, op);

      if (isHFP && !checkOnly){// if pushable, push it
          hbaseFilterColVIDlist_.insert(colVID);
          if (valueVID != NULL_VALUE_ID) hbaseFilterValueVIDlist_.insert(valueVID);// don't insert valueID for unary operators.
          opList_.insert(op);
          if (addedNode>0)opList_.insert("AND"); // if it is not the first node add to the push down, AND it with the rest
          addedNode++; // we just pushed it down, so increase the node count pushed down.
        }else if (!checkOnly){//if not pushable, pass it for executor evaluation.
            newExePreds.insert(vid);
        }
      if (preds.entries()==1){
          return isHFP; // if we are not on the first call level, where we can have multiple preds, exit returning the pushability
      }

    } // end for

  return TRUE;//don't really care, means we are top level.
}


void HbaseAccess::computeRetrievedCols()
{
  GroupAttributes     fakeGA;
  ValueIdSet          requiredValueIds(getGroupAttr()->
				       getCharacteristicOutputs());
  ValueIdSet          coveredExprs;

  // ---------------------------------------------------------------------
  // Make fake group attributes with all inputs that are available to
  // the file scan node and with no "native" values.
  // Then call the "coverTest" method, offering it all the index columns
  // as additional inputs. "coverTest" will mark those index columns that
  // it actually needs to satisfy the required value ids, and that is
  // what we actually want. The actual cover test should always succeed,
  // otherwise the FileScan node would have been inconsistent.
  // ---------------------------------------------------------------------

  fakeGA.addCharacteristicInputs(getGroupAttr()->getCharacteristicInputs());
  requiredValueIds += selectionPred();
  requiredValueIds += executorPred();

  fakeGA.coverTest(requiredValueIds,              // char outputs + preds
		   getIndexDesc()->getIndexColumns(), // all index columns
		   coveredExprs,                  // dummy parameter
		   retrievedCols());               // needed index cols

  //
  // *** This CMPASSERT goes off sometimes, indicating an actual problem.
  // Hans has agreed to look into it (10/18/96) but I (brass) am
  // commenting it out for now, for sake of my time in doing a checking.
  //
  //  CMPASSERT(coveredExprs == requiredValueIds);

}

RelExpr * HbaseAccess::preCodeGen(Generator * generator,
				  const ValueIdSet & externalInputs,
				  ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  const PartitioningFunction* myPartFunc = getPartFunc();

  // use const HBase keys only if we don't have to add
  // partitioning key predicates
  if ( myPartFunc == NULL ||
       !myPartFunc->isPartitioned() ||
       myPartFunc->isAReplicationPartitioningFunction())
    if (!processConstHBaseKeys(
           generator,
           this,
           getSearchKey(),
           getIndexDesc(),
           executorPred(),
           getHbaseSearchKeys(),
           listOfUniqueRows_,
           listOfRangeRows_))
      return NULL;

  if (! FileScan::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  //compute isUnique:
  NABoolean isUnique = FALSE;
  if (listOfRangeRows_.entries() == 0)
    {
      if ((searchKey() && searchKey()->isUnique()) &&
    (listOfUniqueRows_.entries() == 0))
  isUnique = TRUE;
      else if ((NOT (searchKey() && searchKey()->isUnique())) &&
         (listOfUniqueRows_.entries() == 1) &&
         (listOfUniqueRows_[0].rowIds_.entries() == 1))
  isUnique = TRUE;
    }

  // executorPred() contains an ANDed list of predicates.
  // if hbase filter preds are enabled, then extracts those preds from executorPred()
  // which could be pushed down to hbase.
  // Do this only for non-unique scan access.
  ValueIdSet newExePreds;
  ValueIdSet* originExePreds = new (generator->wHeap())ValueIdSet(executorPred()) ;//saved for futur nullable column check

  if (CmpCommon::getDefault(HBASE_FILTER_PREDS) != DF_MINIMUM){ // the check for V2 and above is moved up before calculating retrieved columns
      if ((NOT isUnique) &&
          (extractHbaseFilterPredsVX(generator, executorPred(), newExePreds)))
        return this;

      // if some filter preds were found, then initialize executor preds with new exe preds.
      // newExePreds may be empty which means that all predicates were changed into
      // hbase preds. In this case, nuke existing exe preds.
      if (hbaseFilterColVIDlist_.entries() > 0)
        setExecutorPredicates(newExePreds);
  }

  ValueIdSet colRefSet;

  computeRetrievedCols();
  for (ValueId valId = retrievedCols().init();
       retrievedCols().next(valId);
       retrievedCols().advance(valId))
    {
      ValueId dummyValId;
      if ((valId.getItemExpr()->getOperatorType() != ITM_CONSTANT) &&
	  (getGroupAttr()->getCharacteristicOutputs().referencesTheGivenValue(valId, dummyValId)))
	colRefSet.insert(valId);
    }

  if (getTableDesc()->getNATable()->isHbaseCellTable())
    {
      for (Lng32 i = 0; i < getIndexDesc()->getIndexColumns().entries(); i++)
	{
	  //	  retColRefSet_.insert(getIndexDesc()->getIndexColumns()[i]);
	}
    }
  else if (getTableDesc()->getNATable()->isHbaseRowTable())
    {
      NASet<NAString> * hbaseColNameSet = 
	generator->getBindWA()->hbaseColUsageInfo()->hbaseColNameSet
	((QualifiedName*)&getTableDesc()->getNATable()->getTableName());

      NABoolean starFound = FALSE;
      for (Lng32 ij = 0; ij < hbaseColNameSet->entries(); ij++)
	{
	  NAString &colName = (*hbaseColNameSet)[ij];

	  retHbaseColRefSet_.insert(colName);

	  if (colName == "*")
	    starFound = TRUE;
	}

      if (starFound)
	retHbaseColRefSet_.clear();
    }
  else
    {
      // create the list of columns that need to be retrieved from hbase .
      // first add all columns referenced in the executor pred.
      HbaseAccess::addReferenceFromVIDset(executorPred(), TRUE, TRUE, colRefSet);


      HbaseAccess::addReferenceFromVIDset
        (getGroupAttr()->getCharacteristicOutputs(), TRUE, TRUE, colRefSet);

      for (ValueId valId = colRefSet.init();
	   colRefSet.next(valId);
	   colRefSet.advance(valId))
	{
	  ValueId dummyValId;
	  if (NOT getGroupAttr()->getCharacteristicInputs().referencesTheGivenValue(valId, dummyValId))
            {
              retColRefSet_.insert(valId);

              if (valId.getItemExpr()->getOperatorType() == ITM_HBASE_TIMESTAMP)
                {
                  Lng32 colNumber = ((BaseColumn*)((HbaseTimestamp*)valId.getItemExpr())->col())->getColNumber();
                  ValueId colVID = getIndexDesc()->getIndexColumns()[colNumber];
                  retColRefSet_.insert(colVID);
                }

              if (valId.getItemExpr()->getOperatorType() == ITM_HBASE_VERSION)
                {
                  Lng32 colNumber = ((BaseColumn*)((HbaseVersion*)valId.getItemExpr())->col())->getColNumber();
                  ValueId colVID = getIndexDesc()->getIndexColumns()[colNumber];
                  retColRefSet_.insert(colVID);
                }

            }
        }

      // add key columns. If values are missing in hbase, then atleast the key
      // value is needed to retrieve a row.
      //only if needed. If there is already a non nullable non added non nullable with default columns in the set, we should not need to add
      //any other columns.
      if (CmpCommon::getDefault(HBASE_FILTER_PREDS) == DF_MEDIUM && getMdamKeyPtr() == NULL){ //only enable column retrieval optimization with DF_MEDIUM and not for MDAM scan
          bool needAddingNonNullableColumn = true; //assume we need to add one non nullable column
          for (ValueId vid = retColRefSet_.init();// look for each column in th eresult set if one match the criteria non null non added non nullable with default
                  retColRefSet_.next(vid);
                  retColRefSet_.advance(vid))
          {
            if (originExePreds->isNotNullable(vid)){// it is non nullable
                OperatorTypeEnum operatorType = vid.getItemExpr()->getOperatorType();
                if ((operatorType == ITM_BASECOLUMN || operatorType == ITM_INDEXCOLUMN) && !vid.isColumnWithNonNullNonCurrentDefault()){//check if with non null or non current default... notgood
                    needAddingNonNullableColumn = false; // we found one column meeting all criteria
                    break;
                }
            }
          }
          if (needAddingNonNullableColumn){ // ok now we need to add one key column that is not nullable
              bool foundAtLeastOneKeyColumnNotNullable = false;
              for(int i=getIndexDesc()->getIndexKey().entries()-1; i>=0;i--)// doing reverse search is making sure we are trying to avoid to use _SALT_ column
                                                                         // because _SALT_ is physicaly the last column therefore we don't skip columns optimally if using _SALT_ column
              {
                  ValueId vaId = getIndexDesc()->getIndexKey()[i];
                  if ( (vaId.getItemExpr()->getOperatorType() == ITM_BASECOLUMN && !((BaseColumn*)vaId.getItemExpr())->getNAColumn()->getType()->supportsSQLnullPhysical())||
                          (vaId.getItemExpr()->getOperatorType() == ITM_INDEXCOLUMN && !((IndexColumn*)vaId.getItemExpr())->getNAColumn()->getType()->supportsSQLnullPhysical())
                          ){ //found good key column candidate?
                      HbaseAccess::addReferenceFromItemExprTree(vaId.getItemExpr(),TRUE,FALSE,retColRefSet_); // add it
                      foundAtLeastOneKeyColumnNotNullable = true; //tag we found it
                      break; // no need to look further
                  }
              }
              if (!foundAtLeastOneKeyColumnNotNullable){//oh well, did not find any key column non nullable, let s add all key columns
                  HbaseAccess::addColReferenceFromVIDlist(getIndexDesc()->getIndexKey(), retColRefSet_);
              }
          }
      }else //end if DF_MEDIUM
          HbaseAccess::addColReferenceFromVIDlist(getIndexDesc()->getIndexKey(), retColRefSet_);
    }

  if ((getMdamKeyPtr()) &&
      ((listOfRangeRows_.entries() > 0) ||
       (listOfUniqueRows_.entries() > 0)))
    {
      GenAssert(0, "listOfRange/Unique cannot be used if mdam is chosen.");

      return NULL;
    }

  // flag for both hive and hbase tables
  generator->setHdfsAccess(TRUE);

  if (!isUnique)
      generator->oltOptInfo()->setMultipleRowsReturned(TRUE) ;

  // Do not allow cancel of unique queries but allow cancel of queries 
  // that are part of a rowset operation. 
  if ((isUnique) &&
      (NOT generator->oltOptInfo()->multipleRowsReturned()))
    {
      generator->setMayNotCancel(TRUE);
      uniqueHbaseOper() = TRUE;
    }
  else
    {
      generator->oltOptInfo()->setOltCliOpt(FALSE);

      if (isUnique)
	{
	  if ((CmpCommon::getDefault(HBASE_ROWSET_VSBB_OPT) == DF_ON) &&
	      (NOT generator->isRIinliningForTrafIUD()) &&
	      (searchKey() && searchKey()->isUnique()))
	    {
	      uniqueRowsetHbaseOper() = TRUE;
	    }
	}
    }

  // executorPred() contains an ANDed list of predicates.
  // if hbase filter preds are enabled, then extracts those preds from executorPred()
  // which could be pushed down to hbase.
  // Do this only for non-unique scan access.
  if (CmpCommon::getDefault(HBASE_FILTER_PREDS) == DF_MINIMUM){ //keep the check for pushdown after column retrieval for pushdown V1.
    if ((NOT isUnique) &&
        (extractHbaseFilterPreds(generator, executorPred(), newExePreds)))
      return this;

  // if some filter preds were found, then initialize executor preds with new exe preds.
  // newExePreds may be empty which means that all predicates were changed into
  // hbase preds. In this case, nuke existing exe preds.
  if (hbaseFilterColVIDlist_.entries() > 0)
      setExecutorPredicates(newExePreds);
  }//DF_MINIMUM

  snpType_ = SNP_NONE;
  DefaultToken  tok = CmpCommon::getDefault(TRAF_TABLE_SNAPSHOT_SCAN);
  if (tok == DF_LATEST)
    //latest snapshot -- new way used with scan independent from bulk unload
    snpType_= SNP_LATEST;
  else if (tok == DF_SUFFIX)
    //the exsiting where snapshot scan is used with bulk unload
    snpType_ = SNP_SUFFIX;

  markAsPreCodeGenned();
  
  // Done.
  return this;
}

RelExpr * HbaseAccessCoProcAggr::preCodeGen(Generator * generator,
					    const ValueIdSet & externalInputs,
					    ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! HbaseAccess::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  // Rebuild the aggregate expressions tree
  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);
  aggregateExpr().replaceVEGExpressions
                     (availableValues,
  	 	      getGroupAttr()->getCharacteristicInputs());

  markAsPreCodeGenned();
  
  // Done.
  return this;
}

RelExpr * ExeUtilHbaseCoProcAggr::preCodeGen(Generator * generator,
					    const ValueIdSet & externalInputs,
					    ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! ExeUtilExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  // Rebuild the aggregate expressions tree
  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);
  aggregateExpr().replaceVEGExpressions
                     (availableValues,
  	 	      getGroupAttr()->getCharacteristicInputs());

  markAsPreCodeGenned();
  
  // Done.
  return this;
}

RelExpr * ExeUtilOrcFastAggr::preCodeGen(Generator * generator,
                                         const ValueIdSet & externalInputs,
                                         ValueIdSet &pulledNewInputs)
{
  if (nodeIsPreCodeGenned())
    return this;

  if (! ExeUtilExpr::preCodeGen(generator,externalInputs,pulledNewInputs))
    return NULL;

  // Rebuild the aggregate expressions tree
  ValueIdSet availableValues;
  getInputValuesFromParentAndChildren(availableValues);
  aggregateExpr().replaceVEGExpressions
                     (availableValues,
  	 	      getGroupAttr()->getCharacteristicInputs());

  markAsPreCodeGenned();
  
  // Done.
  return this;
}

ItemExpr * SplitPart::preCodeGen(Generator *generator)
{
  if (nodeIsPreCodeGenned())
    return this;

  child(0) = child(0)->preCodeGen(generator);
  if (! child(0).getPtr())
    return NULL;

  child(1) = child(1)->preCodeGen(generator);
  if (! child(1).getPtr())
    return NULL;

  for (Int32 i = 2; i < getArity(); i++)
    {
      if (child(i))
        {
          const NAType &typ1 = child(i)->getValueId().getType();
          
          //Insert a cast node to convert child to an INT.
          child(i) = new (generator->wHeap())
            Cast(child(i), new (generator->wHeap()) SQLInt(generator->wHeap(), TRUE,
                                                         typ1.supportsSQLnullLogical()));

          child(i)->bindNode(generator->getBindWA());
          child(i) = child(i)->preCodeGen(generator);
          if (! child(i).getPtr())
            return NULL;

        }
    }

  markAsPreCodeGenned();
  return this;
}
