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