short BiArithCount::codeGen(Generator * generator)
{
  Attributes ** attr;
  ExpGenerator * eg = generator->getExpGenerator();
  
  if (eg->genItemExpr(this, &attr, (1+getArity()), -1) == 1)
    return 0;

  // if temp space is needed for this operation, set it.
  if (attr[0]->isComplexType())
    {
      eg->addTempsLength(((ComplexType *)attr[0])->setTempSpaceInfo(getOperatorType(),
#pragma nowarn(1506)   // warning elimination 
								    eg->getTempsLength()));
#pragma warn(1506)  // warning elimination 
    }
			      
  ex_arith_count_clause * arith_clause =
    new(generator->getSpace()) 
    ex_arith_count_clause(getOperatorType(), 
			  attr, 
			  generator->getSpace());
  
  generator->getExpGenerator()->linkClause(this, arith_clause);

  return 0;
}
short UnArith::codeGen(Generator * generator)
{
  Attributes ** attr;
  ExpGenerator * eg = generator->getExpGenerator();
  
  if (eg->genItemExpr(this, &attr, (1+getArity()), -1) == 1)
    return 0;


  ex_arith_clause * arith_clause = 
    new(generator->getSpace()) 
    ex_arith_clause(getOperatorType(), attr, generator->getSpace(),
                    0, FALSE);
  
  generator->getExpGenerator()->linkClause(this, arith_clause);

  return 0;
}
// ItmBlockFunction::codeGen
//
// The Block function executes the code represented by both its children and
// then returns the result of the right child (child(1)).
//
short ItmBlockFunction::codeGen(Generator * generator) {
  // Get local handles...
  //
  Attributes **attr;
  Space* space = generator->getSpace();
  CollHeap *heap = generator->wHeap();
  ExpGenerator *exp = generator->getExpGenerator();

  // If this Block has already been codeGenned, then bug out...
  // Otherwise, allocate space for the result if necessary and set
  // attr[0] to point to the result attribute data. Also, mark this
  // node as codeGenned.
  //
  if (exp->genItemExpr(this, &attr, 2, 0) == 1)
    return 0;

  // CodeGen the left child.
  //
  child(0)->codeGen(generator);

  // CodeGen the right child.
  //
  child(1)->codeGen(generator);

  // The result of the Block is the result of the right child. Set
  // the src attribute for the convert (added below) to be the right child
  // The dst attribute has already been set in genItemExpr().
  //
  attr[1] = generator->getMapInfo
    (child(1)->castToItemExpr()->getValueId())->getAttr();

  // Allocate a convert clause to move the result from child(1) to the
  // result of this node. This move is necessary so that future
  // side-effects of the result of child(1) -- if it is a local variable,
  // for instance -- will not change the result of the Block.
  //
  ex_conv_clause * convClause =
    new(generator->getSpace()) ex_conv_clause
    (getOperatorType(), attr, space);
  generator->getExpGenerator()->linkClause(this, convClause);

  return 0;
}
void PartitioningFunction::generatePivLayout(
     Generator *generator,
     Lng32 &partitionInputDataLength,
     Lng32 atp,
     Lng32 atpIndex,
     Attributes ***pivAttrs)
{
  // assign offsets to the PIVs in a standard way

  ExpGenerator *expGen = generator->getExpGenerator();
  
  expGen->processValIdList(
       getPartitionInputValuesLayout(),
       ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
       (ULng32 &) partitionInputDataLength,
       atp,
       atpIndex,
       NULL,
       ExpTupleDesc::SHORT_FORMAT,
       0,
       pivAttrs);
}
short BiArith::codeGen(Generator * generator)
{
  Attributes ** attr;
  ExpGenerator * eg = generator->getExpGenerator();
  
  if (eg->genItemExpr(this, &attr, (1+getArity()), -1) == 1)
    return 0;

  // if temp space is needed for this operation, set it.
  if (attr[0]->isComplexType())
    {
      eg->addTempsLength(((ComplexType *)attr[0])->setTempSpaceInfo(getOperatorType(),
#pragma nowarn(1506)   // warning elimination 
								    eg->getTempsLength()));
#pragma warn(1506)  // warning elimination 
    }
			      
  attr[0]->resetlastdaymonthflag();
  attr[0]->resetlastdayonerrflag();

// Check to see which type of rounding is needed for add_months, date_add
// functions.  Set flags here for use in executor datetime.cpp.
  if (isStandardNormalization())
     attr[0]->setlastdayonerrflag();
  if (isKeepLastDay())
     attr[0]->setlastdaymonthflag();

  ex_arith_clause * arith_clause =
    new(generator->getSpace()) 
    ex_arith_clause(getOperatorType(), attr, generator->getSpace(),
		    (short)getRoundingMode(),
		    getDivToDownscale());

  generator->getExpGenerator()->linkClause(this, arith_clause);

  return 0;
}
short BiLogic::codeGen(Generator * generator)
{
  Attributes ** attr;

  if (generator->getExpGenerator()->genItemExpr(this, &attr, (1+getArity()), 0) == 1)
    return 0;
    
  Space * space = generator->getSpace();
  ExpGenerator * expGen = generator->getExpGenerator();

  // Normally, if code for a value id has been generated, and if
  // that value id is seen again, then code is not generated. The
  // location where the result is available is returned instead.
  // The case of a logical operator is different. Code is generated
  // again if a value id from the left child is also present in
  // the right child. This is done 
  // because at expression evaluation time, some of the expressions
  // may be skipped due to short circuit evaluation. 
  //
  // Allocate a new map table before generating code for each child.
  // This map table contains all the temporary results produced by
  // the child. 
  // Remove this map table after generating code for each child.
  generator->appendAtEnd();
  expGen->incrementLevel();

  codegen_and_set_attributes(generator, attr, 2); 
  //  generator->getExpGenerator()->setClauseLinked(FALSE);
  // child(0)->codeGen(generator);
  // attr[1] = generator->getAttr(child(0));
  // generator->getExpGenerator()->setClauseLinked(FALSE);

  /* generate boolean short circuit code */
  Attributes ** branch_attr = new(generator->wHeap()) Attributes * [2];

  branch_attr[0] = attr[0]->newCopy(generator->wHeap());
  branch_attr[0]->copyLocationAttrs(attr[0]);

  branch_attr[1] = attr[1]->newCopy(generator->wHeap());
  branch_attr[1]->copyLocationAttrs(attr[1]);

  branch_attr[0]->resetShowplan();
  ex_branch_clause * branch_clause 
    = new(space) ex_branch_clause(getOperatorType(), branch_attr, space);
  
  generator->getExpGenerator()->linkClause(0, branch_clause);
 
  generator->removeLast();
  expGen->decrementLevel();
  generator->appendAtEnd();
  expGen->incrementLevel();

  ValueIdSet markedEntries;
  // This ia a MapTable entry related fix for RangeSpec transformation.
  if( child(1)->getOperatorType() == ITM_RANGE_SPEC_FUNC )
    markGeneratedEntries(generator, child(1)->child(1), markedEntries);
  else
    markGeneratedEntries(generator, child(1), markedEntries);
//  if( child(1)->getOperatorType() == ITM_RANGE_SPEC_FUNC )
//    child(1)->child(1)->codeGen(generator);
//  else
    child(1)->codeGen(generator);
  ItemExpr *rightMost;
  if( child(1)->getOperatorType() == ITM_RANGE_SPEC_FUNC )
    rightMost = child(1)->child(1)->castToItemExpr();
  else
    rightMost = child(1)->castToItemExpr();

  while (rightMost->getOperatorType() == ITM_ITEM_LIST)
    rightMost = rightMost->child(1)->castToItemExpr();

  attr[2] = generator->
    getMapInfo(rightMost->getValueId())->getAttr();

  ex_bool_clause * bool_clause =
    new(space) ex_bool_clause(getOperatorType(), attr, space);

  generator->getExpGenerator()->linkClause(this, bool_clause);

  branch_clause->set_branch_clause((ex_clause *)bool_clause);
  
  generator->removeLast();
  expGen->decrementLevel();
  if( child(1)->getOperatorType() == ITM_RANGE_SPEC_FUNC )
    unGenerate(generator, child(1)->child(1));
  else
    unGenerate(generator, child(1));
  generateMarkedEntries(generator, markedEntries);

  return 0;
}
/////////////////////////////////////////////////////////////////////
//
// Contents:
//    
//   RelStoredProc::codeGen()
//
//////////////////////////////////////////////////////////////////////
short generateSPIOExpr(RelInternalSP * sp,
		       Generator * generator,
		       ExSPInputOutput * &inputExpr,
		       ExSPInputOutput * &outputExpr)
{
  ExpGenerator * expGen = generator->getExpGenerator();
  Space * genSpace = generator->getSpace();

  // Generate input(extract) expr
  FragmentDir * compFragDir = generator->getFragmentDir();

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

  // Start generation by creating the ExSPInputOutput class.
  //It will be initialized later.
  ExSPInputOutput * lInputExpr = new(space) ExSPInputOutput();

  ULng32 recordLen;
  ExpTupleDesc * tupleDesc = NULL;

  if (expGen->processValIdList(sp->procTypes(),
			       ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
			       recordLen,
			       0, 1,
			       &tupleDesc, 
			       ExpTupleDesc::LONG_FORMAT) == -1)
    return -1;

  ConvInstruction * cia = 
    (ConvInstruction *)space->allocateMemory(sp->procTypes().entries() * 
					    sizeof(ConvInstruction));

  ULng32 totalLen = space->getAllocatedSpaceSize();
 
  lInputExpr->initialize(tupleDesc, totalLen, cia);

  ExSPInputOutputPtr(lInputExpr).pack(space);

  // the generated expr is generated in chunks internally by
  // the space class. Make it contiguous by allocating and
  // moving it to a contiguous area.
  char * expr = new(generator->wHeap()) char[totalLen];
  space->makeContiguous((char *)expr, totalLen);
  inputExpr =
    (ExSPInputOutput *)(genSpace->allocateAndCopyToAlignedSpace((char *)expr, totalLen, 0));

  compFragDir->removeFragment();

  // Delete expr
  NADELETEBASIC(expr, generator->wHeap());
  expr = NULL;

  // Now generate the move to output row expr
  myFragmentId = compFragDir->pushFragment(FragmentDir::MASTER);
  space = generator->getSpace();

  ExSPInputOutput * lOutputExpr = new(space) ExSPInputOutput();

  if (expGen->processValIdList(sp->getTableDesc()->getColumnList(),
			       ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
			       recordLen,
			       0, 1,
			       &tupleDesc, 
			       ExpTupleDesc::LONG_FORMAT) == -1)
    return -1;

  cia = 
    (ConvInstruction *)space->allocateMemory(sp->getTableDesc()->getColumnList().entries() * 
					    sizeof(ConvInstruction));

  for (short i = 0; i < (short) tupleDesc->numAttrs(); i++)
    {
      ex_conv_clause tempClause;

      cia[i] = tempClause.findInstruction(REC_BYTE_V_ASCII, 
					  -1, // no op 
					  tupleDesc->getAttr(i)->getDatatype(), 
					  tupleDesc->getAttr(i)->getLength(),
					  0);
      
    }

  totalLen = space->getAllocatedSpaceSize();
 
  lOutputExpr->initialize(tupleDesc, totalLen, cia);

  ExSPInputOutputPtr(lOutputExpr).pack(space);

  expr = new(generator->wHeap()) char[totalLen];
  space->makeContiguous((char *)expr, totalLen);
  outputExpr =
    (ExSPInputOutput *)(genSpace->allocateAndCopyToAlignedSpace((char *)expr, totalLen, 0));

  compFragDir->removeFragment();

  // Delete expr
  NADELETEBASIC(expr, generator->wHeap());
  expr = NULL;
  
  return 0;
}
short RelInternalSP::codeGen(Generator * generator)
{
  Space * space          = generator->getSpace();
  ExpGenerator * exp_gen = generator->getExpGenerator();
  MapTable * last_map_table = generator->getLastMapTable();

  ex_expr * input_expr  = NULL;
  ex_expr * output_expr = NULL;

  ////////////////////////////////////////////////////////////////////////////
  //
  // Returned atp layout:
  //
  // |--------------------------------|
  // | input data  |  stored proc row |
  // | ( I tupps ) |  ( 1 tupp )      |
  // |--------------------------------|
  // <-- returned row to parent ---->
  //
  // input data:        the atp input to this node by its parent. 
  // stored proc row:   tupp where the row read from SP is moved.
  //
  ////////////////////////////////////////////////////////////////////////////

  ex_cri_desc * given_desc 
    = generator->getCriDesc(Generator::DOWN);

  ex_cri_desc * returned_desc 
    = new(space) ex_cri_desc(given_desc->noTuples() + 1, space);
 
  // cri descriptor for work atp has 3 entries:
  // -- the first two entries for consts and temps.
  // -- Entry 3(index #2) is where the input and output rows will be created.
  ex_cri_desc * work_cri_desc = new(space) ex_cri_desc(3, space);
  const Int32 work_atp = 1;
  const Int32 work_atp_index = 2;
 
  ExpTupleDesc * input_tuple_desc = NULL;
  ExpTupleDesc * output_tuple_desc = NULL;

  // Generate expression to create the input row that will be
  // given to the stored proc.
  // The input value is in sp->getProcAllParams() 
  // and has to be converted to sp->procType().
  // Generate Cast node to convert procParam to ProcType.
  // If procType is a varchar, explode it. This is done
  // so that values could be extracted correctly.
  ValueIdList procVIDList;
  for (CollIndex i = 0; i < procTypes().entries(); i++)
    {
      Cast * cn;

      if ((procTypes())[i].getType().getVarLenHdrSize() > 0) 
	{

// 5/9/98: add support for VARNCHAR
          const CharType& char_type =
                (CharType&)((procTypes())[i].getType());

	  // Explode varchars by moving them to a fixed field
	  // whose length is equal to the max length of varchar.
	  cn = new(generator->wHeap()) 
	    Cast ((getProcAllParamsVids())[i].getItemExpr(), 
		  (new(generator->wHeap())
		   SQLChar(generator->wHeap(),
		           CharLenInfo(char_type.getStrCharLimit(), char_type.getDataStorageSize()),
			   char_type.supportsSQLnull(),
			   FALSE, FALSE, FALSE,
			   char_type.getCharSet(),
			   char_type.getCollation(),
			   char_type.getCoercibility()
/*
                           (procTypes())[i].getType().getNominalSize(),
			   (procTypes())[i].getType().supportsSQLnull()
*/
                          )
                  )
                 );
	  
	  // Move the exploded field to a varchar field since 
	  // procType is varchar.
	  // Can optimize by adding an option to convert node to
	  // blankpad. TBD.
	  //
	  cn = new(generator->wHeap())
	    Cast(cn, &((procTypes())[i].getType()));
	} 
      else
 	cn = new(generator->wHeap()) Cast((getProcAllParamsVids())[i].getItemExpr(),
					  &((procTypes())[i].getType()));

      cn->bindNode(generator->getBindWA());
      procVIDList.insert(cn->getValueId());
    }

  ULng32 inputRowlen_ = 0;
  exp_gen->generateContiguousMoveExpr(procVIDList, -1, /*add conv nodes*/
				      work_atp, work_atp_index,
				      ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
				      inputRowlen_,
				      &input_expr,
				      &input_tuple_desc,
				      ExpTupleDesc::LONG_FORMAT);

  // add all columns from this SP to the map table. 
  ULng32 tupleLength;
  exp_gen->processValIdList(getTableDesc()->getColumnList(),
			    ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
			    tupleLength,
			    work_atp, 
			    work_atp_index);
 
  // Generate expression to move the output row returned by the
  // stored proc back to parent.
  ULng32 outputRowlen_ = 0;
  MapTable * returnedMapTable = 0;
  exp_gen->generateContiguousMoveExpr(getTableDesc()->getColumnList(),
				      -1 /*add conv nodes*/,
				      0, returned_desc->noTuples() - 1,
				      ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
				      outputRowlen_,
				      &output_expr,
				      &output_tuple_desc,
				      ExpTupleDesc::LONG_FORMAT,
				      &returnedMapTable);
 
  // Now generate expressions used to extract or move input or
  // output values. See class ExSPInputOutput.
  ExSPInputOutput * extractInputExpr = NULL;
  ExSPInputOutput * moveOutputExpr = NULL;
  
  generateSPIOExpr(this, generator,
		   extractInputExpr,
		   moveOutputExpr);

  // done with expressions at this operator. Remove the appended map tables.
  generator->removeAll(last_map_table);

  // append the map table containing the returned columns
  generator->appendAtEnd(returnedMapTable);

  NAString procNameAsNAString(procName_);
  char * sp_name = 
    space->allocateAndCopyToAlignedSpace(procNameAsNAString,
					 procNameAsNAString.length(), 0);

  ExpGenerator *expGen = generator->getExpGenerator();

  // expression to conditionally return 0 or more rows.
  ex_expr *predExpr = NULL;

  // generate tuple selection expression, if present
  if(NOT selectionPred().isEmpty())
  {
    ItemExpr* pred = selectionPred().rebuildExprTree(ITM_AND,TRUE,TRUE);
    expGen->generateExpr(pred->getValueId(),ex_expr::exp_SCAN_PRED,&predExpr);
  }

  ComTdbStoredProc * sp_tdb = new(space)
    ComTdbStoredProc(sp_name, 
		     input_expr,
		     inputRowlen_,
		     output_expr,
		     outputRowlen_,
		     work_cri_desc,
		     work_atp_index,
		     given_desc,
		     returned_desc,
		     extractInputExpr,
		     moveOutputExpr,
		     2,
		     1024,
		     (Cardinality) getGroupAttr()->
		     getOutputLogPropList()[0]->
		     getResultCardinality().value(),
		     5,
		     64000,  //10240
		     predExpr,
		     (UInt16) arkcmpInfo_);
		      
  generator->initTdbFields(sp_tdb);

  if(!generator->explainDisabled()) 
    {
      generator->setExplainTuple(
				 addExplainInfo(sp_tdb, 0, 0, generator));
    }
  // Do not infer that any transaction started can 
  // be in READ ONLY mode if ISPs are present.
  generator->setNeedsReadWriteTransaction(TRUE);

  generator->setCriDesc(given_desc, Generator::DOWN);
  generator->setCriDesc(returned_desc, Generator::UP);
  generator->setGenObj(this, sp_tdb);

  // Some built-in functions require a TMF transaction
  // because they get their information from catman
  generator->setTransactionFlag(getRequiresTMFTransaction());

  return 0;
}
ItemExpr * buildEncodeTree(desc_struct * column,
                           desc_struct * key,
                           NAString * dataBuffer, //IN:contains original value
                           Generator * generator,
                           ComDiagsArea * diagsArea)
{
  ExpGenerator * expGen = generator->getExpGenerator();

  // values are encoded by evaluating the expression:
  //    encode (cast (<dataBuffer> as <datatype>))
  // where <dataBuffer> points to the string representation of the
  //      data value to be encoded, and <datatype> contains the
  //      PIC repsentation of the columns's datatype.

  // create the CAST part of the expression using the parser.
  
  // if this is a nullable column and the key value passed in
  // is a NULL value, then treat it as a special case. A NULL value
  // is passed in as an unquoted string of characters NULL in the
  // dataBuffer. This case has to be treated different since the
  // parser doesn't recognize the syntax "CAST (NULL as <datatype>)".
  NAString ns;
  ItemExpr * itemExpr;
  NABoolean nullValue = FALSE;

  NABoolean caseinsensitiveEncode = FALSE;
  if (column->body.columns_desc.caseinsensitive)
    caseinsensitiveEncode = TRUE;

  if (column->body.columns_desc.null_flag &&
      dataBuffer->length() >= 4 &&
      str_cmp(*dataBuffer, "NULL", 4) == 0)
    {
      nullValue = TRUE;

      ns = "CAST ( @A1 AS ";
      ns += column->body.columns_desc.pictureText;
      ns += ");";
  
      // create a NULL constant
      ConstValue * nullConst = new(expGen->wHeap()) ConstValue();
      nullConst->synthTypeAndValueId();

      itemExpr = expGen->createExprTree(ns,
                                        CharInfo::UTF8,
					ns.length(),
					1, nullConst);
    }
  else
    {
      ns = "CAST ( ";
      ns += *dataBuffer;
      ns += " AS ";
      ns += column->body.columns_desc.pictureText;
      ns += ");";
  
      itemExpr = expGen->createExprTree(ns,
                                        CharInfo::UTF8,
					ns.length());
    }

  CMPASSERT(itemExpr != NULL);
  ItemExpr *boundItemExpr =
  itemExpr->bindNode(generator->getBindWA());
  if (boundItemExpr == NULL)
    return NULL;

  // make sure that the source and target values have compatible type.
  // Do this only if source is not a null value.
  NAString srcval;
  srcval = "";
  srcval += *dataBuffer;
  srcval += ";";
  ItemExpr * srcNode = expGen->createExprTree(srcval, CharInfo::UTF8, srcval.length());
  CMPASSERT(srcNode != NULL);
  srcNode->synthTypeAndValueId();
  if ((NOT nullValue) &&
      (NOT srcNode->getValueId().getType().isCompatible(itemExpr->getValueId().getType())))
    {
      if (diagsArea)
	{
	  emitDyadicTypeSQLnameMsg(-4039, 
				   itemExpr->getValueId().getType(),
				   srcNode->getValueId().getType(),
				   column->body.columns_desc.colname,
				   NULL,
				   diagsArea);
	}

      return NULL;
    }

  if (column->body.columns_desc.null_flag)
    ((NAType *)&(itemExpr->getValueId().getType()))->setNullable(TRUE);
  else
    ((NAType *)&(itemExpr->getValueId().getType()))->setNullable(FALSE);
  
  // Explode varchars by moving them to a fixed field
  // whose length is equal to the max length of varchar.
  ////collation??
  DataType datatype = column->body.columns_desc.datatype;
  if (DFS2REC::isSQLVarChar(datatype))
    {
      char lenBuf[10];
      NAString vc((NASize_T)100);	// preallocate a big-enough buf

      size_t len = column->body.columns_desc.length;
      if (datatype == REC_BYTE_V_DOUBLE) len /= SQL_DBCHAR_SIZE;

      vc = "CAST (@A1 as CHAR(";
      vc += str_itoa(len, lenBuf);
      if ( column->body.columns_desc.character_set == CharInfo::UTF8 ||
           ( column->body.columns_desc.character_set == CharInfo::SJIS &&
             column->body.columns_desc.encoding_charset == CharInfo::SJIS ) )
        {
          vc += " BYTE";
          if (len > 1)
            vc += "S";
        }
      vc += ") CHARACTER SET ";
      vc += CharInfo::getCharSetName(column->body.columns_desc.character_set);
      vc += ");";

      itemExpr = expGen->createExprTree(vc, CharInfo::UTF8, vc.length(), 1, itemExpr);
      itemExpr->synthTypeAndValueId();

      ((NAType *)&(itemExpr->getValueId().getType()))->
        setNullable(column->body.columns_desc.null_flag);
  }

  // add the encode node on top of it.
  short desc_flag = TRUE;
  if (key->body.keys_desc.ordering == 0) // ascending
    desc_flag = FALSE;
  
  itemExpr = new(expGen->wHeap()) CompEncode(itemExpr, desc_flag);
  
  itemExpr->synthTypeAndValueId();
  
  ((CompEncode*)itemExpr)->setCaseinsensitiveEncode(caseinsensitiveEncode);

  return itemExpr;
}
short
PhysUnPackRows::codeGen(Generator *generator)
{
    // Get handles on expression generator, map table, and heap allocator
    //
    ExpGenerator *expGen = generator->getExpGenerator();
    Space *space = generator->getSpace();

    // Allocate a new map table for this operation
    //
    MapTable *localMapTable = generator->appendAtEnd();

    // Generate the child and capture the task definition block and a description
    // of the reply composite row layout and the explain information.
    //
    child(0)->codeGen(generator);

    ComTdb *childTdb = (ComTdb*)(generator->getGenObj());

    ex_cri_desc *childCriDesc = generator->getCriDesc(Generator::UP);

    ExplainTuple *childExplainTuple = generator->getExplainTuple();

    // Make all of my child's outputs map to ATP 1. Since they are
    // not needed above, they will not be in the work ATP (0).
    // (Later, they will be removed from the map table)
    //
    localMapTable->setAllAtp(1);

    // Generate the given and returned composite row descriptors.
    // unPackRows adds a tupp (for the generated outputs) to the
    // row given by the parent. The workAtp will have the 2 more
    // tupps (1 for the generated outputs and another for the
    // indexValue) than the given.
    //
    ex_cri_desc *givenCriDesc = generator->getCriDesc(Generator::DOWN);

    ex_cri_desc *returnedCriDesc =
#pragma nowarn(1506)   // warning elimination 
        new(space) ex_cri_desc(givenCriDesc->noTuples() + 1, space);
#pragma warn(1506)  // warning elimination 

    ex_cri_desc *workCriDesc =
#pragma nowarn(1506)   // warning elimination 
        new(space) ex_cri_desc(givenCriDesc->noTuples() + 2, space);
#pragma warn(1506)  // warning elimination 


    // unPackCols is the next to the last Tp in Atp 0, the work ATP.
    // and the last Tp in the returned ATP.
    //
    const Int32 unPackColsAtpIndex = workCriDesc->noTuples() - 2;
    const Int32 unPackColsAtp = 0;

    // The length of the new tuple which will contain the columns
    // generated by unPackRows
    //
    ULng32 unPackColsTupleLen;

    // The Tuple Desc describing the tuple containing the new unPacked columns
    // It is generated when the expression is generated.
    //
    ExpTupleDesc *unPackColsTupleDesc = 0;

    // indexValue is the last Tp in Atp 0, the work ATP.
    //
    const Int32 indexValueAtpIndex = workCriDesc->noTuples() - 1;
    const Int32 indexValueAtp = 0;

    // The length of the work tuple which will contain the value
    // of the index.  This should always be sizeof(int).
    //
    ULng32 indexValueTupleLen = 0;

    // The Tuple Desc describing the tuple containing the new unPacked columns
    // It is generated when the expression is generated.
    //
    ExpTupleDesc *indexValueTupleDesc = 0;

    ValueIdList indexValueList;

    if (indexValue() != NULL_VALUE_ID)
    {
        indexValueList.insert(indexValue());

        expGen->processValIdList(indexValueList,
                                 ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                                 indexValueTupleLen,
                                 indexValueAtp,
                                 indexValueAtpIndex,
                                 &indexValueTupleDesc,
                                 ExpTupleDesc::SHORT_FORMAT);

        GenAssert(indexValueTupleLen == sizeof(Int32),
                  "UnPackRows::codeGen: Internal Error");
    }

    // If a packingFactor exists, generate a move expression for this.
    // It is assumed that the packingFactor expression evaluates to a
    // 4 byte integer.
    //
    ex_expr *packingFactorExpr = 0;
    ULng32 packingFactorTupleLen;

    if(packingFactor().entries() > 0) {
        expGen->generateContiguousMoveExpr(packingFactor(),
                                           -1,
                                           unPackColsAtp,
                                           unPackColsAtpIndex,
                                           ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                                           packingFactorTupleLen,
                                           &packingFactorExpr);

        GenAssert(packingFactorTupleLen == sizeof(Int32),
                  "UnPackRows::codeGen: Internal Error");
    }

    // Generate the UnPack expressions.
    //
    // characteristicOutputs() - refers to the list of expressions
    // to be move to another tuple.
    //
    // 0 - Do not add conv. nodes.
    //
    // unPackColsAtp - this expression will move data to the
    // unPackColsAtp (0) ATP.
    //
    // unPackColsAtpIndex - within the unPackColsAtp (0) ATP, the destination
    // for this move expression will be the unPackColsAtpIndex TP. This should
    // be the next to the last TP of the work ATP. (The indexValue will be in
    // the last position)
    //
    // SQLARK_EXPLODED_FORMAT - generate the move expression to construct
    // the destination tuple in EXPLODED FORMAT.
    //
    // unPackColsTupleLen - This is an output which will contain the length
    // of the destination Tuple.
    //
    // &unPackColsExpr - The address of the pointer to the expression
    // which will be generated.
    //
    // &unPackColsTupleDesc - The address of the tuple descriptor which is
    // generated.  This describes the destination tuple of the move expression.
    //
    // SHORT_FORMAT - generate the unPackColsTupleDesc in the SHORT FORMAT.
    //
    ex_expr *unPackColsExpr = 0;

    expGen->
    genGuardedContigMoveExpr(selectionPred(),
                             getGroupAttr()->getCharacteristicOutputs(),
                             0, // No Convert Nodes added
                             unPackColsAtp,
                             unPackColsAtpIndex,
                             ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                             unPackColsTupleLen,
                             &unPackColsExpr,
                             &unPackColsTupleDesc,
                             ExpTupleDesc::SHORT_FORMAT);

#pragma nowarn(1506)   // warning elimination 
    workCriDesc->setTupleDescriptor(unPackColsAtpIndex,
#pragma warn(1506)  // warning elimination 
                                    unPackColsTupleDesc);

#pragma nowarn(1506)   // warning elimination 
    returnedCriDesc->setTupleDescriptor(unPackColsAtpIndex,
#pragma warn(1506)  // warning elimination 
                                        unPackColsTupleDesc);


    // expressions for rowwise rowset implementation.
    ex_expr * rwrsInputSizeExpr = 0;
    ex_expr * rwrsMaxInputRowlenExpr = 0;
    ex_expr * rwrsBufferAddrExpr = 0;
    ULng32 rwrsInputSizeExprLen = 0;
    ULng32 rwrsMaxInputRowlenExprLen = 0;
    ULng32 rwrsBufferAddrExprLen = 0;

    const Int32 rwrsAtp = 1;
    const Int32 rwrsAtpIndex = workCriDesc->noTuples() - 2;
    ExpTupleDesc * rwrsTupleDesc = 0;
    ValueIdList rwrsVidList;
    if (rowwiseRowset())
    {
        rwrsVidList.insert(this->rwrsInputSizeExpr()->getValueId());
        expGen->generateContiguousMoveExpr(rwrsVidList,
                                           0 /*don't add conv nodes*/,
                                           rwrsAtp, rwrsAtpIndex,
                                           ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                                           rwrsInputSizeExprLen,
                                           &rwrsInputSizeExpr,
                                           &rwrsTupleDesc,ExpTupleDesc::SHORT_FORMAT);

        rwrsVidList.clear();
        rwrsVidList.insert(this->rwrsMaxInputRowlenExpr()->getValueId());
        expGen->generateContiguousMoveExpr(rwrsVidList,
                                           0 /*don't add conv nodes*/,
                                           rwrsAtp, rwrsAtpIndex,
                                           ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                                           rwrsMaxInputRowlenExprLen,
                                           &rwrsMaxInputRowlenExpr,
                                           &rwrsTupleDesc,ExpTupleDesc::SHORT_FORMAT);

        rwrsVidList.clear();
        rwrsVidList.insert(this->rwrsBufferAddrExpr()->getValueId());
        expGen->generateContiguousMoveExpr(rwrsVidList,
                                           0 /*don't add conv nodes*/,
                                           rwrsAtp, rwrsAtpIndex,
                                           ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                                           rwrsBufferAddrExprLen,
                                           &rwrsBufferAddrExpr,
                                           &rwrsTupleDesc,ExpTupleDesc::SHORT_FORMAT);

        expGen->assignAtpAndAtpIndex(rwrsOutputVids(),
                                     unPackColsAtp, unPackColsAtpIndex);
    }

    // Move the generated maptable entries, to the localMapTable,
    // so that all other entries can later be removed.
    //
    for(ValueId outputValId = getGroupAttr()->getCharacteristicOutputs().init();
            getGroupAttr()->getCharacteristicOutputs().next(outputValId);
            getGroupAttr()->getCharacteristicOutputs().advance(outputValId)) {

        generator->addMapInfoToThis(localMapTable, outputValId,
                                    generator->getMapInfo(outputValId)->
                                    getAttr());

        // Indicate that code was generated for this map table entry.
        //
        generator->getMapInfoFromThis(localMapTable, outputValId)->codeGenerated();
    }

    NABoolean tolerateNonFatalError = FALSE;

    if (isRowsetIterator() && (generator->getTolerateNonFatalError())) {
        tolerateNonFatalError = TRUE;
        setTolerateNonFatalError(RelExpr::NOT_ATOMIC_);
    }


    // Allocate the UnPack TDB
    //
    ComTdbUnPackRows *unPackTdb = NULL;

    if (rowwiseRowset())
    {
        unPackTdb =
            new (space) ComTdbUnPackRows(NULL, //childTdb,
                                         rwrsInputSizeExpr,
                                         rwrsMaxInputRowlenExpr,
                                         rwrsBufferAddrExpr,
                                         rwrsAtpIndex,
                                         givenCriDesc,
                                         returnedCriDesc,
                                         workCriDesc,
                                         16,
                                         1024,
                                         (Cardinality) getGroupAttr()->
                                         getOutputLogPropList()[0]->
                                         getResultCardinality().value(),
                                         2, 20000);
    }
    else
    {

        // Base the initial queue size on the est. cardinality.
        // UnPackRows does not do dyn queue resize, so passed in
        // queue size values represent initial (and final) queue
        // sizes (not max queue sizes).
        //
        queue_index upQueueSize =
            (queue_index)getGroupAttr()->getOutputLogPropList()[0]->getResultCardinality().value();

        // Make sure it is at least 1024.
        upQueueSize = (upQueueSize < 1024 ? 1024 : upQueueSize);

        // Make sure that it is not more the 64K.
        upQueueSize = (upQueueSize > 65536 ? 65536 : upQueueSize);

        unPackTdb =
            new (space) ComTdbUnPackRows(childTdb,
                                         packingFactorExpr,
                                         unPackColsExpr,
#pragma nowarn(1506)   // warning elimination 
                                         unPackColsTupleLen,
                                         unPackColsAtpIndex,
                                         indexValueAtpIndex,
                                         givenCriDesc,
                                         returnedCriDesc,
                                         workCriDesc,
                                         16,
                                         upQueueSize,
                                         (Cardinality) getGroupAttr()->
                                         getOutputLogPropList()[0]->
                                         getResultCardinality().value(),
                                         isRowsetIterator(),
                                         tolerateNonFatalError);
    }

#pragma warn(1506)  // warning elimination 
    generator->initTdbFields(unPackTdb);

    // Remove child's outputs from mapTable, They are not needed
    // above.
    //
    generator->removeAll(localMapTable);

    // Add the explain Information for this node to the EXPLAIN
    // Fragment.  Set the explainTuple pointer in the generator so
    // the parent of this node can get a handle on this explainTuple.
    //
    if(!generator->explainDisabled()) {
        generator->setExplainTuple(addExplainInfo(unPackTdb,
                                   childExplainTuple,
                                   0,
                                   generator));
    }

    // Restore the Cri Desc's and set the return object.
    //
    generator->setCriDesc(givenCriDesc, Generator::DOWN);
    generator->setCriDesc(returnedCriDesc, Generator::UP);
    generator->setGenObj(this, unPackTdb);


    return 0;
}
short
PhysSequence::codeGen(Generator *generator) 
{
  // Get a local handle on some of the generator objects.
  //
  CollHeap *wHeap = generator->wHeap();
  Space *space = generator->getSpace();
  ExpGenerator *expGen = generator->getExpGenerator();
  MapTable *mapTable = generator->getMapTable();

  // Allocate a new map table for this node. This must be done
  // before generating the code for my child so that this local
  // map table will be sandwiched between the map tables already
  // generated and the map tables generated by my offspring.
  //
  // Only the items available as output from this node will
  // be put in the local map table. Before exiting this function, all of
  // my offsprings map tables will be removed. Thus, none of the outputs 
  // from nodes below this node will be visible to nodes above it except 
  // those placed in the local map table and those that already exist in
  // my ancestors map tables. This is the standard mechanism used in the
  // generator for managing the access to item expressions.
  //
  MapTable *localMapTable = generator->appendAtEnd();

  // Since this operation doesn't modify the row on the way down the tree,
  // go ahead and generate the child subtree. Capture the given composite row
  // descriptor and the child's returned TDB and composite row descriptor.
  //
  ex_cri_desc * givenCriDesc = generator->getCriDesc(Generator::DOWN);
  child(0)->codeGen(generator);
  ComTdb *childTdb = (ComTdb*)generator->getGenObj();
  ex_cri_desc * childCriDesc = generator->getCriDesc(Generator::UP);
  ExplainTuple *childExplainTuple = generator->getExplainTuple();

  // Make all of my child's outputs map to ATP 1. The child row is only 
  // accessed in the project expression and it will be the second ATP 
  // (ATP 1) passed to this expression.
  //
  localMapTable->setAllAtp(1);

  // My returned composite row has an additional tupp.
  //
  Int32 numberTuples = givenCriDesc->noTuples() + 1;
  ex_cri_desc * returnCriDesc 
#pragma nowarn(1506)   // warning elimination 
    = new (space) ex_cri_desc(numberTuples, space);
#pragma warn(1506)  // warning elimination 

  // For now, the history buffer row looks just the return row. Later,
  // it may be useful to add an additional tupp for sequence function
  // itermediates that are not needed above this node -- thus, this
  // ATP is kept separate from the returned ATP.
  //
  const Int32 historyAtp = 0;
  const Int32 historyAtpIndex = numberTuples-1;
#pragma nowarn(1506)   // warning elimination 
  ex_cri_desc *historyCriDesc = new (space) ex_cri_desc(numberTuples, space);
#pragma warn(1506)  // warning elimination 
  ExpTupleDesc *historyDesc = 0;

  //seperate the read and retur expressions
  seperateReadAndReturnItems(wHeap);

  // The history buffer consists of items projected directly from the
  // child, the root sequence functions, the value arguments of the 
  // offset functions, and running sequence functions. These elements must 
  // be materialized in the  history buffer in order to be able to compute 
  // the outputs of this node -- the items projected directly from the child 
  // (projectValues) and the root sequence functions (sequenceFunctions).
  //
  // Compute the set of sequence function items that must be materialized
  // int the history buffer. -- sequenceItems
  //
  // Compute the set of items in the history buffer: the union of the 
  // projected values and the value arguments. -- historyIds
  //
  // Compute the set of items in the history buffer that are computed:
  // the difference between all the elements in the history buffer
  // and the projected items. -- computedHistoryIds
  //

  // KB---will need to return atp with 3 tups only 0,1 and 2 
  // 2 -->values from history buffer after ther are moved to it

 
  addCheckPartitionChangeExpr(generator, TRUE);

  ValueIdSet historyIds;

  historyIds += movePartIdsExpr(); 
  historyIds += sequencedColumns();
  
  ValueIdSet outputFromChild = child(0)->getGroupAttr()->getCharacteristicOutputs();

  getHistoryAttributes(readSeqFunctions(),outputFromChild, historyIds, TRUE, wHeap);

  // Add in the top level sequence functions.
  historyIds += readSeqFunctions();

  getHistoryAttributes(returnSeqFunctions(),outputFromChild, historyIds, TRUE, wHeap);
  // Add in the top level functions.
  historyIds += returnSeqFunctions();
  
  // Layout the work tuple format which consists of the projected
  // columns and the computed sequence functions. First, compute
  // the number of attributes in the tuple.
  //
  ULng32 numberAttributes 
    = ((NOT historyIds.isEmpty()) ? historyIds.entries() : 0);

  // Allocate an attribute pointer vector from the working heap.
  //
  Attributes **attrs = new(wHeap) Attributes*[numberAttributes];

  // Fill in the attributes vector for the history buffer including
  // adding the entries to the map table. Also, compute the value ID
  // set for the elements to project from the child row.
  //
  //??????????re-visit this function??
  computeHistoryAttributes(generator, 
                           localMapTable,
                           attrs,
                           historyIds);

  // Create the tuple descriptor for the history buffer row and
  // assign the offsets to the attributes. For now, this layout is 
  // identical to the returned row. Set the tuple descriptors for
  // the return and history rows.
  //
  ULng32 historyRecLen;
  expGen->processAttributes(numberAttributes,
                            attrs,
                            ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                            historyRecLen,
                            historyAtp,
                            historyAtpIndex,
                            &historyDesc,
                            ExpTupleDesc::SHORT_FORMAT);
  NADELETEBASIC(attrs, wHeap);
#pragma nowarn(1506)   // warning elimination 
  returnCriDesc->setTupleDescriptor(historyAtpIndex, historyDesc);
#pragma warn(1506)  // warning elimination 
#pragma nowarn(1506)   // warning elimination 
  historyCriDesc->setTupleDescriptor(historyAtpIndex, historyDesc);
#pragma warn(1506)  // warning elimination 

  // If there are any sequence function items, generate the sequence 
  // function expressions.
  //
  ex_expr * readSeqExpr = NULL;
  if(NOT readSeqFunctions().isEmpty())
    {
      ValueIdSet seqVals = readSeqFunctions();
      seqVals += sequencedColumns();
      seqVals += movePartIdsExpr(); 
      expGen->generateSequenceExpression(seqVals,
                                         readSeqExpr);
    }

  ex_expr *checkPartChangeExpr = NULL;
  if (!checkPartitionChangeExpr().isEmpty()) {
    ItemExpr * newCheckPartitionChangeTree= 
        checkPartitionChangeExpr().rebuildExprTree(ITM_AND,TRUE,TRUE);

    expGen->generateExpr(newCheckPartitionChangeTree->getValueId(), 
                         ex_expr::exp_SCAN_PRED,
                         &checkPartChangeExpr);
  }

  //unsigned long rowLength;
  ex_expr * returnExpr = NULL;
  if(NOT returnSeqFunctions().isEmpty())
  {
    expGen->generateSequenceExpression(returnSeqFunctions(),
                                         returnExpr);

  }

  // Generate expression to evaluate predicate on the output
  //
  ex_expr *postPred = 0;

  if (! selectionPred().isEmpty()) {
    ItemExpr * newPredTree = 
      selectionPred().rebuildExprTree(ITM_AND,TRUE,TRUE);

    expGen->generateExpr(newPredTree->getValueId(), ex_expr::exp_SCAN_PRED,
                         &postPred);
  }


  // Reset ATP's to zero for parent.
  //
  localMapTable->setAllAtp(0);


  // Generate expression to evaluate the cancel expression
  //
  ex_expr *cancelExpression = 0;

  if (! cancelExpr().isEmpty()) {
    ItemExpr * newCancelExprTree = 
      cancelExpr().rebuildExprTree(ITM_AND,TRUE,TRUE);

    expGen->generateExpr(newCancelExprTree->getValueId(), ex_expr::exp_SCAN_PRED,
                         &cancelExpression);
  }

  //
  //  For overflow
  //
  // ( The following are meaningless if ! unlimitedHistoryRows() ) 
  NABoolean noOverflow =  
    CmpCommon::getDefault(EXE_BMO_DISABLE_OVERFLOW) == DF_ON ;
  NABoolean logDiagnostics = 
    CmpCommon::getDefault(EXE_DIAGNOSTIC_EVENTS) == DF_ON ;
  NABoolean possibleMultipleCalls = generator->getRightSideOfFlow() ;
  short scratchTresholdPct = 
    (short) CmpCommon::getDefaultLong(SCRATCH_FREESPACE_THRESHOLD_PERCENT);
  // determione the memory usage (amount of memory as percentage from total
  // physical memory used to initialize data structures)
  unsigned short memUsagePercent =
    (unsigned short) getDefault(BMO_MEMORY_USAGE_PERCENT);
  short memPressurePct = (short)getDefault(GEN_MEM_PRESSURE_THRESHOLD);

  historyRecLen = ROUND8(historyRecLen);

  Lng32 maxNumberOfOLAPBuffers;
  Lng32 maxRowsInOLAPBuffer;
  Lng32 minNumberOfOLAPBuffers;
  Lng32 numberOfWinOLAPBuffers;
  Lng32 olapBufferSize;

  computeHistoryParams(historyRecLen,
                       maxRowsInOLAPBuffer,
                       minNumberOfOLAPBuffers,
                       numberOfWinOLAPBuffers,
                       maxNumberOfOLAPBuffers,
                       olapBufferSize);

  ComTdbSequence *sequenceTdb
    = new(space) ComTdbSequence(readSeqExpr,
                                returnExpr,
                                postPred,
                                cancelExpression,
                                getMinFollowingRows(),
#pragma nowarn(1506)   // warning elimination 
                                historyRecLen,
                                historyAtpIndex,
                                childTdb,
                                givenCriDesc,
                                returnCriDesc,
                                (queue_index)getDefault(GEN_SEQFUNC_SIZE_DOWN),
                                (queue_index)getDefault(GEN_SEQFUNC_SIZE_UP),
                                getDefault(GEN_SEQFUNC_NUM_BUFFERS),
                                getDefault(GEN_SEQFUNC_BUFFER_SIZE),
				olapBufferSize,
                                maxNumberOfOLAPBuffers,
                                numHistoryRows(),
                                getUnboundedFollowing(),
				logDiagnostics,
				possibleMultipleCalls,
				scratchTresholdPct,
				memUsagePercent,
				memPressurePct,
                                maxRowsInOLAPBuffer,
                                minNumberOfOLAPBuffers,
                                numberOfWinOLAPBuffers,
                                noOverflow,
                                checkPartChangeExpr);
#pragma warn(1506)  // warning elimination 
  generator->initTdbFields(sequenceTdb);

  // update the estimated value of HistoryRowLength with actual value
  //setEstHistoryRowLength(historyIds.getRowLength());

  double sequenceMemEst = getEstimatedRunTimeMemoryUsage(sequenceTdb);
  generator->addToTotalEstimatedMemory(sequenceMemEst);

  if(!generator->explainDisabled()) {
    Lng32 seqMemEstInKBPerCPU = (Lng32)(sequenceMemEst / 1024) ;
    seqMemEstInKBPerCPU = seqMemEstInKBPerCPU/
      (MAXOF(generator->compilerStatsInfo().dop(),1));
    generator->setOperEstimatedMemory(seqMemEstInKBPerCPU);

    generator->
      setExplainTuple(addExplainInfo(sequenceTdb,
                                     childExplainTuple,
                                     0,
                                     generator));

    generator->setOperEstimatedMemory(0);
  }

  sequenceTdb->setScratchIOVectorSize((Int16)getDefault(SCRATCH_IO_VECTOR_SIZE_HASH));
  sequenceTdb->setOverflowMode(generator->getOverflowMode());

  sequenceTdb->setBmoMinMemBeforePressureCheck((Int16)getDefault(EXE_BMO_MIN_SIZE_BEFORE_PRESSURE_CHECK_IN_MB));
  
  if(generator->getOverflowMode() == ComTdb::OFM_SSD )
    sequenceTdb->setBMOMaxMemThresholdMB((UInt16)(ActiveSchemaDB()->
				   getDefaults()).
			  getAsLong(SSD_BMO_MAX_MEM_THRESHOLD_IN_MB));
  else
    sequenceTdb->setBMOMaxMemThresholdMB((UInt16)(ActiveSchemaDB()->
				   getDefaults()).
			  getAsLong(EXE_MEMORY_AVAILABLE_IN_MB));

  // The CQD EXE_MEM_LIMIT_PER_BMO_IN_MB has precedence over the mem quota sys
  NADefaults &defs = ActiveSchemaDB()->getDefaults();
  UInt16 mmu = (UInt16)(defs.getAsDouble(EXE_MEM_LIMIT_PER_BMO_IN_MB));
  UInt16 numBMOsInFrag = (UInt16)generator->getFragmentDir()->getNumBMOs();
  if (mmu != 0)
    sequenceTdb->setMemoryQuotaMB(mmu);
  else {
    // Apply quota system if either one the following two is true:
    //   1. the memory limit feature is turned off and more than one BMOs 
    //   2. the memory limit feature is turned on
    NABoolean mlimitPerCPU = defs.getAsDouble(EXE_MEMORY_LIMIT_PER_CPU) > 0;

    if ( mlimitPerCPU || numBMOsInFrag > 1 ) {

        double memQuota = 
           computeMemoryQuota(generator->getEspLevel() == 0,
                              mlimitPerCPU,
                              generator->getBMOsMemoryLimitPerCPU().value(),
                              generator->getTotalNumBMOsPerCPU(),
                              generator->getTotalBMOsMemoryPerCPU().value(),
                              numBMOsInFrag, 
                              generator->getFragmentDir()->getBMOsMemoryUsage()
                             );
                                  
        sequenceTdb->setMemoryQuotaMB( UInt16(memQuota) );
    }
  }

  generator->setCriDesc(givenCriDesc, Generator::DOWN);
  generator->setCriDesc(returnCriDesc, Generator::UP);
  generator->setGenObj(this, sequenceTdb);

  return 0;

}
void RangePartitioningFunction::generatePivLayout(
     Generator *generator,
     Lng32 &partitionInputDataLength,
     Lng32 atp,
     Lng32 atpIndex,
     Attributes ***pivAttrs)
{
  // Make a layout of the partition input data record such that
  // begin and end key are aligned in the same way.
  // (layout = ((beg. key) (filler1) (end key) (filler2) (exclusion flag)))

  ExpGenerator *expGen = generator->getExpGenerator();
  CollIndex numPartInputs = getPartitionInputValuesLayout().entries();
  CollIndex numPartKeyCols = (numPartInputs - 1) / 2;
  // the number of partition input variables must be odd
  GenAssert(2*numPartKeyCols+1 == numPartInputs,
	    "NOT 2*numPartKeyCols+1 == numPartInputs");


  // ---------------------------------------------------------------------
  // Start by processing the begin key PIVs
  // ---------------------------------------------------------------------
  ValueIdList partialPivs;
  Attributes **returnedAttrs = NULL;
  Attributes **localPartialAttrs;
  Lng32 maxAlignment = 1;
  Lng32 alignedPartKeyLen;

  if (pivAttrs)
    {
      returnedAttrs = new(generator->wHeap()) Attributes *[numPartInputs];
    }

  CollIndex i = 0;
  for (i = 0; i < numPartKeyCols; i++)
    partialPivs.insert(getPartitionInputValuesLayout()[i]);
  
  expGen->processValIdList(
       partialPivs,
       ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
       (ULng32 &) partitionInputDataLength,
       atp,
       atpIndex,
       NULL,
       ExpTupleDesc::SHORT_FORMAT,
       0,
       &localPartialAttrs);

  if (returnedAttrs)
    for (i = 0; i < numPartKeyCols; i++)
      returnedAttrs[i] = localPartialAttrs[i];

  // ---------------------------------------------------------------------
  // Now find out the max. alignment that is needed in the begin key,
  // make sure that the end key starts on an offset that is a
  // multiple of the max. alignment in the partition input values
  // ---------------------------------------------------------------------
  for (i = 0; i < numPartKeyCols; i++)
    {
      if (localPartialAttrs[i]->getDataAlignmentSize() > maxAlignment)
	maxAlignment = localPartialAttrs[i]->getDataAlignmentSize();
      if (localPartialAttrs[i]->getVCIndicatorLength() > maxAlignment)
	maxAlignment = localPartialAttrs[i]->getVCIndicatorLength();
      if (localPartialAttrs[i]->getNullIndicatorLength() > maxAlignment)
	maxAlignment = localPartialAttrs[i]->getNullIndicatorLength();
    }

  alignedPartKeyLen = partitionInputDataLength;
  while (alignedPartKeyLen % maxAlignment != 0)
    alignedPartKeyLen++;

  // ---------------------------------------------------------------------
  // Now that we are starting on a good offset, process the end key
  // ---------------------------------------------------------------------
  partialPivs.clear();
  for (i = numPartKeyCols; i < numPartInputs-1; i++)
    partialPivs.insert(getPartitionInputValuesLayout()[i]);
  
  expGen->processValIdList(
       partialPivs,
       ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
       (ULng32 &) partitionInputDataLength,
       atp,
       atpIndex,
       NULL,
       ExpTupleDesc::SHORT_FORMAT,
       alignedPartKeyLen,
       &localPartialAttrs);

  if (returnedAttrs)
    for (i = numPartKeyCols; i < numPartInputs-1; i++)
      returnedAttrs[i] = localPartialAttrs[i-numPartKeyCols];

  // ---------------------------------------------------------------------
  // Process the exclusion flag at offset 2*alignedPartKeyLen
  // ---------------------------------------------------------------------
  partialPivs.clear();
  partialPivs.insert(getPartitionInputValuesLayout()[numPartInputs-1]);
  
  expGen->processValIdList(
       partialPivs,
       ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
       (ULng32 &) partitionInputDataLength,
       atp,
       atpIndex,
       NULL,
       ExpTupleDesc::SHORT_FORMAT,
       2*alignedPartKeyLen,
       &localPartialAttrs);

  // set up return values

  if (returnedAttrs)
    returnedAttrs[numPartInputs-1] = localPartialAttrs[0];

  partitionInputDataLength += 2*alignedPartKeyLen;

  if (pivAttrs)
    {
      *pivAttrs = returnedAttrs;
    }
  else
    {
      NADELETEBASIC(returnedAttrs, generator->wHeap());
    }
}
// ItmDoWhileFunction::codeGen
//
// The DoWhile function executes the code represented by child(0) until 
// the condition represented by child(1) becomes false. The result of 
// the DoWhile is the final value of child(0).
//
// The looping is accomplished by inserting a NOOP/BRANCH pair. The NOOP
// is inserted before generating the code for either child and serves as a 
// branch target. The BRANCH is inserted after generating the code for
// both children and is targeted at the NOOP clause based on the result of
// child(1). Between the NOOP and the BRANCH the body of the loop (child(0)) 
// and the termination condition (child(1)) are repeatedly evaluated. After
// the branch the final result of the loop body is assigned as the result
// of the DoWhile.
//
short ItmDoWhileFunction::codeGen(Generator * generator) {
  // Get local handles...
  //
  Attributes **attr;
  Space* space = generator->getSpace();
  CollHeap *wHeap = generator->wHeap();
  ExpGenerator *exp = generator->getExpGenerator();

  // If this DoWhile has already been codeGenned, then bug out...
  // Otherwise, allocate space for the result if necessary and set
  // attr[0] to point to the result attribute data. Also, mark this
  // node as codeGenned.
  //
  if (exp->genItemExpr(this, &attr, 2, 0) == 1)
    return 0;

  // Insert the NOOP clause to use as the branch target for the
  // start of the loop body.
  //
  ex_clause * branchTarget = new(space) ex_noop_clause();
  exp->linkClause(this, branchTarget);

  // CodeGen the body of the loop.
  //
  child(0)->codeGen(generator);

  // The result of the DoWhile is the result of the body of the loop. Set
  // the src attribute for the convert (added below) to be the body of
  // the while loop. The dst attribute has already been set in genItemExpr().
  //
  attr[1] = generator->getMapInfo
    (child(0)->castToItemExpr()->getValueId())->getAttr();

  // CodeGen the loop termination condition.
  //
  child(1)->codeGen(generator);

  // Construct a BRANCH clause to loop back and repeat the expression
  // and condition if the condition evaluates to TRUE.
  //
  Attributes ** branchAttrs = new(wHeap) Attributes*[2];
  Attributes *boolAttr = generator->getMapInfo
    (child(1)->castToItemExpr()->getValueId())->getAttr();
  branchAttrs[0] = boolAttr->newCopy(wHeap);
  branchAttrs[1] = boolAttr->newCopy(wHeap);
  //  branchAttrs[0]->copyLocationAttrs(boolAttr);
  //  branchAttrs[1]->copyLocationAttrs(boolAttr);

  branchAttrs[0]->resetShowplan();
  ex_branch_clause * branchClause
    = new(space) ex_branch_clause(ITM_OR, branchAttrs, space);
  branchClause->set_branch_clause(branchTarget);

  // Insert the branch clause into the expression.
  //
  exp->linkClause(this, branchClause);

  // Allocate a convert clause to move the result from child(0) to the
  // result of this node. This move is necessary so that future
  // side-effects of the result of child(0) -- if it is a local variable,
  // for instance -- will not change the result of the DoWhile.
  //
  ex_conv_clause * convClause =
    new(generator->getSpace()) ex_conv_clause
    (getOperatorType(), attr, space);
  exp->linkClause(this, convClause);

  return 0;
}
short
PhysSample::codeGen(Generator *generator) 
{  
  // Get a local handle on some of the generator objects.
  //
  CollHeap *wHeap = generator->wHeap();
  Space *space = generator->getSpace();
  MapTable *mapTable = generator->getMapTable();
  ExpGenerator *expGen = generator->getExpGenerator();

  // Allocate a new map table for this node. This must be done
  // before generating the code for my child so that this local
  // map table will be sandwiched between the map tables already
  // generated and the map tables generated by my offspring.
  //
  // Only the items available as output from this node will
  // be put in the local map table. Before exiting this function, all of
  // my offsprings map tables will be removed. Thus, none of the outputs 
  // from nodes below this node will be visible to nodes above it except 
  // those placed in the local map table and those that already exist in
  // my ancestors map tables. This is the standard mechanism used in the
  // generator for managing the access to item expressions.
  //
  MapTable *localMapTable = generator->appendAtEnd();

  // Since this operation doesn't modify the row on the way down the tree,
  // go ahead and generate the child subtree. Capture the given composite row
  // descriptor and the child's returned TDB and composite row descriptor.
  //
  ex_cri_desc * givenCriDesc = generator->getCriDesc(Generator::DOWN);
  child(0)->codeGen(generator);
  ComTdb *childTdb = (ComTdb*)generator->getGenObj();
  ex_cri_desc * childCriDesc = generator->getCriDesc(Generator::UP);
  ExplainTuple *childExplainTuple = generator->getExplainTuple();

  // Geneate the sampling expression.
  //
  ex_expr *balExpr = NULL;
  Int32 returnFactorOffset = 0;
  ValueId val;
  val = balanceExpr().init();
  if(balanceExpr().next(val))
    expGen->generateSamplingExpr(val, &balExpr, returnFactorOffset);

  // Alias the sampleColumns() so that they reference the underlying
  // expressions directly. This is done to avoid having to generate and
  // execute a project expression that simply moves the columns from
  // one tupp to another to reflect the application of the sampledCol
  // function.
  //
//   ValueId valId;
//   for(valId = sampledColumns().init();
//       sampledColumns().next(valId);
//       sampledColumns().advance(valId))
//     {
//       MapInfo *mapInfoChild = localMapTable->getMapInfoAsIs
// 	(valId.getItemExpr()->child(0)->castToItemExpr()->getValueId());
//       GenAssert(mapInfoChild, "Sample::codeGen -- no child map info.");
//       Attributes *attr = mapInfoChild->getAttr();
//       MapInfo *mapInfo = localMapTable->addMapInfoToThis(valId, attr);
//       mapInfo->codeGenerated();
//     }
// check if any of the columns inthe sampled columns are lob columns. If so, return an error.
  ValueId valId;
  for(valId = sampledColumns().init();
      sampledColumns().next(valId);
      sampledColumns().advance(valId))
    {
      const NAType &colType = valId.getType();
      if ((colType.getFSDatatype() == REC_BLOB) ||
	  (colType.getFSDatatype() == REC_CLOB))
	{
	   *CmpCommon::diags() << DgSqlCode(-4322);
	   GenExit();
	}
    }
  // Now, remove all attributes from the map table except the 
  // the stuff in the local map table -- the result of this node.
  //
//  localMapTable->removeAll();

  // Generate the expression to evaluate predicate on the sampled row.
  //
  ex_expr *postPred = 0;
  if (!selectionPred().isEmpty()) {
    ItemExpr * newPredTree 
      = selectionPred().rebuildExprTree(ITM_AND,TRUE,TRUE);

    expGen->generateExpr(newPredTree->getValueId(), ex_expr::exp_SCAN_PRED,
			 &postPred);
  }

  // Construct the Sample TDB.
  //
  ComTdbSample *sampleTdb
    = new(space) ComTdbSample(NULL,
			      balExpr,
			      returnFactorOffset,
			      postPred,
			      childTdb,
			      givenCriDesc,
			      childCriDesc,
			      (queue_index)getDefault(GEN_SAMPLE_SIZE_DOWN),
			      (queue_index)getDefault(GEN_SAMPLE_SIZE_UP));
  generator->initTdbFields(sampleTdb);

  if(!generator->explainDisabled()) {
    generator->
      setExplainTuple(addExplainInfo(sampleTdb,
                                     childExplainTuple,
                                     0,
                                     generator));
  }

  generator->setCriDesc(givenCriDesc, Generator::DOWN);
  generator->setCriDesc(childCriDesc, Generator::UP);
  generator->setGenObj(this, sampleTdb);

  return 0;
}