// 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);
}
// 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;
}
// 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);
}
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);

}
// 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);
}
예제 #6
0
// BiRelat for which the following is called will be a predicate for one of the
// endpoints of an MDAM_BETWEEN.
void BiRelat::getMdamPredDetails(Generator* generator,
                                 MdamCodeGenHelper& mdamHelper, 
                                 MdamPred::MdamPredType& predType,
                                 ex_expr** vexpr)
{
  // Find out what kind of predicate this is. Inequality preds are not inverted
  // for descending keys here; instead, the endpoints of the MDAM_BETWEEN
  // interval are switched during creation of the mdam network in the executor.
  switch (getOperatorType())
    {
      case ITM_LESS:
        predType = MdamPred::MDAM_LT;
        break;
      
      case ITM_LESS_EQ:
        predType = MdamPred::MDAM_LE;
        break;
      
      case ITM_GREATER:
        predType = MdamPred::MDAM_GT;
        break;
      
      case ITM_GREATER_EQ:
        predType = MdamPred::MDAM_GE;
        break;
      
      default:
        GenAssert(0, "mdamPredGen: invalid comparison for subrange.");
        break;
    }
  
  ItemExpr* child0 = child(0);
  ItemExpr* child1 = child(1);
  ValueId keyColumn = mdamHelper.getKeyColumn();
  
  // Canonical form used by rangespec is <key> <compare> <value>.
  ItemExpr* keyValue = child1;
  GenAssert(child0->getValueId() == keyColumn,
            "mdamPredGen:  unexpected form for key predicate.");

  // generate an expression to convert the key value to the
  // type of the key column (in its key buffer) and encode it
  ItemExpr* vnode = NULL;
  
  // errorsCanOccur() determines if errors can occur converting the class
  // datatype to the target datatype.  The object on whose behalf the
  // member function is called is expected to be a NAType.
  NABoolean generateNarrow = 
      keyValue->getValueId().getType().errorsCanOccur(*mdamHelper.getTargetType());

#ifdef _DEBUG
  if ((generateNarrow) &&
      (getenv("NO_NARROWS"))) // for testing -- allows turning off Narrows
    generateNarrow = FALSE; 
#endif

  if (generateNarrow)
    vnode = new(generator->wHeap())
              Narrow(keyValue,
                     mdamHelper.getDataConversionErrorFlag(),
                     mdamHelper.getTargetType()->newCopy(generator->wHeap()));
  else
    vnode = new(generator->wHeap()) 
              Cast(keyValue,
                   mdamHelper.getTargetType()->newCopy(generator->wHeap()));

  vnode->bindNode(generator->getBindWA());
  vnode->preCodeGen(generator);

#pragma nowarn(1506)  // warning elimination 
  vnode = new(generator->wHeap()) CompEncode(vnode,mdamHelper.isDescending());
#pragma warn(1506)    // warning elimination 
  vnode->bindNode(generator->getBindWA());
  
  ValueIdList vnodeList;
  vnodeList.insert(vnode->getValueId());
  
  ULng32 dummyLen = 0;
  
  short rc = 
       generator->getExpGenerator()
                ->generateContiguousMoveExpr(vnodeList,
                                             0, // don't add convert nodes
                                             mdamHelper.getAtp(),
                                             mdamHelper.getAtpIndex(),
                                             mdamHelper.getTupleDataFormat(),
                                             dummyLen, // out
                                             vexpr);
       
  GenAssert(rc == 0, "generateContiguousMoveExpr() returned error when called "
                     "from BiRelat::getMdamPredDetails().");
}
예제 #7
0
short BiRelat::mdamPredGen(Generator * generator,
                                MdamPred ** head,
                                MdamPred ** tail,
                                MdamCodeGenHelper & mdamHelper,
                                ItemExpr * parent)
{
  short rc = 0;     // assume success
  
  enum MdamPred::MdamPredType predType = 
    MdamPred::MDAM_EQ; // just to initialize

  // Find out what kind of predicate this is.  Note that for DESCending
  // columns, we reverse the direction of any comparison.
  switch (getOperatorType())
    {
      case ITM_EQUAL:
      {
        predType = MdamPred::MDAM_EQ;
        break;
      }
      
      case ITM_LESS:
      {
        predType = MdamPred::MDAM_LT;
        if (mdamHelper.isDescending()) predType = MdamPred::MDAM_GT;
        break;
      }
      
      case ITM_LESS_EQ:
      {
        predType = MdamPred::MDAM_LE;
        if (mdamHelper.isDescending()) predType = MdamPred::MDAM_GE;
        break;
      }
      
      case ITM_GREATER:
      {
        predType = MdamPred::MDAM_GT;
        if (mdamHelper.isDescending()) predType = MdamPred::MDAM_LT;
        break;
      }
      
      case ITM_GREATER_EQ:
      {
        predType = MdamPred::MDAM_GE;
        if (mdamHelper.isDescending()) predType = MdamPred::MDAM_LE;
        break;
      }
      
      case ITM_ITEM_LIST:
      {
        GenAssert(0, "mdamPredGen: encountered multivalued predicate.");
        break;
      }

      default:
      {
        GenAssert(0, "mdamPredGen: unsupported comparison.");
        break;
      }
    }
  
  ItemExpr * child0 = child(0);
  ItemExpr * child1 = child(1);
  ValueId keyColumn = mdamHelper.getKeyColumn();
  
  //  assume predicate is <key> <compare> <value>
  ItemExpr * keyValue = child1;

  if (child1->getValueId() == keyColumn)
    {
      // we guessed wrong -- predicate is <value> <compare> <key>
      keyValue = child0;
      GenAssert(child0->getValueId() != keyColumn,
        "mdamPredGen:  unexpected form for key predicate.");
      // Reverse the comparison operator if it is <, <=, > or >=.
      switch (predType)
        {
          case MdamPred::MDAM_LT:
          {
            predType = MdamPred::MDAM_GT;
            break;
          }

          case MdamPred::MDAM_LE:
          {
            predType = MdamPred::MDAM_GE;
            break;
          }

          case MdamPred::MDAM_GT:
          {
            predType = MdamPred::MDAM_LT;
            break;

          }
          case MdamPred::MDAM_GE:
          {
            predType = MdamPred::MDAM_LE;
            break;
          }
        }  // switch (predType)
    }
  else
    {
      GenAssert(child0->getValueId() == keyColumn,
        "mdamPredGen:  unexpected form for key predicate.");
    }
  
  // generate an expression to convert the key value to the
  // type of the key column (in its key buffer) and encode it

  ItemExpr * vnode = 0;
  
  // errorsCanOccur() determines if errors can occur converting the class
  // datatype to the target datatype.  The object on whose behalf the
  // member function is called is expected to be a NAType.

  NABoolean generateNarrow = 
    keyValue->getValueId().getType().errorsCanOccur(*mdamHelper.getTargetType());

#ifdef _DEBUG
  if ((generateNarrow) &&
      (getenv("NO_NARROWS"))) // for testing -- allows turning off Narrows
    generateNarrow = FALSE; 
#endif

  if (generateNarrow)
    {
      vnode = new(generator->wHeap()) Narrow(keyValue,
                                 mdamHelper.getDataConversionErrorFlag(),
                                 mdamHelper.getTargetType()->newCopy(generator->wHeap()));
    }
  else
    {
      vnode = new(generator->wHeap()) Cast(keyValue,mdamHelper.getTargetType()->newCopy(generator->wHeap()));
    }
  vnode->bindNode(generator->getBindWA());
  vnode->preCodeGen(generator);

#pragma nowarn(1506)   // warning elimination 
  vnode = new(generator->wHeap()) CompEncode(vnode,mdamHelper.isDescending());
#pragma warn(1506)  // warning elimination 
  vnode->bindNode(generator->getBindWA());
  
  ValueIdList vnodeList;
  vnodeList.insert(vnode->getValueId());
  
  ex_expr *vexpr = 0;
  ULng32 dummyLen = 0;
  
  rc = generator->getExpGenerator()->generateContiguousMoveExpr(
       vnodeList,
       0, // don't add convert nodes
       mdamHelper.getAtp(),
       mdamHelper.getAtpIndex(),
       mdamHelper.getTupleDataFormat(),
       dummyLen, // out
       &vexpr);

#pragma nowarn(1506)   // warning elimination   
  *head = *tail = new(generator->getSpace()) MdamPred(
       mdamHelper.getDisjunctNumber(),
       predType,
       vexpr);
#pragma warn(1506)  // warning elimination 
  
  return rc;
}