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