/**********************************************************************
// @@@ 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:         GenExpGenerator.cpp
 * Description:  Methods for class ExpGenerator
 *
 * Created:      6/28/95
 * Language:     C++
 *
 *
 *****************************************************************************
 */


#define   SQLPARSERGLOBALS_FLAGS
#define   SQLPARSERGLOBALS_NADEFAULTS
#include "SqlParserGlobalsCmn.h"
#include "SqlParserGlobals.h"	// Parser Flags

#include <ctype.h>
#include <math.h>
#include "CmpContext.h"
#include "CmpStatement.h"
#include "CmpMain.h"
#include "CmpSeabaseDDL.h"

#include "GenExpGenerator.h"
#include "str.h"
#include "Sqlcomp.h"
#include "exp_clause_derived.h"
#include "exp_attrs.h"
#include "exp_function.h"
#include "exp_datetime.h"
#include "exp_bignum.h"
#include "DatetimeType.h"
#include "NumericType.h"
#include "IntervalType.h"
#include "CharType.h"
#include "charinfo.h"
#include "SQLCLIdev.h"
#include "BindWA.h"

#include "ExpCriDesc.h"
#include "ExpAtp.h"
#include "exp_attrs.h"
#include "exp_tuple_desc.h"
#include "exp_dp2_expr.h"
#include "ComQueue.h"

#include "ControlDB.h"

#include "ComSmallDefs.h"
#include "sqlcli.h"
#include "OptimizerSimulator.h"
#include "ItmFlowControlFunction.h"
#include "ExpPCodeOptimizations.h"
#include "ItemFunc.h"

#define   NEW_LEAN_EXPR

static short mapMode(ComColumnDirection direction);

static short mapMode(ComColumnDirection direction)
{
  switch(direction)
  {
  case COM_UNKNOWN_DIRECTION:

	return PARAMETER_MODE_UNDEFINED;

  case COM_INPUT_COLUMN:

	return PARAMETER_MODE_IN;

  case COM_OUTPUT_COLUMN:

	return PARAMETER_MODE_OUT;

  case COM_INOUT_COLUMN:

	return PARAMETER_MODE_INOUT;

  default:

	BriefAssertion(0, "Unrecognized ComColumnDirection");

	return 0; // not reached
  }
}

// End


ExpGenerator::ExpGenerator(Generator * generator_)
{
  generator = generator_;

  // $$$ is this the correct heap???
  cache_ = new(generator->wHeap()) ExpGeneratorCache(generator_);

  temps_length = 0;  // Initialize various member variables
  mapTable_ = 0;
  clause_list = 0;
  constant_list = 0;
  persistentList_ = 0;
  flags_ = 0;
  rowsSinceCounter_ = NULL;

  setHandleIndirectVC( TRUE );

  // default value for Pcode mode
  DefaultToken pcodeOptLevel = CmpCommon::getDefault(PCODE_OPT_LEVEL);

  switch (pcodeOptLevel)
    {
    case DF_OFF:
      // don't use any PCODE features at all
      pCodeMode_ = ex_expr::PCODE_NONE;
      break;

    case DF_MINIMUM:
      // use PCODE to call the regular expression evaluator
      pCodeMode_ =
	ex_expr::PCODE_ON | ex_expr::PCODE_EVAL;
      break;

    case DF_MEDIUM:
      // use PCODE for those clauses that can be translated to PCODE
      pCodeMode_ = ex_expr::PCODE_ON;
      break;

    case DF_HIGH:
      // use PCODE where possible and optimize it
      pCodeMode_ = ex_expr::PCODE_ON | ex_expr::PCODE_OPTIMIZE;
      break;

    case DF_MAXIMUM:
    case DF_ON:
    case DF_SYSTEM:
    default:
      // use PCODE where possible and run LLO (low-level) advanced optimizations
      pCodeMode_ = ex_expr::PCODE_ON | ex_expr::PCODE_OPTIMIZE |
                   ex_expr::PCODE_LLO;
      break;
    }
  static Int32 pcodeEnvSet = 0;
  static Int32 pcodeEnv = 1;  // if non-zero, pcode is enabled as before.
  if (pcodeEnvSet == 0)
    {
      char * pcodeEnvStr = getenv("64BIT_PCODE");
      if (pcodeEnvStr != NULL)
        pcodeEnv = atoi(pcodeEnvStr);

      pcodeEnvSet = 1;
    }
  if (pcodeEnv == 0)
    pCodeMode_ = ex_expr::PCODE_NONE;

  addPCodeMode( ex_expr::PCODE_SPECIAL_FIELDS );

  // May be used during key encoding expression generation if there are
  // added fields present.
  savedPCodeMode_ = -1;
};

ExpGenerator::~ExpGenerator()
  {
  delete cache_;
  }


///////////////////////////////////////////////////////////////////////////
// The following is a static function used by aggregate node when generating
// aggregate expression of type ITM_ONE_ROW
///////////////////////////////////////////////////////////////////////////
void createCastNodesatLeaves(ItemExpr *exp, Generator *generator)
{
  // expecting input of the kind: a,b,c,d....
  for (short i=0; i<exp->getArity(); i++)
  {
    if (exp->child(i)->getOperatorType() != ITM_ITEM_LIST)
    {
      ValueId val_id;
      ItemExpr *newExpr;
      val_id = exp->child(i)->castToItemExpr()->getValueId();
      newExpr = new(generator->wHeap()) Cast(exp->child(i), &(val_id.getType()));
      newExpr = newExpr->bindNode(generator->getBindWA());
      exp->child(i) = newExpr;
    }
    else
      createCastNodesatLeaves(exp->child(i), generator);
  }

} // createCastNodesatLeaves()

///////////////////////////////////////////////////////////
// returns a ConstValue node with min or max value
// The max value could either be the null max value or
// the non-null max value, based on the input min_max.
//////////////////////////////////////////////////////////
ItemExpr * ExpGenerator::getMinMaxValue(const NAType &type,
					short min_max /*0=min, -1=max, -2=max-without-null*/)
{
  NABoolean includeNulls = (min_max > -2);
  NABoolean getMin = (min_max == 0);

  return new(CmpCommon::statementHeap())
    ConstValue(&type,getMin,includeNulls);
}

/////////////////////////////////////////////////////////////////
// Make an equivalent Attributes object (or derived class)
// from an NAType.
/////////////////////////////////////////////////////////////////
Attributes * ExpGenerator::convertNATypeToAttributes
(const NAType &naType_x, CollHeap* wHeap)
{
  // ----------------------------------------------------------------
  // Each NAType corresponds to an object derived from class
  // "Attributes" used by expression generator to evaluate
  // operations on it.
  // All 'simple' types return SimpleType.
  // All 'complex' types return the class specific to them. These
  // classes contain methods used to perform operations on this type.
  // ----------------------------------------------------------------

  Attributes   *result = NULL;
  const NAType *naType = &naType_x;

  Int32 rsSize = 0;
  if (naType->getTypeQualifier() == NA_ROWSET_TYPE)
    {
      rsSize = ((SQLRowset *)naType)->getNumElements();
      naType = ((const SQLRowset *)naType)->getElementType();
    }

  if (naType->isSimpleType())
    {
      SimpleType * attr;

      switch (naType->getTypeQualifier()) {
      case NA_DATETIME_TYPE:
        attr = new(wHeap) ExpDatetime;
        break;
      default:
        attr = new(wHeap) SimpleType;
        break;
      }

      attr->setRowsetSize(rsSize);
      result = attr;
      attr->setNullFlag(naType->supportsSQLnull());
      attr->setNullIndicatorLength((short) naType->getSQLnullHdrSize());
      attr->setVCIndicatorLength((short) naType->getVarLenHdrSize());
      attr->setDatatype(naType->getFSDatatype());
      attr->setLength(naType->getNominalSize());
      attr->setDataAlignmentSize(naType->getDataAlignment());
      if (naType_x.getTypeQualifier() == NA_ROWSET_TYPE) {
	if (((SQLRowset *)(&naType_x))->useTotalSize()) {
	  // This indicates us to use the whole array size
 	  attr->setLength(sizeof(Lng32) + (attr->getRowsetSize() * naType->getTotalSize()));
	  result->setUseTotalRowsetSize();
	  ((SQLRowset *)(&naType_x))->useTotalSize() = FALSE;
	}
      }

      attr->setIsoMapping((CharInfo::CharSet)SqlParser_ISO_MAPPING);

      if (naType->getTypeQualifier() == NA_CHARACTER_TYPE) 
	{
	  const CharType *charType = (CharType *)naType;

	  if (charType->isUpshifted())
	    attr->setUpshift(1);

	  if (charType->isCaseinsensitive())
	    attr->setCaseinsensitive(1);

	  CharInfo::CharSet cs = charType->getCharSet();
	  if ( cs == CharInfo::UCS2       ||
               cs == CharInfo::KANJI_MP   ||
               cs == CharInfo::KSC5601_MP )
	    attr->setWidechar(1);

          attr->setPrecision(charType->getPrecisionOrMaxNumChars());
	  attr->setCharSet(charType->getCharSet());
	  attr->setCollation(charType->getCollation());
	}
      else if (naType->getTypeQualifier() == NA_NUMERIC_TYPE)
        {
          const NumericType *numericType = (const NumericType *) naType;

          if (numericType->binaryPrecision() && numericType->isExact() &&
              (numericType->getFSDatatype() != REC_BPINT_UNSIGNED))
            attr->setPrecision(0);
          else
            attr->setPrecision(numericType->getPrecision());

          attr->setScale((short) numericType->getScale());
        }
      else if (naType->getTypeQualifier() == NA_DATETIME_TYPE)
        {
          const DatetimeType *datetimeType = (const DatetimeType *) naType;

          // Map the datetime type (start and end fields) to the
          // corresponding REC_DATETIME_CODE.  Note that in order to
          // support the non-standard SQL/MP datetime types, the
          // REC_DATETIME_CODE enumeration has been extended to
          // contain a value for each legal (including non-standard)
          // combination of start and end fields.  This means that the
          // correspondence between the values of the SQLDATETIME_CODE
          // and REC_DATETIME_CODE enumerations holds only for the
          // standard datetime types.  The method getRecDateTimeCode()
          // maps the datetime types based on the start and end
          // fields.
          //
          // This method has been modified as part of the MP Datetime
          // Compatibility project.
          //
          attr->setPrecision(datetimeType->getRecDateTimeCode());
          if (attr->getPrecision() == REC_DTCODE_FRACTION)
          {
            attr->setPrecision(REC_DTCODE_SECOND);
          }
          attr->setScale(datetimeType->getFractionPrecision());
        }
      else if (naType->getTypeQualifier() == NA_INTERVAL_TYPE)
        {
          const IntervalType *intervalType = (const IntervalType *) naType;
          attr->setPrecision(intervalType->getLeadingPrecision());
          attr->setScale(intervalType->getFractionPrecision());
          if (attr->getDatatype() == REC_INT_FRACTION)
          {
           attr->setDatatype(REC_INT_SECOND);
          }
        }
      
      else if (naType->getTypeQualifier() == NA_LOB_TYPE)
        {
          
	  SQLlob *lobType = (SQLlob *) naType;
          attr->setCharSet(lobType->getCharSet());
	}
      
      else
        {
          attr->setPrecision(0);
          attr->setScale(0);
        }
    }
  else
    {
      if (naType->getSimpleTypeName() == "BIG NUM")
        {
          const NumericType *numericType = (const NumericType *) naType;

          BigNum * attr = new(wHeap)
            BigNum(numericType->getNominalSize(),
                   numericType->getPrecision(),
                   (short)numericType->getScale(),
                   numericType->isUnsigned());

	  attr->setRowsetSize(rsSize);
          result = attr;

          attr->setNullFlag(naType->supportsSQLnull());
          attr->setNullIndicatorLength((short) naType->getSQLnullHdrSize());
          attr->setVCIndicatorLength((short) naType->getVarLenHdrSize());
          attr->setDatatype(numericType->getFSDatatype());
          attr->setComplexDatatype(numericType->getFSDatatype());
          attr->setDataAlignmentSize(naType->getDataAlignment());
	  if (naType_x.getTypeQualifier() == NA_ROWSET_TYPE) {
	    if (((SQLRowset *)(&naType_x))->useTotalSize()) {
	      // This indicates us to use the whole array size
	      attr->setLength(sizeof(Lng32) + (attr->getRowsetSize() * naType->getTotalSize()));
	      result->setUseTotalRowsetSize();
	      ((SQLRowset *)(&naType_x))->useTotalSize() = FALSE;
	    }
	  }
        }

      else
        {
          GenAssert(0,"Don't know how to convert complex type to Attributes");
        }
    }

  return result;
}

Attributes::DefaultClass ExpGenerator::getDefaultClass(const NAColumn * col)
{
  Attributes::DefaultClass dc;

  switch (col->getDefaultClass())
  {
    case COM_CURRENT_DEFAULT:
      dc = Attributes::DEFAULT_CURRENT; break;
    case COM_CURRENT_UT_DEFAULT:
      dc = Attributes::DEFAULT_CURRENT_UT; break;
    case COM_UUID_DEFAULT:
      dc = Attributes::DEFAULT_UUID; break;
    case COM_FUNCTION_DEFINED_DEFAULT:
      dc = Attributes::DEFAULT_FUNCTION; break;
    case COM_NO_DEFAULT:
    case COM_ALWAYS_COMPUTE_COMPUTED_COLUMN_DEFAULT:
    case COM_ALWAYS_DEFAULT_COMPUTED_COLUMN_DEFAULT:
      dc = Attributes::NO_DEFAULT; break;
    case COM_NULL_DEFAULT:
      dc = Attributes::DEFAULT_NULL; break;
    case COM_USER_DEFINED_DEFAULT:
      dc = Attributes::DEFAULT_USER; break;
    case COM_USER_FUNCTION_DEFAULT:
      dc = Attributes::DEFAULT_USER_FUNCTION; break;
    case COM_IDENTITY_GENERATED_BY_DEFAULT:
    case COM_IDENTITY_GENERATED_ALWAYS:
      dc = Attributes::DEFAULT_IDENTITY; break;
    default:
      dc = Attributes::INVALID_DEFAULT; break;
  }

  return dc;
}

short ExpGenerator::addDefaultValue(NAColumn * col, Attributes * attr,
				    ComDiagsArea  * diagsArea,
				    COM_VERSION   objectSchemaVersion)
{
  Attributes::DefaultClass dc;
  char		*defaultValue = NULL;
  ComDiagsArea	* da;
  short		fsDataType;
  short		extraFltLen = 0;
  NAString      terminalName;

  dc = getDefaultClass(col);
  if (dc == Attributes::INVALID_DEFAULT)
    {
      // invalid default value
      da = (diagsArea ? diagsArea : CmpCommon::diags());
      *da << DgSqlCode(-7001)
	  << DgString0(col->getDefaultValue() ? col->getDefaultValue() : " ")
	  << DgString1(col->getFullColRefNameAsAnsiString());
      return -1;
    }

  NAString *castStr;

  if ((col) && 
      (col->isAddedColumn()))
    {
      attr->setAddedCol();
    }

  fsDataType = attr->getDatatype();
  NABoolean isUpshifted = FALSE;
  switch (dc)
  {
    case Attributes::DEFAULT_CURRENT:
      // This value is for the old rows before the alter table with add column
      // For new rows compiler will produce a node with CURRENT exp
      castStr = new(wHeap()) NAString("CAST(TIMESTAMP '0001-01-01:12:00:00.000000' AS ", wHeap());
      break;
    case Attributes::DEFAULT_CURRENT_UT:
      // This value is for the old rows before the alter table with add column
      // For new rows compiler will produce a node with CURRENT exp
      castStr = new(wHeap()) NAString("CAST( 0 AS ", wHeap());
      break;
    case Attributes::DEFAULT_NULL:
      if (attr->getNullFlag())
      {
	  defaultValue =
	    new(generator->getSpace())char[attr->getDefaultValueStorageLength()];
	  // move null value
	  str_pad(defaultValue, ExpTupleDesc::NULL_INDICATOR_LENGTH, '\377');
      }
      // else treat them as if it is no default
      attr->setDefaultValue(dc, defaultValue);
      return 0;
    case Attributes::DEFAULT_USER_FUNCTION:
     {
      const NAType* colType = col->getType();
         castStr = new(wHeap()) NAString("CAST('\' \'' AS ", wHeap());
     }
      break;
    case Attributes::DEFAULT_USER:
      if (col->getDefaultValue() != NULL)
      {
        if (col->getType()->getTypeQualifier() == NA_CHARACTER_TYPE)
          {
            const CharType *colCharType = (const CharType *)col->getType();
 
            if (colCharType->isUpshifted())
              isUpshifted = TRUE;
          }

	castStr = new(wHeap()) NAString("CAST(", wHeap());
	castStr->append(NAString(col->getDefaultValue(), wHeap()));
	castStr->append(NAString(" AS ", wHeap()));
      }
      else
      {
	da = (diagsArea ? diagsArea : CmpCommon::diags());
	*da << DgSqlCode(-7001)
	  << DgString0("NULL POINTER")
	  << DgString1(col->getFullColRefNameAsAnsiString());
	return -1;
      }
      break;
    case Attributes::DEFAULT_IDENTITY:
      // since this is used only for AddColumn and that we don't allow to add
      // IDENTITY column, it is Ok. to cast it to zero.
      castStr = new(wHeap()) NAString("CAST(0 AS ", wHeap());
      break;
    case Attributes::DEFAULT_FUNCTION:
      castStr = new(wHeap()) NAString("CAST( \' \' AS ", wHeap());
      break;

    case Attributes::NO_DEFAULT:
    default:
      attr->setDefaultValue(dc, NULL);
      return 0;
  }
  // Append Type Name
  castStr->append(NAString(col->getType()->getTypeSQLname(TRUE), wHeap()));
  if (isUpshifted)
    castStr->append(NAString(" UPSHIFT ", wHeap()));
  if (! attr->getNullFlag())
      castStr->append(NAString(" NOT NULL)", wHeap()));
  else
      castStr->append(NAString(")", wHeap()));

  BindWA *bindWA = generator->getBindWA();

  // When creating an SQL/MX table, (Called from
  // addDefaultValuesToRCB) the NATable is NULL.  
  Parser parser(bindWA->currentCmpContext());

  ItemExpr *defaultValueExpr = parser.getItemExprTree(*castStr);

  // if this column is serialized, then encode the default value.
  if (CmpSeabaseDDL::isEncodingNeededForSerialization(col))
    {
      defaultValueExpr = new(wHeap()) CompEncode
	(defaultValueExpr, FALSE, -1, CollationInfo::Sort, TRUE);
    }

  if (!defaultValueExpr || bindWA->errStatus())
  {
    // invalid default value
    da = (diagsArea ? diagsArea : CmpCommon::diags());
    *da << DgSqlCode(-7001)
        << DgString0(col->getDefaultValue() ? col->getDefaultValue() : " ")
        << DgString1(col->getFullColRefNameAsAnsiString());
    
    return -1;
  }

  defaultValueExpr->bindNode(bindWA);

  ValueIdList defaultValueIdList;
  defaultValueIdList.insert(defaultValueExpr->getValueId());
  defaultValue = new(generator->getSpace()) char[attr->getDefaultValueStorageLength()];
  Lng32 length;
  Lng32 offset;
  Lng32 daMark;

  da = (diagsArea ? diagsArea : CmpCommon::diags());
  daMark = da->mark();
  ex_expr::exp_return_type evalReturnCode = defaultValueIdList.evalAtCompileTime
    (0,
     ExpTupleDesc::PACKED_FORMAT,
     defaultValue, attr->getDefaultValueStorageLength() + extraFltLen,
     &length, &offset, da);

  if ((evalReturnCode != ex_expr::EXPR_OK) || (da->getNumber() != daMark))
  {
    // remove all the errors inserted in expression evaluation
    da->rewind(daMark, TRUE);
    // invalid default value
    NAString *cTemp;
    cTemp = unicodeToChar((const NAWchar *) (col->getDefaultValue())
                        , (Int32)NAWstrlen((const NAWchar *) (col->getDefaultValue()))
                        , ComGetErrMsgInterfaceCharSet()
                        , CmpCommon::statementHeap());

    if ( cTemp == NULL ) /* Prevent null ptr reference */
      cTemp = new (CmpCommon::statementHeap()) NAString(CmpCommon::statementHeap());

    *da << DgSqlCode(-7001)
        << DgString0(convertNAString(*cTemp,CmpCommon::statementHeap()))
        << DgString1(col->getFullColRefNameAsAnsiString());
    delete cTemp;
    return -1;
  }

  // Adjusting the resultBuffer's variable Character indicator length to
  // attr VCIndicatorLength
  if (attr->getVCIndicatorLength() > 0)
  {
    char *defaultValueAdj =
           new(generator->getSpace()) char[attr->getDefaultValueStorageLength()];
    short len;
    char *lenPtr;
    char *valuePtr = defaultValueAdj;

    if (attr->getNullFlag())
    {
      str_pad(valuePtr, ExpTupleDesc::NULL_INDICATOR_LENGTH, 0);
      valuePtr += ExpTupleDesc::NULL_INDICATOR_LENGTH;
    }

    if (attr->getVCIndicatorLength() == sizeof(short))
    {
      len = (short)length;
      lenPtr = (char *)&len;
    }
    else
      lenPtr = (char *)&length;

    str_cpy_all(valuePtr, lenPtr, attr->getVCIndicatorLength());
    valuePtr += attr->getVCIndicatorLength();

    str_cpy_all(valuePtr, defaultValue + offset, length);
    attr->setDefaultValue(dc, defaultValueAdj);
  }
  else
    attr->setDefaultValue(dc, defaultValue);

  return 0;
}

void ExpGenerator::addDefaultValues(const ValueIdList & val_id_list,
				    const NAColumnArray &naColArr,
				    ExpTupleDesc * tupleDesc,
				    NABoolean inputIsColumnList)
{
  NABoolean setAddedColumn = FALSE;
  NAString defVal;

  for (unsigned short i = 0; i < val_id_list.entries(); i++)
    {
      NAColumn * col = NULL;
      
      if (inputIsColumnList)
	{
	  ItemExpr * ie = val_id_list[i].getItemExpr();
	  GenAssert(((ie->getOperatorType() == ITM_BASECOLUMN) ||
		     (ie->getOperatorType() == ITM_INDEXCOLUMN)), 
		    "Must be a base or index column");

	  if (ie->getOperatorType() == ITM_BASECOLUMN)
	    {
	      BaseColumn * bc = (BaseColumn *)ie;
	      col = bc->getNAColumn();
	    }
	  else
	    {
	      IndexColumn * ic = (IndexColumn *)ie;
	      col = ic->getNAColumn();
	    }
	}
      else
	{
	  col = naColArr.getColumn(i);
	}

      Attributes * attr = (tupleDesc ? tupleDesc->getAttr(i) : NULL);

      if (attr)
	{
	  short rc = addDefaultValue(col, attr);
	  if (rc)
	    {
	      GenExit();
	      return;
	    }
	}

      if (col->isAddedColumn())
	{
	  setAddedColumn = TRUE;

          // the i-th attribute
          Attributes * ithAttr =
            generator->getMapInfo(val_id_list[i])->getAttr();
          ithAttr->setAddedCol();
          ithAttr->setDefaultFieldNum(i);

	  if (attr)
            {
              attr->setAddedCol();
              attr->setDefaultFieldNum(i);
            }
	}
    } // for

  if ((setAddedColumn) && (tupleDesc))
    tupleDesc->setAddedField();

  // Set EID Olt optimization off for tables with added columns.
  if ( setAddedColumn
       && !( CmpCommon::getDefault( EXPAND_DP2_SHORT_ROWS ) == DF_ON ) )
    //    generator->doOltQueryOptimization() = FALSE;
    generator->oltOptInfo()->setOltEidOpt(FALSE);
}

void ExpGenerator::copyDefaultValues(
				     ExpTupleDesc * tgtTupleDesc,
				     ExpTupleDesc * srcTupleDesc)
{
  Lng32 numAttrs = MINOF(srcTupleDesc->numAttrs(), tgtTupleDesc->numAttrs());
  for (CollIndex i = 0; i < numAttrs; i++)
    {
      Attributes * srcAttr = srcTupleDesc->getAttr(i);
      Attributes * tgtAttr = tgtTupleDesc->getAttr(i);

      if (srcAttr->isAddedCol())
	tgtAttr->setAddedCol();
      
      tgtAttr->setDefaultClass(srcAttr->getDefaultClass());

      if (srcAttr->getDefaultValue())
	{
          Lng32 tgtDefLen = tgtAttr->getDefaultValueStorageLength();
          Lng32 srcDefLen = srcAttr->getDefaultValueStorageLength();
          char* srcDefVal = srcAttr->getDefaultValue();
	  char * tgtDefVal = new(generator->getSpace()) char[tgtDefLen];

          // if source and target def storage lengths dont match, then
          // need to move each part (null, vclen, data) separately.
          if ((tgtDefLen == srcDefLen) &&
              (tgtAttr->getNullFlag() == srcAttr->getNullFlag()) &&
              (tgtAttr->getVCIndicatorLength() == srcAttr->getVCIndicatorLength()) &&
              (tgtAttr->getLength() == srcAttr->getLength()))
            {
              str_cpy_all(tgtDefVal, srcDefVal, srcDefLen);
            }
          else
            {
              char * tgtDefValCurr = tgtDefVal;

              short nullVal = 0;
              if (srcAttr->getNullFlag())
                {
                  str_cpy_all((char*)&nullVal, srcDefVal, 
                              ExpTupleDesc::NULL_INDICATOR_LENGTH);
                  srcDefVal += ExpTupleDesc::NULL_INDICATOR_LENGTH;
                }
              
              if (tgtAttr->getNullFlag())
                {
                  str_cpy_all(tgtDefVal, (char*)&nullVal, 
                              ExpTupleDesc::NULL_INDICATOR_LENGTH);
                  tgtDefValCurr += ExpTupleDesc::NULL_INDICATOR_LENGTH;
                }
              
              Lng32 srcDefLen    = srcAttr->getLength(srcDefVal);
              tgtAttr->setVarLength(srcDefLen, tgtDefValCurr);
              tgtDefValCurr += tgtAttr->getVCIndicatorLength();
              srcDefVal += srcAttr->getVCIndicatorLength();

              str_cpy_all(tgtDefValCurr, srcDefVal, srcDefLen);
            }
	  
	  tgtAttr->setDefaultValue(srcAttr->getDefaultClass(), tgtDefVal);
	}
    }
  
}

short ExpGenerator::genColNameList(const NAColumnArray &naColArr,
				   Queue* &colNameList)
{
  colNameList = NULL;
  if (naColArr.entries() == 0)
    return 0;

  Space * space = generator->getSpace();

  colNameList = new(space) Queue(space);
  for (unsigned short i = 0; i < naColArr.entries(); i++)
    {
      NAColumn * col = naColArr.getColumn(i);

      char * colName =
	space->allocateAndCopyToAlignedSpace(col->getColName().data(),
					     col->getColName().length());

      colNameList->insert(colName);
    }

  return 0;
}

short ExpGenerator::handleUnsupportedCast(Cast * castNode)
{
  const NAType &srcNAType = castNode->child(0)->getValueId().getType();
  const NAType &tgtNAType = castNode->getValueId().getType();
  short srcFsType = srcNAType.getFSDatatype();
  short tgtFsType = tgtNAType.getFSDatatype();

  // check if conversion involves tinyint or largeint unsigned
  NABoolean tinyintCast = FALSE;
  NABoolean largeUnsignedCast = FALSE;
  if (((DFS2REC::isTinyint(srcFsType)) &&
       (NOT DFS2REC::isTinyint(tgtFsType))) ||
      ((NOT DFS2REC::isTinyint(srcFsType)) &&
       (DFS2REC::isTinyint(tgtFsType))))
    tinyintCast = TRUE;

  if ((srcFsType == REC_BIN64_UNSIGNED) ||
      (tgtFsType == REC_BIN64_UNSIGNED))
    largeUnsignedCast = TRUE;

  if ((NOT tinyintCast) && (NOT largeUnsignedCast))
    return 0;

  ex_conv_clause tempClause;
  if (tempClause.isConversionSupported(srcFsType, srcNAType.getNominalSize(),
                                       tgtFsType, tgtNAType.getNominalSize()))
    return 0;

  // if this cast involved a tinyint and is unsupported, convert to
  // smallint.
  if (tinyintCast)
    {
      // add a Cast node to convert from/to tinyint to/from small int.
      NumericType * newType = NULL;
      if (DFS2REC::isInterval(srcFsType)) // interval to tinyint
        {
          const IntervalType &srcInt = (IntervalType&)srcNAType; 
          newType = new (generator->wHeap())
            SQLNumeric(generator->wHeap(), sizeof(short), srcInt.getTotalPrecision(), 
                       srcInt.getFractionPrecision(),
                       TRUE, srcNAType.supportsSQLnull());
        }
      else if (DFS2REC::isInterval(tgtFsType)) // tinyint to interval
        {
          const NumericType &srcNum = (NumericType&)srcNAType; 
           newType = new (generator->wHeap())
             SQLNumeric(generator->wHeap(), sizeof(short), srcNum.getPrecision(), 
                        srcNum.getScale(),
                        NOT srcNum.isUnsigned(), srcNAType.supportsSQLnull());
        }
      else if (DFS2REC::isTinyint(srcFsType)) // tinyint to non-tinyint
        {
          const NumericType &srcNum = (NumericType&)srcNAType; 
          
          if ((srcNum.getScale() == 0) &&
              (srcNum.binaryPrecision()))
            newType = new (generator->wHeap())
              SQLSmall(generator->wHeap(), NOT srcNum.isUnsigned(),
                       tgtNAType.supportsSQLnull());
          else
            newType = new (generator->wHeap())
              SQLNumeric(generator->wHeap(), sizeof(short), srcNum.getPrecision(), 
                         srcNum.getScale(),
                         NOT srcNum.isUnsigned(), 
                         tgtNAType.supportsSQLnull());
        }
      else if (DFS2REC::isTinyint(tgtFsType)) // non-tinyint to tinyint
        {
          const NumericType &srcNum = (NumericType&)srcNAType; 
          const NumericType &tgtNum = (NumericType&)tgtNAType; 
          
          if ((tgtNum.getScale() == 0) &&
              (tgtNum.binaryPrecision()))
            newType = new (generator->wHeap())
              SQLSmall(generator->wHeap(), NOT tgtNum.isUnsigned(),
                       tgtNAType.supportsSQLnull());
          else
            newType = new (generator->wHeap())
              SQLNumeric(generator->wHeap(), sizeof(short), tgtNum.getPrecision(), 
                         tgtNum.getScale(),
                         NOT tgtNum.isUnsigned(), 
                         tgtNAType.supportsSQLnull());
        }

      ItemExpr * newChild =
        new (generator->wHeap())
        Cast(castNode->child(0), newType);
      ((Cast*)newChild)->setFlags(castNode->getFlags());
      castNode->setSrcIsVarcharPtr(FALSE);
      newChild = newChild->bindNode(generator->getBindWA());
      newChild = newChild->preCodeGen(generator);
      if (! newChild)
        return -1;
      
      castNode->setChild(0, newChild);
      srcFsType = castNode->child(0)->getValueId().getType().getFSDatatype();
    }

  if ((srcFsType == REC_BIN64_UNSIGNED) ||
      (tgtFsType == REC_BIN64_UNSIGNED))
    {
      const NumericType &numSrc = (NumericType&)srcNAType;
      // add a Cast node to convert to sqllargeint signed.
      ItemExpr * newChild =
        new (generator->wHeap())
        Cast(castNode->child(0),
             new (generator->wHeap())
             SQLLargeInt(generator->wHeap(), numSrc.getScale(), 1,
                         TRUE,
                         srcNAType.supportsSQLnull()));
      ((Cast*)newChild)->setFlags(castNode->getFlags());
      castNode->setSrcIsVarcharPtr(FALSE);
      newChild = newChild->bindNode(generator->getBindWA());
      newChild = newChild->preCodeGen(generator);
      if (! newChild)
        return -1;
      
      castNode->setChild(0, newChild);
      srcFsType = castNode->child(0)->getValueId().getType().getFSDatatype();
    }

  return 0;
}

/////////////////////////////////////////////////////////////////
// this function returns an expr tree that multiplies the source
// by 10 ** exponent.  If exponent is negative, the returned expr
// tree divides the source by 10 ** (- exponent).
/////////////////////////////////////////////////////////////////
ItemExpr * ExpGenerator::scaleBy10x(const ValueId & source, Lng32 exponent)
{
  ItemExpr * retTree = source.getItemExpr();
  OperatorTypeEnum srcOrigOpType = retTree->origOpType(); 

  //
  // If the exponent is 0, return the source tree unchanged.
  //
  if (exponent == 0)
    return retTree;

  NABoolean downscale = (exponent < 0 ? TRUE : FALSE);
  
  // Retain this flag and pass it on to next ITM_DIVIDE
  // operator if any. This flag indicates that no special
  // rounding be performed. This is set in the case of
  // date-time kind of operations.
  NABoolean ignoreSpecialRounding = 
    (retTree->getOperatorType() != ITM_DIVIDE)? FALSE :
    ((BiArith*)retTree)->ignoreSpecialRounding();
  //
  // If the exponent is positive, multiply the source.  Otherwise, divide the
  // source.
  //
  char *str = new(wHeap()) char[ 100 + abs( exponent ) ];
  if (exponent > 0)
    strcpy(str, "@A1 * 1");
  else {
    strcpy(str, "@A1 / 1");
    exponent = - exponent;
  }
  do {
    strcat(str, "0");
  } while (--exponent > 0);
  retTree = createExprTree(str, 0, 1, retTree);

  // inherit and propogate OrigOpType_
  retTree->setOrigOpType(srcOrigOpType);

  NADELETEBASIC( str, wHeap() );

  if ((retTree) && (downscale) &&
      (retTree->getOperatorType() == ITM_DIVIDE))
    {
      ((BiArith*)retTree)->setDivToDownscale(TRUE);

      if(ignoreSpecialRounding)
        ((BiArith*)retTree)->setIgnoreSpecialRounding();
    }

  //
  // Bind the tree.  If necessary, change the scale of the result to match the
  // scale of the source, so the generator won't upscale the numerator.
  //
  retTree->bindNode(generator->getBindWA());
  const NAType& resultType = retTree->getValueId().getType();
  if (resultType.getTypeQualifier() == NA_NUMERIC_TYPE) {
    Lng32 sourceScale = ((NumericType &) source.getType()).getScale();
    if (((NumericType &) resultType).getScale() != sourceScale)
      ((NumericType &) resultType).setScale(sourceScale);
  }
  return retTree;
}

/////////////////////////////////////////////////////////////////
// if the scales of the source and target types are not
// the same, this function returns an expr tree to upscale
// or downscale the source to the target scale by multiplying
// the source by 10 ** (target_scale - source_scale).
/////////////////////////////////////////////////////////////////
ItemExpr * ExpGenerator::matchScales(const ValueId & source,
				     const NAType & targetType)
{
  ItemExpr * sourceTree = source.getItemExpr();
  ItemExpr * retTree = matchScalesNoCast(source,targetType);

  if (sourceTree != retTree)
    {
      // we generated an expression to change the scale of the source;
      // now add a Cast to make the source datatype match the target
      retTree = new(wHeap()) Cast(retTree, &targetType);
      retTree->bindNode(generator->getBindWA());

      if (handleUnsupportedCast((Cast*)retTree))
        return NULL;

      // Mark this as preCodeGenned so we don't generate more
      // scaling code to handle possible scale differences in the
      // new Cast (note that matchScalesNoCast() in this case has
      // already preCodeGenned the child of the Cast)
      retTree->markAsPreCodeGenned();
    }

  // Note that if sourceTree == retTree above, the tree might not
  // have been preCodeGenned; we let the caller take care of that.

  return retTree;
}


//////////////////////////////////////////////////////////////////
// This function is the "guts" of matchScales(), but it does not
// cast the resulting expression into the target type.  Usually,
// we get to this function via matchScales().  The one exception
// is in key building, where we wish to detect truncation and overflow
// errors due to scaling in a special way.  So, key building calls
// this method directly to avoid generating a Cast.
//////////////////////////////////////////////////////////////////
ItemExpr * ExpGenerator::matchScalesNoCast(const ValueId & source,
					   const NAType & targetType)
{
  ItemExpr * retTree = source.getItemExpr();
  //
  // If the source or target is neither interval nor numeric, return the
  // source tree unchanged.
  //
  NABuiltInTypeEnum sourceTypeQual = source.getType().getTypeQualifier();
  NABuiltInTypeEnum targetTypeQual = targetType.getTypeQualifier();

  if (((sourceTypeQual != NA_NUMERIC_TYPE) &&
       (sourceTypeQual != NA_INTERVAL_TYPE)) ||
      ((targetTypeQual != NA_NUMERIC_TYPE) &&
       (targetTypeQual != NA_INTERVAL_TYPE)))
    return retTree;

  // If it is a null constant no need to scale it.
  if (retTree->getOperatorType() == ITM_CONSTANT)
    {
      ConstValue * constant = (ConstValue *) retTree;
      if (constant->isNull())
        return retTree;
    }

  //
  // Upscale or downscale the source to the target scale.  If the source scale
  // is the same as the target scale, return the source tree unchanged.
  //
  Lng32 sourceScale = (source.getType().getTypeQualifier() == NA_NUMERIC_TYPE)
    ? ((NumericType &) source.getType()).getScale()
    : ((IntervalType &) source.getType()).getFractionPrecision();
  Lng32 targetScale = (targetType.getTypeQualifier() == NA_NUMERIC_TYPE)
    ? ((NumericType &) targetType).getScale()
    : ((IntervalType &) targetType).getFractionPrecision();
  if (sourceScale == targetScale)
    return retTree;

  if ((sourceTypeQual == NA_INTERVAL_TYPE) &&
      (targetTypeQual == NA_INTERVAL_TYPE))
    {
    // the Cast operator can do interval to interval scaling itself
    retTree = new(wHeap()) Cast(retTree,&targetType);
    retTree->bindNode(generator->getBindWA());
    }
  else {
    if (((NumericType &) source.getType()).isExact() &&
        (NOT((NumericType &)targetType).isExact()) &&
	(targetScale != sourceScale)) {
    retTree = new(wHeap()) Cast(retTree,&targetType);
    retTree->bindNode(generator->getBindWA());

    if (handleUnsupportedCast((Cast*)retTree))
      return NULL;

    retTree->markAsPreCodeGenned();
    retTree = scaleBy10x(retTree->getValueId(), targetScale - sourceScale);
    }
    else
      retTree = scaleBy10x(source, targetScale - sourceScale);
  };

  retTree = retTree->preCodeGen(generator);

  return retTree;
}

/////////////////////////////////////////////////////////////////
// if the source is an interval, this function returns an expr
// tree to convert the source type to numeric.
/////////////////////////////////////////////////////////////////
ItemExpr * ExpGenerator::convertIntervalToNumeric(const ValueId & source)
{
  ItemExpr * retTree = source.getItemExpr();
  //
  // If the source is not an interval, return the source tree unchanged.
  //
  if (source.getType().getTypeQualifier() != NA_INTERVAL_TYPE)
    return retTree;
  IntervalType& sourceInterval = (IntervalType&) source.getType();
  //
  // If the source interval does not consist of only a single datetime field,
  // cast it to an interval consisting of only the end field.
  //
  if (sourceInterval.getStartField() != sourceInterval.getEndField())
    retTree = new(wHeap())
      Cast(retTree, new(wHeap())
	   SQLInterval(wHeap(), sourceInterval.supportsSQLnull(),
		       sourceInterval.getEndField(),
		       sourceInterval.getTotalPrecision() -
		       sourceInterval.getFractionPrecision(),
		       sourceInterval.getEndField(),
		       sourceInterval.getFractionPrecision()));
  //
  // Convert the source interval to numeric, bind the tree, and return it.
  //
  const Int16 DisAmbiguate = 0;
  retTree = new(wHeap())
    Cast(retTree, new(wHeap()) SQLNumeric(wHeap(), TRUE, /* signed */
				     sourceInterval.getTotalPrecision(),
				     sourceInterval.getFractionPrecision(),
				     DisAmbiguate, // added for 64bit proj.
				     sourceInterval.supportsSQLnull()));
  retTree->bindNode(generator->getBindWA());

  return retTree;
}

/////////////////////////////////////////////////////////////////
// if the source is a numeric, this function returns an expr
// tree to convert the source type to interval.
/////////////////////////////////////////////////////////////////
ItemExpr * ExpGenerator::convertNumericToInterval(const ValueId & source,
                                                  const NAType & targetType)
{
  ItemExpr * retTree = source.getItemExpr();
  //
  // If the source is not numeric or the target type is not an interval,
  // return the source tree unchanged.
  //
  if ((source.getType().getTypeQualifier() != NA_NUMERIC_TYPE) ||
      (targetType.getTypeQualifier() != NA_INTERVAL_TYPE))
    return retTree;
  NumericType& sourceNumeric = (NumericType&) source.getType();
  IntervalType& targetInterval = (IntervalType&) targetType;

  //
  // Factor the source so that its scale matches the fractional precision of
  // the target, and cast the result to an interval consisting of the target's
  // end field.
  //

  SQLInterval *interval =
    new(wHeap()) SQLInterval(wHeap(), targetInterval.supportsSQLnull(),
                    targetInterval.getEndField(),
                    targetInterval.getTotalPrecision() -
                      targetInterval.getFractionPrecision(),
                    targetInterval.getEndField(),
                    targetInterval.getFractionPrecision());

  retTree = ((UInt32) sourceNumeric.getScale() !=
             targetInterval.getFractionPrecision())
            ? matchScales(retTree->getValueId(), *interval)
            : new(wHeap()) Cast(retTree, interval);
  //
  // Bind the tree and return it.
  //
  retTree->bindNode(generator->getBindWA());
  return retTree;
}

/////////////////////////////////////////////////////////////////
// if the source and target are intervals with different end fields,
// this function returns an expr tree to convert the source type to
// match the target's end field.
/////////////////////////////////////////////////////////////////
ItemExpr * ExpGenerator::matchIntervalEndFields(const ValueId & source,
                                                const NAType & targetType)
{
  ItemExpr * retTree = source.getItemExpr();
  //
  // If either the source or target is not an interval, or if they both have
  // the same end fields, return the source tree unchanged.
  //
  if ((source.getType().getTypeQualifier() != NA_INTERVAL_TYPE) ||
      (targetType.getTypeQualifier() != NA_INTERVAL_TYPE))
    return retTree;
  IntervalType& sourceInterval = (IntervalType&) source.getType();
  IntervalType& targetInterval = (IntervalType&) targetType;
  if (sourceInterval.getEndField() == targetInterval.getEndField())
    return retTree;

  // Create a Cast node to convert to the target type.
  retTree = new(wHeap()) Cast(retTree,&targetType);
  retTree->bindNode(generator->getBindWA());
  return retTree;
}


// input is a ValueIdSet of aggregate nodes
short ExpGenerator::generateAggrExpr(const ValueIdSet &val_id_set,
				     ex_expr::exp_node_type /* node_type */,
				     ex_expr ** expr,
				     short gen_last_clause,
				     NABoolean groupByOperation,
                                     const ValueIdSet *addedInitSet/*optional*/
                                     )
{
  ///////////////////////////////////////////////////////////////////////
  // 3 expressions are generated to evaluate the aggregate.
  // They are used to initialize, evaluate the aggr for each row,
  // and finalize with no rows (move nulls)
  //
  // Different expressions are generated depending on whether operand
  // is nullable or non-nullabls.
  //
  // for MIN, MAX and SUM aggregates.
  //
  // Case 1: when the operand is non-nullable.
  //         For non-grouping operation,
  //         NULL value is moved to result if no rows are found.
  // Case 2: when operand is nullable.
  //         This case needs extra handling for the scenario where all
  //         values of operand that are part of the same group, contain
  //         null values. In this case, the result becomes null.
  //
  //
  // Initialize Expr:
  //
  //                  (converted to)
  // Case 1:
  //   Sum           --------------->   Aggr = 0
  //   Min           --------------->   Aggr = Max value for that datatype
  //   Max           --------------->   Aggr = Min value for that datatype
  //
  // Case 2:
  //   Min/Max/Sum   --------------->   Aggr = NULL
  //
  // Case 1 and 2:
  //   Count         --------------->   Aggr = 0
  //   One/Any True  --------------->   Aggr = FALSE.
  //
  //
  // Perrec Eval Expr:
  // =================
  //
  // MIN Aggregate:
  // Case 1:
  //   Min(A)   ------> AggrMinMax(A, "A < Min(A)");
  // Case 2:
  //   Min(A)   ------> Case
  //                       When Min(A) is NULL then Min(A) = A
  //                       When A is not null AND A < Min(A) Then Min(A) = A
  //                    End
  //
  // MAX Aggregate:
  // Case 1:
  //   Max(A)   ------> AggrMinMax(A, "A > Max(A)");
  // Case 2:
  //   Max(A)   ------> Case
  //                       When Max(A) is NULL then Max(A) = A
  //                       When A is not null AND A > Max(A) Then Max(A) = A
  //                    End
  //
  // SUM Aggregate:
  // Case 1:
  //   Sum(A)   ------> Sum(A) + A
  //
  // Case 2:
  //   Sum(A)   ------> Case
  //                       When Sum(A) is NULL then Sum(A) = A
  //                       When A is not null Then Sum(A) = Sum(A) + A
  //                    End
  //
  // COUNT(A) Aggregate:
  // Case 1:
  //   Count(A)     ------>  Count(A) + 1;
  //
  // Case 2:
  //   Count(A)    -------> Count(A) + Case
  //                                     When A is not null then 1 else 0
  //                                   End
  //
  // Other aggregates, all cases:
  //   Count(*) ------> Count(*) = Count(*) + 1
  //   OneTrue(A)  ------> Aggr = TRUE
  //   AnyTrue(A)  ------> Case
  //                         When A is True then TRUE  (caller short circuits)
  //                         When A is Unknown then NULL
  //                       End
  //
  //
  // Finalize (no rows found). Case 1(with no groupBy) and 2:
  //
  //   Non-count Aggr = NULL
  //
  ////////////////////////////////////////////////////////////////////////


  // generate code to evaluate the initialize expression
  ValueId val_id;
  ItemExpr * newExpr = NULL;
  ValueIdSet * newValIdSet = new(wHeap()) ValueIdSet();
  MapInfo * map_info;

  CollIndex num_aggr_entries = val_id_set.entries();

  short case_;
  for (val_id = val_id_set.init(); val_id_set.next(val_id); val_id_set.advance(val_id))
    {
      ItemExpr * item_expr = val_id.getValueDesc()->getItemExpr();
      if (NOT item_expr->child(0)->castToItemExpr()->getValueId().getType().supportsSQLnull())
	case_ = 1;
      else
	case_ = 2;

      // the original value id list contains the aggregate nodes
      // which are being converted to an equivalent tree in some cases
      // to compute their values. Mark the original aggr nodes
      // to indicate that code has been generated for them.
      // We don't want to generate aggregate clauses for the
      // original aggregate nodes.

      switch (item_expr->getOperatorType())
	{
	case ITM_MIN:
	case ITM_MAX:
	case ITM_SUM:
	  {
	    generator->getMapInfo(val_id)->codeGenerated();
	    ItemExpr * initVal;
	    if (case_ == 1)
		{
		  if (item_expr->getOperatorType() == ITM_MIN)
		    initVal = getMinMaxValue(val_id.getType(),
					     -2/*max without null*/
					     );
		  else if (item_expr->getOperatorType() == ITM_MAX)
		    initVal = getMinMaxValue(val_id.getType(),
					     0 /* min value */
					     );
		  else //SUM
		    {
		      if (val_id.getType().getTypeQualifier() == NA_INTERVAL_TYPE)
			{
			  Int64 zero = 0;
			  NAType *type = val_id.getType().newCopy(wHeap());
			  type->setNullable(FALSE);
			  NAString * nas = new (wHeap()) NAString("0", wHeap());
			  initVal =
			    new(wHeap()) ConstValue(type,
						    (void *)&zero,
						    type->getNominalSize(),
						    nas);
			}
		      else
	  		initVal = new(wHeap()) ConstValue(0);
		  }
		  newExpr = new(wHeap())
		    Cast(initVal, &(val_id.getType()));
		}
	    else // Case 2
	      {
		initVal = generateNullConst(val_id.getType());
		NAType *newType
		  = item_expr->getValueId().getType().newCopy(wHeap());
		newType->setSQLnullFlag();

		newExpr = new(wHeap())
		  Cast(initVal, newType );
	      }

	  }
	  break;

	case ITM_COUNT:
	case ITM_COUNT_NONULL:
	  {
	    generator->getMapInfo(val_id)->codeGenerated();
            newExpr = new(wHeap())
              Cast(new(wHeap()) ConstValue(0), &(val_id.getType()));
	  }
	  break;

	case ITM_ONE_TRUE:
	case ITM_ANY_TRUE:
	  {
	    GenAssert((num_aggr_entries == 1), "Cannot have more than one 'special' aggregates.");

	    generator->getMapInfo(val_id)->codeGenerated();

	    // move boolean FALSE to result
	    newExpr = new(wHeap()) BoolVal(ITM_RETURN_FALSE);
	  }
	  break;

	case ITM_ANY_TRUE_MAX:
	  {
	    GenAssert((num_aggr_entries == 1), "Cannot have more than one 'special' aggregates.");

	    // move boolean FALSE to result
	    newExpr = new(wHeap()) BoolVal(ITM_RETURN_FALSE);
	  }
	  break;

	case ITM_ONE_ROW:
	  {

	    // move null value to all outputs
            ValueId outvid;
            ValueIdSet init_val_id_set;
           
            init_val_id_set += *addedInitSet; // other values to be init'ed.

            for ( outvid = init_val_id_set.init();
                           init_val_id_set.next(outvid);
                           init_val_id_set.advance(outvid) )
            {
              NAType *outType = outvid.getType().newCopy(wHeap());

              // Should be nullable, since one row aggregates are inst-null'ed.
              // except if this is an output from the aggregate node, plus it's
              // boolean.
              if (!outType->supportsSQLnull())
              {
               // The following assertion has been commented out because of the case where
               // although subqueries are nullable the statement enclosing the subquery is
               // not but if the subquery does not contain reference to the outer tables then
               // the whole statement can be pushed down to this side of the tree.
               // GenAssert(outType->getTypeQualifier() == NA_BOOLEAN_TYPE),
               // "outputs from one_row_aggr node should be nullable or BOOLEAN"
               // );
                outType->setNullable(TRUE);
              }

              // Make a null const of the same type as the value to be init'ed.
	      ConstValue * nullv = generateNullConst(outvid.getType());

              // Make a copy of the value, used in the generation of initExpr.
              newExpr = new(wHeap()) Cast(nullv,outType);
	      newExpr = newExpr->bindNode(generator->getBindWA());
	      newValIdSet->insert(newExpr->getValueId());

              // Attach the destination location to the copy. Used later to
              // generate the initExpr.
              Attributes *attr = generator->getMapInfo(outvid)->getAttr();
	      map_info = generator->addMapInfo(newExpr->getValueId(),attr);

              // seems unnecessary, since attr is passed in the call above. ??
	      // (map_info->getAttr())->copyLocationAttrs(attr);

            } // for

            newExpr = NULL;
	  }
	  break;

	case ITM_PIVOT_GROUP:
	  {
	    generator->getMapInfo(val_id)->codeGenerated();
            newExpr = new(wHeap())
              Cast(new(wHeap()) ConstValue(""), &(val_id.getType()));
	  }
	  break;

	default:
	  newExpr = NULL;
	  break;

	}

      if (newExpr != NULL)
	{
	  newExpr->bindNode(generator->getBindWA());
	  newValIdSet->insert(newExpr->getValueId());

	  // assign the data attributes of the aggr node to the convert node.
	  // This will make the result of initialization be moved to the
	  // aggregate location.
          Attributes * attr = generator->getMapInfo(val_id)->getAttr();
	  map_info = generator->addMapInfo(newExpr->getValueId(), attr);
	  (map_info->getAttr())->copyLocationAttrs(attr);
          if(attr->isForceFixed())
            (map_info->getAttr())->setForceFixed();
	}

    }

  ex_expr * init_expr = 0;
  generateSetExpr(*newValIdSet, ex_expr::exp_ARITH_EXPR, &init_expr);

  delete newValIdSet;

  // generate expression to move in null value as the aggr result
  // on an empty set. Applies to all non-count aggr for non-grouping
  // operation.
  ex_expr * final_null_expr = 0;
  if (groupByOperation == FALSE)
    {
      newValIdSet = new(wHeap()) ValueIdSet();
      for (val_id = val_id_set.init(); val_id_set.next(val_id); val_id_set.advance(val_id))
	{
	  ItemExpr * item_expr = val_id.getValueDesc()->getItemExpr();
          if(!item_expr->isAnAggregate()) {
            newExpr = NULL;
          } else {
            // part of fix to genesis case 10-070628-2258, soln 10-070610-5412:
            // guard against boundary case queries against empty table t
            //   "select count(distinct i), count(*) from t"
            //   "select avg(distinct i), count(*) from t"
            //   "select sum(distinct i), count(*) from t"
            // which transforms 
            //   "count(*)" into "sum(count(*))"
            // and can emit false alarms
            //   "error 8421 null cannot be assigned to a not null column"
            // when t is an empty table. 
            // The "sum" in the rewritten aggregate transformed by 
            // Aggregate::rewriteForStageEvaluation() should be treated like the
            // "count(*)" case below so it returns 0 when t is an empty table.
            switch (((Aggregate*)item_expr)->getEffectiveOperatorType())
            {
            case ITM_SUM:
            case ITM_MIN:
            case ITM_MAX:
            case ITM_ONEROW:
            case ITM_PIVOT_GROUP:
	      {
		generator->getMapInfo(val_id)->codeGenerated();
		ConstValue * const_value =
		  generateNullConst(val_id.getType());

		NAType *newType
		  = item_expr->getValueId().getType().newCopy(wHeap());
		newType->setSQLnullFlag();

		newExpr = new(wHeap())
		  Cast(const_value, newType );

	      }
	      break;

	    case ITM_COUNT:
	    case ITM_COUNT_NONULL:
	    case ITM_ONE_TRUE:
	    case ITM_ANY_TRUE:
	    case ITM_ANY_TRUE_MAX:
	    case ITM_ONE_ROW:
	      {
		newExpr = NULL;
	      }
	      break;

	    default:
	      newExpr = NULL;
	      break;

	    }
          }
	  if (newExpr != NULL)
	    {
	      newExpr->bindNode(generator->getBindWA());
	      newValIdSet->insert(newExpr->getValueId());

	      // assign the data attributes of the aggr node to the convert node.
	      // This will make the final null value to be moved to the
	      // aggregate location.
              Attributes * attr = generator->getMapInfo(val_id)->getAttr();
	      map_info = generator->addMapInfo(newExpr->getValueId(), attr);
	      (map_info->getAttr())->copyLocationAttrs(attr);
              if(attr->isForceFixed())
                (map_info->getAttr())->setForceFixed();
	    }
          
	} // for loop

      generateSetExpr(*newValIdSet, ex_expr::exp_ARITH_EXPR,
                      &final_null_expr);

      delete newValIdSet;
    }

  newValIdSet = new(wHeap())  ValueIdSet();

  // generate expression tree to evaluate the perrec aggr expression
  newExpr = 0;
  NABoolean raiseErrorGenerated = FALSE;
  ValueIdList NullSwitcharooVidList;
  for (val_id = val_id_set.init(); val_id_set.next(val_id); val_id_set.advance(val_id))
    {
      NABoolean nullSwitcharoo = FALSE;
      ItemExpr * item_expr = val_id.getValueDesc()->getItemExpr();
      if (NOT item_expr->child(0)->castToItemExpr()->getValueId().getType().supportsSQLnull())
	case_ = 1;
      else
	case_ = 2;

      switch (item_expr->getOperatorType())
	{
	case ITM_MIN:
	  {
	    if (case_ == 1)
	      {
		newExpr =
		  createExprTree("@A2 < @A1", 0, 2, item_expr,
				 item_expr->child(0));
		newExpr =
		  new(wHeap()) AggrMinMax(item_expr->child(0), newExpr);
		if (item_expr->getValueId().getType().supportsSQLnull())
		  nullSwitcharoo = TRUE;
	      } // Case 1
	    else
	      { //Case 2
                newExpr =
                  createExprTree("@A1 IS NULL OR"
                                 "(@A2 IS NOT NULL AND @A2 < @A1)",
                                 0, 2, item_expr, item_expr->child(0));
		newExpr =
                  new(wHeap()) AggrMinMax(item_expr->child(0), newExpr);
	      } // Case 2
	  }
  	  break;

	case ITM_MAX:
	  {
	    if (case_ == 1)
	      {
		newExpr = createExprTree("@A2 > @A1",
                                         0, 2, item_expr, item_expr->child(0));
		newExpr =
                  new(wHeap()) AggrMinMax(item_expr->child(0), newExpr);
		if (item_expr->getValueId().getType().supportsSQLnull())
		  nullSwitcharoo = TRUE;
	      }
	    else
	      {
                newExpr =
                  createExprTree("@A1 IS NULL OR"
                                 "(@A2 IS NOT NULL AND @A2 > @A1)",
                                 0, 2, item_expr, item_expr->child(0));
		newExpr =
                  new(wHeap()) AggrMinMax(item_expr->child(0), newExpr);
	      }
	  }
	  break;

	  // SUM --
	  //
	case ITM_SUM:
	  {
	    // The sum expression is not nullable. Cast the expression
	    // to the same width as the SUM but retain it non-nullability.
	    // BiArithSum has the following semantics:
	    //      if(operandA IS NOT NULL)
	    //        if(operandB IS NOT NULL) SUM = operandA + operandB
	    //        else SUM = operandA
	    //
	    if (case_ == 1)
	      {
		NAType *sumType
		  = item_expr->getValueId().getType().newCopy(wHeap());
		sumType->setNullable(FALSE);
		if (item_expr->child(0)->getValueId().getType().supportsSQLnull())
		  newExpr = new(wHeap()) Cast(item_expr->child(0),
					      sumType, ITM_CAST);
		else
		  newExpr = item_expr->child(0);
		//newExpr = new(wHeap()) Cast(item_expr->child(0),
		//			    sumType,
		//			    ITM_CAST);
		newExpr = new(wHeap()) BiArithSum(ITM_PLUS,
						  newExpr,
						  item_expr);
	      }
	    // The SUM expression is nullable. Cast the expression to the
	    // same width as the SUM. Then apply BiArithSum as above.
	    //
	    else // case_ == 2
	      {
		const NAType &sumType = item_expr->getValueId().getType();
		newExpr = new(wHeap()) Cast(item_expr->child(0),
					    &sumType,
					    ITM_CAST);
		newExpr = new(wHeap()) BiArithSum(ITM_PLUS,
					       newExpr,
					       item_expr);
	      }
	  }
	  break;

	  // COUNT (everything)
	  // BiArithCount has the following semantics:
	  //      if(operandA IS NOT NULL)
	  //        if(operandB IS NOT NULL) SUM = operandB + 1
	  //        else SUM = 1;
	  //
	case ITM_COUNT:
	  {
	    NAType *sumType
	      = item_expr->getValueId().getType().newCopy(wHeap());
	    sumType->setNullable(FALSE);

	    newExpr = new(wHeap()) ConstValue(1);
	    newExpr = new(wHeap()) Cast(newExpr, sumType, ITM_CAST);
	    newExpr = new(wHeap()) BiArithSum(ITM_PLUS,
					      newExpr,
					      item_expr);
	  }
	  break;

	  // COUNT (non nulls)
	  //
	case ITM_COUNT_NONULL:
	  {
	    // The COUNT attribute is non nullable.
	    //
	    NAType *sumType
	      = item_expr->getValueId().getType().newCopy(wHeap());
	    sumType->setNullable(FALSE);
	    if (case_ == 1)
	      {
		newExpr = new(wHeap()) ConstValue(1);
		newExpr = new(wHeap()) Cast(newExpr, sumType, ITM_CAST);
		newExpr = new(wHeap()) BiArithSum(ITM_PLUS,
						  newExpr,
						  item_expr);
	      }
	    // The COUNT attribute is nullable.
	    //
	    else
	      {
		ItemExpr *constZero = new(wHeap()) ConstValue(0);
		ItemExpr *constOne = new(wHeap()) ConstValue(1);
		newExpr = new(wHeap()) ReplaceNull(item_expr->child(0),
						   constOne,
						   constZero);
		newExpr = new(wHeap()) Cast(newExpr, sumType, ITM_CAST);
		newExpr = new(wHeap()) BiArithSum(ITM_PLUS,
						  newExpr,
						  item_expr);
	      }
	  }
	  break;

	case ITM_ONE_TRUE:
	  {
	    // move boolean TRUE to result
	    newExpr = new(wHeap()) BoolVal(ITM_RETURN_TRUE);

	    // assign the data attributes of the original aggr node
	    // to the newExpr.
	    // This will make the result of newExpr be moved to the
	    // original aggregate location.
	    newExpr->bindNode(generator->getBindWA());
            Attributes * attr = generator->getMapInfo(val_id)->getAttr();
	    map_info = generator->addMapInfo(newExpr->getValueId(), attr);
	    (map_info->getAttr())->copyLocationAttrs(attr);

	    // generate the expression that would return TRUE back
	    // to the caller which would short circuit.
	    newExpr = new(wHeap())BoolResult(newExpr);
	    newExpr->bindNode(generator->getBindWA());
	    newValIdSet->insert(newExpr->getValueId());

	    // no need to assign data attrs to newExpr anymore.
	    newExpr = 0;

	    // no need to generate last clause
	    gen_last_clause = 0;
	  }
	  break;

	case ITM_ANY_TRUE:
	  {
	    newExpr = createExprTree("CASE WHEN @B1 IS TRUE THEN @A2 WHEN @B1 IS UNKNOWN THEN @A3 ELSE @A4 END", 0,
				     4,
				     item_expr->child(0),
				     new(wHeap()) BoolVal(ITM_RETURN_TRUE),
				     new(wHeap()) BoolVal(ITM_RETURN_NULL),
				     0);

	    // assign the data attributes of the original aggr node
	    // to the newExpr.
	    // This will make the result of newExpr be moved to the
	    // original aggregate location.
	    newExpr->bindNode(generator->getBindWA());
            Attributes * attr = generator->getMapInfo(val_id)->getAttr();
	    map_info = generator->addMapInfo(newExpr->getValueId(), attr);
	    (map_info->getAttr())->copyLocationAttrs(attr);

	    // generate the expression that would return TRUE back
	    // to the caller which would short circuit.
	    // BTW, BoolResult returns TRUE only if its operand
	    // has evaluated to TRUE.
	    newExpr = new(wHeap())  BoolResult(newExpr);
	    newExpr->bindNode(generator->getBindWA());
	    newValIdSet->insert(newExpr->getValueId());

	    // no need to assign data attrs to newExpr anymore.
	    newExpr = 0;

	    // no need to generate last clause
	    gen_last_clause = 0;
	  }
	  break;

	case ITM_ONE_ROW:
	  {
            // Just create a dummy ONE_ROW aggregate node. Nothing is going
            // to be done on the atp at runtime anyway. We just want a one_row
            // clause generated so that we can keep track of the number of rows
            // returned so far.
            //
            newExpr = new(wHeap()) Aggregate(ITM_ONE_ROW,
                                             new(wHeap()) ConstValue(0),
                                             FALSE,
                                             ITM_ONE_ROW,' ');
	    newExpr->bindNode(generator->getBindWA());

            // Just create an entry in the map table. It won't be used anyway.
	    map_info = generator->addMapInfo(newExpr->getValueId(),0);

            // Just use the same location attrs as the original aggr. It won't
            // be used anyway.
            Attributes * attr = generator->getMapInfo(val_id)->getAttr();
	    (map_info->getAttr())->copyLocationAttrs(attr);

	     // So that a one_row_aggr clause can be generated in a later call.
            newValIdSet->insert(newExpr->getValueId());
            newExpr = NULL;

	  }
	  break;

	case ITM_ANY_TRUE_MAX:
	  {
	    // no conversion is done for these cases
	    newExpr = item_expr;
	  }
	  break;

	case ITM_PIVOT_GROUP:
	  {
            PivotGroup * pg = (PivotGroup*)item_expr;
            newExpr = 
              new(wHeap()) PivotGroup(ITM_PIVOT_GROUP, item_expr->child(0), 
                                      pg->delim(), pg->orderBy(), pg->reqdOrder(),
                                      pg->maxLen(), pg->isDistinct());
	  }
	  break;

	case ITM_ONEROW:
	  {
	   generator->getMapInfo(val_id)->codeGenerated();

	    const NAType &oneRowType = item_expr->getValueId().getType();
	    newExpr = new(wHeap()) Cast(item_expr->child(0),
					&oneRowType,
					ITM_CAST);
	   if (NOT raiseErrorGenerated)
	   {
	     ItemExpr * raiseError = new(wHeap()) Aggregate(ITM_ONE_ROW,
					       new(wHeap()) ConstValue(0),
					       FALSE,
					       ITM_ONE_ROW,' ');
	      raiseError->bindNode(generator->getBindWA());
	      newExpr = new(wHeap()) ItmBlockFunction(raiseError,newExpr);
	      raiseErrorGenerated = TRUE ;
	   }
	  }
	  break ;


	default:
	  newExpr = NULL;
	  break;

	}

      // assign the data attributes of the aggr node to the newExpr.
      // This will make the result of newExpr be moved to the
      // aggregate location.
      if (newExpr != NULL)
	{
	  newExpr->bindNode(generator->getBindWA());
	  newValIdSet->insert(newExpr->getValueId());
	  newExpr->getValueId().changeType(&(val_id.getType()));

          Attributes * attr = generator->getMapInfo(val_id)->getAttr();
	  map_info = generator->addMapInfo(newExpr->getValueId(), attr);
	  (map_info->getAttr())->copyLocationAttrs(attr);
          if(attr->isForceFixed())
            (map_info->getAttr())->setForceFixed();

	  if (nullSwitcharoo)
	    {
	      NullSwitcharooVidList.insert(val_id);
	      attr->setNullFlag(0);
	    }
	}

    }

  // generate expressions to evaluate GROUPING clause
  ValueIdSet groupingValIdSet;
  for (val_id = val_id_set.init(); 
       val_id_set.next(val_id); 
       val_id_set.advance(val_id))
    {
      ItemExpr * item_expr = val_id.getValueDesc()->getItemExpr();
      if (item_expr->getOperatorType() == ITM_GROUPING)
        {
          generator->getMapInfo(val_id)->codeGenerated();
          Aggregate * ag = (Aggregate*)item_expr;
          ItemExpr * groupingExpr = 
            new(wHeap()) AggrGrouping(ag->getRollupGroupIndex());
	  groupingExpr->bindNode(generator->getBindWA());
	  groupingValIdSet.insert(groupingExpr->getValueId());
          
          Attributes * attr = generator->getMapInfo(val_id)->getAttr();
          map_info = generator->addMapInfo(groupingExpr->getValueId(), attr);
          (map_info->getAttr())->copyLocationAttrs(attr);
        }
    } // for

  ex_expr * grouping_expr = NULL;
  if (NOT groupingValIdSet.isEmpty())
    {
      unsigned short pcm = getPCodeMode();
      setPCodeMode(ex_expr::PCODE_NONE);

      generateSetExpr(groupingValIdSet, ex_expr::exp_ARITH_EXPR,
                      &grouping_expr);

      setPCodeMode(pcm);
    }

  ex_expr * perrec_expr = NULL;
  generateSetExpr(*newValIdSet, ex_expr::exp_ARITH_EXPR, &perrec_expr);

  *expr = new(getSpace()) AggrExpr(init_expr,
				   perrec_expr,
				   0, //final_expr,
				   final_null_expr,
                                   grouping_expr);

  for (CollIndex ns = 0; ns < NullSwitcharooVidList.entries(); ns++)
    {
      map_info = generator->getMapInfo(NullSwitcharooVidList[ns]);
      map_info->getAttr()->setNullFlag(-1);
    }

  return 0;
}

// input is a ValueId which points to an arithmetic expression.
short ExpGenerator::generateArithExpr(const ValueId & val_id,
				      ex_expr::exp_node_type node_type,
				      ex_expr ** expr)

{
  initExprGen();
  startExprGen(expr, node_type);

  // generate code for this node and the tree under it
  ItemExpr * temp =
    val_id.getValueDesc()->getItemExpr()->preCodeGen(generator);
  if (! temp)
    return -1;

  temp = temp->preCodeGen(generator);
  ItemExpr * newTemp = NULL;
  Lng32 rc = foldConstants(temp, &newTemp);
  if ((rc == 0) &&
      (newTemp))
    temp = newTemp;

  temp->codeGen(generator);

  endExprGen(expr, -1);

  return 0;
}

// Deterimine if bulk move for Aligned Format can be done or not.
// If so, then generate the new src / tgt bulk move attribute
short ExpGenerator::generateBulkMoveAligned(
                                ValueIdList inValIdList,
                                ValueIdList &outValIdList,
                                UInt32       tupleLength,
                                Int32       *bulkMoveSrcStartOffset //IN(O)
                                )
{
  // turn bulk move off for aligned format for now until more testing is done
  if (CmpCommon::getDefault(COMPRESSED_INTERNAL_FORMAT_BULK_MOVE) == DF_OFF)
    return 0;

  NABoolean bulkMove = TRUE;

  MapInfo * tgtMapInfo = generator->getMapInfoAsIs(inValIdList[0]);
  MapInfo * srcMapInfo =
               generator->getMapInfoAsIs(inValIdList[0].getItemExpr()->
                                 getChild(0)->castToItemExpr()->getValueId());

  GenAssert( tgtMapInfo, "Null target map info");
  GenAssert( srcMapInfo, "Null source map info");

  Attributes * tgtAttr = tgtMapInfo->getAttr();
  Attributes * srcAttr = srcMapInfo->getAttr();

  UInt32 firstTgtAtp   = tgtAttr->getAtp();
  UInt32 firstSrcAtp   = srcAttr->getAtp();
  UInt32 firstTgtAtpIx = tgtAttr->getAtpIndex();
  UInt32 firstSrcAtpIx = srcAttr->getAtpIndex();

  // Determine if bulk move should be considered for nullable columns.
  // Variable length columns can't be done yet since each row will be
  // a different length (based on the values of the variable column values)
  // and the bulk move attribute can only have 1 length - max row size.??????????????????????
  NABoolean bulkMoveNullVarchar =
                    (CmpCommon::getDefault(BULK_MOVE_NULL_VARCHAR) == DF_ON);


  UInt32 voaOffset = 0;
  Int16 vcIndicatorLength=0;
  Int16 nullIndicatorLength=0;
  UInt32 alignment = 0;


  for (CollIndex i = 0; ((i < inValIdList.entries()) && (bulkMove)); i++)
  {
    tgtMapInfo = generator->getMapInfoAsIs(inValIdList[i]);
    if (tgtMapInfo)
      tgtAttr = tgtMapInfo->getAttr();
    else
      tgtAttr = 0;

    srcMapInfo =
      generator->getMapInfoAsIs(inValIdList[i].
                   getItemExpr()->getChild(0)->castToItemExpr()->getValueId());

    if (srcMapInfo)
      srcAttr = srcMapInfo->getAttr();
    else
      srcAttr = 0;

    if (srcAttr && srcAttr->getVCIndicatorLength() && srcAttr->getVoaOffset()> voaOffset)
    {
      voaOffset = srcAttr->getVoaOffset();
      vcIndicatorLength = srcAttr->getVCIndicatorLength();
      nullIndicatorLength = srcAttr->getNullIndicatorLength();

      alignment =  (srcAttr->isSQLMXAlignedFormat() &&
                          (srcAttr->getNextFieldIndex() == ExpOffsetMax))
                          ? ExpAlignedFormat::ALIGNMENT : 0;

    }
    // Must have both the source and target attributes in the same data format
    // to do a bulk move.  Target was checked before getting into this routine.
    if ((srcAttr && (NOT srcAttr->isSQLMXAlignedFormat())) ||
       (tgtAttr &&  (NOT tgtAttr->isSQLMXAlignedFormat())))
      return 0;

    if ((! tgtAttr)                                              ||
        (! srcAttr)                                              ||
        (tgtAttr->getTupleFormat()       != srcAttr->getTupleFormat()) ||
        (tgtAttr->getDatatype()          != srcAttr->getDatatype())    ||
        ((NOT bulkMoveNullVarchar) &&
         (tgtAttr->getNullFlag() || srcAttr->getNullFlag()))           ||
        (tgtAttr->getNullFlag()          != srcAttr->getNullFlag())    ||
        (tgtAttr->getScale()             != srcAttr->getScale())       ||
        (tgtAttr->getPrecision()         != srcAttr->getPrecision())   ||
        (tgtAttr->getLength()            != srcAttr->getLength())      ||
        (srcAttr->getAtpIndex() == 0)                                  ||
        (srcAttr->getAtpIndex() == 1)                                  ||
        ((UInt32)tgtAttr->getAtp()       != firstTgtAtp)          ||
        ((UInt32)srcAttr->getAtp()       != firstSrcAtp)          ||
        ((UInt32)tgtAttr->getAtpIndex()  != firstTgtAtpIx)        ||
        ((UInt32)srcAttr->getAtpIndex()  != firstSrcAtpIx)        ||
        (tgtAttr->getOffset()            != srcAttr->getOffset()) ||
        (tgtAttr->getNullIndOffset()     != srcAttr->getNullIndOffset())  ||
        (tgtAttr->getNullBitIndex()      != srcAttr->getNullBitIndex())   ||
        //(srcAttr->getVCIndicatorLength() > 0)                          ||
	(tgtAttr->getVCIndicatorLength() != srcAttr->getVCIndicatorLength()) ||
        (tgtAttr->getVCLenIndOffset()    != srcAttr->getVCLenIndOffset()) ||
        (tgtAttr->getNullIndOffset()     != srcAttr->getNullIndOffset())   ||
        (tgtAttr->getVoaOffset()         != srcAttr->getVoaOffset())  ||
        (srcAttr->isAddedCol()) ||
        (tgtAttr->isAddedCol()))
    bulkMove = FALSE;
  }

  if (bulkMove == TRUE)
  {
    for (CollIndex i = 0; (i < inValIdList.entries()); i++)
    {
      outValIdList.insert(inValIdList[i].
                    getItemExpr()->getChild(0)->castToItemExpr()->getValueId());
    }

    // 5/21/98: Since the tuple is to be moved as a byte array,
    // the current SQLChar constructor should be sufficient.

    NAType * type = new(generator->wHeap()) SQLChar(generator->wHeap(), (Int32)tupleLength, FALSE);
    ItemExpr * bulkMoveSrc = new(generator->wHeap()) NATypeToItem(type);
    //ItemExpr * bulkMoveTgt = new(generator->wHeap()) Convert (bulkMoveSrc);
    ItemExpr * bulkMoveTgt = new(generator->wHeap()) Convert (bulkMoveSrc,
                                                              voaOffset,
                                                              vcIndicatorLength,
                                                              nullIndicatorLength,
                                                              alignment);

    bulkMoveTgt->synthTypeAndValueId();

    Attributes * tgtAttr = generator->getMapInfo(inValIdList[0])->getAttr();
    Attributes * srcAttr =
      generator->getMapInfo(inValIdList[0].getItemExpr()->getChild(0)->castToItemExpr()->getValueId())->getAttr();

    Attributes * bulkMoveTgtAttr =
                  generator->addMapInfo(bulkMoveTgt->getValueId(), 0)->getAttr();
    Attributes * bulkMoveSrcAttr =
                  generator->addMapInfo(bulkMoveSrc->getValueId(), 0)->getAttr();

    bulkMoveTgtAttr->copyLocationAttrs(tgtAttr);

    bulkMoveSrcAttr->copyLocationAttrs(srcAttr);

    // Bulk move is only done when the complete data row is the same for
    // all source attributes and target attributes.  The starting offset must
    // encompass the Aligned Format header thus set it to 0.
    UInt32 bulkSrcStartOffset = 0;
    UInt32 bulkTgtStartOffset = 0;

    bulkMoveSrcAttr->setOffset( bulkSrcStartOffset );
    bulkMoveTgtAttr->setOffset( bulkTgtStartOffset );

    // If orignal source was a varchar, then must change the bulk src/tgt
    // attribute vc indicator length back to 0 since these are now fixed
    // char's.
    if (srcAttr->isVariableLength())
    {
      bulkMoveSrcAttr->setVCIndicatorLength(0);
      bulkMoveTgtAttr->setVCIndicatorLength(0);
    }

    // Both source and destinations are no longer rowsets
    bulkMoveTgtAttr->setRowsetSize(0);
    bulkMoveSrcAttr->setRowsetSize(0);

    outValIdList.insert(bulkMoveTgt->getValueId());

    if (bulkMoveSrcStartOffset) // param passed in.
    {
      *bulkMoveSrcStartOffset = bulkSrcStartOffset;
    }
  }
  return 0;
}

// Generate a bulk move of the input value Ids if possible.  There are very
// specific conditions for this to be possible - listed below.
// This routine handles the Exploded Internal format and branches to
// the routine ExpGenerator::generateBulkMoveAligned if the target attribute
// has data format Compressed Internal format.
short ExpGenerator::generateBulkMove(ValueIdList inValIdList,
				     ValueIdList &outValIdList,
				     ULng32 tupleLength,
				     Lng32 *bulkMoveSrcStartOffset) //IN(O)
{
  if (bulkMoveSrcStartOffset) // param passed in.
    {
      *bulkMoveSrcStartOffset = -1;
    }

  // no need to check for bulk move if list is empty.
  if (inValIdList.entries() == 0)
    return 0;

  NABoolean bulkMove = TRUE;

  MapInfo * tgtMapInfo;
  MapInfo * srcMapInfo;

  Attributes * tgtAttr;
  Attributes * srcAttr;

  tgtMapInfo = generator->getMapInfoAsIs(inValIdList[0]);

  if (!tgtMapInfo)
    return 0; // must be in maptable to check for bulkmove attrs

  tgtAttr = tgtMapInfo->getAttr();

  srcMapInfo = generator->getMapInfoAsIs(inValIdList[0].getItemExpr()->getChild(0)->castToItemExpr()->getValueId());

  if (!srcMapInfo)
    return 0; // must be in maptable to check for bulkmove attrs

  srcAttr = srcMapInfo->getAttr();

  // If there is only 1 input value id and the associated attribute is
  // not nullable, then bulk move is not needed.
  if ((NOT bulkMoveSrcStartOffset)  // parameter not passed in
      && (inValIdList.entries() == 0)
      && (NOT srcAttr->getNullFlag()))
    return 0;

  // The Compressed Internal format (ie. the Aligned Row Format) has a
  // different criteria when bulk move can be applied.
  // See the method comments for details.
  if ( tgtAttr && tgtAttr->isSQLMXAlignedFormat() )
  {
    return generateBulkMoveAligned( inValIdList,
                                    outValIdList,
                                    tupleLength,
                                    bulkMoveSrcStartOffset );
  }

  // Now only the Exploded Internal format exists as a possibility.
  UInt32 firstTgtAtp = tgtAttr->getAtp();
  UInt32 firstSrcAtp = srcAttr->getAtp();
  UInt32 firstTgtAtpIx = tgtAttr->getAtpIndex();
  UInt32 firstSrcAtpIx = srcAttr->getAtpIndex();
  Int32 firstTgtOffset = tgtAttr->getOffset();
  Int32 firstSrcOffset = srcAttr->getOffset();
  Int32 firstTgtNullOffset = ExpOffsetMax;
  Int32 firstSrcNullOffset = ExpOffsetMax;
  Int32 firstTgtVCLenIndOffset = ExpOffsetMax;
  Int32 firstSrcVCLenIndOffset = ExpOffsetMax;

  // Determine if bulk move should be considered for nullable and/or variable
  // length column values.
  NABoolean bulkMoveNullVarchar =
                    (CmpCommon::getDefault(BULK_MOVE_NULL_VARCHAR) == DF_ON);

  for (CollIndex i = 0;
       ((i < inValIdList.entries()) && (bulkMove));
       i++)
    {
      tgtMapInfo = generator->getMapInfoAsIs(inValIdList[i]);
      if (tgtMapInfo)
	tgtAttr = tgtMapInfo->getAttr();
      else
	tgtAttr = 0;

      srcMapInfo =
	generator->getMapInfoAsIs(inValIdList[i].getItemExpr()->getChild(0)->castToItemExpr()->getValueId());
      if (srcMapInfo)
	srcAttr = srcMapInfo->getAttr();
      else
	srcAttr = 0;

      // initialize the first offset variables
      if (tgtAttr && tgtAttr->getNullFlag() && 
         (firstTgtNullOffset == ExpOffsetMax))
        firstTgtNullOffset = tgtAttr->getNullIndOffset();
      if (srcAttr && srcAttr->getNullFlag() && 
         (firstSrcNullOffset == ExpOffsetMax))
        firstSrcNullOffset = srcAttr->getNullIndOffset();
      if (tgtAttr && tgtAttr->isVariableLength() && 
         (firstTgtVCLenIndOffset == ExpOffsetMax))
        firstTgtVCLenIndOffset = tgtAttr->getVCLenIndOffset();
      if (srcAttr && srcAttr->isVariableLength() && 
         (firstSrcVCLenIndOffset == ExpOffsetMax))
        firstSrcVCLenIndOffset = srcAttr->getVCLenIndOffset();

      if ((! tgtAttr)                                                  ||
          (! srcAttr)                                                  ||
          ((NOT bulkMoveNullVarchar) &&
           (tgtAttr->getNullFlag() || srcAttr->getNullFlag()))         ||
          (tgtAttr->getNullFlag()    != srcAttr->getNullFlag())        ||
          (tgtAttr->getTupleFormat() != srcAttr->getTupleFormat())     ||
          (tgtAttr->getDatatype()    != srcAttr->getDatatype())        ||
          (tgtAttr->getScale()       != srcAttr->getScale())           ||
          (tgtAttr->getPrecision()   != srcAttr->getPrecision())       ||
          (tgtAttr->getLength()      != srcAttr->getLength())          ||
          ((UInt32)tgtAttr->getAtp() != firstTgtAtp)                   ||
          ((UInt32)srcAttr->getAtp() != firstSrcAtp)                   ||
          ((UInt32)tgtAttr->getAtpIndex() != firstTgtAtpIx)            ||
          ((UInt32)srcAttr->getAtpIndex() != firstSrcAtpIx)            ||
          ((tgtAttr->getOffset() - firstTgtOffset)
            != (srcAttr->getOffset() - firstSrcOffset))                ||
          (tgtAttr->getNullFlag() &&
            ((tgtAttr->getOffset() - tgtAttr->getNullIndOffset()) 
              != (srcAttr->getOffset() - srcAttr->getNullIndOffset())))  ||
          (tgtAttr->getNullFlag() &&
            ((tgtAttr->getNullIndOffset() - firstTgtNullOffset) 
              != (srcAttr->getNullIndOffset() - firstSrcNullOffset)))  ||    
          ((NOT bulkMoveNullVarchar) &&
           ((tgtAttr->getVCIndicatorLength() > 0) 
            || (srcAttr->getVCIndicatorLength() > 0)))                 ||
          (tgtAttr->isVariableLength() &&
           ((tgtAttr->getVCLenIndOffset() - firstTgtVCLenIndOffset)
             != (srcAttr->getVCLenIndOffset() - firstSrcVCLenIndOffset))) ||
          (srcAttr->getAtpIndex() == 0)     ||
          (srcAttr->getAtpIndex() == 1)     ||
          (srcAttr->isAddedCol())       ||
          (tgtAttr->isAddedCol()))
      bulkMove = FALSE;
  }

  if (bulkMove == TRUE)
    {
      for (CollIndex i = 0; (i < inValIdList.entries()); i++)
	{
	  outValIdList.insert(inValIdList[i].getItemExpr()->getChild(0)->castToItemExpr()->getValueId());
	}

// 5/21/98: Since the tuple is to be moved as a byte array,
// the current SQLChar constructor should be sufficient.

      NAType * type = new(generator->wHeap()) SQLChar(generator->wHeap(), tupleLength, FALSE);
      ItemExpr * bulkMoveSrc = new(generator->wHeap()) NATypeToItem(type);
      ItemExpr * bulkMoveTgt = new(generator->wHeap()) Convert (bulkMoveSrc);
      bulkMoveTgt->synthTypeAndValueId();

      Attributes * tgtAttr =
	generator->getMapInfo(inValIdList[0])->getAttr();
      Attributes * srcAttr =
	generator->getMapInfo(inValIdList[0].getItemExpr()->getChild(0)->castToItemExpr()->getValueId())->getAttr();

      Attributes * bulkMoveTgtAttr = generator->addMapInfo(bulkMoveTgt->getValueId(), 0)->getAttr();
      Attributes * bulkMoveSrcAttr = generator->addMapInfo(bulkMoveSrc->getValueId(), 0)->getAttr();

      bulkMoveTgtAttr->copyLocationAttrs(tgtAttr);

      bulkMoveSrcAttr->copyLocationAttrs(srcAttr);

      UInt32 bulkSrcStartOffset = srcAttr->getOffset();
      UInt32 bulkTgtStartOffset = tgtAttr->getOffset();

      // Since the src / tgt attributes may be nullable or variable
      // must get the correct beginning offset to use and set it in the
      // new corresponding bulk attribute.
      if ( srcAttr->getNullFlag() )
        bulkSrcStartOffset = srcAttr->getNullIndOffset();
      else if ( srcAttr->isVariableLength() )
        bulkSrcStartOffset = srcAttr->getVCLenIndOffset();
           
      if ( tgtAttr->getNullFlag() )
        bulkTgtStartOffset = tgtAttr->getNullIndOffset();
      else if ( tgtAttr->isVariableLength() )
        bulkTgtStartOffset = tgtAttr->getVCLenIndOffset();
            
      bulkMoveSrcAttr->setOffset( bulkSrcStartOffset );
      bulkMoveTgtAttr->setOffset( bulkTgtStartOffset );

      // If orignal source was a varchar, then must change the bulk src/tgt
      // attribute vc indicator length back to 0 since these are now fixed
      // char's.
      if (srcAttr->isVariableLength())
      {
        bulkMoveSrcAttr->setVCIndicatorLength(0);
        bulkMoveTgtAttr->setVCIndicatorLength(0);
      }

      // Both source and destinations are no longer rowsets
      bulkMoveTgtAttr->setRowsetSize(0);

      bulkMoveSrcAttr->setRowsetSize(0);

      outValIdList.insert(bulkMoveTgt->getValueId());

      if (bulkMoveSrcStartOffset) // param passed in.
	{
          *bulkMoveSrcStartOffset = (Int32)bulkMoveSrcAttr->getOffset();
          // If the field is nullable, then its null indicator offset
          // Else if the field is a varchar, then its var len indicator offset
          if (bulkMoveSrcAttr->getNullIndicatorLength() > 0)
            *bulkMoveSrcStartOffset = (Int32)bulkMoveSrcAttr->getNullIndOffset();
          else if (bulkMoveSrcAttr->isVariableLength())
            *bulkMoveSrcStartOffset = (Int32)bulkMoveSrcAttr->getVCLenIndOffset();
	}
    }

  return 0;
}


//////////////////////////////////////////////////////////////////////
// See GenExpGenerator.h for comments.
///////////////////////////////////////////////////////////////////////
short ExpGenerator::generateContiguousMoveExpr(
					       const ValueIdList & valIdList,
					       short addConvNodes,
					       Int32 atp,
					       Int32 atpIndex,
					       ExpTupleDesc::TupleDataFormat tdataF,
					       ULng32 &tupleLength,
					       ex_expr ** moveExpr,
					       ExpTupleDesc ** tupleDesc,
					       ExpTupleDesc::TupleDescFormat tdescF,
					       MapTable ** newMapTable,
					       ValueIdList *tgtValues,
					       ULng32 startOffset,
					       Lng32 * bulkMoveSrcStartOffset,
					       NABoolean disableConstFolding,
                                               NAColumnArray *colArray,
                                               NABoolean doBulkMoves)
{
  // ---------------------------------------------------------------------
  // Generate an expression to take scattered values (given in valIdList)
  // and copy them to a contiguous buffer tuple (atp,atpIndex). The values
  // are allocated in the tuple in the sequence given in valIdList.
  // On request, the method also returns a map table with new attributes
  // for the value ids in valIdList and a list of the target expressions
  // that were generated.
  // ---------------------------------------------------------------------
  // a list with convert nodes corresponding to valIdList
  ValueIdList convValIdList;

  // Allocate a new map table that describes the value ids in valIdList
  // and convValList. Append it to the end of the list of map tables.
  MapTable *contBufferMapTable = generator->appendAtEnd();

  // should we use a temporary map table for the convert nodes? $$$$

  // ---------------------------------------------------------------------
  // For each value in the list, put a convert node on its top which
  // will take care of the move. Assign attributes for all those convert
  // nodes such that they are stored adjacently in a single tuple
  // (the one described by (atp, atpIndex)).
  // ---------------------------------------------------------------------

  NABoolean alignedFormat = (tdataF == ExpTupleDesc::SQLMX_ALIGNED_FORMAT);
  Attributes ** attrs = new(wHeap()) Attributes * [valIdList.entries()];
  NAColumn *col;
  for (CollIndex i = 0; i < valIdList.entries(); i++)
    {
      ItemExpr * itemExpr = valIdList[i].getItemExpr();

      ItemExpr * convNode;
      if (addConvNodes)
	{
	  // add the convert node
	  convNode = new(wHeap()) Convert (itemExpr);
	  convNode->bindNode(generator->getBindWA());
	}
      else
	convNode = itemExpr;

      convNode->setConstFoldingDisabled(TRUE);
      if (NOT disableConstFolding)
	{
	  convNode->preCodeGen(generator);
	  foldConstants(convNode, NULL);
	}

      // bind/type propagate the new/old node
      convNode->bindNode(generator->getBindWA());
      ValueId convValueId = convNode->getValueId();

      // get a pointer to the map table attributes and set them the
      // way we want them to be
      if (addConvNodes)
	attrs[i] = (generator->addMapInfoToThis(contBufferMapTable, convValueId, 0))->getAttr();
      else
	attrs[i] = (generator->addMapInfo(convValueId, 0))->getAttr();

      if ( alignedFormat  &&
           (colArray == NULL) &&
           ((col = valIdList[i].getNAColumn( TRUE )) != NULL) &&
           col->isAddedColumn() )
        attrs[i]->setAddedCol();

      convValIdList.insert(convValueId);
    }

  // Ensure added columns are tagged before computing offset for the aligned
  // record format since added columns are arranged differently.
  //  if ( (colArray != NULL) && alignedFormat )
  if ( (colArray != NULL) )
  {
    for( Int32 i = 0; i < (Int32)colArray->entries(); i++ )
    {
      col = (*colArray)[i];
      addDefaultValue(col, attrs[i], CmpCommon::diags()); 
    }
  }

  // If generating a contiguous move expression where the target tuple data
  // format is a disk format - Packed or Aligned - then header information
  // must be gathered during processing the attributes. This allows a new 
  // header clause to be generated during endExprGen()
  ExpHdrInfo *hdrInfo = NULL;
  if ( isHeaderNeeded(tdataF) )
    hdrInfo = new( wHeap() )ExpHdrInfo();

  // compute offsets and create tuple descriptor.
  processAttributes((ULng32)valIdList.entries(), attrs, tdataF,
		    tupleLength, atp, atpIndex,  tupleDesc, tdescF,
                    startOffset, hdrInfo);

  // deallocate the attributes array. Don't deallocate the attributes
  // pointed to by the array entries since we didn't allocate them.
  NADELETEBASIC(attrs,wHeap());

  // if bulkmovesrcstartoffset passed in is -2, then always generate
  // move expression even if bulk move using bulkmovesrcstartoffset
  // could be done.
  NABoolean alwaysGenMoveExpr = FALSE;
  if ((moveExpr) &&
      (bulkMoveSrcStartOffset) &&
      (*bulkMoveSrcStartOffset == -2))
    alwaysGenMoveExpr = TRUE;

  ValueIdList bulkMoveValueIdList;

  // Since convert nodes are asked for, check if a bulk move of all source
  // values can be done to the target.
  // if asked not to do bulk move, don't do it.
  if (addConvNodes && doBulkMoves)
  {
    if (generateBulkMove(convValIdList, bulkMoveValueIdList,
                         tupleLength,
                         bulkMoveSrcStartOffset) == -1)
      return -1;

    // If bulk move will be used, then no header clause needs
    // to be generated.
    if (hdrInfo  &&  bulkMoveValueIdList.entries() > 0)
    {
      NADELETEBASIC( hdrInfo, wHeap() );
      hdrInfo = NULL;
    }
  }

  ValueIdList * newValIdList;

  if (bulkMoveValueIdList.entries() > 0)
    newValIdList = &bulkMoveValueIdList;
  else
    newValIdList = &convValIdList;

  // generate the copy expression, if moveExpr is passed in,
  // and bulk move info is not to be returned
  // or bulk move info is to be returned but bulk move is not being done.
  if ((moveExpr) &&
      ((! bulkMoveSrcStartOffset) ||
       (*bulkMoveSrcStartOffset == -1) ||
       (alwaysGenMoveExpr)))
  {
    generateListExpr(*newValIdList, ex_expr::exp_ARITH_EXPR, moveExpr,
                     atp, atpIndex, hdrInfo);

    if ( newValIdList != &convValIdList )
    {
      for (int j =0; (UInt32)j< convValIdList.entries(); j++)
      {
        generator->getMapInfo(convValIdList[j])->codeGenerated();
      }
    }

    if ( hdrInfo != NULL )
    {
      NADELETEBASIC( hdrInfo, wHeap() );
    }
  }

  // if the user requested a map table back, make a new map table and
  // add all the original value ids to it, but assign the attributes
  // of the new, contiguous buffers
  if (newMapTable)
    {
      generator->appendAtEnd();
      *newMapTable = generator->unlinkLast();
      for (CollIndex i = 0; i < valIdList.entries(); i++)
	{
	  // don't add constants. Constants have a fixed location
	  // (atp_index = 0) and are added whenever they are used in an
	  // expression.
	  if (convValIdList[i].getItemExpr()->getOperatorType() !=
	      ITM_CONSTANT)
	    {
	      // Get the attributes of the contiguous buffer...
	      Attributes *contAttrib =
		generator->getMapInfo((convValIdList)[i])->getAttr();

	      // ...add it to the new map table as if it belonged to
	      // the original value id...
              MapInfo * mapInfo =
                generator->addMapInfoToThis((*newMapTable), valIdList[i],contAttrib);

	      // ... and make sure no more code gets generated for it.
	      mapInfo->codeGenerated();
	    }
	}
    }

  // if the caller wants to see the generated expressions for the move
  // targets, insert them into the list supplied by the caller
  if (tgtValues != NULL)
    tgtValues->insert(convValIdList);

  return 0;
}

short
ExpGenerator::genGuardedContigMoveExpr(const ValueIdSet guard,
                                       const ValueIdList & valIdList,
                                       short addConvNodes,
                                       Int32 atp,
                                       Int32 atpIndex,
                                       ExpTupleDesc::TupleDataFormat tdataF,
                                       ULng32 &tupleLength,
                                       ex_expr ** moveExpr,
                                       ExpTupleDesc ** tupleDesc,
                                       ExpTupleDesc::TupleDescFormat tdescF,
                                       MapTable ** newMapTable,
                                       ValueIdList *tgtValues,
                                       ULng32 start_offset)
{
  // ---------------------------------------------------------------------
  // Generate an expression to take scattered values (given in valIdList)
  // and copy them to a contiguous buffer tuple (atp,atpIndex). The values
  // are allocated in the tuple in the sequence given in valIdList.
  // On request, the method also returns a map table with new attributes
  // for the value ids in valIdList and a list of the target expressions
  // that were generated.
  // ---------------------------------------------------------------------
  // a list with convert nodes corresponding to valIdList
  ValueIdList convValIdList;

  // Allocate a new map table that describes the value ids in valIdList
  // and convValList. Append it to the end of the list of map tables.
  MapTable *contBufferMapTable = generator->appendAtEnd();

  // should we use a temporary map table for the convert nodes? $$$$

  // ---------------------------------------------------------------------
  // For each value in the list, put a convert node on its top which
  // will take care of the move. Assign attributes for all those convert
  // nodes such that they are stored adjacently in a single tuple
  // (the one described by (atp, atpIndex)).
  // ---------------------------------------------------------------------

  Attributes ** attrs = new(wHeap()) Attributes * [valIdList.entries()];
  for (CollIndex i = 0; i < valIdList.entries(); i++)
    {
      ItemExpr * itemExpr = valIdList[i].getItemExpr();

      ItemExpr * convNode;
      if (addConvNodes)
	{
	  // add the convert node
	  convNode = new(wHeap()) Convert (itemExpr);
	}
      else
	convNode = itemExpr;

      // bind/type propagate the new/old node
      convNode->bindNode(generator->getBindWA());
      ValueId convValueId = convNode->getValueId();

      // get a pointer to the map table attributes and set them the
      // way we want them to be
      if (addConvNodes)
	attrs[i] = (generator->addMapInfoToThis(contBufferMapTable, convValueId, 0))->getAttr();
      else
	attrs[i] = (generator->addMapInfo(convValueId, 0))->getAttr();

      convValIdList.insert(convValueId);
    }

  // compute offsets and create tuple descriptor.
  processAttributes((ULng32)valIdList.entries(), attrs, tdataF,
		    tupleLength, atp, atpIndex,  tupleDesc, tdescF,
		    start_offset);

  // deallocate the attributes array. Don't deallocate the attributes
  // pointed to by the array entries since we didn't allocate them.
  NADELETEBASIC(attrs,wHeap());

  // generate the copy expression
  genGuardedListExpr(guard, convValIdList,ex_expr::exp_ARITH_EXPR,moveExpr);

  // if the user requested a map table back, make a new map table and
  // add all the original value ids to it, but assign the attributes
  // of the new, contiguous buffers
  if (newMapTable)
    {
      generator->appendAtEnd();
      *newMapTable = generator->unlinkLast();
      for (CollIndex i = 0; i < valIdList.entries(); i++)
	{
	  // don't add constants. Constants have a fixed location
	  // (atp_index = 0) and are added whenever they are used in an
	  // expression.
	  if (convValIdList[i].getItemExpr()->getOperatorType() !=
	      ITM_CONSTANT)
	    {
	      // Get the attributes of the contiguous buffer...
	      Attributes *contAttrib =
		generator->getMapInfo((convValIdList)[i])->getAttr();

	      // ...add it to the new map table as if it belonged to
	      // the original value id...
              MapInfo * mapInfo =
                generator->addMapInfoToThis((*newMapTable), valIdList[i],contAttrib);

	      // ... and make sure no more code gets generated for it.
	      mapInfo->codeGenerated();
	    }
	}
    }

  // if the caller wants to see the generated expressions for the move
  // targets, insert them into the list supplied by the caller
  if (tgtValues != NULL)
    tgtValues->insert(convValIdList);

  return 0;
}

//////////////////////////////////////////////////////////////////////
// Input is a ValueIdList to be exploded into a contiguous buffer.
// Every other parameter is similar to generateContiguousMoveExpr.
///////////////////////////////////////////////////////////////////////
short ExpGenerator::generateExplodeExpr(
     const ValueIdList & val_id_list,  // IN
     Int32 atp,                          // IN
     Int32 atpIndex,                     // IN
     ExpTupleDesc::TupleDataFormat tf, // IN
     ULng32 &tupleLength,       // OUT
     ex_expr ** explodeExpr,              // OUT
     ExpTupleDesc ** tupleDesc, // OUT(O)
     ExpTupleDesc::TupleDescFormat tdescF, // IN
     MapTable ** newMapTable,   // OUT(O)
     ValueIdList *tgtValues,    // OUT(O)
     ULng32 start_offset)  // IN(O)
{
  ValueIdList explodeVidList;
  for (CollIndex i = 0; i < val_id_list.entries(); i++)
    {
      ItemExpr * ie = val_id_list[i].getItemExpr();

      ItemExpr * cast_node;
      if (ie->getValueId().getType().getVarLenHdrSize() > 0)
	{
	  // Explode varchars.
	  cast_node = new(generator->wHeap())
	    ExplodeVarchar (ie, &(ie->getValueId().getType()), FALSE);
	}
      else
	{
	  cast_node = new(generator->wHeap())
	    Cast(ie, &(ie->getValueId().getType()));
      }

      // Bind the cast node and insert the value ID into the list.
      //
      cast_node->bindNode(generator->getBindWA());
      explodeVidList.insert(cast_node->getValueId());
    }

  return generateContiguousMoveExpr(explodeVidList, 0/*don't add conv nodes*/,
				    atp, atpIndex, tf, tupleLength,
				    explodeExpr, tupleDesc, tdescF,
				    newMapTable, tgtValues,
				    start_offset);
}

//
// Expression generated for inserts and non-optimized updates to clear
// any header data areas in the buffer being written to.  This expression
// is only generated when the target is one of the 2 SQL/MX disk formats
//    SQLMX_FORMAT or SQLMX_ALIGNED_FORMAT
// For SQLMX_FORMAT the first fixed field area will be cleared,
// for the aligned format, everything up to the first fixed field will
// be cleared (header + entire VOA + bitmap + any padding).
// For the aligned format, the bitmap offset will be set too.
short ExpGenerator::generateHeaderClause( Int32       atp,
                                          Int32       atpIndex,
                                          ExpHdrInfo *hdrInfo)
{
  ExHeaderClause *hdrClause = NULL;
  Int16 numOperands = 1;        // target row that must have its header cleared
  Attributes **attr;

  GenAssert( hdrInfo != NULL, "Null expression" );

  ExpTupleDesc::TupleDataFormat tdf = (hdrInfo->getBitmapEntryOffset() > 0
                                       ? ExpTupleDesc::SQLMX_ALIGNED_FORMAT
                                       : ExpTupleDesc::SQLMX_FORMAT);

  // This is a showplan statement.
  if (getShowplan())
    numOperands = (Int16)(numOperands * 2);

  attr = new(generator->wHeap()) Attributes * [numOperands];

  // Initialize an attribute for the full header.
  attr[0] = (Attributes *)new(generator->wHeap())
                          SimpleType(hdrInfo->getAdminSize(), 1, 0);
  attr[0]->setDatatype(REC_BYTE_F_ASCII);
  attr[0]->setTupleFormat(tdf);
  attr[0]->setOffset(hdrInfo->getStartOffset()); 
  attr[0]->setNullIndicatorLength(0);
  attr[0]->setNullFlag(0);
  attr[0]->setVCIndicatorLength(0);
  attr[0]->setAtpIndex((Int16)atpIndex);
  attr[0]->setAtp((Int16)atp);

  if (getShowplan())
  {
    attr[0]->setShowplan();
    NAString hdrStr = "Hdr";
    ValueId dummyVID(NULL_VALUE_ID);

    attr[1] = new(generator->wHeap())
              ShowplanAttributes(dummyVID,
                                 convertNAString(hdrStr, generator->wHeap()));
  }

  hdrClause = new(getSpace())ExHeaderClause(attr, getSpace(),
                                            hdrInfo->getAdminSize(),
                                            hdrInfo->getBitmapEntryOffset(),
                                            hdrInfo->getBitmapOffset(),
                                            hdrInfo->getFirstFixedOffset());

  // don't end the expression generation since we didn't start it
  // endExprGen (expr, -1);

  // Add clear header clause to the clause_list. This is attached to the
  // expression by the method endExprGen()
  linkClause(0, hdrClause);

  return 0;
}

// input is a ValueId which points to a boolean tree.
// Generate code for the ItemExprTree corresponding
// to this ValueId.
short ExpGenerator::generateExpr(const ValueId & val_id,
				 ex_expr::exp_node_type node_type,
				 ex_expr ** expr)
{
  initExprGen();
  startExprGen(expr, node_type);

  // generate code for this node and the tree under it
  ItemExpr * temp =
    val_id.getValueDesc()->getItemExpr()->preCodeGen(generator);
  if (! temp)
    return -1;
  temp->codeGen(generator);

  endExprGen(expr, 0);

  return 0;
}

///////////////////////////////////////////////////////////////////////////
// This method is used to figure out if keys are to be extracted from base
// table row and encoded at runtime. If encoding is not needed based on
// certain criteria (detailed below), then offset of the first key column
// inside the base table row is returned.
// At runtime, this offset is used to directly access the key values
// from the base row instead of going thru expression evaluator to
// encode each key. This check is done for performance improvement.
//
// Encoding is needed if:
//   -- the datatype of key column needs encoding (for ex, if it is a
//      signed datatype)
//   -- it is a nullable column. This restriction could be removed in future.
//   -- it is a descending key
//   -- the key columns are not 'next' to each other from left to right
//      in the base row
//   -- the difference in offsets of any two consecutive key columns is
//      not the same as the size of first column. This case can happen
//      if columns are aligned inside base row by introducing filler bytes.
//   -- if any column preceding the first key column in the base table
//      is a varchar
//
// RETURN: TRUE,  if key encoding is needed.
//         FALSE, if key encoding is not needed, in this case the
//                firstKeyColumnOffset contains the offset of the first
//                key column inside the base table row.
/////////////////////////////////////////////////////////////////////////////
NABoolean ExpGenerator::processKeyEncodingOptimization(
     const NAColumnArray &allColumns,             /* IN */
     const NAColumnArray &indexKeyColumns,        /* IN */
     const ValueIdList   &indexKey,               /* IN */
     const short keyTag,                          /* IN */
     ULng32 &keyLen,
     ULng32 &firstKeyColumnOffset)
{
  CollIndex prevColNumber;

  // if this is a primary index (base table), then get the position
  // of the first key in the base table.
  // If this is an index, then the index key columns are the stored
  // in the beginning of the index row. Do not use the getPosition()
  // method as that will give the position of the index column in
  // the base table row. The position of the first
  // index key column in the index is 0.
  // NOTE: if this 'assumtion' about index columns changes, then
  // need to change this logic.
  if (keyTag == 0) // primary index
    prevColNumber =
      (CollIndex)indexKeyColumns[0]->getPosition();
  else
    {
      // index
      prevColNumber = (CollIndex)0;
    }

  ValueId prevValId = indexKey[0];

  // make sure that none of the columns preceding the first key column
  // in the base table row is a varchar
  CollIndex i = 0;
  while ( i < prevColNumber )
    {
      if (allColumns.getColumn(i)->getType()->getVarLenHdrSize() > 0)
	return TRUE;
      else
	i++;
    }

  keyLen = 0;
  const CollIndex indexKeyEntries = indexKey.entries();
  Attributes * prevAttr = generator->getMapInfo(prevValId)->getAttr();
  for (i = 0; i < indexKeyEntries; i++)
    {
      ValueId valId = indexKey[i];

      NAColumn * naCol = indexKeyColumns.getColumn(i);

      Attributes * thisAttr = generator->getMapInfo(valId)->getAttr();

      if ((valId.getType().isEncodingNeeded() == TRUE)  ||
	  ((valId.getType().getTypeQualifier() == NA_CHARACTER_TYPE) &&  
	   ((((CharType&)valId.getType()).isCaseinsensitive())  ||
           (CollationInfo::isSystemCollation(((CharType&)valId.getType()).getCollation())))) ||
	  (valId.getType().supportsSQLnull()  == TRUE)  ||
	  (indexKeyColumns.isAscending(i) == FALSE)     ||
	  ((naCol->getPosition() - prevColNumber) < 0)   ||
	  ((naCol->getPosition() - prevColNumber) > 1)   ||
	  ((thisAttr->getOffset() - prevAttr->getOffset())
	   > prevAttr->getStorageLength())               ||
          (!naCol->isStoredOnDisk()))
	return TRUE;

      prevColNumber = naCol->getPosition();
      prevValId = valId;
      prevAttr = thisAttr;
      keyLen += prevAttr->getStorageLength();
    }

  firstKeyColumnOffset = generator->getMapInfo(indexKey[0])->getAttr()->getOffset();

  return FALSE;
}

NABoolean ExpGenerator::isKeyEncodingNeeded(const IndexDesc * indexDesc,
					    ULng32 &keyLen,
					    ULng32 &firstKeyColumnOffset)
{
  return processKeyEncodingOptimization(
       indexDesc->getNAFileSet()->getAllColumns(),
       indexDesc->getNAFileSet()->getIndexKeyColumns(),
       indexDesc->getIndexKey(),
       indexDesc->getNAFileSet()->getKeytag(),
       keyLen,
       firstKeyColumnOffset);
}

// input is the index descriptor. Generate an expression to
// extract and encode the key of the table and create a
// contiguous row of encoded keys.
// If optimizeKeyEncoding is TRUE, then check to see if encoding could
// be avoided. If so, return the offset to the first key column in
// the data row.
short ExpGenerator::generateKeyEncodeExpr(const IndexDesc * indexDesc,
					  Int32 atp, Int32 atp_index,
					  ExpTupleDesc::TupleDataFormat tf,
					  ULng32 &keyLen,
					  ex_expr ** encode_expr,
					  NABoolean optimizeKeyEncoding,
					  ULng32 &firstKeyColumnOffset,
					  const ValueIdList * inKeyList,
					  NABoolean handleSerialization)
{
  if ((optimizeKeyEncoding == TRUE) &&
      (isKeyEncodingNeeded(indexDesc, keyLen, firstKeyColumnOffset) == FALSE))
    return 0;

  MapTable * mapTable = generator->getMapTable();

  ValueIdList encode_val_id_list;
  CollIndex i = 0;

  Lng32 numEntries = indexDesc->getIndexKey().entries();
  if (inKeyList)
    numEntries = MINOF(inKeyList->entries(),  indexDesc->getIndexKey().entries());

  for (i = 0; i < numEntries; i++)
    {
      // Allocate convert node
      // to move the key value to the key buffer.
      ItemExpr * col_node = 
	(inKeyList ? (*inKeyList)[i].getItemExpr() : 
	 (indexDesc->getIndexKey())[i].getItemExpr());

      short desc_flag = TRUE;
      if ((indexDesc->getNAFileSet()->getIndexKeyColumns()).isAscending(i))
	desc_flag = FALSE;
      
      if ((tf == ExpTupleDesc::SQLMX_KEY_FORMAT) &&
	  (col_node->getValueId().getType().getVarLenHdrSize() > 0) &&
          (NOT ((indexDesc->getNAFileSet()->getIndexKeyColumns()[i])->isPrimaryKeyNotSerialized())))
	{
	  // Explode varchars by moving them to a fixed field
	  // whose length is equal to the max length of varchar.
	  
	  // handle different character set cases.
          const CharType& char_t =
	    (CharType&)(col_node->getValueId().getType());
	  if (!CollationInfo::isSystemCollation(char_t.getCollation()))
	    {
	      col_node = new(wHeap())
		Cast (col_node,
		      (new(wHeap())
		       SQLChar(wHeap(), CharLenInfo(char_t.getStrCharLimit(), char_t.getDataStorageSize()),
			       col_node->getValueId().getType().supportsSQLnull(),
			       FALSE, FALSE, FALSE,
			       char_t.getCharSet(),
			       char_t.getCollation(),
			       char_t.getCoercibility()
			       )
		       )
		      );
	    }
	}

      ItemExpr * enode = NULL;
      if (handleSerialization)
	{
	  NAColumn * nac = indexDesc->getNAFileSet()->getIndexKeyColumns()[i];
          NABoolean isAlignedRowFormat = indexDesc->getNAFileSet()->isSqlmxAlignedRowFormat();
	  if ((!isAlignedRowFormat) && CmpSeabaseDDL::isEncodingNeededForSerialization(nac))
	    {
	      if (desc_flag)
		{
		  // this value is in serializable encoded form. Decode it before generating the
		  // key expr. Do this only if the new key order is different than the original
		  // order. Original encoding is in ascending order.
		  col_node = new(generator->wHeap()) CompDecode
		    (col_node, &col_node->getValueId().getType(),
		     FALSE, TRUE);
		}
	      else
		// col_node is already in encoded format.
		enode = 
		  new(generator->wHeap()) Cast(col_node, &col_node->getValueId().getType());
	    } // encoding/decoding needed
	} // handleSerialization

      if (enode == NULL)
        {
          if (NOT ((indexDesc->getNAFileSet()->getIndexKeyColumns()[i])->isPrimaryKeyNotSerialized()))
            enode = new(wHeap()) CompEncode(col_node, desc_flag);
          else 
            enode = 
              new(generator->wHeap()) Cast(col_node, &col_node->getValueId().getType());
        }            
      
      enode->bindNode(generator->getBindWA());

      encode_val_id_list.insert(enode->getValueId());
    }

  generateContiguousMoveExpr(encode_val_id_list,
			     0, // don't add convert nodes,
			     atp,
			     atp_index,
			     tf,
			     keyLen,
			     encode_expr);

  return 0;
}

short ExpGenerator::generateDeserializedMoveExpr(
						 const ValueIdList & valIdList,
						 Int32 atp,
						 Int32 atpIndex,
						 ExpTupleDesc::TupleDataFormat tdataF,
						 ULng32 &tupleLength,
						 ex_expr ** moveExpr,
						 ExpTupleDesc ** tupleDesc,
						 ExpTupleDesc::TupleDescFormat tdescF,
						 ValueIdList &deserVIDlist,
						 ValueIdSet &alreadyDeserialized)
{
  for (Lng32 i = 0; i < valIdList.entries(); i++)
    {
      ValueId vid = valIdList[i];
      NAColumn * nac = vid.getNAColumn( TRUE );

      ItemExpr * ie = NULL;
      if (nac && CmpSeabaseDDL::isEncodingNeededForSerialization(nac) &&
	  !alreadyDeserialized.contains(vid))
	{
	  ie = new(generator->wHeap()) CompDecode(vid.getItemExpr(), &vid.getType(),
						  FALSE, TRUE);
	}
      else
	{
	  ie = new(generator->wHeap()) Cast(vid.getItemExpr(), &vid.getType());
	}

      ie->bindNode(generator->getBindWA());
      deserVIDlist.insert(ie->getValueId());
    }

  return generateContiguousMoveExpr(
				    deserVIDlist,
				    0, // no conv nodes
				    atp, atpIndex,
				    tdataF,
				    tupleLength,
				    moveExpr,
				    tupleDesc,
				    tdescF);
}

short ExpGenerator::generateExtractKeyColsExpr(
					       const ValueIdList &colVidList,//const IndexDesc * indexDesc,
					       Int32 atp, Int32 atp_index,
					       ULng32 &keyLen,
					       ex_expr ** key_cols_expr)
{
  ValueIdList val_id_list;
  CollIndex i = 0;
  for (i = 0; i < colVidList.entries(); i++)
    //  for (i = 0; i < indexDesc->getIndexColumns().entries(); i++)
    {
      ItemExpr * col_node = colVidList[i].getItemExpr();

      val_id_list.insert(col_node->getValueId());
    }

  generateContiguousMoveExpr(val_id_list,
			     1, // add convert nodes,
			     atp,
			     atp_index,
			     ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
			     keyLen,
			     key_cols_expr);

  return 0;
}

short ExpGenerator::generateKeyColValueExpr(
					    const ValueId vid,
					    Int32 atp, Int32 atp_index,
					    ULng32 &len,
					    ex_expr ** colValExpr)
{

  ItemExpr * eq_node = (vid.getValueDesc())->getItemExpr();

  ItemExpr * keycol = ((*eq_node)[0])->castToItemExpr();
  ItemExpr * keyval = ((*eq_node)[1])->castToItemExpr();

  keyval = keyval->preCodeGen(generator);

  const NAType * sourceType = &(keyval->getValueId().getType());
  const NAType * targetType = &(keycol->getValueId().getType());

  NABoolean generateNarrow = sourceType->errorsCanOccur(*targetType);

  // if narrow is to be generated or varchar key col, then checkAndDelete opt
  // cannot be done (for now).
  if (NOT ((generateNarrow) ||(targetType->getVarLenHdrSize() > 0)))
    {
      ItemExpr * cv = NULL;
      cv = new(wHeap()) Cast(keyval, targetType);

      if (HbaseAccess::isEncodingNeededForSerialization(keycol))
	{
	  cv = new(generator->wHeap()) CompEncode
	    (cv, FALSE, -1, CollationInfo::Sort, TRUE);
	}

      cv = cv->bindNode(generator->getBindWA());
      cv = cv->preCodeGen(generator);

      ValueIdList val_id_list;
      val_id_list.insert(cv->getValueId());
      generateContiguousMoveExpr(val_id_list,
				 0, // no conv nodes
				 atp,
				 atp_index,
				 ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
				 len,
				 colValExpr);
    }

  return 0;
}


ItemExpr * ExpGenerator::generateKeyCast(const ValueId vid,
					 ItemExpr * dataConversionErrorFlag,
					 NABoolean desc_flag,
					 ExpTupleDesc::TupleDataFormat tf,
					 Lng32 &possibleErrorCount,
					 NABoolean allChosenPredsAreEqualPreds,
                                         NABoolean castVarcharToAnsiChar)
{

  ItemExpr * eq_node = (vid.getValueDesc())->getItemExpr();

  ItemExpr * keycol = ((*eq_node)[0])->castToItemExpr();
  ItemExpr * keyval = ((*eq_node)[1])->castToItemExpr();

  // do preCodeGen now, to avoid inserting scaling later
  keyval = keyval->preCodeGen(generator);

  const NAType * sourceType = &(keyval->getValueId().getType());
  const NAType * targetType = &(keycol->getValueId().getType());

  NABoolean caseinsensitiveEncode = FALSE;

  ItemExpr * knode = 0;  // the node to be returned

  NABoolean generateNarrow = sourceType->errorsCanOccur(*targetType);

  switch (tf)
    {
    case ExpTupleDesc::SQLMX_KEY_FORMAT:
      {
	ItemExpr * cnode;

	if (targetType->getTypeQualifier() == NA_CHARACTER_TYPE)
	  {
	    const CharType& char_t =
	      (CharType&)(keycol->getValueId().getType());

	    // Explode varchars by moving them to a fixed field
	    // whose length is equal to the max length of varchar.
	    // Remove the UPSHIFT attr from the target. We don't want
	    // to upshift data for key lookup.
	    if ((keycol->getValueId().getType().getVarLenHdrSize() > 0) ||
		(char_t.isUpshifted()))
	      {
		if (!CollationInfo::isSystemCollation(char_t.getCollation()))
		{
                  if ((castVarcharToAnsiChar) &&
                      (keycol->getValueId().getType().getVarLenHdrSize() > 0))
                    {
                      targetType = new(wHeap())
                        ANSIChar(wHeap(), char_t.getDataStorageSize(),
                                 keycol->getValueId().getType().supportsSQLnull(),
                                 FALSE,
                                 FALSE,
                                 char_t.getCharSet(),
                                 char_t.getCollation(),
                                 char_t.getCoercibility()
                                 );
                    }
                  else
                    {
                      targetType = new(wHeap())
                        SQLChar(wHeap(), CharLenInfo(char_t.getStrCharLimit(), char_t.getDataStorageSize()),
                                keycol->getValueId().getType().supportsSQLnull(),
                                FALSE,
                                ((CharType*)targetType)->isCaseinsensitive(),
                                FALSE,
                                char_t.getCharSet(),
                                char_t.getCollation(),
                                char_t.getCoercibility()
                                );
                    }
		}
	      }
	  }

	NABoolean compEncodeGenerated = FALSE;
	if (generateNarrow)
	  {
	    cnode = new(wHeap()) Narrow (keyval,dataConversionErrorFlag,targetType,
                                         ITM_NARROW, desc_flag);
	  }
	else
	  {
	    if (*sourceType == *targetType)
	      {
		// if source & target are exactly the same and normal scaling
		// is being done, then generate the encode node. This avoids
		// an extra conversion node.
		cnode = new(wHeap()) CompEncode(keyval, desc_flag);
		compEncodeGenerated = TRUE;
	      }
	    else
	      {
		cnode = new(wHeap()) Cast (keyval,targetType);
	      }
	  }

        cnode = cnode->bindNode(generator->getBindWA());
        cnode = cnode->preCodeGen(generator);

	// if both source and target are caseinsensitive, then
	// do caseinsensitive encode.
	if ((targetType->getTypeQualifier() == NA_CHARACTER_TYPE) &&
	    (keyval->getValueId().getType().getTypeQualifier() == NA_CHARACTER_TYPE) &&
	    (((CharType*)targetType)->isCaseinsensitive()) &&
	    (((CharType&)keyval->getValueId().getType()).isCaseinsensitive()))
	  {
	    caseinsensitiveEncode = TRUE;
	  }

	// encode the key for byte comparison.
        knode = cnode;
	if (compEncodeGenerated)
	  {
	    knode = cnode;
	    ((CompEncode*)knode)->setCaseinsensitiveEncode(caseinsensitiveEncode);
	  }
	else if (NOT castVarcharToAnsiChar)
	  {
	    knode = new(wHeap()) CompEncode(cnode, desc_flag);
            knode = knode->bindNode(generator->getBindWA());
	    ((CompEncode*)knode)->setCaseinsensitiveEncode(caseinsensitiveEncode);
	    knode = knode->preCodeGen(generator);
	  }
      }
      break;

    default:
      {
	GenAssert(0, "Unrecognized tuple format");
      }
      break;
    }

  // if data conversion errors could have occurred on a prior column,
  // generate a CASE statement to move in the min or max value for the
  // datatype instead (depending on the conversion error and on whether
  // this column is ascending or descending)

  if ((possibleErrorCount > 0) &&
      (NOT allChosenPredsAreEqualPreds))
    {
      ItemExpr * relativeMin = new(wHeap()) ConstValue(targetType->newCopy(wHeap()),
						       !desc_flag,
						       targetType->supportsSQLnull());
      relativeMin = new(wHeap()) Cast(relativeMin,targetType);

      // Add an encode node here.
      relativeMin = new(wHeap()) CompEncode(relativeMin, desc_flag);

      ItemExpr * relativeMax = new(wHeap()) ConstValue(targetType->newCopy(wHeap()),
						       desc_flag,
						       targetType->supportsSQLnull());
      relativeMax = new(wHeap()) Cast(relativeMax,targetType);

      // Add an encode node here.
      relativeMax = new(wHeap()) CompEncode(relativeMax, desc_flag);

      knode = createExprTree("CASE WHEN @A1 = 0 THEN @A2 WHEN @A1 < 0 THEN @A3 ELSE @A4 END",
                             0,
			     4,
			     dataConversionErrorFlag, // @A1
			     knode, // @A2
			     relativeMax, // @A3
			     relativeMin); // @A4
    }

  GenAssert(knode, "generateKeyCast: knode null pointer ");
  knode = knode->bindNode(generator->getBindWA());
  knode = knode->preCodeGen(generator);

  // knode->displayTree();

  // Check for an error binding the node.
  GenAssert(!generator->getBindWA()->errStatus(),"MDAM: Error binding node.");

  // update count of columns that can have conversion errors
  if (generateNarrow)
    possibleErrorCount++;

  return knode;
}


short ExpGenerator::generateKeyExpr(const NAColumnArray & indexKeyColumns,
				    const ValueIdList & val_id_list,
				    Int32 atp, Int32 atp_index,
				    ItemExpr * dataConversionErrorFlag,
				    ExpTupleDesc::TupleDataFormat tf,
				    ULng32 &keyLen,
				    ex_expr ** key_expr,
				    NABoolean allChosenPredsAreEqualPreds)
{
  // generate key expression.
  // Key value id list has entries of the form:
  //    col1 = value1, col2 = value2, ... colN = valueN
  // All key values are present (missing keys are added in preCodeGen).
  if (val_id_list.entries() > 0)
    {
      ValueIdList key_val_id_list;

      // generate expression to create the key buffer. All key values
      // are part of a contiguous key buffer whose length is same
      // as the key length of the table. Allocate convert nodes
      // to move the key values to the key buffer.

      Lng32 possibleErrorCount = 0;

      short prevAtp = -1, prevAtpIndex = -1;
      UInt32 prevOffset = 0;
      UInt32 firstOffset = 0;
      UInt32 prevStorageLength = 0;
      for (ULng32 i = 0; i < val_id_list.entries(); i++)
	{
	  ItemExpr * knode = NULL;

	  if ((indexKeyColumns[i]->getNATable()->isHbaseCellTable()) ||
	      (indexKeyColumns[i]->getNATable()->isHbaseRowTable()) ||
              (indexKeyColumns[i]->isPrimaryKeyNotSerialized()) ||
              ((indexKeyColumns[i]->getNATable()->isHbaseMapTable()) &&
               (indexKeyColumns[i]->getNATable()->getClusteringIndex()->hasSingleColVarcharKey())))
	    {
	      ItemExpr * eq_node = (val_id_list[i].getValueDesc())->getItemExpr();
	      
	      ItemExpr * keycol = ((*eq_node)[0])->castToItemExpr();
	      ItemExpr * keyval = ((*eq_node)[1])->castToItemExpr();
	      
	      // do preCodeGen now, to avoid inserting scaling later
	      keyval = keyval->preCodeGen(generator);
	      
	      const NAType * sourceType = &(keyval->getValueId().getType());
	      const NAType * targetType = &(keycol->getValueId().getType());
	      
	      knode = new(wHeap()) Cast (keyval,targetType);
	      knode = knode->bindNode(generator->getBindWA());
	      knode = knode->preCodeGen(generator);
	    }
	  else
	    {
	      knode =
		generateKeyCast(val_id_list[i],
				dataConversionErrorFlag,
				!indexKeyColumns.isAscending(i),
				tf,
				possibleErrorCount /* in/out */,
				allChosenPredsAreEqualPreds,
                                FALSE);
	    }

	  key_val_id_list.insert(knode->getValueId());

	}

      generateContiguousMoveExpr(key_val_id_list,
                                 0, // don't add convert nodes,
                                 atp, atp_index, tf, keyLen,
                                 key_expr);
    }

  return 0;
}


short ExpGenerator::generateExclusionExpr(ItemExpr *expr,
					  Int32 atp,
					  Int32 atpindex,
					  ex_expr ** excl_expr)
{
  // if the begin/end key exclusion flag is dynamically calculated, generate
  // a move expression to get the value into a predetermined place
  if (expr)
    {
      // generate move expression
      ValueIdList exclusionResult;
      ULng32 resultLen;

      exclusionResult.insert(expr->getValueId());
      generateContiguousMoveExpr(
	   exclusionResult,
	   -1, // add convert node
	   atp,
	   atpindex,
	   ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
	   resultLen,
	   excl_expr);

      // executor has hard-coded assumption that the result is a long
      GenAssert(resultLen == sizeof(Lng32),
		"Exclusion flag expression result must have length 4");
    }
  return 0;
}

// generate code to do Describe Input and move input values
// from user area to executor area.
short ExpGenerator::generateInputExpr(const ValueIdList &val_id_list,
				      ex_expr::exp_node_type /* node_type */,
				      ex_expr ** expr)
{
  Space * space;
  Lng32 num_input_entries = 0;
  InputOutputExpr * ioExpr;
  Attributes ** attr;
  short retCode;

  initExprGen();

  space = getSpace();
  num_input_entries = 0;
  ioExpr = new(getSpace()) InputOutputExpr();
  *expr = ioExpr;

  (*expr)->setLength(getSpace()->getAllocatedSpaceSize());
  startExprGen(expr, ioExpr->getType());

  ValueId val_id;
  ex_inout_clause * input_clause = 0;

  const NABoolean isJdbc =
    (CmpCommon::getDefault(JDBC_PROCESS) == DF_ON ? TRUE : FALSE);
  const NABoolean isOdbc =
    (CmpCommon::getDefault(ODBC_PROCESS) == DF_ON ? TRUE : FALSE);

  for (CollIndex i = 0; i < val_id_list.entries(); i++)
    {
      val_id = val_id_list[i];

      ValueDesc * val_desc = val_id.getValueDesc();
      ItemExpr * item_expr = val_desc->getItemExpr();
      if ((item_expr->getOperatorType() == ITM_HOSTVAR) ||
	  (item_expr->getOperatorType() == ITM_DYN_PARAM))
	  {

	  item_expr->preCodeGen(generator);
	  item_expr->codeGen(generator);

	  const NAString *hostvarOrParamName = NULL;

	  if (item_expr->getOperatorType() == ITM_HOSTVAR)
	    {
	      hostvarOrParamName = &((HostVar *)item_expr)->getName();
	    }
	  else
	    {
	      hostvarOrParamName = &((DynamicParam *)item_expr)->getName();
	    }

	  Lng32 numAttrs = 1;
	  if (getShowplan())
	    numAttrs *= 2;

	  attr    = new(wHeap()) Attributes * [numAttrs];
	  //	  attr[0] = generator->getMapInfo(val_id)->getAttr();
	  attr[0] = generator->getAttr(item_expr);

	  if (getShowplan())
	    attr[1] =
	      new(wHeap()) ShowplanAttributes(val_id,
					      convertNAString(item_expr->getText(),
							      generator->wHeap()));

	  num_input_entries++;

	  // just give it ITM_CONVERT operator type since there is
	  // no ITM_INOUT type available.
	  input_clause = new(space) ex_inout_clause(ITM_CONVERT, attr, getSpace());

          // The name we assign to the clause will typically be the
          // host variable or dynamic parameter name or an empty name
          // if this is an unnamed dynamic paramter. There is one
          // exception though. When JDBC or ODBC compiles a CALL
          // statement and an IN or INOUT argument is a single UNNAMED
          // dynamic parameter, we assign the FORMAL parameter name to
          // the clause instead of the empty dynamic parameter name.
          const NAString *nameForClause = hostvarOrParamName;
          NABoolean isDynamicParam =
            (item_expr->getOperatorType() == ITM_DYN_PARAM ? TRUE : FALSE);

          if ((isOdbc || isJdbc) && isDynamicParam)
          {
            DynamicParam *param = (DynamicParam *) item_expr;
            const NAString &formalParamName = param->getUdrFormalParamName();
            if (!formalParamName.isNull())
            {
              // Note that we only come here for CALL statements
              const NAString &paramName = param->getName();
              if (paramName.isNull())
              {
                nameForClause = &formalParamName;
              }
            }
          }

          char *nameBuffer = getSpace()->
            AllocateAndCopyToAlignedSpace(*nameForClause, sizeof(Lng32));
          input_clause->setName(nameBuffer);

          if (isJdbc)
	    {
	      if (isDynamicParam) {
		  DynamicParam * param = (DynamicParam *)item_expr;
		  if (NOT param->getParamHeading().isNull())
		  {
		    char * heading =
		      getSpace()->AllocateAndCopyToAlignedSpace(param->getParamHeading(),
								sizeof(Lng32));
		    input_clause->setHeading(heading);
		  }

		if (NOT param->getParamTablename().isNull())
		  {
		    char * tablename =
		      getSpace()->AllocateAndCopyToAlignedSpace(param->getParamTablename(),
								sizeof(Lng32));
		    input_clause->setTableName(tablename);
		  }
		}
	      else { // HostVar
		  HostVar * hv = (HostVar *)item_expr;
		  if (NOT hv->getParamHeading().isNull())
		  {
		    char * heading =
		      getSpace()->AllocateAndCopyToAlignedSpace(hv->getParamHeading(),
								sizeof(Lng32));
		    input_clause->setHeading(heading);
		  }

		if (NOT hv->getParamTablename().isNull())
		  {
		    char * tablename =
		      getSpace()->AllocateAndCopyToAlignedSpace(hv->getParamTablename(),
								sizeof(Lng32));
		    input_clause->setTableName(tablename);
		  }
	      }
	    }

	  // Put CALL statement specific info into input clauses
	  short paramMode = mapMode(item_expr->getParamMode());
	  short paramIdx = (short) item_expr->getHVorDPIndex();

	  if(paramIdx) {
	    ioExpr->setCall(TRUE);
	  }
	  else{
	    ioExpr->setCall(FALSE);
	  }

	  short ordPos = (short) item_expr->getOrdinalPosition();

	  if(ioExpr->isCall()){
	    input_clause->setParamMode(paramMode);
	    input_clause->setParamIdx(paramIdx);
	    input_clause->setOrdPos(ordPos);
	  }
	  else{
	    BriefAssertion(paramMode==0,"Invalid value for param mode");
	    BriefAssertion(paramIdx==0,"Invalid value for param index");
	    BriefAssertion(ordPos==0,"Invalid value for ordinal position");
	    paramMode = PARAMETER_MODE_IN;
	    paramIdx = (short)num_input_entries;
	    ordPos = (short)num_input_entries;
	    input_clause->setParamMode(paramMode);
	    input_clause->setParamIdx(paramIdx);
	    input_clause->setOrdPos(ordPos);
	  }
	  // End
	  linkClause(0, input_clause);
	}
      else
	if ((item_expr->isAUserSuppliedInput()) || //evaluate once functions
		(item_expr->getOperatorType() == ITM_CURRENT_TIMESTAMP) ||
		(item_expr->getOperatorType() == ITM_UNIX_TIMESTAMP) ||
		(item_expr->getOperatorType() == ITM_SLEEP) ||
	    (item_expr->getOperatorType() == ITM_CURRENT_USER) ||
	    (item_expr->getOperatorType() == ITM_SESSION_USER) ||
            (item_expr->getOperatorType() == ITM_EXEC_COUNT) ||
	    (item_expr->getOperatorType() == ITM_CURR_TRANSID))
	{
	  item_expr->preCodeGen(generator);
	  item_expr->codeGen(generator);
	}
    }

  ioExpr->setNumEntries(num_input_entries);

  retCode = endExprGen(expr, -1);

  // Reset ioExpr since after endExprGen() it's possible that the space used
  // for the expression was copied elsewhere and deallocated.
  ioExpr = (InputOutputExpr*)(*expr);

  // if all clauses are inout clauses, then do not evaluate
  // input expr at runtime. This is an optimization.
  // Don't do this optimization if we no longer have a pointer to all clauses
  ex_clause * clause = ioExpr->getClauses();
  NABoolean allInoutClauses = (retCode) ? FALSE : TRUE;
  while ((clause) && (allInoutClauses))
    {
      if (clause->getType() != ex_clause::INOUT_TYPE)
	allInoutClauses = FALSE;

      clause = clause->getNextClause();
    }

  if (allInoutClauses)
    ioExpr->setNoEval(TRUE);

  if (isOdbc || isJdbc)
    {
      // skip type compatibility check at runtime between the user hvar
      // and the input value. Skipping the check will make all conversions
      // (if they are possible) go through. So a user hvar(char,
      // for example) could be converted to an integer input value.
      ioExpr->setSkipTypeCheck(TRUE);
    }

  if (CmpCommon::getDefault(IMPLICIT_HOSTVAR_CONVERSION) == DF_ON)
    {
      ioExpr->setSkipTypeCheck(TRUE);

      ioExpr->setRestrictedSkipTypeCheck(TRUE);
    }

  if (CmpCommon::getDefault(SUPPRESS_CHAR_LIMIT_CHECK) == DF_ON)
    // suppress the fix for TRAFODION-2719, use this only
    // if the new behavior causes a regression in an existing
    // application that cannot be fixed easily
    ioExpr->setSuppressCharLimitCheck(TRUE);

  if ( CmpCommon::getDefault(MARIAQUEST_PROCESS) == DF_ON ) 
    {
      ioExpr->setNoDatetimeValidation(TRUE);
    }

  return 0;
}


// input is a ValueIdList
short ExpGenerator::generateListExpr(const ValueIdList      &val_id_list,
				     ex_expr::exp_node_type  node_type,
				     ex_expr               **expr,
                                     Int32                   atp,
                                     Int32                   atpIndex,
                                     ExpHdrInfo             *hdrInfo)
{
  if (val_id_list.entries() == 0)
    {
      return 0;
    }

  ValueIdList * vidList = (ValueIdList *)&val_id_list;

  /*
  // Do constant folding and simplify expressions.
  ValueIdList tempList;
  tempList = vidList->constantFolding();
  if (!tempList.isEmpty())
    {
      vidList = &tempList;
    }
    */

  initExprGen();
  startExprGen(expr, node_type);

  if ( hdrInfo != NULL )
  {
    if (atp < 0)
    {
      Attributes *attr = generator->getMapInfo( (*vidList)[0] )->getAttr();
      atp = attr->getAtp();
      atpIndex = attr->getAtpIndex();
    }    
    generateHeaderClause(atp, atpIndex, hdrInfo);
  }

  ValueId val_id;
  for (CollIndex i = 0; i < vidList->entries(); i++)
    {
      val_id = (*vidList)[i];

      // generate code for this node and the tree under it
      ItemExpr *itmExpr = val_id.getValueDesc()->getItemExpr();
#ifdef GEN_SF_SC_BUG_TESTING
      if(getenv("GEN_ENABLE_SF_PROTECT_ALL"))
	itmExpr->protectiveSequenceFunctionTransformation(generator);
#endif
      itmExpr = itmExpr->preCodeGen(generator);
      itmExpr->codeGen(generator);
    }

  endExprGen(expr, -1);

  return 0;
}

short ExpGenerator::genGuardedListExpr(const ValueIdSet guard,
                                       const ValueIdList &val_id_list,
                                       ex_expr::exp_node_type node_type,
                                       ex_expr ** expr)
{
  if (val_id_list.entries() == 0 && guard.entries() == 0) {
    return 0;
  }

  ItemExpr *guardedTree = NULL;

  if(val_id_list.entries() == 0 && guard.entries() != 0) {
    guardedTree = new(wHeap()) BoolResult(guard.rebuildExprTree(ITM_AND));
  } else if(guard.entries() == 0) {
    guardedTree = new(wHeap())
      BoolResult(new(wHeap())
                 ItemList(val_id_list.rebuildExprTree(ITM_ITEM_LIST),
                          new(wHeap()) BoolVal(ITM_RETURN_TRUE)));
  } else {

    ItemExpr * trueListTree = new(wHeap())
      ItemList(val_id_list.rebuildExprTree(ITM_ITEM_LIST),
               new(wHeap()) BoolVal(ITM_RETURN_TRUE));

    guardedTree = new(wHeap())
      BoolResult(new (wHeap())
                 BiLogic(ITM_AND,
                         guard.rebuildExprTree(ITM_AND),
                         trueListTree));
  }

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

  generateExpr(guardedTree->getValueId(),
               ex_expr::exp_SCAN_PRED,
               expr);

  return 0;
}

// generate code to do Describe Output and move output values
// from executor area to user area.
short ExpGenerator::generateOutputExpr(const ValueIdList &val_id_list,
				       ex_expr::exp_node_type /* node_type */,
				       ex_expr ** expr,
				       RETDesc * ret_desc,
                                       const ItemExprList *spOutParams,
                                       ConstNAStringPtr *colNamesForExpr,
                                       ConstQualifiedNamePtr *tblNamesForExpr)
{
  Lng32 rc;
  Space* space;
  Lng32 num_output_entries;
  InputOutputExpr * ioExpr;

  initExprGen();

  space = getSpace();

  num_output_entries = 0;

  ioExpr = new(getSpace()) InputOutputExpr();
  *expr = ioExpr;

  (*expr)->setLength(getSpace()->getAllocatedSpaceSize());
  startExprGen(expr, ioExpr->getType());

  ValueId val_id;
  ex_inout_clause * output_clause = 0;

  const NABoolean isJdbc =
    (CmpCommon::getDefault(JDBC_PROCESS) == DF_ON ? TRUE : FALSE);
  const NABoolean isOdbc =
    (CmpCommon::getDefault(ODBC_PROCESS) == DF_ON ? TRUE : FALSE);

  const NABoolean isCallStatement = (spOutParams ? TRUE : FALSE);

  // Output expression must produce result in exploded format.
  generator->setExplodedInternalFormat();

  // Normally the name we assign to an unnamed column is "(EXPR)".
  // However for CALL statements, ODBC and JDBC requested we use an
  // empty string.
  NAString empty_colname("(EXPR)", CmpCommon::statementHeap());
  if (isCallStatement && (isOdbc || isJdbc))
    empty_colname = "";

  for (CollIndex i = 0; i < val_id_list.entries(); i++)
  {
    val_id = val_id_list[i];
    ItemExpr * item_expr = val_id.getItemExpr();

    char *nameForClause = 0;
    char *heading = 0;
    char *tableName = 0;
    char *schemaName = 0;
    char *catalogName = 0;

    ItemExpr *spOutExpr = NULL;
    if (isCallStatement)
    {
      spOutExpr = (*spOutParams)[i];
      BriefAssertion(spOutExpr, "Unmatched spOutParams");
    }

    // We allow the caller of this function to inject special names
    // into the generated object. Currently this is only being done
    // for stored procedure result set proxy plans. If a special
    // column name was passed in, colNameFromCaller will point to it.
    const NAString *colNameFromCaller =
      (colNamesForExpr ? colNamesForExpr[i] : NULL);

    // colNameFromRETDesc is the column name from the RETDesc
    const NAString colNameFromRETDesc
      (ret_desc->getColRefNameObj(i).getColNameAsAnsiString());

    // The next IF block will set colname_ptr to point to the name we
    // want in the generated object
    const NAString *colname_ptr = NULL;

    if (colNameFromCaller)
    {
      // The caller wants a special name
      colname_ptr = colNameFromCaller;
    }
    else
    {
      // Use the name from the RETDesc or if that name is not
      // specified, use our manufactured name for unnamed columns
      if (colNameFromRETDesc.length() > 0)
        colname_ptr = &colNameFromRETDesc;
      else
        colname_ptr = &empty_colname;

      // For CALL statements, ODBC and JDBC requested that non-empty
      // parameter names in the SQL text (e.g. "call foo(?x)") take
      // precedence over formal parameter names.
      NAString spOutParamName("", CmpCommon::statementHeap());
      if (isCallStatement && (isOdbc || isJdbc))
      {
        // Even though ODBC and JDBC always do dynamic compiles, we
        // also check for a named static host variable here, to cover
        // the case of SQLJ static compiles. SQLJ static plans are
        // generated with the ODBC_PROCESS default turned on and
        // involve the JDBC runtime stack during execution.
        if (spOutExpr->getOperatorType() == ITM_DYN_PARAM)
          spOutParamName = ((DynamicParam *) spOutExpr)->getName();
        else if (spOutExpr->getOperatorType() == ITM_HOSTVAR)
          spOutParamName = ((HostVar *) spOutExpr)->getName();

        if (spOutParamName.length() > 0)
        {
          colname_ptr = &spOutParamName;
        }
      }

    } // if (colNameFromCaller) else ...

    nameForClause =
      space->AllocateAndCopyToAlignedSpace(*colname_ptr, sizeof(Lng32));

    if (ret_desc->getHeading(i) != NULL)
    {
      heading =
        space->allocateAndCopyToAlignedSpace(ret_desc->getHeading(i),
                                             strlen(ret_desc->getHeading(i)),
                                             sizeof(Lng32));
    }

    // if the output expression (item_expr) and the select list
    // item (from ret_desc) do not have the same type, generate
    // conversion clause.
    item_expr = item_expr->preCodeGen(generator);
    val_id = item_expr->getValueId();

    // If the value is in compressed format, then conversion
    // nodes must be added to convert back to exploded format.
    // Sometimes this is done already - i.e., in the split bottom of top level
    // ESPs.
    NABoolean genConvertNodes = false;
    MapInfo *mapInfo = generator->getMapInfoAsIs(val_id);
    if(mapInfo) {
      genConvertNodes = mapInfo->getAttr()->isSQLMXAlignedFormat();
    }
    else
    {
      if(item_expr->getOperatorType() == ITM_BASECOLUMN) {
        item_expr->codeGen(generator);
        MapInfo *mapInfo = generator->getMapInfoAsIs(val_id);
        if(mapInfo) {
          genConvertNodes = mapInfo->getAttr()->isSQLMXAlignedFormat();
        }
      }
    }

    if ( (NOT(val_id.getType() == ret_desc->getType(i))) || genConvertNodes )
    {
      {
      
         item_expr = new(wHeap()) Cast(item_expr, &(ret_desc->getType(i)));
      }

      item_expr->bindNode(generator->getBindWA());
    }

    ItemExpr * temp = item_expr->preCodeGen(generator);
    ItemExpr *outExpr = NULL;
    rc = foldConstants(temp, &outExpr);
    if ((rc == 0) && (outExpr))
      temp = outExpr;
    temp->codeGen(generator);

    {
      MapInfo *mapInfo = generator->getMapInfoAsIs(temp->getValueId());
      GenAssert(mapInfo, "no mapinf");
      GenAssert(!mapInfo->getAttr()->isSQLMXAlignedFormat(), "Aligned Output");
    }

    //attr = new(wHeap()) Attributes * [1];
    ItemExpr * outNode
      = new(wHeap()) NATypeToItem((NAType *)&temp->getValueId().getType());
    outNode->synthTypeAndValueId();

    Attributes ** attr;
    if (genItemExpr(outNode, &attr, 1, -1) == 1)
      return 0;

    attr[0]->copyLocationAttrs(
      generator->getMapInfo(((ItemExpr *)temp)->getValueId())->getAttr());

    if (genConvertNodes)
    {// bulk move may cause an issue where the values are overriden
      attr[0]->setBulkMoveable(FALSE);
    }
    //attr[0] = getMapTable()->getMapInfo(((ItemExpr *)temp)->getValueId())->getAttr();

    // Get the table/catalog and schema names
    // We get this from the ret_desc because we want the original column
    // list - NOT the VEG transformed column list because some of the
    // columns may have been replaced by constants.

    // We also allow the caller of this function to inject special
    // names into the generated object. Currently this is only being
    // done for stored procedure result set proxy plans.
    const QualifiedName *tblNameFromCaller =
      (tblNamesForExpr ? tblNamesForExpr[i] : NULL);

    // Another case to consider is that NO catalog/schema/table names
    // should be set for this column. In that case, the following
    // boolean should remain FALSE.
    NABoolean tableNameShouldBeSet = FALSE;

    if (tblNamesForExpr)
    {
      if (tblNameFromCaller)
        tableNameShouldBeSet = TRUE;
    }
    else if (((ret_desc->getValueId(i)).getItemExpr()->getOperatorType()
              == ITM_BASECOLUMN) ||
             ((ret_desc->getValueId(i)).getItemExpr()->getOperatorType()
              == ITM_INDEXCOLUMN))
    {
      tableNameShouldBeSet = TRUE;
    }

    if (tableNameShouldBeSet)
    {
      // Initially we set qaname to the caller's special name. If that
      // name was not specified then qaname is changed to point to the
      // name from the RETDesc.
      const QualifiedName *qaname = tblNameFromCaller;

      if (qaname == NULL)
      {
        NAColumn *column = (ret_desc->getValueId(i)).getNAColumn();
        qaname = (const QualifiedName *) column->getTableName(TRUE);
      }

      if (NOT qaname->getObjectName().isNull())
      {
        tableName = space->AllocateAndCopyToAlignedSpace
          (qaname->getObjectName(), sizeof(Lng32));
      }

      // If nametype is Shortansi, we need to extract the schema name
      // from bindWA because at this point the shortansi name has been
      // converted to NSK format. We do not consider SHORTANSI cases
      // when the caller of this function is passing in special table
      // names.
      if (tblNameFromCaller == NULL && SqlParser_NAMETYPE == DF_SHORTANSI)
      {
        SchemaName shortAnsiSchema = ActiveSchemaDB()->getDefaultSchema();

        if (NOT shortAnsiSchema.getSchemaName().isNull())
          schemaName = space->AllocateAndCopyToAlignedSpace
            (shortAnsiSchema.getSchemaName(),sizeof(Lng32));

        if (NOT shortAnsiSchema.getCatalogName().isNull())
          catalogName = space->AllocateAndCopyToAlignedSpace
            (shortAnsiSchema.getCatalogName(),sizeof(Lng32));
      }
      else
      {
        if (NOT qaname->getSchemaName().isNull())
        {
          schemaName = space->AllocateAndCopyToAlignedSpace
            (qaname->getSchemaName(),sizeof(Lng32));
        }
        if (NOT qaname->getCatalogName().isNull())
        {
          catalogName = space->AllocateAndCopyToAlignedSpace
            (qaname->getCatalogName(), sizeof(Lng32));
        }
      }

    } // if (tableNameShouldBeSet)

    output_clause = new(space) ex_inout_clause(ITM_NATYPE, attr, space);

    num_output_entries++;

    output_clause->setName(nameForClause);
    output_clause->setHeading(heading);

    // Put CALL statement specific info into output clauses
    if (spOutExpr)
    {
      short paramMode = mapMode(spOutExpr->getParamMode());
      short paramIdx = (short) spOutExpr->getHVorDPIndex();

      if (paramIdx != 0)
        ioExpr->setCall(TRUE);
      else
        BriefAssertion(0, "Invalid parameter index");

      short ordPos = (short) spOutExpr->getOrdinalPosition();
      output_clause->setParamMode(paramMode);
      output_clause->setParamIdx(paramIdx);
      output_clause->setOrdPos(ordPos);

    }
    else
    {
      short paramMode = PARAMETER_MODE_OUT;
      short paramIdx = 0;
      short ordPos = 0;
      output_clause->setParamMode(paramMode);
      output_clause->setParamIdx(paramIdx);
      output_clause->setOrdPos(ordPos);
    }

    output_clause->setTableName(tableName);
    output_clause->setSchemaName(schemaName);
    output_clause->setCatalogName(catalogName);

    linkClause(0, output_clause);

  } // for each entry in the ValueId list

  if (output_clause)
  {
    short retCode;

    ioExpr->setNumEntries(num_output_entries);

    output_clause->setLastClause();

    retCode = endExprGen(expr, 0);

    // Reset ioExpr since after endExprGen() it's possible that the space used
    // for the expression was copied elsewhere and deallocated.
    ioExpr = (InputOutputExpr*)(*expr);

    // if all clauses are inout clauses, then do not evaluate
    // output expr at runtime. This is an optimization.
    // Don't do this optimization if we no longer have a pointer to all clauses
    ex_clause * clause = ioExpr->getClauses();
    NABoolean allInoutClauses = (retCode) ? FALSE : TRUE;
    while ((clause) && (allInoutClauses))
    {
      if (clause->getType() != ex_clause::INOUT_TYPE)
        allInoutClauses = FALSE;

      clause = clause->getNextClause();
    }

    if (allInoutClauses)
      ioExpr->setNoEval(TRUE);

    if (isOdbc || isJdbc)
    {
      // skip type compatibility check at runtime between the user hvar
      // and the input value. Skipping the check will make all conversions
      // (if they are possible) go through. So a user hvar(char,
      // for example) could be converted to an integer input value.
      ioExpr->setSkipTypeCheck(TRUE);
    }

    if ((CmpCommon::getDefault(IMPLICIT_HOSTVAR_CONVERSION) == DF_ON) ||
        (CmpCommon::getDefault(IMPLICIT_DATETIME_INTERVAL_HOSTVAR_CONVERSION) == DF_ON))
    {
      ioExpr->setSkipTypeCheck(TRUE);

      ioExpr->setRestrictedSkipTypeCheck(TRUE);
    }
  } // output_clause

  return 0;
}

// input is a ValueIdSet
short ExpGenerator::generateSetExpr(const ValueIdSet &val_id_set,
				    ex_expr::exp_node_type node_type,
				    ex_expr ** expr,
				    short gen_last_clause,
                                    ExpHdrInfo * hdrInfo)
{
  ValueId val_id;
  val_id = val_id_set.init();
  if (!val_id_set.next(val_id))
    return 0; // empty set

  initExprGen();
  startExprGen(expr, node_type);

  if (hdrInfo != NULL)
  {
    Attributes *attr = generator->getMapInfo(val_id)->getAttr();
    generateHeaderClause(attr->getAtp(), attr->getAtpIndex(), hdrInfo);
  }

  for (val_id = val_id_set.init(); val_id_set.next(val_id); val_id_set.advance(val_id))
    {
      // generate code for this node and the tree under it
      ItemExpr * temp =
	val_id.getValueDesc()->getItemExpr()->preCodeGen(generator);
      temp->codeGen(generator);
    }

  endExprGen(expr, gen_last_clause);

  return 0;
}

// generateSequenceExpression
//
short ExpGenerator::generateSequenceExpression(const ValueIdSet &sequenceItems, 
                                               ex_expr* &expr)
{
  // If there are no items, just return
  //
  if (sequenceItems.isEmpty()) return 0;

  initExprGen();
  setInSequenceFuncExpr(TRUE);
  startExprGen(&expr, ex_expr::exp_ARITH_EXPR);

  // Loop over the sequence items calling the protective short-circuit
  // transformation, preCodeGen and codeGen on each.
  //
  ValueId valId;
  for (valId = sequenceItems.init();
       sequenceItems.next(valId);
       sequenceItems.advance(valId))
    {
      ItemExpr *itmExpr = valId.getValueDesc()->getItemExpr();
#ifdef GEN_SF_SC_BUG_TESTING
      if(!getenv("GEN_DISABLE_SF_PROTECT"))
#endif
	itmExpr->protectiveSequenceFunctionTransformation(generator);
      itmExpr = valId.getValueDesc()->getItemExpr();
      itmExpr = itmExpr->preCodeGen(generator);
      itmExpr->codeGen(generator);
    }

  setInSequenceFuncExpr(FALSE);
  // Finalize the expression generation machinery.
  //
  endExprGen(&expr, 1);

  return 0;
}

// input is a list of ValueIdUnion.
short ExpGenerator::generateUnionExpr(const ValueIdList &val_id_list,
				      ex_expr::exp_node_type node_type,
				      ex_expr ** left_expr,
				      ex_expr ** right_expr)
{
  // generate code to move the left child row to result row

  initExprGen();
  startExprGen(left_expr, node_type);

  Space * space = getSpace();

  CollIndex i = 0;
  for (i = 0; i < val_id_list.entries(); i++)
    {
      ValueIdUnion * vidu_node = (ValueIdUnion *)(((val_id_list[i]).getValueDesc())->getItemExpr());
      ItemExpr * left_node = ((vidu_node->getLeftSource()).getValueDesc())->getItemExpr();

      Attributes ** attr = new(wHeap()) Attributes * [2];
      ex_conv_clause * conv_clause;

      /* assign result attributes*/
      attr[0] = generator->getMapInfo(vidu_node->getResult())->getAttr();

      ItemExpr * temp = left_node->preCodeGen(generator);
      temp->codeGen(generator);

      attr[1] = generator->getMapInfo(((ItemExpr *)temp)->getValueId())->getAttr();
      conv_clause = new(space) ex_conv_clause(ITM_CONVERT, attr, space);
      linkClause(0, conv_clause);
    }

  endExprGen(left_expr, -1);

  // generate code to move the right child row to result row
  initExprGen();
  startExprGen(right_expr, node_type);

  // Reset space since temporary space object may be used
  space = getSpace();

  for (i = 0; i < val_id_list.entries(); i++)
    {
      ValueIdUnion * vidu_node = (ValueIdUnion *)(((val_id_list[i]).getValueDesc())->getItemExpr());
      ItemExpr * right_node = ((vidu_node->getRightSource()).getValueDesc())->getItemExpr();

      Attributes ** attr = new(wHeap()) Attributes * [2];
      ex_conv_clause * conv_clause;

      /* assign result attributes*/
      attr[0] = generator->getMapInfo(vidu_node->getResult())->getAttr();

      ItemExpr * temp = right_node->preCodeGen(generator);
      temp->codeGen(generator);

      attr[1] = generator->getMapInfo(((ItemExpr *)temp)->getValueId())->getAttr();
      conv_clause = new(space) ex_conv_clause(ITM_CONVERT, attr, space);
      linkClause(0, conv_clause);
    }

  endExprGen(right_expr, -1);

  return 0;
}


short ExpGenerator::processAttributes(ULng32 numAttrs,
				      Attributes ** attrs,
				      ExpTupleDesc::TupleDataFormat tdataF,
				      ULng32 &tupleLength,
				      Int32 atp,
				      Int32 atpIndex,
				      ExpTupleDesc ** tupleDesc,
				      ExpTupleDesc::TupleDescFormat tdescF,
				      ULng32 startOffset,
                                      ExpHdrInfo  * hdrInfo)
{
  ULng32 tuppDescFlags = 0x0;

  ExpTupleDesc::computeOffsets(numAttrs,
			       attrs,
			       tdataF,
			       tupleLength,
			       startOffset,
			       &tuppDescFlags,
			       &tdataF,
                               hdrInfo);

  for (Int32 i = 0; i < (Int32) numAttrs; i++)
    {
      attrs[i]->setAtp(atp);
      attrs[i]->setAtpIndex(atpIndex);
      attrs[i]->setDefaultFieldNum(i);		// this is needed for handling
						// SQL/MP added cols correctly.
    }

  // if tuple descriptor is to be returned, allocate it in 'space'
  if (tupleDesc)
    {
      *tupleDesc
	= new(getSpace()) ExpTupleDesc(numAttrs, attrs, tupleLength,
				       tdataF, tdescF, getSpace());
      (*tupleDesc)->setFlags(tuppDescFlags);
    }

  return 0;
}

short ExpGenerator::processValIdList(ValueIdList valIdList,
				     ExpTupleDesc::TupleDataFormat tdataF,
				     ULng32 &tupleLength,
				     Int32 atp,
				     Int32 atpIndex,
				     ExpTupleDesc ** tupleDesc,
				     ExpTupleDesc::TupleDescFormat tdescF,
				     Lng32 startOffset,
				     Attributes ***returnedAttrs,
                                     NAColumnArray *colArray,
                                     NABoolean isIndex,
                                     NABoolean placeGuOutputFunctionsAtEnd,
                                     ExpHdrInfo * hdrInfo)
{
  MapTable * myMapTable = generator->appendAtEnd();
  Attributes ** attrs = new(wHeap()) Attributes * [valIdList.entries()];

  NABoolean alignedFormat = (tdataF == ExpTupleDesc::SQLMX_ALIGNED_FORMAT);
  NAColumn *col;

  for (CollIndex i = 0; i < valIdList.entries(); i++)
    {
      // get a pointer to the map table attributes and set them the
      // way we want them to be
      attrs[i] = (generator->addMapInfoToThis(myMapTable, valIdList[i], 0))->getAttr();

      // If this is a GenericUpdateOutputFunction
      // and we want these handled specially - mark the attr.
      if (valIdList[i].getItemExpr()->isAGenericUpdateOutputFunction()
          && placeGuOutputFunctionsAtEnd)
	attrs[i]->setGuOutput();

      // There are times we don't have a column array and must use the value id
      // list to get to the attribute and mark it special (DP2Scan is one place).
      // The attribute must be marked 'special' before computing offsets since
      // for the aligned format we may re-arrange fixed size columns, but
      // can NOT re-arrange added columns.
      // Note that indexes (non-clustering indexes) do not have added columns,
      // because we cannot do an alter index add column operation.
      if ( alignedFormat &&
           !isIndex &&
           ( colArray == NULL ) &&
           ((col = valIdList[i].getNAColumn( TRUE )) != NULL) &&
           col->isAddedColumn() )
        attrs[i]->setAddedCol();
    }

  // Ensure added columns are tagged before computing offset for the aligned
  // record format since added columns are arranged differently.
  if ( (colArray != NULL) )
  {
    for( Int32 i = 0; i < (Int32)colArray->entries(); i++ )
    {
      col = (*colArray)[i];
      if (( col->isAddedColumn() ) && (!isIndex))
        attrs[i]->setAddedCol();
    }
  }

  ExpHdrInfo *retHdrInfo = NULL;
  if ( isHeaderNeeded(tdataF) )
    retHdrInfo = hdrInfo;

  // compute offsets and create tuple descriptor.
  processAttributes((ULng32)valIdList.entries(), attrs, tdataF,
		    tupleLength, atp, atpIndex,  tupleDesc, tdescF,
		    startOffset, retHdrInfo);

  if (returnedAttrs)
    {
      // caller wants array of Attributes pointers returned
      *returnedAttrs = attrs;
    }
  else
    {
      // deallocate the attributes array. Don't deallocate the attributes
      // pointed to by the array entries since we didn't allocate them.
      NADELETEBASIC( attrs, wHeap());
    }

// Below is commented out:  it doesn't work because we're adding the wrong
// attributes.  Can't get the correct ones any more because they will have
// been removed by ExpGenerator::endExprGen (removeLast).
// (This code was added, found wanting, and commented out trying to fix
// Genesis 10-980112-5942.)
//
//for (i = 0; i < valIdList.entries(); i++)
//  {
//    ValueId vid = valIdList[i];
//    ValueId vidRepl = vid.getItemExpr()->getReplacementExpr()->getValueId();
//    if (vidRepl != vid)
//	myMapTable->addMapInfo(vidRepl, myMapTable->getMapInfo(vid)->getAttr());
//  }

  return 0;
}


short ExpGenerator::computeTupleSize(const ValueIdList & valIdList,
                                     ExpTupleDesc::TupleDataFormat tdataF,
                                     ULng32 &tupleLength,
                                     Lng32 startOffset,
                                     UInt32 * varCharSize,
                                     UInt32 * headerSize)
{
  MapTable * myMapTable = generator->appendAtEnd();
  UInt32 vcSize = 0;
  UInt32 numAttrs = valIdList.entries();

  Attributes ** attrs = new(wHeap()) Attributes * [numAttrs];
  
  for (CollIndex i = 0; i < valIdList.entries(); i++)
  {
    attrs[i] = (generator->addMapInfoToThis(myMapTable, valIdList[i], 0))->getAttr();
  }

  UInt32 rtnFlags = 0x0;
  if (varCharSize)
    *varCharSize = 0;

  ExpTupleDesc::computeOffsets((ULng32)numAttrs,
                               attrs,
                               tdataF,
                               tupleLength,
                               startOffset,
                               &rtnFlags,
                               NULL,
                               NULL,
                               headerSize,
                               varCharSize);
 
   // deallocate the attributes array. 
   NADELETEBASIC( attrs, wHeap());
  
   if (myMapTable != NULL)
    generator->unlinkMe(myMapTable);


  return 0;
}

short ExpGenerator::assignAtpAndAtpIndex(ValueIdList valIdList,
					 Int32 atp,
					 Int32 atpIndex)
{
  for (CollIndex i = 0; i < valIdList.entries(); i++)
    {
      Attributes * attr = generator->getMapInfo(valIdList[i])->getAttr();
      if (atp >= 0)
	attr->setAtp(atp);
      if (atpIndex >= 0)
	attr->setAtpIndex(atpIndex);
    }

  return 0;
}

Int32 shafoo() {
  return 10;
}

// Called just before the start of expr generation to determine what space
// object to store the expression in.
void ExpGenerator::initExprGen()
{
#ifdef NEW_LEAN_EXPR
  // Attempt to create tempSpace only if we are compiling for leaner
  // expressions.  Also, only do this if PCODE generation is on *and* we're not
  // just generating PCODE for clause evaluation purposes.  Also, the internal
  // PCODE_NO_LEANER_EXPR mode may be set if there are certain expressions we
  // just don't want to make leaner for whatever reasons.  And also :), don't
  // do this if we're compiling for a showplan.

  if ((CmpCommon::getDefault(GEN_LEANER_EXPRESSIONS) == DF_ON) &&
      !(pCodeMode_ & ex_expr::PCODE_NO_LEANER_EXPR) &&
      (pCodeMode_ & ex_expr::PCODE_ON) &&
      !(pCodeMode_ & ex_expr::PCODE_EVAL))
  {
    // Only create tempSpace if it hasn't been created already.  This is done
    // specifically because AggrExpr attempts to create the expression first by
    // calling new() (as opposed to letting startExprGen do it), and then calls
    // generateSetExpr() to create all the clauses.  Since both need to be
    // in tempSpace, initExprGen() gets called twice, so we don't want to
    // create/delete tempSpace twice.

    if (generator->getTempSpace() == NULL) {
      ComSpace * space = new(wHeap()) ComSpace(ComSpace::GENERATOR_SPACE);
      space->setParent(wHeap());
      generator->setTempSpace(space, TRUE);
    }
  }
#endif
}

// called at the start of expr generation
short ExpGenerator::startExprGen(ex_expr ** expr,
				 ex_expr::exp_node_type node_type)
{
  if (*expr == 0)
    *expr = new(getSpace()) ex_expr(node_type);
  (*expr)->setLength(getSpace()->getAllocatedSpaceSize());

  // copy handleIndirectVC flag from expGenerator to expr
  (*expr)->setHandleIndirectVC( handleIndirectVC() );

  // copy forInsertUpdate flag from expGenerator to expr
  (*expr)->setForInsertUpdate( forInsertUpdate() );

  // set up pointer to NExDbgInfo object
  (*expr)->setNExDbgInfo( generator->getNExDbgInfoAddr() ) ;

  mapTableAllocated = -1;
  mapTable_ = generator->appendAtEnd();

  initClauseList();
  initConstantList();
  initPersistentList();

  savePCodeMode();

  return 0;
}

// Input: gen_last_clause, if not passed in or -1, generate a last NO-OP clause
short ExpGenerator::endExprGen(ex_expr ** expr, short gen_last_clause)
{
  UInt32 optFlags;
  short retCode = 0;

  gen_last_clause = 0;

  // Certain expressions may request no PCode to be generated, otherwise
  // get the PCode mode from the ctor ExpGenerator and set it in the
  // expression itself.  This allows us to regenerate PCode at runtime
  // (for versioning) with the same mode specified at compile time.
  (*expr)->setPCodeMode( getPCodeMode() );

  // Get default low-level opt flags and prevent predicate reordering from
  // happening if this expression represents a case statement.
  optFlags = (UInt32)CmpCommon::getDefaultLong(PCODE_OPT_FLAGS);

  UInt32 Enbld = (UInt32)CmpCommon::getDefaultLong(PCODE_NE_ENABLED);
  if ( Enbld == 0 )
     optFlags &= ~( PCodeCfg::NATIVE_EXPR ); // Disable Native Exprs in optFlags

  Enbld = (UInt32)CmpCommon::getDefaultLong(PCODE_EXPR_CACHE_ENABLED);
  if ( Enbld == 0 )
     optFlags |= PCodeCfg::OPT_PCODE_CACHE_DISABLED ; // Disable feature in optFlags

  Enbld = (UInt32)CmpCommon::getDefaultLong(PCODE_EXPR_CACHE_CMP_ONLY);
  if ( Enbld == 1 )
     optFlags |= ( PCodeCfg::EXPR_CACHE_CMP_ONLY ); // Enable Compare-Only mode -- FOR TESTING!

  if (caseStmtGenerated()) {
    optFlags &= ~(PCodeCfg::REORDER_PREDICATES);
    setCaseStmtGenerated(FALSE);
  }

  // Set pcode low-level optimization flags for this expression
  (*expr)->setPCodeOptFlags(optFlags);

  // Set pcode Max Branch Cnt and Max Instr Cnt for PCODE optimization
  UInt32 maxBrnchCnt = (UInt32)CmpCommon::getDefaultLong(PCODE_MAX_OPT_BRANCH_CNT);
  UInt32 maxInstCnt  = (UInt32)CmpCommon::getDefaultLong(PCODE_MAX_OPT_INST_CNT);
  (*expr)->setPCodeMaxOptBrCnt(maxBrnchCnt);
  (*expr)->setPCodeMaxOptInCnt(maxInstCnt);

  if (gen_last_clause)
    {
      /* generate a no-op clause and set it to be the last clause */
      ex_noop_clause *clause = new(getSpace()) ex_noop_clause;
      clause->setLastClause();
      linkClause(0, clause);
    }

  // fixup the next clause pointers
  fixupNextClause();

  // Set the constant expression storage length and area.
  //
  char * constants_area = placeConstants(getConstantList(), getConstLength());
  (*expr)->setConstantsArea(constants_area);
  (*expr)->setConstsLength(getConstLength());

  // Set the persistent expression storage length and initialization area.
  //
  char *persistentInitializationArea
    = placeConstants(getPersistentList(), persistentLength());
  (*expr)->persistentInitializationArea() = persistentInitializationArea;
  (*expr)->persistentLength() = persistentLength();
  (*expr)->persistentArea()
    = getSpace()->allocateAlignedSpace(persistentLength());


  // Set the temporary expression storage length.
  //
  (*expr)->setTempsLength(getTempsLength());

  // set the pointer to the first clause in the ex_expr
  (*expr)->setClauses((ex_clause *)(getClauseList()->getElement()));

  // Fixup the pointers to the constant, temporary, and persistent
  // expression areas.
  //
  //  (*expr)->setFixupConstsAndTemps((short)getFixupConstsAndTemps());

  if (mapTableAllocated)
    {
      mapTable_ = 0;
      generator->removeLast();
    }

  Lng32 len1 = getSpace()->getAllocatedSpaceSize();

  // generate pcode at compile time
  UInt32 f = 0;
  ex_expr_base::setForShowplan(f, FALSE);
  if (generator->genNoFloatValidatePCode())
    ex_expr_base::setNotValidateFloat64(f, TRUE);

  (*expr)->pCodeGenerate(getSpace(), wHeap(), f);
  (*expr)->setPCodeGenCompile(1);
  if ((*expr)->getPCodeNative() &&
      CmpCommon::getDefault(PCODE_NE_IN_SHOWPLAN) == DF_ON)
    (*expr)->setNEInShowplan(TRUE);

  Lng32 pcodeExprLen = getSpace()->getAllocatedSpaceSize() - len1;
  Lng32 totalExprLen =
    getSpace()->getAllocatedSpaceSize() - (*expr)->getLength();

  (*expr)->setLength(totalExprLen);
#ifdef NEW_LEAN_EXPR
  // If tempSpace exists, then the entire expression was written to it, so
  // we need to now make a "lean" copy of it and copy it back into the
  // fragment space.

  // If we are in the process or generating container expressions, then
  // no need to copy to fragment space yet, let's wait till we complete
  // generating the main expression.
  // Note: The term Container Expression is used to denote an expression
  // - ex_expr within an expression - ex_expr.
  if(inContainerExpr())
    return 0;

  ComSpace * tempSpace = generator->getTempSpace();

  NABoolean saveClauses = (getShowplan() || saveClausesInExpr());

  if (tempSpace)
  {
    ex_expr_base * newExpr = NULL;
    NABoolean branchFound = FALSE;

    // Reset tempSpace back to NULL.  Calls to getSpace() will now return the
    // fragment space.
    generator->setTempSpace(NULL, FALSE);

    // If no pCode was generated for this expression, or if the generated
    // pCode contains a clause eval instruction, we need to selectively copy
    // in the expression from tempSpace into the fragment space.  Otherwise,
    // the expression can completely rid itself of it's clauses and we can
    // make a very lean copy of it.

    // Copying some expressions is too hard because they contain clauses with
    // too many embedded pointers which need copying.  Be selective.
    NABoolean tooHard = FALSE;
    for (ex_clause* clause = (*expr)->getClauses();
         clause;
         clause = clause->getNextClause())
      {
        if ((clause->getClassID() == ex_clause::FUNC_HBASE_COLUMN_CREATE) ||
	    (clause->getClassID() == ex_clause::FUNC_HBASE_COLUMNS_DISPLAY))
	  tooHard = TRUE;
        break;
      }

    if (!tooHard && ((*expr)->getPCodeSegment() != NULL))
    {
      // Needed to set the length of the expression
      len1 = getSpace()->getAllocatedSpaceSize();

      // Previous clause ptr
      ex_clause* prevClause = NULL;

      // Determine size of expression.
      totalExprLen = (*expr)->getClassSize();

      // Allocate space in fragment space for just the expression class and
      // copy it over from the expr (which is in tempSpace).
      newExpr = (ex_expr_base*)
          new(generator->getSpace()) char[totalExprLen];
      str_cpy_all((char*)newExpr, (char*)(*expr), totalExprLen);

      // Call makeLeanCopyAll to just copy over the pCode and other stuff (but
      // not the clauses).  Note, this routine is different than makeLeanCopy
      // since it makes the existing expression lean, as opposed to storing
      // the expression in an "expr_lean" expression.  The advantages are that
      // all expressions are supported (which is exactly what we need).  The
      // disadvantages are that the expression isn't as lean as it could be.
      newExpr->makeLeanCopyAll(generator->getSpace());

      // Initially assume that there are no clauses needed to copy over
      newExpr->setClauses(NULL);

      // Walk through clauses list if expression contains EVAL instruction.
      // Otherwise we're pretty much done since PCODE was already copied over.
      if((*expr)->getPCodeSegment()->containsClauseEval() || saveClauses) {
        for (ex_clause* clause = (*expr)->getClauses();
            clause;
            clause = clause->getNextClause())
        {
          short clauseSize;

          // If this has pCode, then we don't need to copy the clause.  Change
          // retCode, however, to reflect the fact that we got rid of a clause.
          // If we're generating a showplan, all clauses are to be emitted.
          if (!clause->noPCodeAvailable() && !saveClauses)
          {
            retCode = 1;
            continue;
          }

          // TBD:
          // Special case given to ExFunctionRandomSelection since this class
          // does not define the method getClassSize().  Adding it would require
          // a DP2 rebuild.  Maybe later - but soon!

          clauseSize =
            (clause->getClassID() == ex_clause::FUNC_RAND_SELECTION_ID)
              ? sizeof(ExFunctionRandomSelection)
              : clause->getClassSize();

          // Record size of space before allocation of clause and other stuff.
          Lng32 beforeSize = getSpace()->getAllocatedSpaceSize();

          // Allocate space for new clause
          ex_clause* newClause = (ex_clause*) new(getSpace()) char[clauseSize];

          // Copy Clause
          str_cpy_all((char*)newClause, (char*)clause, clauseSize);

          // Null-terminate next clause pointer
          newClause->setNextClause(NULL);

          newClause->copyOperands(clause, getSpace());
          newExpr->getPCodeSegment()->replaceClauseEvalPtr(clause, newClause);

          if (newExpr->getClauses() == NULL) {
            newExpr->setClauses(newClause);
          }
          else {
            prevClause->setNextClause(newClause);
          }

          // If a branch clause was previously seen, then we need to fix up it's
          // branch_clause and saved_next pointers (since they were initialized
          // to 0 in the newly copied clause.  The clause currently being
          // processed needs to be examined to see if it's one of these two
          // pointers for the branch clause.  The algorithm used below can be
          // improved if we allocate a list of pointers to branch clauses, but
          // I think simplicity outweights performance in this case.

          if (branchFound)
          {
            for (ex_clause* tempClause = newExpr->getClauses(); tempClause;
                 tempClause = tempClause->getNextClause())
            {
              if (tempClause->getType() == ex_clause::BRANCH_TYPE) {
                ex_branch_clause* branchClause = (ex_branch_clause*)tempClause;
  
                if (branchClause->get_branch_clause() == clause) {
                  branchClause->set_branch_clause(newClause);
                  break;
                }
                else if (branchClause->get_saved_next() == clause) {
                  branchClause->set_saved_next(newClause);
                  break;
                }
              }
            }
          }

          // If we're keeping a branch clause, we have to keep that clauses
          // associated clauses as well (i.e. branch_clause and saved_next
          // clauses.  This is because at runtime we do a check to see if the
          // two are equal to each other.  Also, when we pack the branch clause,
          // we also try and pack the associated clauses - which would lead to
          // an error if that didn't exist.  There may be a workaround here.
          // Also set the branchFound flag here.
  
          if (newClause->getType() == ex_clause::BRANCH_TYPE) {
            ex_branch_clause* branchClause = (ex_branch_clause*)newClause;

            // Only set no-pcode-available flag if we're not generating a
            // showplan.  If we are generating a showplan, then the clauses
            // will already get emitted.  This way we don't falsely report that
            // no pcode is available.

            if (!saveClauses) {
              branchClause->get_branch_clause()->setNoPCodeAvailable(TRUE);
              branchClause->get_saved_next()->setNoPCodeAvailable(TRUE);
            }

            branchFound = TRUE;
          }

          // Record size of space after clause and other stuff allocated.
          Lng32 afterSize = getSpace()->getAllocatedSpaceSize();

          // If showplan is being generated, make sure to discount the size of
          // those clauses which would be deleted if this wasn't a showplan.
          if (saveClauses)
            len1 += (afterSize - beforeSize);

          prevClause = newClause;
        }
      }

      // Search for embedded addresses in pcode segment and fixup if needed
      newExpr->getPCodeSegment()->replaceAttributesPtr(newExpr->getClauses(),
                                                       getSpace());

      newExpr->setLength(getSpace()->getAllocatedSpaceSize() - len1);

      // Point expr to new expression stored in fragment space
      *expr = (ex_expr*)newExpr;

    }
    else
    {
      // Allocate space in fragment for entire expression.
      newExpr = (ex_expr_base*)
        new(getSpace()) char[tempSpace->getAllocatedSpaceSize()];

      // Call the "pack" routine for the base expr class (via "packExpr").
      // This is done so that we can rebase it starting at the expression's
      // new location in the fragment space once it's copied over.  Also note,
      // only the base expr needs to be packed since any other expression
      // pointed to in the expression was already packed and rebased in the
      // fragment space.
      (*expr)->packExpr(tempSpace);

      // Make a full copy of expr from tempSpace to fragment space
      tempSpace->makeContiguous((char*)newExpr,
				 tempSpace->getAllocatedSpaceSize());

      // Point expr to new expression stored in fragment space
      *expr = (ex_expr*)newExpr;

      // Call the "unpack" routine for the base expr class for rebasing.
      (*expr)->unpackExpr((void*)(*expr), 0);
    }

    delete tempSpace;
  }

#else

  if (genLeanExpr())
    {
      // restore the original fragment space.
      ComSpace * tempSpace = generator->getTempSpace();
      generator->setTempSpace(NULL, FALSE);

      ex_expr_base * newExpr = NULL;
      if (((*expr)->getPCodeSegment() == NULL) ||
	  ((*expr)->getPCodeSegment()->containsClauseEval()))
	{
	  // make full copy of expr in fragment space
	  newExpr = (ex_expr_base*)
	    new(generator->getSpace()) char[tempSpace->getAllocatedSpaceSize()];
	  (*expr)->pack(tempSpace);
	  tempSpace->makeContiguous((char*)newExpr,
				    tempSpace->getAllocatedSpaceSize());
	  *expr = (ex_expr*)newExpr;
	  (*expr)->unpack((void*)(*expr), 0);

	  generator->setGenLeanExpr(FALSE);
	}
      else
	{
	  len1 = getSpace()->getAllocatedSpaceSize();

	  // make lean copy of expr in fragment space
	  newExpr =
	    new(generator->getSpace()) ex_expr_lean();
	  (*expr)->makeLeanCopy((ex_expr_lean*)newExpr, generator->getSpace());
	  *expr = (ex_expr*)newExpr;

	  totalExprLen =
	    getSpace()->getAllocatedSpaceSize() - len1;
	  pcodeExprLen = ((ex_expr_lean*)newExpr)->getPCodeSize();

	  ((ex_expr_lean*)newExpr)->setLength(totalExprLen);
	}

      delete tempSpace;
    }

#endif /* NEW_LEAN_EXPR */

  // clear cache of generated subexpressions
  cache_->clear();

  restorePCodeMode();

  return retCode;
}

void ExpGenerator::initClauseList()
{
  clause_list = new(wHeap()) AListNode(wHeap());
};


void ExpGenerator::linkClause(ItemExpr * node, ex_clause * clause)
{
  if (node)
    {
      setClauseLinked(TRUE);

      node->setClause(clause);
    }

  clause_list->linkElement(clause);

  // Do some specialized processing.

  // If this is a function clause, set the origFunctionOperType.
  // This is used to return correct error info at runtime.
  if ((clause->getType() == ex_clause::FUNCTION_TYPE) &&	node &&
      (((ex_function_clause *)clause)->getOperType() != node->origOpType()))
    {
      ((ex_function_clause *)clause)->setDerivedFunction(TRUE);
      ((ex_function_clause *)clause)->setOrigFunctionOperType(
                                                        node->origOpType());
    }
};

void ExpGenerator::fixupNextClause()
{
  AListNode0 *curr_node = clause_list->getHead();

  unsigned short currClauseNum = 0;
  while (curr_node->getNext())
    {
      ((ex_clause *)(curr_node->getElement()))->setNextClause((ex_clause *)(curr_node->getNext()->getElement()));
      if (((ex_clause *)(curr_node->getElement()))->getType() == ex_clause::BRANCH_TYPE)
	{
	  ((ex_clause *)(curr_node->getElement()))->setNextClause((ex_clause *)(curr_node->getNext()->getElement()));
	  ((ex_branch_clause *)curr_node->getElement())->set_saved_next((ex_clause *)(curr_node->getNext()->getElement()));
	}

      if (!curr_node->getNext())
	{
	  // this is the last clause. Mark it so.
	  ((ex_clause *)(curr_node->getElement()))->setLastClause();
	}

      ((ex_clause *)(curr_node->getElement()))->clauseNum() = ++currClauseNum;
      curr_node = curr_node->getNext();
    };
}

void ExpGenerator::initConstantList()
{
  constant_list = new(wHeap()) AListNode(wHeap());
  constants_length = 0;
  temps_length = 0;
};

void ExpGenerator::initPersistentList()
{
  persistentList_ = new(wHeap()) AListNode(wHeap());
  persistentLength_ = 0;
};

AListNode * ExpGenerator::getConstantList()
{
  return constant_list;
};

AListNode * ExpGenerator::getPersistentList()
{
  return persistentList_;
};

void ExpGenerator::linkConstant(void * expr_tree)
{
  constant_list->linkElement(expr_tree);
};

void ExpGenerator::linkPersistent(void *expTree)
{
  persistentList_->linkElement(expTree);
};

char * ExpGenerator::placeConstants(AListNode *list, Int32 length)
{
  // If there are no constants/persistents, bug out...
  //
  if(length == 0) return 0;

  // Allocate space for storing the image of the constants
  //
  char *area = getSpace()->allocateAlignedSpace(length);

  // All uninitialized constant/peristent variables must be zero.
  //
  // All memory from Space is zeroed out by default.
  // memset(area, 0, length);

  // Loop over each constant in the list and construct it in the image area.
  // The data format for the constants area is assumed to be in
  // SQLARK_EXPLODED_FORMAT.
  // See also method ConstValue::getOffsetsinBuffer()
  ConstValue * item;
  AListNode0 *current = list->getHead();
  while (current->getNext())
    {
      item = (ConstValue *)
	(((ExprNode *)(current->getElement()))->castToItemExpr());

      Attributes * attr
	= generator->getMapInfo(item->getValueId())->getAttr();

      if ((attr->getNullFlag()) && (item->isNull())) // null constant
	{
          ExpTupleDesc::setNullValue( area + attr->getNullIndOffset(),
                                      attr->getNullBitIndex(),
                                      attr->getTupleFormat() );
	}
      else
	{
	  if (attr->getNullFlag())
	    {
              ExpTupleDesc::clearNullValue( area + attr->getNullIndOffset(),
                                            attr->getNullBitIndex(),
                                            attr->getTupleFormat() );
	    }

	  if (attr->getVCIndicatorLength() > 0)
	    {
	      str_cpy_all
		(&area[attr->getVCLenIndOffset()],
		 (char *)item->getConstValue()
		 + item->getValueId().getType().getSQLnullHdrSize(),
		 attr->getVCIndicatorLength());
	    }

	  str_cpy_all
	    (&area[attr->getOffset()],
	     (char *)item->getConstValue()
	     + item->getValueId().getType().getSQLnullHdrSize()
	     + attr->getVCIndicatorLength(),
	     attr->getLength());
	}
      current = current->getNext();
    }

  return area;
}

NABoolean GenEvalPredicate(ItemExpr * rootPtr)
{
  // set up binder/generator stuff so expressions could be generated.
  InitSchemaDB();
  CmpStatement cmpStatement(CmpCommon::context());
  ActiveSchemaDB()->createStmtTables();
  BindWA       bindWA(ActiveSchemaDB(), CmpCommon::context());
  Generator    generator(CmpCommon::context());
  ExpGenerator expGen(&generator);
  generator.appendAtEnd();

  generator.setBindWA(&bindWA);
  generator.setExpGenerator(&expGen);
  FragmentDir * compFragDir = generator.getFragmentDir();

  // create the fragment (independent code space) for this expression
  CollIndex myFragmentId = compFragDir->pushFragment(FragmentDir::MASTER);

  // space where RCB will be generated
  Space * space = generator.getSpace();

  // allocate a work cri desc to encode keys. It has
  // 2 entries: 0, for consts. 1, for temps.
  ex_cri_desc * workCriDesc = new(space) ex_cri_desc(2, space);

  ex_expr * expr = 0;

  ItemExpr * boolResult = new(generator.wHeap()) BoolResult(rootPtr);

  boolResult->bindNode(generator.getBindWA());

  expGen.generateExpr(boolResult->getValueId(),
		      ex_expr::exp_SCAN_PRED,
		      &expr);

  // create a DP2 expression and initialize it with the key encode expr.
  ExpDP2Expr * dp2Expr = new(space) ExpDP2Expr(expr,
					       workCriDesc,
					       space);

  dp2Expr->setPCodeMode( expGen.getPCodeMode() );

  dp2Expr->getExpr()->fixup(0,0,0,NULL,NULL,FALSE,NULL);

  atp_struct * workAtp = dp2Expr->getWorkAtp();

  generator.removeAll();

  if (dp2Expr->getExpr()->eval(workAtp, 0) == ex_expr::EXPR_TRUE)
    return TRUE;
  else
    return FALSE;
}

short ExpGenerator::generateSamplingExpr(const ValueId &valId, ex_expr **expr,
					 Int32 &returnFactorOffset)
{
  // Prime the expression generator.
  //
  initExprGen();
  startExprGen(expr, ex_expr::exp_SCAN_PRED);

  // PreCodeGen the expression.
  //
  ItemExpr *temp = valId.getValueDesc()->getItemExpr()->preCodeGen(generator);
  if (!temp) return -1;

  // Set the result of the sampling expression to be a persistent variable.
  // This must be done after preCodeGen because the original item expression
  // is changed. Also, reset the codeGenerated flag for the item so
  // that the actual code will be generated. This is not the usual way
  // to use a persistent variable.
  //
  MapInfo *mapInfo=addPersistent(temp->getValueId(), generator->getMapTable());
  mapInfo->resetCodeGenerated();

  // If there were no errors, codeGen the expression.
  //
  temp->codeGen(generator);

  // Finialize the expression generator.
  //
  endExprGen(expr, 0);

  // Assert that the result of the sampling expression is stored in
  // persisent space. And, compute the offset for the result.
  //
  mapInfo = generator->getMapInfoAsIs(temp->getValueId());
  GenAssert(mapInfo, "Sampling result not in map table!");

  Attributes *attr = mapInfo->getAttr();
  GenAssert(attr->getAtpIndex() == 1,
	    "Sampling result must be a persistent expression variable.");

  returnFactorOffset = attr->getOffset();

  return 0;
}

MapInfo *ExpGenerator::addTemporary(ValueId val, MapTable *mapTable)
{
  // Add the value ID to the last map table.
  //
  MapInfo *mapInfo =
    generator->addMapInfoToThis(generator->getLastMapTable(), val, NULL);

  // Set the attributes to indicate a temporary ... ATP 0, Index 1
  //
  Attributes * mapAttr = mapInfo->getAttr();
  mapAttr->setAtp(0);
  mapAttr->setAtpIndex(1);

  // Compute length of this temporary and assign offsets to the attributes.
  // All temps are in sqlark_exploded format.
  //
  ULng32 len;
  ExpTupleDesc::TupleDataFormat tdataF = ExpTupleDesc::SQLARK_EXPLODED_FORMAT;
  ExpTupleDesc::computeOffsets(mapAttr,
			       tdataF,
			       len,
			       getTempsLength());
  addTempsLength(len);
  return mapInfo;
}

MapInfo *ExpGenerator::addPersistent(ValueId val, MapTable *mapTable)
{
  // Add the value ID to the map table.
  //
  MapInfo *mapInfo = generator->addMapInfoToThis(mapTable, val, NULL);

  // Set the attributes to indicate a persistent: Atp 1 and AtpIndex 1.
  //
  Attributes * mapAttr = mapInfo->getAttr();
  mapAttr->setAtp(1);
  mapAttr->setAtpIndex(1);

  // Compute length of this persistent and assign offsets to the attributes.
  // All persistents are in sqlark_exploded format.
  //
  ULng32 len;
  ExpTupleDesc::TupleDataFormat tdataF = ExpTupleDesc::SQLARK_EXPLODED_FORMAT;
  ExpTupleDesc::computeOffsets(mapAttr,
			       tdataF,
			       len,
			       persistentLength());
  persistentLength() = persistentLength() + len;

  // Mark the item as codeGenned.
  //
  mapInfo->codeGenerated();

  return mapInfo;
}

short ExpGenerator::genItemExpr(ItemExpr * item_expr, Attributes *** out_attr,
				Lng32 num_attrs, short gen_child)
/////////////////////////////////////////////////////////////////////////////
// Description of parameters:
// item_expr (IN) : the tree for which code is to be generated
// out_attr  (OUT): the generated attributes array is returned here. This
//                  is a pointer to an array of pointers, hence 3 *** s.
// num_attrs (IN) : number of attributes in the attribute array.
// gen_child (IN) : if -1, generate code for children.
//
// RETURN VALUE: 0, all ok. 1, code already been generated. -1, error.
/////////////////////////////////////////////////////////////////////////////
{
  MapInfo * map_info = generator->getMapInfoAsIs(item_expr->getValueId());
  if ((map_info) &&
      (map_info->isCodeGenerated()))
    return 1;

  if (!map_info)
    {
      // attempt to perform common subexpression elimination on this
      // expression
      if (cache_->expressionCanBeEliminated(item_expr))
        {
        // an equivalent expression has already been generated, and
        // this one has been replaced by it
        return 1;   // tell caller expression already generated
        }

      // no equivalent expression has been generated... continue...

      // this value has not been added to the map table. Add it
      // to the last map table as a temp. Temps are allocated
      // at atp_index = 1.
      map_info = addTemporary(item_expr->getValueId(), NULL);
    }

  Lng32 numAttrs = num_attrs;
  if (getShowplan())
    numAttrs *= 2;

  Attributes ** attr = new(wHeap()) Attributes * [numAttrs];
  for (Int32 i = 0; i < numAttrs; i++)
    {
      attr[i] = NULL;
    }

  /* assign result attributes*/
  attr[0] = map_info->getAttr();

  if (gen_child)
  {
    item_expr->codegen_and_set_attributes( generator, attr, num_attrs );
  }

  if (getShowplan())
    {
      attr[0+num_attrs] =
	new(wHeap()) ShowplanAttributes(item_expr->getValueId(),
					convertNAString(item_expr->getText(),
							generator->wHeap()));

      attr[0]->setShowplan();

      for (short i = 0; i < num_attrs - 1; i++)
	{
	  attr[i+1+num_attrs] =
	    new(wHeap())
	    ShowplanAttributes(item_expr->child(i)->getValueId(),
			       convertNAString(item_expr->child(i)->getText(),
					       generator->wHeap()));
	}
    }

  map_info->codeGenerated();

  *out_attr = attr;

  // add expression to generated cache (so if we later encounter an
  // equivalent expression, we can just use this one's generated code)
  cache_->add(item_expr);

  return 0;
}

/////////////////////////////////////////////////////////////////////////////
// methods for class ExpGeneratorCache
/////////////////////////////////////////////////////////////////////////////
ExpGeneratorCache::ExpGeneratorCache(Generator * generator)
: generator_(generator), cachedCasts_(generator->wHeap()),
  cachedBiAriths_(generator->wHeap()),
  substitutions_(generator->wHeap()),
  level_(0)
  {
  enableCommonSubexpressionElimination_ = TRUE;
  // getenv() calls are costly. avoid especially in release code.
#ifdef _DEBUG
  if (getenv("NO_COMMON_SUBEX_ELIM"))
    enableCommonSubexpressionElimination_ = FALSE;
#endif
  }

ExpGeneratorCache::~ExpGeneratorCache(void)
  {
  clear();  // to cause clean-up (e.g. avoid memory leak in substitutions_)
  }

// add an expression (which has had code generated) to the cache
void ExpGeneratorCache::add(ItemExpr * ie)
  {
  if (enableCommonSubexpressionElimination_)
    {
    if (level_ == 0) // don't cache anything that can be short-circuited
      {
      switch (ie->getOperatorType())
        {
        case ITM_CAST:
          {
          Cast * cie = (Cast *)ie;
          cachedCasts_.insert(cie);
          break;
          }
        case ITM_PLUS:
        case ITM_MINUS:
        case ITM_TIMES:
        case ITM_DIVIDE:
          {
          BiArith * bie = (BiArith *)ie;
          cachedBiAriths_.insert(bie);
          break;
          }
        default:
          break;
        }
      }
    }
  }


// find an expression which has already been generated equivalent
// to the input parameter; if none exists, returns NULL
ItemExpr * ExpGeneratorCache::findEquivalentGeneratedExpr(ItemExpr * ie)
  {
  ItemExpr * rc = 0;        // assume none exists

  if ((ie) &&
      (enableCommonSubexpressionElimination_))
    {
    switch (ie->getOperatorType())
      {
      case ITM_CAST:
        {
        for (CollIndex i = 0; (i < cachedCasts_.entries()) && (rc == 0); i++)
          {
          Cast * c = cachedCasts_[i];
          if (c->isEquivalentForCodeGeneration(ie))
            rc = c;
          }
        break;
        }
      case ITM_PLUS:
      case ITM_MINUS:
      case ITM_TIMES:
      case ITM_DIVIDE:
        {
        for (CollIndex i = 0; (i < cachedBiAriths_.entries()) && (rc == 0); i++)
          {
          BiArith * b = cachedBiAriths_[i];
          if (b->isEquivalentForCodeGeneration(ie))
            rc = b;
          }
        break;
        }
      default:
        break;
      }
    }

  return rc;
  }

NABoolean ExpGeneratorCache::expressionCanBeEliminated(ItemExpr * ie)
  {
  NABoolean rc = FALSE;  // assume expression cannot be eliminated

  // look to see if code to compute an equivalent expression has
  // already been generated
  ItemExpr * equiv_expr = findEquivalentGeneratedExpr(ie);
  if (equiv_expr)
    {
    // an equivalent expression has already been generated; replace
    // this one with that (common subexpression elimination)

      ValueId  temp1 = equiv_expr->getValueId();
      ValueId &temp2 = temp1;

      substitutions_.insert(new (generator_->wHeap())
        ExpGeneratorCacheSubstitution(ie,temp2));

      rc = TRUE;   // expression can be (and has been!) eliminated
    }
    return rc;
  }

void ExpGeneratorCache::incrementLevel(void)
  {
  level_++;
  }

void ExpGeneratorCache::decrementLevel(void)
  {
  GenAssert(level_ > 0,"Bad level in generated expression cache");
  level_--;
  }

// clear cache
void ExpGeneratorCache::clear(void)
  {
  cachedCasts_.clear();
  cachedBiAriths_.clear();

  // undo all substitutions and delete the substitution objects
  ExpGeneratorCacheSubstitution * subs = 0;
  while (substitutions_.getFirst(subs /* out */))
    {
    subs->undo();
    delete subs;
    }
  GenAssert(substitutions_.isEmpty(),"Bad undeleted substitutions");

  level_ = 0;
  }

Lng32 ExpGenerator::foldConstants(ItemExpr * inExpr, ItemExpr ** outExpr)
{
  Lng32 rc = 0;

  if (outExpr)
    *outExpr = inExpr;

  if (inExpr == NULL)
    return 0;

  if (CmpCommon::getDefault(CONSTANT_FOLDING) == DF_OFF)
    return 0;

  ValueId dummy;
  Lng32 daMark = CmpCommon::diags()->mark();
  rc = ValueIdList::evaluateExpr(dummy,
				 inExpr->getValueId(),
				 -1,
				 FALSE, // don't simplify expr
				 TRUE,  // do eval all consts
				 outExpr,
				 CmpCommon::diags());
  if ((rc < 0) ||
      (CmpCommon::diags()->getNumber() > 0))
    {
      if (outExpr)
         *outExpr = NULL;
      CmpCommon::diags()->rewind(daMark, TRUE);
      return -1;
    }

  return 0;
}

/////////////////////////////////////////////////////////////////////////////
// methods for class ExpGeneratorCacheSubstitution
/////////////////////////////////////////////////////////////////////////////
ExpGeneratorCacheSubstitution::ExpGeneratorCacheSubstitution(ItemExpr * ie,
                                                             ValueId &newValueId)
: ie_(ie), oldValueId_(ie->getValueId()), newValueId_(newValueId)
  {
  // now replace the old valueId in the ItemExpr with the new
  // (the act of creating a substitution causes substitution to be performed!)
  ie->setValueId(newValueId);
  }

// undo a substitution
void ExpGeneratorCacheSubstitution::undo(void)
  {
  // the 'if' below makes this method idempotent
  if (ie_->getValueId() == newValueId_)
    ie_->setValueId(oldValueId_);
  }

// generate a null constant and type it to input type
ConstValue * ExpGenerator::generateNullConst(const NAType &type)
{
  ConstValue * nullConst = new(wHeap()) ConstValue();
  nullConst->bindNode(generator->getBindWA());
  NAType * newType = type.newCopy(wHeap());
  newType->setNullable(TRUE);
  (nullConst->getValueId()).changeType(newType);
  return nullConst;
}


