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