short BaseColumn::codeGen(Generator * generator)
{
  // if this column has not been added to the map table or
  // it does not have a valid offset, and
  // it has an EIC list, then add it to the map table and
  // assign attributes from the one of the EIC values.
  MapInfo * mapInfo = generator->getMapInfoAsIs(getValueId());
  if ((!mapInfo ||
       !mapInfo->isOffsetAssigned()) &&
      (!getEIC().isEmpty()))
    {
      MapInfo * index_col_map_info;
      short done = 0;
      for (ValueId val_id = getEIC().init();
	   !done && getEIC().next(val_id);
	   getEIC().advance(val_id))
	{
	  if (index_col_map_info = generator->getMapInfoAsIs(val_id))
	    {
	      Attributes * attr = 
		generator->addMapInfo(getValueId(), 0)->getAttr();
	      attr->copyLocationAttrs(index_col_map_info->getAttr());
	      done = -1;
	    }
	}
    }
      
  return 0;
}
short Assign::codeGen(Generator * generator)
{
  Attributes ** attr;

  // If this Assign has already been codeGenned, then bug out early.
  //
  MapInfo * assignMapInfo = generator->getMapInfoAsIs(getValueId());
  if (assignMapInfo && assignMapInfo->isCodeGenerated())
    return 0;

  // If the left child (lvalue) is already in the map table, then
  // add the Assign value Id to the map table with the same attributes
  // as the let child. Mark the Assign node as codeGenned. Also, allocate
  // space for the attributes.
  //
  MapInfo *leftChildMapInfo = generator->getMapInfoAsIs
    (child(0)->castToItemExpr()->getValueId());
  if (leftChildMapInfo)
    {
      if (! assignMapInfo)
	assignMapInfo = 
	  generator->addMapInfoToThis(generator->getLastMapTable(), 
				      getValueId(), 
				      leftChildMapInfo->getAttr());
      assignMapInfo->codeGenerated();
      attr = new(generator->wHeap()) Attributes*[2];

      // Set the result attribute
      //
      attr[0] = assignMapInfo->getAttr();
    }
  // Otherwise, go ahead and generate the Assign attributes (which also
  // allocates space for the Assign result). Add the left child to the
  // map table with the same attributes as the Assign node.
  //
  else
    {
      generator->getExpGenerator()->genItemExpr(this, &attr, 2, 0);
      generator->addMapInfoToThis(generator->getLastMapTable(), 
				  child(0)->castToItemExpr()->getValueId(),
				  attr[0]);
    }

  attr[0]->resetShowplan();

  // Now, generate code for the right child (rvalue).
  //
  generator->getExpGenerator()->setClauseLinked(FALSE);
  child(1)->codeGen(generator);
  attr[1] = generator->getAttr(child(1));
  generator->getExpGenerator()->setClauseLinked(FALSE);

  ex_conv_clause * conv_clause =
    new(generator->getSpace()) ex_conv_clause
    (getOperatorType(), attr, generator->getSpace());
  generator->getExpGenerator()->linkClause(this, conv_clause);

  return 0;
}
示例#3
0
 typename DomainEnumerate<Val>::ValueId
 DomainEnumerate<Val>::insert(const typename Val::Value& value) {
     Val attr(value, this);
     const_iterator found = std::find( values_.begin(), values_.end(), attr );
     if( found != values_.end() )
         return getValueId(found);
     //inserts element on the end (if not found)
     return getValueId( values_.insert( values_.end(), Val(value, this) ) );
 }
short ValueIdRef::codeGen(Generator * generator)
{
  MapInfo * map_info = generator->getMapInfoAsIs(getValueId());
  if (!map_info)
    {
      /* this value has not been added to the map table. Add it.*/
      map_info = 
	generator->addMapInfo(getValueId(), 
			      generator->getMapInfo(isDerivedFrom())->getAttr());
      
    }
  
  return 0;
}
示例#5
0
ValueIdList AbstractTable::copyValueIds(const size_t row, const field_list_t *fields) const {
  ValueIdList valueIdList;

  if (fields) {
for (const field_t & field: *fields) {
      valueIdList.push_back(getValueId(field, row));
    }
  } else {
    for (size_t i = 0; i < columnCount(); ++i) {
      valueIdList.push_back(getValueId(i, row));
    }
  }

  return valueIdList;
}
// ItmSeqNotTHISFunction::preCodeGen
//
// Transforms the NOT THIS sequence function into an offset of its child
// that uses the saved ROWS SINCE offset in the ExpGenerator. This allows
// the entire part of the expression which changes with each history row to be 
// calculated inside a single offset expression. All other parts of the 
// expression are below THIS, i.e., in the current row.
//
// Note: NOT THIS expressions occur only within a ROWS SINCE.
//
// EXAMPLE:
//   select runningsum(this(a)), 
//          rows since (this (b) > a * (c+5))  
//          from iTab2 sort by a;
//
//          rows since      ----->  becomes:     rows since
//                |                                    |
//                >                                    >
//               /  \                                 /  \
//           this   not this                      this      OFFSET                     
//             /          \                         /        /  \                      
//            b            *                       b        *   <not THIS Loop counter>
//                        / \                              / \                         
//                       a   +                            a   +                        
//                          / \                              / \    
//                         c   5                            c   5
//                                                  
//
ItemExpr *ItmSeqNotTHISFunction::preCodeGen(Generator *generator)
{
  if (nodeIsPreCodeGenned())
    return this;
  markAsPreCodeGenned();

  // Get some local handles...
  //
  CollHeap *wHeap = generator->wHeap();
  ItemExpr *itmChild = child(0)->castToItemExpr();
  ItemExpr *savedRowsSinceCounter =
                 generator->getExpGenerator()->getRowsSinceCounter();

  GenAssert(savedRowsSinceCounter, "ItmSeqNotTHIS::preCodeGen -- ROWS SINCE counter is NULL.");

  // Generate the new OFFSET expression
  //
  ItemExpr *offExpr = new(wHeap) ItmSeqOffset(itmChild, savedRowsSinceCounter);
  ((ItmSeqOffset *)offExpr)->setIsOLAP(isOLAP());
  // Get value Ids and types for all of the items. Must do this typing before
  // replacing this value Id's item expression -- otherwise, the typing
  // will give a result different than the type already computed for this
  // sequence function.
  //
  offExpr->synthTypeAndValueId(TRUE);

  // Replace the original value ID with the new expression.
  //
  getValueId().replaceItemExpr(offExpr);

  // Return the preCodeGen of the new OFFSET expression.
  //
  return offExpr->preCodeGen(generator);
}
TEST_F(TableRangeViewTests, pc_using_factory) {
  auto t = io::Loader::shortcuts::load("test/lin_xxs.tbl");
  size_t start = 5;
  size_t end = 20;
  size_t row = 10;
  size_t column = 1;

  auto trv = TableRangeView::create(t, start, end);

  ASSERT_EQ(trv->size(), (end - start));

  ValueId i = trv->getValueId(column, row - start);
  ValueId i2 = t->getValueId(column, row);

  ASSERT_EQ(i.valueId, i2.valueId);
}
// A transformation method for protecting sequence functions from not
// being evaluated due to short-circuit evaluation. 
//
void ItmScalarMinMax::protectiveSequenceFunctionTransformation
(Generator *generator)
{
  // Recurse on the children
  //
  ItemExpr::protectiveSequenceFunctionTransformation(generator);

  // Remove the original value id from the node being transformed.
  //
  ValueId id = getValueId();
  setValueId(NULL_VALUE_ID);
  synthTypeAndValueId(TRUE);

  // Construct the new subtree.
  //
  // SCALAR_MIN/MAX -- force evaluation of both children
  //
  // SCALAR(LEFT_CHILD, RIGHT_CHILD) ==>
  //   BLOCK(BLOCK(LEFT_CHILD, RIGHT_CHILD), 
  //         SCALAR(LEFT_CHILD, RIGHT_CHILD))
  // 
  ItemExpr *block = new(generator->wHeap()) ItmBlockFunction
    (new(generator->wHeap()) ItmBlockFunction(child(0), child(1)), this);
  
  // Replace the old expression with the new expression for the 
  // orginal value id
  //
  id.replaceItemExpr(block);

  // Run the new expression through type and value id synthesis
  //
  block->synthTypeAndValueId(TRUE);
}
// A transformation method for protecting sequence functions from not
// being evaluated due to short-circuit evaluation. 
//
void BiLogic::protectiveSequenceFunctionTransformation(Generator *generator)
{
  // Recurse on the children
  //
  ItemExpr::protectiveSequenceFunctionTransformation(generator);

  // Remove the original value id from the node being transformed and
  // assign it a new value id.
  //
  ValueId id = getValueId();
  setValueId(NULL_VALUE_ID);
  synthTypeAndValueId(TRUE);

  // Construct the new subtree.
  //
  // AND/OR -- force right child evaluation
  //
  // LOGIC(LEFT_CHILD, RIGHT_CHILD) ==>
  //   BLOCK(RIGHT_CHILD, LOGIC(LEFT_CHILD, RIGHT_CHILD))
  //
  ItemExpr *block = new(generator->wHeap()) ItmBlockFunction(child(1), this);

  // Replace the old expression with the new expression for the 
  // orginal value id
  //
  id.replaceItemExpr(block);

  // Run the new expression through type and value id synthesis
  //
  block->synthTypeAndValueId(TRUE);
}
// A transformation method for protecting sequence functions from not
// being evaluated due to short-circuit evaluation.
//
void Case::protectiveSequenceFunctionTransformation(Generator *generator)
{
  // Recurse on the children
  //
  ItemExpr::protectiveSequenceFunctionTransformation(generator);

  // Remove the original value id from the node being transformed and
  // assign it a new value id.
  //
  ValueId id = getValueId();
  setValueId(NULL_VALUE_ID);
  synthTypeAndValueId(TRUE);

  // Construct the new subtree.
  //
  // Case -- force evaluation of all the WHEN, THEN and ELSE parts
  //
  // CASE(IFE1(W1,T1,IFE2(W2,T2,IFE3(...)))) ==>
  //   BLOCK(BLOCK(BLOCK(W1,T1),BLOCK(W2,T2)), CASE(...))
  //
  // Decend the ITM_IF_THEN_ELSE tree pulling out each WHEN and THEN pair.
  // Mate each pair with a block and attach them to the protected block, 
  // which contains all of the WHEN/THEN pairs for the entire tree.
  // Also, pull out any CASE operands and attach them to the protected
  // block as well.
  //
  ItemExpr *block = NULL;
  ItemExpr *ife = child(0);
  for(; (ife != NULL) && (ife->getOperatorType() == ITM_IF_THEN_ELSE);
       ife = ife->child(2))
    {
      ItemExpr *sub = new(generator->wHeap())
	ItmBlockFunction(ife->child(0), ife->child(1));
      if(block)
	block = new(generator->wHeap()) ItmBlockFunction(sub, block);
      else
	block = sub;
    }      

  // Add the ELSE condition, if any to the protected block
  //
  if(ife)
    block = new(generator->wHeap()) ItmBlockFunction(ife, block);

  // Construct the top-level block function. The left child is the protected
  // block, which contains all of the expresssions that need to be 
  // pre-evaluated. This right child is the original case statement.
  //
  block = new(generator->wHeap()) ItmBlockFunction(block, this);

  // Replace the old expression with the new expression for the
  // original id
  //
  id.replaceItemExpr(block);

  // Run the new expression through type and value id synthesis
  //
  block->synthTypeAndValueId(TRUE);
}
示例#11
0
TEST_F(TableRangeViewTests, init_pc) {
  {
    auto t = io::Loader::shortcuts::load("test/lin_xxs.tbl");

    auto trv = new TableRangeView(t, 0, t->size());
    ASSERT_EQ(t->size(), trv->size());

    size_t row = 2;
    size_t column = 2;

    ValueId i = trv->getValueId(column, row);
    ValueId i2 = t->getValueId(column, row);
    ASSERT_EQ(i.valueId, i2.valueId);

    delete trv;
  }
}
示例#12
0
 typename DomainEnumerate<Val>::ValueId
 DomainEnumerate<Val>::find(const typename Val::Value& value) const {
     Val attr(value, const_cast<DomainEnumerate<Val>*>(this)); //ValueNominal requires non-const pointer to domain
     const_iterator found = std::find( values_.begin(), values_.end(), attr );
     if( found != values_.end() ) {
         return getValueId( found);
     }
     throw NotFoundException( getId().c_str() );
 }
示例#13
0
short Aggregate::codeGen(Generator * generator)
{
  Attributes ** attr;

  // If this Aggr has already been codeGenned, then bug out early.
  //
  MapInfo * aggrMapInfo = generator->getMapInfoAsIs(getValueId());
  if (aggrMapInfo && aggrMapInfo->isCodeGenerated())
    return 0;

  if (getOperatorType() != ITM_ONE_ROW)
  {
    if (generator->getExpGenerator()->genItemExpr(this, &attr, (1+getArity()), -1) == 1)
      return 0;
  }

  ex_clause * clause = 0;
  
  switch (getOperatorType())
    {
    case ITM_ONE_ROW:
      {
        Int32 degree = 0;
        findnumleaves(this, degree); // degree has number of leaves in the tree

        if (generator->getExpGenerator()->genItemExpr(this, &attr, (1+degree),
                                                               -1) == 1)
          return 0;

	clause =
	  new(generator->getSpace()) ex_aggr_one_row_clause(getOperatorType(),
							    (short)(1+degree), 
							    attr,
							    generator->getSpace());
      }
      break;

    case ITM_ANY_TRUE_MAX:
      {
	clause =
	  new(generator->getSpace()) ex_aggr_any_true_max_clause(getOperatorType(),
								 (short)(1+getArity()), 
								 attr, generator->getSpace());
      }
      break;
      
    default:
      break;
      
    }

  GenAssert(clause, "Aggregate::codeGen -- missing clause!");
  generator->getExpGenerator()->linkClause(this, clause);  

  return 0;
}
示例#14
0
TEST_F(PointerCalcTests, pc_using_factory) {
  auto t = io::Loader::shortcuts::load("test/lin_xxs.tbl");
  auto pc = PointerCalculator::create(t);

  ASSERT_TRUE(pc->columnCount() == 10);
  size_t tmp = 0;
  ValueId i = pc->getValueId(tmp, tmp);
  ASSERT_EQ((value_id_t)0, i.valueId);
  ASSERT_EQ(0, i.table);
}
// ItmPersistentExpressionVar::codeGen
//
// Adds the persistent variable to the expression generator.
//
short ItmPersistentExpressionVar::codeGen(Generator * generator) {

  // If the variable has already been codeGenned, bug out...
  //
  MapInfo * mi = generator->getMapInfoAsIs(getValueId());
  if (mi && mi->isCodeGenerated()) return 0;

  // Otherwise, generate the code and add it to the map table.
  //
  generator->getExpGenerator()->addPersistent(getValueId(), 
					      generator->getMapTable());

  // Add the initial value to the persistent list in the ExpGenerator.
  //
  generator->getExpGenerator()->linkPersistent(this);

  // ok...
  //
  return 0;
}
示例#16
0
void SimpleStoreMerger::mergeValues(const std::vector<hyrise::storage::c_atable_ptr_t > &input_tables,
                              hyrise::storage::atable_ptr_t merged_table,
                              const column_mapping_t &column_mapping,
                              const uint64_t newSize,
                              bool useValid,
                              const std::vector<bool>& valid) {

  if (useValid)
    throw std::runtime_error("SimpleStoreMerger does not support valid vectors");


  if(input_tables.size() != 2) throw std::runtime_error("SimpleStoreMerger does not support more than two tables");
  auto delta = std::dynamic_pointer_cast<const RawTable>(input_tables[1]);
  auto main = input_tables[0];

  // Prepare type handling
  MergeDictFunctor fun;
  type_switch<hyrise_basic_types> ts;

  std::vector<MergeDictFunctor::result> mergedDictionaries(column_mapping.size());

  // Extract unique values for delta
  for(const auto& kv : column_mapping) {
    const auto& col = kv.first;
    const auto& dst = kv.second;
    fun.prepare(main, delta, col);
    auto result = ts(main->typeOfColumn(col), fun);
    merged_table->setDictionaryAt(result.dict, dst);
    mergedDictionaries[col] = result;
  }


  // Update the values of the new Table
  merged_table->resize(newSize);
  size_t tabSize = main->size();
  for(size_t row=0; row < tabSize; ++row) {
    for( const auto& kv : column_mapping) {
      const auto& col = kv.first;
      const auto& dst = kv.second;
      merged_table->setValueId(dst, row, ValueId{mergedDictionaries[col].mapping[main->getValueId(col, row).valueId], 0});
    }
  }

  // Map the values for the values in the uncompressed delta
  MapValueForValueId map;
  for( const auto& kv : column_mapping) {
    const auto& col = kv.first;
    const auto& dst = kv.second;
    map.prepare(merged_table, dst, mergedDictionaries[col].dict, col, delta);
    ts(merged_table->typeOfColumn(dst), map);
  }
}
示例#17
0
short ConstValue::codeGen(Generator * generator)
{
  MapInfo * map_info = generator->getMapInfoAsIs(getValueId());
  if (map_info && map_info->isCodeGenerated())
    return 0;

  if (!map_info)
    {
      // this value has not been added to the map table. Add it.
      // Constants are added to the root Maptable of the expression
      // being generated.
      // This is done because the last map table may be removed to
      // get rid of temps (like, if BiLogic is being generated: 
      // see BiLogic::codeGen)
      // but we don't want to remove the constants until after the
      // whole expression has been generated.
      map_info = 
	generator->addMapInfoToThis(generator->getExpGenerator()->getExprMapTable(), getValueId(), NULL);

      Attributes * map_attr = map_info->getAttr();
      map_attr->setAtp(0);
      map_attr->setAtpIndex(0);

      // compute length of this temp and assign offsets to map_attr.
      // All temps are in sqlark_exploded format.
      ULng32 len;
      ExpTupleDesc::computeOffsets(map_attr, 
				   ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
				   len, 
				   generator->getExpGenerator()->getConstLength()); // start here
      generator->getExpGenerator()->addConstLength(len);
    }

  map_info->codeGenerated();

  generator->getExpGenerator()->linkConstant(this);
  
  return 0;
}
// ItmSeqRowsSince::preCodeGen
//
// Transform ItmSeqRowsSince to a do-while which iterates over the
// past rows testing the since condition for each row. The expression
// returns the relative index of the first row in which the since condition is
// TRUE or the number of rows in the history buffer + 1.
//
ItemExpr *ItmSeqRowsSince::preCodeGen(Generator *generator)
{
  if (nodeIsPreCodeGenned())
    return this;
  markAsPreCodeGenned();

  // Get some local handles...
  //
  CollHeap *wHeap = generator->wHeap();
  ItemExpr *itmChild = child(0)->castToItemExpr();
  ItemExpr *itmWindow = NULL;
  if(getArity() > 1) itmWindow = child(1)->castToItemExpr();

  // Allocate a counter for iterating through the past rows. The counter
  // also doubles as the result of the rows since. This requires the
  // counter to be nullable in case the condition is never true.
  //
  ItemExpr *itmLocalCounter 
    = new(wHeap) ItmExpressionVar(getValueId().getType().newCopy(wHeap));

  // If the ROWS SINCE is inclusive start the iterator at -1 to
  // include the current row, otherwise, start the iterator at 0 to
  // skip the current row. (The iterator is incremented before testing
  // the condition since a DoWhile loop is used -- thus, the iterator
  // is not starting at 0 and 1.)
  //
  ItemExpr *startExpr;
  if(this->includeCurrentRow()) startExpr = new(wHeap) ConstValue(-1);
  else startExpr = new(wHeap) ConstValue(0);
  
  // Expression to initialize the iterator. -- and put the variable in
  // the map table before it is used in an assignment.
  //
  ItemExpr *itmInitializeCounter = new(wHeap) ItmBlockFunction
    (itmLocalCounter,
     new(wHeap) Assign(itmLocalCounter, 
		       startExpr,
		       FALSE));
  
  // Expression to increment the iterator.
  //
  ItemExpr *itmIncrementCounter = new(wHeap) Assign
    (itmLocalCounter,
     new(wHeap) BiArith(ITM_PLUS,
			itmLocalCounter,
			new (wHeap) ConstValue(1)),
     FALSE);

  // Expression to make the counter NULL.
  //
  ItemExpr *itmNullCounter
    = new(wHeap) Assign(itmLocalCounter,
			new(wHeap) ConstValue(),
			FALSE);
  
  // Expression for DoWhile looping condition.
  //
  // AND(0) returns TRUE if the looping should continue, FALSE otherwise.
  // The looping should continue as long as the counter is within the
  // row history. the counter is less than the maximum search offset, and
  // the condition has not returned TRUE.
  //
  // The left side of AND(0) returns TRUE if the OFFSET of the current
  // counter value is within the row history and the counter is less
  // than the maximum search offset. If the left side of the AND(0)
  // returns FALSE, the counter is set to NULL because the condition
  // was not found to be true withing the search window -- and the
  // counter doubles as the result. In this case the right side of the
  // AND(0) is not evaluated because of short circuit evaluation.
  //
  // The right side of AND(0) returns TRUE if the condition is not TRUE
  // relative to the row indicated by counter.
  //
  //                 
  //                                    AND(0)
  //                               ____/      \___
  //                              /               \
  //                             /                 \
  //                       _ OR _                   IS_NOT_TRUE
  //                      /      \                      |    
  //                     /        BLOCK               OFFSET
  //               AND(2)        /     \             /      \
  //              /     \  Counter=NULL FALSE  ROWS SINCE  Counter     
  //    IS_NOT_NULL      \                       (cond)      
  //        /        LESS THAN               
  //       /         /       \               
  //     OFFSET   Counter  MaxWindow  
  //    /      \                  
  //ROWS SINCE  Counter           
  //  (cond)
  //        

  // Expression to test if counter is within history range. 
  //
  ItemExpr *itmRangeIndicator =  new (wHeap) ItmSeqOffset(
                                                          new (wHeap) UnLogic
                                                         (ITM_IS_TRUE,itmChild),
							  itmLocalCounter);
  ((ItmSeqOffset *)itmRangeIndicator)->setIsOLAP(isOLAP());
  // Expression to compute AND(2). If the window is not specified, then
  // return the left child of AND(2).
  //
  ItemExpr *itmAnd2;
  if(itmWindow)
    {
      itmAnd2 = new(wHeap) BiLogic
	(ITM_AND,
	 new(wHeap) UnLogic (ITM_IS_NOT_NULL, itmRangeIndicator),
	 new(wHeap) BiRelat (ITM_LESS_EQ, itmLocalCounter, itmWindow));
    }
  else
    {
      itmAnd2 = new(wHeap) UnLogic (ITM_IS_NOT_NULL, itmRangeIndicator);
    }

  // Expression to compute OR
  //
  ItemExpr *itmOr = new(wHeap) BiLogic
    (ITM_OR,
     itmAnd2,
     new(wHeap) ItmBlockFunction(itmNullCounter, new(wHeap) ConstValue(0)));

  // Expression to compute AND(0)
  //
  ItemExpr *itmLoopCondition = new(wHeap) BiLogic
    (ITM_AND, 
     itmOr, 
     new(wHeap) UnLogic(ITM_NOT, new (wHeap) UnLogic(ITM_IS_TRUE,itmChild)));

  // Construct the Do-While loop
  //
  ItemExpr *itmDoWhile 
    = new(wHeap) ItmDoWhileFunction(itmIncrementCounter,
				    itmLoopCondition);
  
  // Construct the counter initialization along with the looping.
  //
  ItemExpr *itmBlockPart
    = new(wHeap) ItmBlockFunction(itmInitializeCounter,
				  itmDoWhile);

  // Finally, construct a block to execute the operation and return
  // the FINAL value of the counter as the result. This is tricky, because
  // the do-while returns the value of the counter for the last time
  // the body (the increment expression) is executed which may be
  // different than the last value of the counter.
  //
  ItemExpr *itmBlock
    = new(wHeap) ItmBlockFunction(itmBlockPart, itmLocalCounter);
  
  // Replace the item for this value id with the new result item expression.
  //
  getValueId().replaceItemExpr(itmBlock);

  // Run the new expression through type and value Id synthesis.
  //
  itmBlock->synthTypeAndValueId(TRUE);

  // Save the previous rows since counter and set to the current one.
  //
  ItemExpr *savedRowsSinceCounter 
    = generator->getExpGenerator()->getRowsSinceCounter();

  generator->getExpGenerator()->setRowsSinceCounter (itmLocalCounter);

  // Save the preCodeGen of the new expression.
  //
  ItemExpr *tmpBlock = itmBlock->preCodeGen(generator);

  // Restore the saved ROWS SINCE counter expression.
  //
  generator->getExpGenerator()->setRowsSinceCounter (savedRowsSinceCounter);

  // return the saved expression
  //
  return tmpBlock;
}
// ItmSeqRunningFunction::preCodeGen
//
// Transforms the running sequence functions into scalar expressions
// that use offset to reference the previous value of the function.
//
ItemExpr *ItmSeqRunningFunction::preCodeGen(Generator *generator)
{
  if (nodeIsPreCodeGenned())
    return this;
  markAsPreCodeGenned();

  // Get some local handles...
  //
  CollHeap *wHeap = generator->wHeap();
  ItemExpr *itmChild = child(0)->castToItemExpr();

  // Allocate a HostVar for referencing the result before it is computed.
  //
  ItemExpr *itmResult 
    = new(wHeap) HostVar("_sys_Result",
			 getValueId().getType().newCopy(wHeap),
			 TRUE);

  // Create an item expression to reference the previous
  // value of this running sequence function.
  //
  ItemExpr *offExpr = new(wHeap) ItmSeqOffset(itmResult, 1);
  ((ItmSeqOffset *)offExpr)->setIsOLAP(isOLAP());
  // Add the sequence function specific computation.
  //
  ItemExpr *itmNewSeqFunc = 0;
  switch(getOperatorType())
    {
    case ITM_RUNNING_COUNT:
      {
	// By this point ITM_RUNNING_COUNT is count(column). The count
	// is one more than the previous count if the current column is
	// not null, otherwise, it is the previous count.
	//

        // Create the increment value.  For non-nullable values, this
        // is always 1, essentially runningcount(*).
        //
        ItemExpr *incr;
        if(itmChild->getValueId().getType().supportsSQLnullLogical()) {
          incr = generator->getExpGenerator()->createExprTree
            ("CASE WHEN @A1 IS NULL THEN @A3 ELSE @A2 END", 
             0, 3, 
             itmChild,
             new(wHeap) ConstValue(1),
             new(wHeap) ConstValue(0));
        } else {
          incr = new(wHeap) ConstValue(1);
        }

        ((ItmSeqOffset *)offExpr)->setNullRowIsZero(TRUE);
        ItemExpr *src = offExpr;

        // Do the increment.
        //
        itmNewSeqFunc = new(wHeap)
              BiArith(ITM_PLUS, src, incr);
      }
    break;
    
    case ITM_RUNNING_SUM:
      {
	// SUM(sum from previous row, child)
	//
	itmNewSeqFunc = new(wHeap) BiArithSum(ITM_PLUS, offExpr, itmChild);
      }
    break;
    
    case ITM_RUNNING_MIN:
      {
	// MIN(min from previous rows, child)
	//
	itmNewSeqFunc 
	  = new(wHeap) ItmScalarMinMax(ITM_SCALAR_MIN,
				       offExpr,
				       itmChild);
      }
    break;
    
    case ITM_RUNNING_MAX:
      {
	// MAX(max from previous row, child)
	//
	itmNewSeqFunc 
	  = new(wHeap) ItmScalarMinMax(ITM_SCALAR_MAX,
				       offExpr,
				       itmChild);
      }
    break;
    
    case ITM_LAST_NOT_NULL:
      {
	// If the current value is null then use the previous value
	// of last not null.
	//
	itmNewSeqFunc = generator->getExpGenerator()->createExprTree
	  ("CASE WHEN @A2 IS NOT NULL THEN @A2 ELSE @A1 END", 
	   0, 2, offExpr, itmChild);
      }
    break;

    case ITM_RUNNING_CHANGE:
      {
        // The running change (or 'rows since changed') can have a
        // composite child (a list of values)
        // Convert the list of values to a list of offset of values.
        //
        ItemExpr *offChild = itmChild;
      
        if (itmChild->getOperatorType() == ITM_ITEM_LIST)
          {
            // child is a multi-valued expression, transform into multiple
            // 
            ExprValueId treePtr = itmChild;

            ItemExprTreeAsList changeValues(&treePtr,
                                            ITM_ITEM_LIST,
                                            RIGHT_LINEAR_TREE);

            offChild = new(wHeap) ItmSeqOffset( changeValues[0], 1);
	    ((ItmSeqOffset *)offChild)->setIsOLAP(isOLAP());
            // add Offset expressions for all the items of the list
            // 
            CollIndex nc = changeValues.entries();
            for (CollIndex i = 1; i < nc; i++)
              {
                ItemExpr *off = new(generator->wHeap()) ItmSeqOffset( changeValues[i], 1);
		((ItmSeqOffset *)off)->setIsOLAP(isOLAP());
                offChild = new(generator->wHeap()) ItemList(offChild, off);
              }
          } else {
            offChild = new(wHeap) ItmSeqOffset( offChild, 1);
	    ((ItmSeqOffset *)offChild)->setIsOLAP(isOLAP());
          }
        
 
        ((ItmSeqOffset *)offExpr)->setNullRowIsZero(TRUE);
        ItemExpr *prevValue = offExpr;

        // Compare the value(s) to the previous value(s).  Use special
        // NULLs flags to treat NULLs as values.  Two NULL values are
        // considered equal here.
        //
        ItemExpr *pred = new (wHeap) BiRelat(ITM_EQUAL,
                                             itmChild,
                                             offChild,
                                             TRUE); // Special NULLs
        // running change = 
        //      (value(s) == prev(value(s))) ? prev(running change)+1 : 1
        //
        // Compute base value.
        //
        itmNewSeqFunc = new (wHeap) 
                IfThenElse(pred, prevValue, new (wHeap) SystemLiteral(0));
        
        itmNewSeqFunc = new (wHeap) Case(NULL, itmNewSeqFunc);

        // Force the evaluation of the offset expression so that the
        // result can be reused by subsequent references.
        //
        itmNewSeqFunc = new(wHeap) ItmBlockFunction(offChild, itmNewSeqFunc);

        // Increment the base value.
        //
        itmNewSeqFunc = new (wHeap) BiArith(ITM_PLUS, 
                                            itmNewSeqFunc,
                                            new(wHeap) SystemLiteral(1));

      }
      break;
      
    }
  
  // Get value Ids and types for all of the items. Must do this typing before
  // replacing this value Id's item expression -- otherwise, the typing
  // will give a result different than the type already computed for this
  // sequence function.
  //
  GenAssert(itmNewSeqFunc, "ItmSeqRunningFunction::preCodeGen -- Unexpected Operator Type!");
  itmNewSeqFunc->synthTypeAndValueId(TRUE);

  // Replace the original value ID with the new expression.
  //
  getValueId().replaceItemExpr(itmNewSeqFunc);
  
  // Map the reference to the result to the actual result in the map table.
  //
  Attributes *attr =  generator->getMapInfo
    (itmNewSeqFunc->getValueId())->getAttr();
  MapInfo *mapInfo = generator->addMapInfo(itmResult->getValueId(), attr);
  itmResult->markAsPreCodeGenned();
  mapInfo->codeGenerated();

  // Return the preCodeGen of the new expression.
  //
  return itmNewSeqFunc->preCodeGen(generator);
}
ItemExpr *ItmSeqOlapFunction::preCodeGen(Generator *generator)
{
  if (getOperatorType() != ITM_OLAP_MIN && getOperatorType() != ITM_OLAP_MAX)
  {
    GenAssert(0, "ItmSeqOlapFunction::preCodeGen -- Should never get here!");
    return 0;
  }


  if (nodeIsPreCodeGenned())
    return this;
  markAsPreCodeGenned();

  // Get some local handles...
  //
  CollHeap *wHeap = generator->wHeap();
  ItemExpr *itmChild = child(0)->castToItemExpr();
  //ItemExpr *itmWindow = child(1)->castToItemExpr();

  // What scalar operation needs to be done.
  //
  OperatorTypeEnum operation;
  if(getOperatorType() == ITM_OLAP_MIN) operation = ITM_SCALAR_MIN;
  else operation = ITM_SCALAR_MAX;

  // Allocate a HostVar for local storage of the index.
  //
  ItemExpr *itmLocalCounter 
    = new(wHeap) HostVar("_sys_LocalCounter",
			 new(wHeap) SQLInt(wHeap, TRUE,FALSE),
			 TRUE);

  // Expression to initailize the iterator.
  //
  ItemExpr *itmLocalCounterInitialize
              = new(wHeap) Assign(itmLocalCounter, 
                                  new(wHeap) ConstValue(frameStart_),
			          FALSE);

  // Expression to increment the iterator.
  //
  ItemExpr *itmLocalCounterIncrement
    = new(wHeap) Assign(itmLocalCounter,
			new(wHeap) BiArith(ITM_PLUS,
					   itmLocalCounter,
					   new (wHeap) ConstValue(1)),
			FALSE);

  // Allocate a HostVar for referencing the result before it is computed.
  //
  ItemExpr *itmResult 
    = new(wHeap) HostVar("_sys_Result",
			 getValueId().getType().newCopy(wHeap),
			 TRUE);

  // Expression to initialize the result.
  //
  ItemExpr *itmResultInitialize
    = new(wHeap) Assign(itmResult,
			new(wHeap) ConstValue());
			
  // Expression to compute the min/max.
  //

  ItemExpr * invCouter= new(wHeap) BiArith(ITM_MINUS,
                                                new (wHeap) ConstValue(0),
					        itmLocalCounter);
					   
  ItemExpr *  itmOffsetExpr = new(wHeap) ItmSeqOffset( itmChild, invCouter);


  //ItemExpr * itmOffsetIsNotNull = new (wHeap) UnLogic(ITM_IS_NOT_NULL, itmOffsetExpr);

  ((ItmSeqOffset *)itmOffsetExpr)->setIsOLAP(isOLAP());
  ItemExpr *itmResultUpdate
    = new(wHeap) Assign(itmResult,
			new(wHeap) ItmScalarMinMax(operation, 
						   itmResult, 
						   itmOffsetExpr));

  // Construct code blocks for the initialization and body for the while-loop
  //
  ItemExpr *itmInit 
    = new(wHeap) ItmBlockFunction(itmLocalCounterInitialize,
				  itmResultInitialize);
  ItemExpr *itmBody
    = new(wHeap) ItmBlockFunction(itmResultUpdate,
				  itmLocalCounterIncrement);
  
  // Construct the While loop (i < window)
  //
  ItemExpr *itmLoopCondition = new(wHeap) BiRelat
    (ITM_LESS_EQ, itmLocalCounter, new(wHeap) ConstValue(frameEnd_));
  
  if (isFrameEndUnboundedFollowing()) //(frameEnd_ == INT_MAX)// not needed in other cases -- can cause issues fo the preceding part
  {
    ItemExpr *  itmOffset1 = new(wHeap) ItmSeqOffset( itmChild, invCouter,NULL,TRUE);
    ItemExpr * itmOffset1IsNotNull = new (wHeap) UnLogic(ITM_IS_NOT_NULL, itmOffset1);

    ((ItmSeqOffset *)itmOffset1)->setIsOLAP(isOLAP());

    itmLoopCondition = itmOffset1IsNotNull;
    //new (wHeap) BiLogic( ITM_AND,
                        //                  itmLoopCondition,
                       //                   itmOffset1IsNotNull);
  }
  ItemExpr *itmWhile 
    = new(wHeap) ItmWhileFunction(itmBody,
				    itmLoopCondition);
  
  
  // Construct the blocks to contain the initialization and looping.
  // The result is the final value of the min/max.
  //
  ItemExpr *itmBlock = new(wHeap) ItmBlockFunction
    (new(wHeap) ItmBlockFunction(itmInit, itmWhile),
     itmResult);
  
  // Replace the item for this value id with the new item expression.
  //
  getValueId().replaceItemExpr(itmBlock);

  // Run the new expression through type and value Id synthesis.
  //
  itmBlock->synthTypeAndValueId(TRUE);

  // Map the reference to the result to the actual result in the map table.
  //
  Attributes *attr =  generator->getMapInfo(itmBlock->getValueId())->getAttr();
  MapInfo *mapInfo = generator->addMapInfo(itmResult->getValueId(), attr);
  itmResult->markAsPreCodeGenned();
  mapInfo->codeGenerated();

  // Return the preCodeGen of the new expression.
  //
  return itmBlock->preCodeGen(generator);

}
// ItmSeqMovingFunction::preCodeGen
//
// All of the moving sequence functions have been transformed away at this
// point except min and max. Transform these operations to a while-loop which 
// iterates over the past rows testing the min/max condition for each row. 
// Use the ItmScalarMin/Max functions for computing the min/max.
//
ItemExpr *ItmSeqMovingFunction::preCodeGen(Generator *generator)
{
  if (nodeIsPreCodeGenned())
    return this;
  markAsPreCodeGenned();

  // Get some local handles...
  //
  CollHeap *wHeap = generator->wHeap();
  ItemExpr *itmChild = child(0)->castToItemExpr();
  ItemExpr *itmWindow = child(1)->castToItemExpr();

  // What scalar operation needs to be done.
  //
  OperatorTypeEnum operation;
  if(getOperatorType() == ITM_MOVING_MIN) operation = ITM_SCALAR_MIN;
  else operation = ITM_SCALAR_MAX;

  // Allocate a HostVar for local storage of the index.
  //
  ItemExpr *itmLocalCounter 
    = new(wHeap) HostVar("_sys_LocalCounter",
			 new(wHeap) SQLInt(wHeap, TRUE,FALSE),
			 TRUE);

  // Expression to initailize the iterator.
  //
  ItemExpr *itmLocalCounterInitialize
    = new(wHeap) Assign(itmLocalCounter, 
			new(wHeap) ConstValue(0),
			FALSE);

  // Expression to increment the iterator.
  //
  ItemExpr *itmLocalCounterIncrement
    = new(wHeap) Assign(itmLocalCounter,
			new(wHeap) BiArith(ITM_PLUS,
					   itmLocalCounter,
					   new (wHeap) ConstValue(1)),
			FALSE);

  // Allocate a HostVar for referencing the result before it is computed.
  //
  ItemExpr *itmResult 
    = new(wHeap) HostVar("_sys_Result",
			 getValueId().getType().newCopy(wHeap),
			 TRUE);

  // Expression to initialize the result.
  //
  ItemExpr *itmResultInitialize
    = new(wHeap) Assign(itmResult,
			new(wHeap) ConstValue());
			
  // Expression to compute the min/max.
  //
  ItemExpr *itmOffsetExpr = new(wHeap) ItmSeqOffset( itmChild, itmLocalCounter);
  ((ItmSeqOffset *)itmOffsetExpr)->setIsOLAP(isOLAP());
  ItemExpr *itmResultUpdate
    = new(wHeap) Assign(itmResult,
			new(wHeap) ItmScalarMinMax(operation, 
						   itmResult, 
						   itmOffsetExpr));

  // Construct code blocks for the initialization and body for the while-loop
  //
  ItemExpr *itmInit 
    = new(wHeap) ItmBlockFunction(itmLocalCounterInitialize,
				  itmResultInitialize);
  ItemExpr *itmBody
    = new(wHeap) ItmBlockFunction(itmResultUpdate,
				  itmLocalCounterIncrement);
  
  // Construct the While loop (i < window)
  //
  ItemExpr *itmLoopCondition = new(wHeap) BiRelat
    (ITM_LESS, itmLocalCounter, itmWindow);
  ItemExpr *itmWhile 
    = new(wHeap) ItmWhileFunction(itmBody,
				    itmLoopCondition);
  
  
  // Construct the blocks to contain the initialization and looping.
  // The result is the final value of the min/max.
  //
  ItemExpr *itmBlock = new(wHeap) ItmBlockFunction
    (new(wHeap) ItmBlockFunction(itmInit, itmWhile),
     itmResult);
  
  // Replace the item for this value id with the new item expression.
  //
  getValueId().replaceItemExpr(itmBlock);

  // Run the new expression through type and value Id synthesis.
  //
  itmBlock->synthTypeAndValueId(TRUE);

  // Map the reference to the result to the actual result in the map table.
  //
  Attributes *attr =  generator->getMapInfo(itmBlock->getValueId())->getAttr();
  MapInfo *mapInfo = generator->addMapInfo(itmResult->getValueId(), attr);
  itmResult->markAsPreCodeGenned();
  mapInfo->codeGenerated();

  // Return the preCodeGen of the new expression.
  //
  return itmBlock->preCodeGen(generator);
}