short BiArithCount::codeGen(Generator * generator) { Attributes ** attr; ExpGenerator * eg = generator->getExpGenerator(); if (eg->genItemExpr(this, &attr, (1+getArity()), -1) == 1) return 0; // if temp space is needed for this operation, set it. if (attr[0]->isComplexType()) { eg->addTempsLength(((ComplexType *)attr[0])->setTempSpaceInfo(getOperatorType(), #pragma nowarn(1506) // warning elimination eg->getTempsLength())); #pragma warn(1506) // warning elimination } ex_arith_count_clause * arith_clause = new(generator->getSpace()) ex_arith_count_clause(getOperatorType(), attr, generator->getSpace()); generator->getExpGenerator()->linkClause(this, arith_clause); return 0; }
short UnArith::codeGen(Generator * generator) { Attributes ** attr; ExpGenerator * eg = generator->getExpGenerator(); if (eg->genItemExpr(this, &attr, (1+getArity()), -1) == 1) return 0; ex_arith_clause * arith_clause = new(generator->getSpace()) ex_arith_clause(getOperatorType(), attr, generator->getSpace(), 0, FALSE); generator->getExpGenerator()->linkClause(this, arith_clause); return 0; }
// ItmBlockFunction::codeGen // // The Block function executes the code represented by both its children and // then returns the result of the right child (child(1)). // short ItmBlockFunction::codeGen(Generator * generator) { // Get local handles... // Attributes **attr; Space* space = generator->getSpace(); CollHeap *heap = generator->wHeap(); ExpGenerator *exp = generator->getExpGenerator(); // If this Block has already been codeGenned, then bug out... // Otherwise, allocate space for the result if necessary and set // attr[0] to point to the result attribute data. Also, mark this // node as codeGenned. // if (exp->genItemExpr(this, &attr, 2, 0) == 1) return 0; // CodeGen the left child. // child(0)->codeGen(generator); // CodeGen the right child. // child(1)->codeGen(generator); // The result of the Block is the result of the right child. Set // the src attribute for the convert (added below) to be the right child // The dst attribute has already been set in genItemExpr(). // attr[1] = generator->getMapInfo (child(1)->castToItemExpr()->getValueId())->getAttr(); // Allocate a convert clause to move the result from child(1) to the // result of this node. This move is necessary so that future // side-effects of the result of child(1) -- if it is a local variable, // for instance -- will not change the result of the Block. // ex_conv_clause * convClause = new(generator->getSpace()) ex_conv_clause (getOperatorType(), attr, space); generator->getExpGenerator()->linkClause(this, convClause); return 0; }
void PartitioningFunction::generatePivLayout( Generator *generator, Lng32 &partitionInputDataLength, Lng32 atp, Lng32 atpIndex, Attributes ***pivAttrs) { // assign offsets to the PIVs in a standard way ExpGenerator *expGen = generator->getExpGenerator(); expGen->processValIdList( getPartitionInputValuesLayout(), ExpTupleDesc::SQLARK_EXPLODED_FORMAT, (ULng32 &) partitionInputDataLength, atp, atpIndex, NULL, ExpTupleDesc::SHORT_FORMAT, 0, pivAttrs); }
short BiArith::codeGen(Generator * generator) { Attributes ** attr; ExpGenerator * eg = generator->getExpGenerator(); if (eg->genItemExpr(this, &attr, (1+getArity()), -1) == 1) return 0; // if temp space is needed for this operation, set it. if (attr[0]->isComplexType()) { eg->addTempsLength(((ComplexType *)attr[0])->setTempSpaceInfo(getOperatorType(), #pragma nowarn(1506) // warning elimination eg->getTempsLength())); #pragma warn(1506) // warning elimination } attr[0]->resetlastdaymonthflag(); attr[0]->resetlastdayonerrflag(); // Check to see which type of rounding is needed for add_months, date_add // functions. Set flags here for use in executor datetime.cpp. if (isStandardNormalization()) attr[0]->setlastdayonerrflag(); if (isKeepLastDay()) attr[0]->setlastdaymonthflag(); ex_arith_clause * arith_clause = new(generator->getSpace()) ex_arith_clause(getOperatorType(), attr, generator->getSpace(), (short)getRoundingMode(), getDivToDownscale()); generator->getExpGenerator()->linkClause(this, arith_clause); return 0; }
short BiLogic::codeGen(Generator * generator) { Attributes ** attr; if (generator->getExpGenerator()->genItemExpr(this, &attr, (1+getArity()), 0) == 1) return 0; Space * space = generator->getSpace(); ExpGenerator * expGen = generator->getExpGenerator(); // Normally, if code for a value id has been generated, and if // that value id is seen again, then code is not generated. The // location where the result is available is returned instead. // The case of a logical operator is different. Code is generated // again if a value id from the left child is also present in // the right child. This is done // because at expression evaluation time, some of the expressions // may be skipped due to short circuit evaluation. // // Allocate a new map table before generating code for each child. // This map table contains all the temporary results produced by // the child. // Remove this map table after generating code for each child. generator->appendAtEnd(); expGen->incrementLevel(); codegen_and_set_attributes(generator, attr, 2); // generator->getExpGenerator()->setClauseLinked(FALSE); // child(0)->codeGen(generator); // attr[1] = generator->getAttr(child(0)); // generator->getExpGenerator()->setClauseLinked(FALSE); /* generate boolean short circuit code */ Attributes ** branch_attr = new(generator->wHeap()) Attributes * [2]; branch_attr[0] = attr[0]->newCopy(generator->wHeap()); branch_attr[0]->copyLocationAttrs(attr[0]); branch_attr[1] = attr[1]->newCopy(generator->wHeap()); branch_attr[1]->copyLocationAttrs(attr[1]); branch_attr[0]->resetShowplan(); ex_branch_clause * branch_clause = new(space) ex_branch_clause(getOperatorType(), branch_attr, space); generator->getExpGenerator()->linkClause(0, branch_clause); generator->removeLast(); expGen->decrementLevel(); generator->appendAtEnd(); expGen->incrementLevel(); ValueIdSet markedEntries; // This ia a MapTable entry related fix for RangeSpec transformation. if( child(1)->getOperatorType() == ITM_RANGE_SPEC_FUNC ) markGeneratedEntries(generator, child(1)->child(1), markedEntries); else markGeneratedEntries(generator, child(1), markedEntries); // if( child(1)->getOperatorType() == ITM_RANGE_SPEC_FUNC ) // child(1)->child(1)->codeGen(generator); // else child(1)->codeGen(generator); ItemExpr *rightMost; if( child(1)->getOperatorType() == ITM_RANGE_SPEC_FUNC ) rightMost = child(1)->child(1)->castToItemExpr(); else rightMost = child(1)->castToItemExpr(); while (rightMost->getOperatorType() == ITM_ITEM_LIST) rightMost = rightMost->child(1)->castToItemExpr(); attr[2] = generator-> getMapInfo(rightMost->getValueId())->getAttr(); ex_bool_clause * bool_clause = new(space) ex_bool_clause(getOperatorType(), attr, space); generator->getExpGenerator()->linkClause(this, bool_clause); branch_clause->set_branch_clause((ex_clause *)bool_clause); generator->removeLast(); expGen->decrementLevel(); if( child(1)->getOperatorType() == ITM_RANGE_SPEC_FUNC ) unGenerate(generator, child(1)->child(1)); else unGenerate(generator, child(1)); generateMarkedEntries(generator, markedEntries); return 0; }
///////////////////////////////////////////////////////////////////// // // Contents: // // RelStoredProc::codeGen() // ////////////////////////////////////////////////////////////////////// short generateSPIOExpr(RelInternalSP * sp, Generator * generator, ExSPInputOutput * &inputExpr, ExSPInputOutput * &outputExpr) { ExpGenerator * expGen = generator->getExpGenerator(); Space * genSpace = generator->getSpace(); // Generate input(extract) expr FragmentDir * compFragDir = generator->getFragmentDir(); // create the fragment (independent code space) for this expression CollIndex myFragmentId = compFragDir->pushFragment(FragmentDir::MASTER); Space * space = generator->getSpace(); // Start generation by creating the ExSPInputOutput class. //It will be initialized later. ExSPInputOutput * lInputExpr = new(space) ExSPInputOutput(); ULng32 recordLen; ExpTupleDesc * tupleDesc = NULL; if (expGen->processValIdList(sp->procTypes(), ExpTupleDesc::SQLARK_EXPLODED_FORMAT, recordLen, 0, 1, &tupleDesc, ExpTupleDesc::LONG_FORMAT) == -1) return -1; ConvInstruction * cia = (ConvInstruction *)space->allocateMemory(sp->procTypes().entries() * sizeof(ConvInstruction)); ULng32 totalLen = space->getAllocatedSpaceSize(); lInputExpr->initialize(tupleDesc, totalLen, cia); ExSPInputOutputPtr(lInputExpr).pack(space); // the generated expr is generated in chunks internally by // the space class. Make it contiguous by allocating and // moving it to a contiguous area. char * expr = new(generator->wHeap()) char[totalLen]; space->makeContiguous((char *)expr, totalLen); inputExpr = (ExSPInputOutput *)(genSpace->allocateAndCopyToAlignedSpace((char *)expr, totalLen, 0)); compFragDir->removeFragment(); // Delete expr NADELETEBASIC(expr, generator->wHeap()); expr = NULL; // Now generate the move to output row expr myFragmentId = compFragDir->pushFragment(FragmentDir::MASTER); space = generator->getSpace(); ExSPInputOutput * lOutputExpr = new(space) ExSPInputOutput(); if (expGen->processValIdList(sp->getTableDesc()->getColumnList(), ExpTupleDesc::SQLARK_EXPLODED_FORMAT, recordLen, 0, 1, &tupleDesc, ExpTupleDesc::LONG_FORMAT) == -1) return -1; cia = (ConvInstruction *)space->allocateMemory(sp->getTableDesc()->getColumnList().entries() * sizeof(ConvInstruction)); for (short i = 0; i < (short) tupleDesc->numAttrs(); i++) { ex_conv_clause tempClause; cia[i] = tempClause.findInstruction(REC_BYTE_V_ASCII, -1, // no op tupleDesc->getAttr(i)->getDatatype(), tupleDesc->getAttr(i)->getLength(), 0); } totalLen = space->getAllocatedSpaceSize(); lOutputExpr->initialize(tupleDesc, totalLen, cia); ExSPInputOutputPtr(lOutputExpr).pack(space); expr = new(generator->wHeap()) char[totalLen]; space->makeContiguous((char *)expr, totalLen); outputExpr = (ExSPInputOutput *)(genSpace->allocateAndCopyToAlignedSpace((char *)expr, totalLen, 0)); compFragDir->removeFragment(); // Delete expr NADELETEBASIC(expr, generator->wHeap()); expr = NULL; return 0; }
short RelInternalSP::codeGen(Generator * generator) { Space * space = generator->getSpace(); ExpGenerator * exp_gen = generator->getExpGenerator(); MapTable * last_map_table = generator->getLastMapTable(); ex_expr * input_expr = NULL; ex_expr * output_expr = NULL; //////////////////////////////////////////////////////////////////////////// // // Returned atp layout: // // |--------------------------------| // | input data | stored proc row | // | ( I tupps ) | ( 1 tupp ) | // |--------------------------------| // <-- returned row to parent ----> // // input data: the atp input to this node by its parent. // stored proc row: tupp where the row read from SP is moved. // //////////////////////////////////////////////////////////////////////////// ex_cri_desc * given_desc = generator->getCriDesc(Generator::DOWN); ex_cri_desc * returned_desc = new(space) ex_cri_desc(given_desc->noTuples() + 1, space); // cri descriptor for work atp has 3 entries: // -- the first two entries for consts and temps. // -- Entry 3(index #2) is where the input and output rows will be created. ex_cri_desc * work_cri_desc = new(space) ex_cri_desc(3, space); const Int32 work_atp = 1; const Int32 work_atp_index = 2; ExpTupleDesc * input_tuple_desc = NULL; ExpTupleDesc * output_tuple_desc = NULL; // Generate expression to create the input row that will be // given to the stored proc. // The input value is in sp->getProcAllParams() // and has to be converted to sp->procType(). // Generate Cast node to convert procParam to ProcType. // If procType is a varchar, explode it. This is done // so that values could be extracted correctly. ValueIdList procVIDList; for (CollIndex i = 0; i < procTypes().entries(); i++) { Cast * cn; if ((procTypes())[i].getType().getVarLenHdrSize() > 0) { // 5/9/98: add support for VARNCHAR const CharType& char_type = (CharType&)((procTypes())[i].getType()); // Explode varchars by moving them to a fixed field // whose length is equal to the max length of varchar. cn = new(generator->wHeap()) Cast ((getProcAllParamsVids())[i].getItemExpr(), (new(generator->wHeap()) SQLChar(generator->wHeap(), CharLenInfo(char_type.getStrCharLimit(), char_type.getDataStorageSize()), char_type.supportsSQLnull(), FALSE, FALSE, FALSE, char_type.getCharSet(), char_type.getCollation(), char_type.getCoercibility() /* (procTypes())[i].getType().getNominalSize(), (procTypes())[i].getType().supportsSQLnull() */ ) ) ); // Move the exploded field to a varchar field since // procType is varchar. // Can optimize by adding an option to convert node to // blankpad. TBD. // cn = new(generator->wHeap()) Cast(cn, &((procTypes())[i].getType())); } else cn = new(generator->wHeap()) Cast((getProcAllParamsVids())[i].getItemExpr(), &((procTypes())[i].getType())); cn->bindNode(generator->getBindWA()); procVIDList.insert(cn->getValueId()); } ULng32 inputRowlen_ = 0; exp_gen->generateContiguousMoveExpr(procVIDList, -1, /*add conv nodes*/ work_atp, work_atp_index, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, inputRowlen_, &input_expr, &input_tuple_desc, ExpTupleDesc::LONG_FORMAT); // add all columns from this SP to the map table. ULng32 tupleLength; exp_gen->processValIdList(getTableDesc()->getColumnList(), ExpTupleDesc::SQLARK_EXPLODED_FORMAT, tupleLength, work_atp, work_atp_index); // Generate expression to move the output row returned by the // stored proc back to parent. ULng32 outputRowlen_ = 0; MapTable * returnedMapTable = 0; exp_gen->generateContiguousMoveExpr(getTableDesc()->getColumnList(), -1 /*add conv nodes*/, 0, returned_desc->noTuples() - 1, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, outputRowlen_, &output_expr, &output_tuple_desc, ExpTupleDesc::LONG_FORMAT, &returnedMapTable); // Now generate expressions used to extract or move input or // output values. See class ExSPInputOutput. ExSPInputOutput * extractInputExpr = NULL; ExSPInputOutput * moveOutputExpr = NULL; generateSPIOExpr(this, generator, extractInputExpr, moveOutputExpr); // done with expressions at this operator. Remove the appended map tables. generator->removeAll(last_map_table); // append the map table containing the returned columns generator->appendAtEnd(returnedMapTable); NAString procNameAsNAString(procName_); char * sp_name = space->allocateAndCopyToAlignedSpace(procNameAsNAString, procNameAsNAString.length(), 0); ExpGenerator *expGen = generator->getExpGenerator(); // expression to conditionally return 0 or more rows. ex_expr *predExpr = NULL; // generate tuple selection expression, if present if(NOT selectionPred().isEmpty()) { ItemExpr* pred = selectionPred().rebuildExprTree(ITM_AND,TRUE,TRUE); expGen->generateExpr(pred->getValueId(),ex_expr::exp_SCAN_PRED,&predExpr); } ComTdbStoredProc * sp_tdb = new(space) ComTdbStoredProc(sp_name, input_expr, inputRowlen_, output_expr, outputRowlen_, work_cri_desc, work_atp_index, given_desc, returned_desc, extractInputExpr, moveOutputExpr, 2, 1024, (Cardinality) getGroupAttr()-> getOutputLogPropList()[0]-> getResultCardinality().value(), 5, 64000, //10240 predExpr, (UInt16) arkcmpInfo_); generator->initTdbFields(sp_tdb); if(!generator->explainDisabled()) { generator->setExplainTuple( addExplainInfo(sp_tdb, 0, 0, generator)); } // Do not infer that any transaction started can // be in READ ONLY mode if ISPs are present. generator->setNeedsReadWriteTransaction(TRUE); generator->setCriDesc(given_desc, Generator::DOWN); generator->setCriDesc(returned_desc, Generator::UP); generator->setGenObj(this, sp_tdb); // Some built-in functions require a TMF transaction // because they get their information from catman generator->setTransactionFlag(getRequiresTMFTransaction()); return 0; }
ItemExpr * buildEncodeTree(desc_struct * column, desc_struct * key, NAString * dataBuffer, //IN:contains original value Generator * generator, ComDiagsArea * diagsArea) { ExpGenerator * expGen = generator->getExpGenerator(); // values are encoded by evaluating the expression: // encode (cast (<dataBuffer> as <datatype>)) // where <dataBuffer> points to the string representation of the // data value to be encoded, and <datatype> contains the // PIC repsentation of the columns's datatype. // create the CAST part of the expression using the parser. // if this is a nullable column and the key value passed in // is a NULL value, then treat it as a special case. A NULL value // is passed in as an unquoted string of characters NULL in the // dataBuffer. This case has to be treated different since the // parser doesn't recognize the syntax "CAST (NULL as <datatype>)". NAString ns; ItemExpr * itemExpr; NABoolean nullValue = FALSE; NABoolean caseinsensitiveEncode = FALSE; if (column->body.columns_desc.caseinsensitive) caseinsensitiveEncode = TRUE; if (column->body.columns_desc.null_flag && dataBuffer->length() >= 4 && str_cmp(*dataBuffer, "NULL", 4) == 0) { nullValue = TRUE; ns = "CAST ( @A1 AS "; ns += column->body.columns_desc.pictureText; ns += ");"; // create a NULL constant ConstValue * nullConst = new(expGen->wHeap()) ConstValue(); nullConst->synthTypeAndValueId(); itemExpr = expGen->createExprTree(ns, CharInfo::UTF8, ns.length(), 1, nullConst); } else { ns = "CAST ( "; ns += *dataBuffer; ns += " AS "; ns += column->body.columns_desc.pictureText; ns += ");"; itemExpr = expGen->createExprTree(ns, CharInfo::UTF8, ns.length()); } CMPASSERT(itemExpr != NULL); ItemExpr *boundItemExpr = itemExpr->bindNode(generator->getBindWA()); if (boundItemExpr == NULL) return NULL; // make sure that the source and target values have compatible type. // Do this only if source is not a null value. NAString srcval; srcval = ""; srcval += *dataBuffer; srcval += ";"; ItemExpr * srcNode = expGen->createExprTree(srcval, CharInfo::UTF8, srcval.length()); CMPASSERT(srcNode != NULL); srcNode->synthTypeAndValueId(); if ((NOT nullValue) && (NOT srcNode->getValueId().getType().isCompatible(itemExpr->getValueId().getType()))) { if (diagsArea) { emitDyadicTypeSQLnameMsg(-4039, itemExpr->getValueId().getType(), srcNode->getValueId().getType(), column->body.columns_desc.colname, NULL, diagsArea); } return NULL; } if (column->body.columns_desc.null_flag) ((NAType *)&(itemExpr->getValueId().getType()))->setNullable(TRUE); else ((NAType *)&(itemExpr->getValueId().getType()))->setNullable(FALSE); // Explode varchars by moving them to a fixed field // whose length is equal to the max length of varchar. ////collation?? DataType datatype = column->body.columns_desc.datatype; if (DFS2REC::isSQLVarChar(datatype)) { char lenBuf[10]; NAString vc((NASize_T)100); // preallocate a big-enough buf size_t len = column->body.columns_desc.length; if (datatype == REC_BYTE_V_DOUBLE) len /= SQL_DBCHAR_SIZE; vc = "CAST (@A1 as CHAR("; vc += str_itoa(len, lenBuf); if ( column->body.columns_desc.character_set == CharInfo::UTF8 || ( column->body.columns_desc.character_set == CharInfo::SJIS && column->body.columns_desc.encoding_charset == CharInfo::SJIS ) ) { vc += " BYTE"; if (len > 1) vc += "S"; } vc += ") CHARACTER SET "; vc += CharInfo::getCharSetName(column->body.columns_desc.character_set); vc += ");"; itemExpr = expGen->createExprTree(vc, CharInfo::UTF8, vc.length(), 1, itemExpr); itemExpr->synthTypeAndValueId(); ((NAType *)&(itemExpr->getValueId().getType()))-> setNullable(column->body.columns_desc.null_flag); } // add the encode node on top of it. short desc_flag = TRUE; if (key->body.keys_desc.ordering == 0) // ascending desc_flag = FALSE; itemExpr = new(expGen->wHeap()) CompEncode(itemExpr, desc_flag); itemExpr->synthTypeAndValueId(); ((CompEncode*)itemExpr)->setCaseinsensitiveEncode(caseinsensitiveEncode); return itemExpr; }
short PhysUnPackRows::codeGen(Generator *generator) { // Get handles on expression generator, map table, and heap allocator // ExpGenerator *expGen = generator->getExpGenerator(); Space *space = generator->getSpace(); // Allocate a new map table for this operation // MapTable *localMapTable = generator->appendAtEnd(); // Generate the child and capture the task definition block and a description // of the reply composite row layout and the explain information. // child(0)->codeGen(generator); ComTdb *childTdb = (ComTdb*)(generator->getGenObj()); ex_cri_desc *childCriDesc = generator->getCriDesc(Generator::UP); ExplainTuple *childExplainTuple = generator->getExplainTuple(); // Make all of my child's outputs map to ATP 1. Since they are // not needed above, they will not be in the work ATP (0). // (Later, they will be removed from the map table) // localMapTable->setAllAtp(1); // Generate the given and returned composite row descriptors. // unPackRows adds a tupp (for the generated outputs) to the // row given by the parent. The workAtp will have the 2 more // tupps (1 for the generated outputs and another for the // indexValue) than the given. // ex_cri_desc *givenCriDesc = generator->getCriDesc(Generator::DOWN); ex_cri_desc *returnedCriDesc = #pragma nowarn(1506) // warning elimination new(space) ex_cri_desc(givenCriDesc->noTuples() + 1, space); #pragma warn(1506) // warning elimination ex_cri_desc *workCriDesc = #pragma nowarn(1506) // warning elimination new(space) ex_cri_desc(givenCriDesc->noTuples() + 2, space); #pragma warn(1506) // warning elimination // unPackCols is the next to the last Tp in Atp 0, the work ATP. // and the last Tp in the returned ATP. // const Int32 unPackColsAtpIndex = workCriDesc->noTuples() - 2; const Int32 unPackColsAtp = 0; // The length of the new tuple which will contain the columns // generated by unPackRows // ULng32 unPackColsTupleLen; // The Tuple Desc describing the tuple containing the new unPacked columns // It is generated when the expression is generated. // ExpTupleDesc *unPackColsTupleDesc = 0; // indexValue is the last Tp in Atp 0, the work ATP. // const Int32 indexValueAtpIndex = workCriDesc->noTuples() - 1; const Int32 indexValueAtp = 0; // The length of the work tuple which will contain the value // of the index. This should always be sizeof(int). // ULng32 indexValueTupleLen = 0; // The Tuple Desc describing the tuple containing the new unPacked columns // It is generated when the expression is generated. // ExpTupleDesc *indexValueTupleDesc = 0; ValueIdList indexValueList; if (indexValue() != NULL_VALUE_ID) { indexValueList.insert(indexValue()); expGen->processValIdList(indexValueList, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, indexValueTupleLen, indexValueAtp, indexValueAtpIndex, &indexValueTupleDesc, ExpTupleDesc::SHORT_FORMAT); GenAssert(indexValueTupleLen == sizeof(Int32), "UnPackRows::codeGen: Internal Error"); } // If a packingFactor exists, generate a move expression for this. // It is assumed that the packingFactor expression evaluates to a // 4 byte integer. // ex_expr *packingFactorExpr = 0; ULng32 packingFactorTupleLen; if(packingFactor().entries() > 0) { expGen->generateContiguousMoveExpr(packingFactor(), -1, unPackColsAtp, unPackColsAtpIndex, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, packingFactorTupleLen, &packingFactorExpr); GenAssert(packingFactorTupleLen == sizeof(Int32), "UnPackRows::codeGen: Internal Error"); } // Generate the UnPack expressions. // // characteristicOutputs() - refers to the list of expressions // to be move to another tuple. // // 0 - Do not add conv. nodes. // // unPackColsAtp - this expression will move data to the // unPackColsAtp (0) ATP. // // unPackColsAtpIndex - within the unPackColsAtp (0) ATP, the destination // for this move expression will be the unPackColsAtpIndex TP. This should // be the next to the last TP of the work ATP. (The indexValue will be in // the last position) // // SQLARK_EXPLODED_FORMAT - generate the move expression to construct // the destination tuple in EXPLODED FORMAT. // // unPackColsTupleLen - This is an output which will contain the length // of the destination Tuple. // // &unPackColsExpr - The address of the pointer to the expression // which will be generated. // // &unPackColsTupleDesc - The address of the tuple descriptor which is // generated. This describes the destination tuple of the move expression. // // SHORT_FORMAT - generate the unPackColsTupleDesc in the SHORT FORMAT. // ex_expr *unPackColsExpr = 0; expGen-> genGuardedContigMoveExpr(selectionPred(), getGroupAttr()->getCharacteristicOutputs(), 0, // No Convert Nodes added unPackColsAtp, unPackColsAtpIndex, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, unPackColsTupleLen, &unPackColsExpr, &unPackColsTupleDesc, ExpTupleDesc::SHORT_FORMAT); #pragma nowarn(1506) // warning elimination workCriDesc->setTupleDescriptor(unPackColsAtpIndex, #pragma warn(1506) // warning elimination unPackColsTupleDesc); #pragma nowarn(1506) // warning elimination returnedCriDesc->setTupleDescriptor(unPackColsAtpIndex, #pragma warn(1506) // warning elimination unPackColsTupleDesc); // expressions for rowwise rowset implementation. ex_expr * rwrsInputSizeExpr = 0; ex_expr * rwrsMaxInputRowlenExpr = 0; ex_expr * rwrsBufferAddrExpr = 0; ULng32 rwrsInputSizeExprLen = 0; ULng32 rwrsMaxInputRowlenExprLen = 0; ULng32 rwrsBufferAddrExprLen = 0; const Int32 rwrsAtp = 1; const Int32 rwrsAtpIndex = workCriDesc->noTuples() - 2; ExpTupleDesc * rwrsTupleDesc = 0; ValueIdList rwrsVidList; if (rowwiseRowset()) { rwrsVidList.insert(this->rwrsInputSizeExpr()->getValueId()); expGen->generateContiguousMoveExpr(rwrsVidList, 0 /*don't add conv nodes*/, rwrsAtp, rwrsAtpIndex, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, rwrsInputSizeExprLen, &rwrsInputSizeExpr, &rwrsTupleDesc,ExpTupleDesc::SHORT_FORMAT); rwrsVidList.clear(); rwrsVidList.insert(this->rwrsMaxInputRowlenExpr()->getValueId()); expGen->generateContiguousMoveExpr(rwrsVidList, 0 /*don't add conv nodes*/, rwrsAtp, rwrsAtpIndex, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, rwrsMaxInputRowlenExprLen, &rwrsMaxInputRowlenExpr, &rwrsTupleDesc,ExpTupleDesc::SHORT_FORMAT); rwrsVidList.clear(); rwrsVidList.insert(this->rwrsBufferAddrExpr()->getValueId()); expGen->generateContiguousMoveExpr(rwrsVidList, 0 /*don't add conv nodes*/, rwrsAtp, rwrsAtpIndex, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, rwrsBufferAddrExprLen, &rwrsBufferAddrExpr, &rwrsTupleDesc,ExpTupleDesc::SHORT_FORMAT); expGen->assignAtpAndAtpIndex(rwrsOutputVids(), unPackColsAtp, unPackColsAtpIndex); } // Move the generated maptable entries, to the localMapTable, // so that all other entries can later be removed. // for(ValueId outputValId = getGroupAttr()->getCharacteristicOutputs().init(); getGroupAttr()->getCharacteristicOutputs().next(outputValId); getGroupAttr()->getCharacteristicOutputs().advance(outputValId)) { generator->addMapInfoToThis(localMapTable, outputValId, generator->getMapInfo(outputValId)-> getAttr()); // Indicate that code was generated for this map table entry. // generator->getMapInfoFromThis(localMapTable, outputValId)->codeGenerated(); } NABoolean tolerateNonFatalError = FALSE; if (isRowsetIterator() && (generator->getTolerateNonFatalError())) { tolerateNonFatalError = TRUE; setTolerateNonFatalError(RelExpr::NOT_ATOMIC_); } // Allocate the UnPack TDB // ComTdbUnPackRows *unPackTdb = NULL; if (rowwiseRowset()) { unPackTdb = new (space) ComTdbUnPackRows(NULL, //childTdb, rwrsInputSizeExpr, rwrsMaxInputRowlenExpr, rwrsBufferAddrExpr, rwrsAtpIndex, givenCriDesc, returnedCriDesc, workCriDesc, 16, 1024, (Cardinality) getGroupAttr()-> getOutputLogPropList()[0]-> getResultCardinality().value(), 2, 20000); } else { // Base the initial queue size on the est. cardinality. // UnPackRows does not do dyn queue resize, so passed in // queue size values represent initial (and final) queue // sizes (not max queue sizes). // queue_index upQueueSize = (queue_index)getGroupAttr()->getOutputLogPropList()[0]->getResultCardinality().value(); // Make sure it is at least 1024. upQueueSize = (upQueueSize < 1024 ? 1024 : upQueueSize); // Make sure that it is not more the 64K. upQueueSize = (upQueueSize > 65536 ? 65536 : upQueueSize); unPackTdb = new (space) ComTdbUnPackRows(childTdb, packingFactorExpr, unPackColsExpr, #pragma nowarn(1506) // warning elimination unPackColsTupleLen, unPackColsAtpIndex, indexValueAtpIndex, givenCriDesc, returnedCriDesc, workCriDesc, 16, upQueueSize, (Cardinality) getGroupAttr()-> getOutputLogPropList()[0]-> getResultCardinality().value(), isRowsetIterator(), tolerateNonFatalError); } #pragma warn(1506) // warning elimination generator->initTdbFields(unPackTdb); // Remove child's outputs from mapTable, They are not needed // above. // generator->removeAll(localMapTable); // Add the explain Information for this node to the EXPLAIN // Fragment. Set the explainTuple pointer in the generator so // the parent of this node can get a handle on this explainTuple. // if(!generator->explainDisabled()) { generator->setExplainTuple(addExplainInfo(unPackTdb, childExplainTuple, 0, generator)); } // Restore the Cri Desc's and set the return object. // generator->setCriDesc(givenCriDesc, Generator::DOWN); generator->setCriDesc(returnedCriDesc, Generator::UP); generator->setGenObj(this, unPackTdb); return 0; }
short PhysSequence::codeGen(Generator *generator) { // Get a local handle on some of the generator objects. // CollHeap *wHeap = generator->wHeap(); Space *space = generator->getSpace(); ExpGenerator *expGen = generator->getExpGenerator(); MapTable *mapTable = generator->getMapTable(); // Allocate a new map table for this node. This must be done // before generating the code for my child so that this local // map table will be sandwiched between the map tables already // generated and the map tables generated by my offspring. // // Only the items available as output from this node will // be put in the local map table. Before exiting this function, all of // my offsprings map tables will be removed. Thus, none of the outputs // from nodes below this node will be visible to nodes above it except // those placed in the local map table and those that already exist in // my ancestors map tables. This is the standard mechanism used in the // generator for managing the access to item expressions. // MapTable *localMapTable = generator->appendAtEnd(); // Since this operation doesn't modify the row on the way down the tree, // go ahead and generate the child subtree. Capture the given composite row // descriptor and the child's returned TDB and composite row descriptor. // ex_cri_desc * givenCriDesc = generator->getCriDesc(Generator::DOWN); child(0)->codeGen(generator); ComTdb *childTdb = (ComTdb*)generator->getGenObj(); ex_cri_desc * childCriDesc = generator->getCriDesc(Generator::UP); ExplainTuple *childExplainTuple = generator->getExplainTuple(); // Make all of my child's outputs map to ATP 1. The child row is only // accessed in the project expression and it will be the second ATP // (ATP 1) passed to this expression. // localMapTable->setAllAtp(1); // My returned composite row has an additional tupp. // Int32 numberTuples = givenCriDesc->noTuples() + 1; ex_cri_desc * returnCriDesc #pragma nowarn(1506) // warning elimination = new (space) ex_cri_desc(numberTuples, space); #pragma warn(1506) // warning elimination // For now, the history buffer row looks just the return row. Later, // it may be useful to add an additional tupp for sequence function // itermediates that are not needed above this node -- thus, this // ATP is kept separate from the returned ATP. // const Int32 historyAtp = 0; const Int32 historyAtpIndex = numberTuples-1; #pragma nowarn(1506) // warning elimination ex_cri_desc *historyCriDesc = new (space) ex_cri_desc(numberTuples, space); #pragma warn(1506) // warning elimination ExpTupleDesc *historyDesc = 0; //seperate the read and retur expressions seperateReadAndReturnItems(wHeap); // The history buffer consists of items projected directly from the // child, the root sequence functions, the value arguments of the // offset functions, and running sequence functions. These elements must // be materialized in the history buffer in order to be able to compute // the outputs of this node -- the items projected directly from the child // (projectValues) and the root sequence functions (sequenceFunctions). // // Compute the set of sequence function items that must be materialized // int the history buffer. -- sequenceItems // // Compute the set of items in the history buffer: the union of the // projected values and the value arguments. -- historyIds // // Compute the set of items in the history buffer that are computed: // the difference between all the elements in the history buffer // and the projected items. -- computedHistoryIds // // KB---will need to return atp with 3 tups only 0,1 and 2 // 2 -->values from history buffer after ther are moved to it addCheckPartitionChangeExpr(generator, TRUE); ValueIdSet historyIds; historyIds += movePartIdsExpr(); historyIds += sequencedColumns(); ValueIdSet outputFromChild = child(0)->getGroupAttr()->getCharacteristicOutputs(); getHistoryAttributes(readSeqFunctions(),outputFromChild, historyIds, TRUE, wHeap); // Add in the top level sequence functions. historyIds += readSeqFunctions(); getHistoryAttributes(returnSeqFunctions(),outputFromChild, historyIds, TRUE, wHeap); // Add in the top level functions. historyIds += returnSeqFunctions(); // Layout the work tuple format which consists of the projected // columns and the computed sequence functions. First, compute // the number of attributes in the tuple. // ULng32 numberAttributes = ((NOT historyIds.isEmpty()) ? historyIds.entries() : 0); // Allocate an attribute pointer vector from the working heap. // Attributes **attrs = new(wHeap) Attributes*[numberAttributes]; // Fill in the attributes vector for the history buffer including // adding the entries to the map table. Also, compute the value ID // set for the elements to project from the child row. // //??????????re-visit this function?? computeHistoryAttributes(generator, localMapTable, attrs, historyIds); // Create the tuple descriptor for the history buffer row and // assign the offsets to the attributes. For now, this layout is // identical to the returned row. Set the tuple descriptors for // the return and history rows. // ULng32 historyRecLen; expGen->processAttributes(numberAttributes, attrs, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, historyRecLen, historyAtp, historyAtpIndex, &historyDesc, ExpTupleDesc::SHORT_FORMAT); NADELETEBASIC(attrs, wHeap); #pragma nowarn(1506) // warning elimination returnCriDesc->setTupleDescriptor(historyAtpIndex, historyDesc); #pragma warn(1506) // warning elimination #pragma nowarn(1506) // warning elimination historyCriDesc->setTupleDescriptor(historyAtpIndex, historyDesc); #pragma warn(1506) // warning elimination // If there are any sequence function items, generate the sequence // function expressions. // ex_expr * readSeqExpr = NULL; if(NOT readSeqFunctions().isEmpty()) { ValueIdSet seqVals = readSeqFunctions(); seqVals += sequencedColumns(); seqVals += movePartIdsExpr(); expGen->generateSequenceExpression(seqVals, readSeqExpr); } ex_expr *checkPartChangeExpr = NULL; if (!checkPartitionChangeExpr().isEmpty()) { ItemExpr * newCheckPartitionChangeTree= checkPartitionChangeExpr().rebuildExprTree(ITM_AND,TRUE,TRUE); expGen->generateExpr(newCheckPartitionChangeTree->getValueId(), ex_expr::exp_SCAN_PRED, &checkPartChangeExpr); } //unsigned long rowLength; ex_expr * returnExpr = NULL; if(NOT returnSeqFunctions().isEmpty()) { expGen->generateSequenceExpression(returnSeqFunctions(), returnExpr); } // Generate expression to evaluate predicate on the output // ex_expr *postPred = 0; if (! selectionPred().isEmpty()) { ItemExpr * newPredTree = selectionPred().rebuildExprTree(ITM_AND,TRUE,TRUE); expGen->generateExpr(newPredTree->getValueId(), ex_expr::exp_SCAN_PRED, &postPred); } // Reset ATP's to zero for parent. // localMapTable->setAllAtp(0); // Generate expression to evaluate the cancel expression // ex_expr *cancelExpression = 0; if (! cancelExpr().isEmpty()) { ItemExpr * newCancelExprTree = cancelExpr().rebuildExprTree(ITM_AND,TRUE,TRUE); expGen->generateExpr(newCancelExprTree->getValueId(), ex_expr::exp_SCAN_PRED, &cancelExpression); } // // For overflow // // ( The following are meaningless if ! unlimitedHistoryRows() ) NABoolean noOverflow = CmpCommon::getDefault(EXE_BMO_DISABLE_OVERFLOW) == DF_ON ; NABoolean logDiagnostics = CmpCommon::getDefault(EXE_DIAGNOSTIC_EVENTS) == DF_ON ; NABoolean possibleMultipleCalls = generator->getRightSideOfFlow() ; short scratchTresholdPct = (short) CmpCommon::getDefaultLong(SCRATCH_FREESPACE_THRESHOLD_PERCENT); // determione the memory usage (amount of memory as percentage from total // physical memory used to initialize data structures) unsigned short memUsagePercent = (unsigned short) getDefault(BMO_MEMORY_USAGE_PERCENT); short memPressurePct = (short)getDefault(GEN_MEM_PRESSURE_THRESHOLD); historyRecLen = ROUND8(historyRecLen); Lng32 maxNumberOfOLAPBuffers; Lng32 maxRowsInOLAPBuffer; Lng32 minNumberOfOLAPBuffers; Lng32 numberOfWinOLAPBuffers; Lng32 olapBufferSize; computeHistoryParams(historyRecLen, maxRowsInOLAPBuffer, minNumberOfOLAPBuffers, numberOfWinOLAPBuffers, maxNumberOfOLAPBuffers, olapBufferSize); ComTdbSequence *sequenceTdb = new(space) ComTdbSequence(readSeqExpr, returnExpr, postPred, cancelExpression, getMinFollowingRows(), #pragma nowarn(1506) // warning elimination historyRecLen, historyAtpIndex, childTdb, givenCriDesc, returnCriDesc, (queue_index)getDefault(GEN_SEQFUNC_SIZE_DOWN), (queue_index)getDefault(GEN_SEQFUNC_SIZE_UP), getDefault(GEN_SEQFUNC_NUM_BUFFERS), getDefault(GEN_SEQFUNC_BUFFER_SIZE), olapBufferSize, maxNumberOfOLAPBuffers, numHistoryRows(), getUnboundedFollowing(), logDiagnostics, possibleMultipleCalls, scratchTresholdPct, memUsagePercent, memPressurePct, maxRowsInOLAPBuffer, minNumberOfOLAPBuffers, numberOfWinOLAPBuffers, noOverflow, checkPartChangeExpr); #pragma warn(1506) // warning elimination generator->initTdbFields(sequenceTdb); // update the estimated value of HistoryRowLength with actual value //setEstHistoryRowLength(historyIds.getRowLength()); double sequenceMemEst = getEstimatedRunTimeMemoryUsage(sequenceTdb); generator->addToTotalEstimatedMemory(sequenceMemEst); if(!generator->explainDisabled()) { Lng32 seqMemEstInKBPerCPU = (Lng32)(sequenceMemEst / 1024) ; seqMemEstInKBPerCPU = seqMemEstInKBPerCPU/ (MAXOF(generator->compilerStatsInfo().dop(),1)); generator->setOperEstimatedMemory(seqMemEstInKBPerCPU); generator-> setExplainTuple(addExplainInfo(sequenceTdb, childExplainTuple, 0, generator)); generator->setOperEstimatedMemory(0); } sequenceTdb->setScratchIOVectorSize((Int16)getDefault(SCRATCH_IO_VECTOR_SIZE_HASH)); sequenceTdb->setOverflowMode(generator->getOverflowMode()); sequenceTdb->setBmoMinMemBeforePressureCheck((Int16)getDefault(EXE_BMO_MIN_SIZE_BEFORE_PRESSURE_CHECK_IN_MB)); if(generator->getOverflowMode() == ComTdb::OFM_SSD ) sequenceTdb->setBMOMaxMemThresholdMB((UInt16)(ActiveSchemaDB()-> getDefaults()). getAsLong(SSD_BMO_MAX_MEM_THRESHOLD_IN_MB)); else sequenceTdb->setBMOMaxMemThresholdMB((UInt16)(ActiveSchemaDB()-> getDefaults()). getAsLong(EXE_MEMORY_AVAILABLE_IN_MB)); // The CQD EXE_MEM_LIMIT_PER_BMO_IN_MB has precedence over the mem quota sys NADefaults &defs = ActiveSchemaDB()->getDefaults(); UInt16 mmu = (UInt16)(defs.getAsDouble(EXE_MEM_LIMIT_PER_BMO_IN_MB)); UInt16 numBMOsInFrag = (UInt16)generator->getFragmentDir()->getNumBMOs(); if (mmu != 0) sequenceTdb->setMemoryQuotaMB(mmu); else { // Apply quota system if either one the following two is true: // 1. the memory limit feature is turned off and more than one BMOs // 2. the memory limit feature is turned on NABoolean mlimitPerCPU = defs.getAsDouble(EXE_MEMORY_LIMIT_PER_CPU) > 0; if ( mlimitPerCPU || numBMOsInFrag > 1 ) { double memQuota = computeMemoryQuota(generator->getEspLevel() == 0, mlimitPerCPU, generator->getBMOsMemoryLimitPerCPU().value(), generator->getTotalNumBMOsPerCPU(), generator->getTotalBMOsMemoryPerCPU().value(), numBMOsInFrag, generator->getFragmentDir()->getBMOsMemoryUsage() ); sequenceTdb->setMemoryQuotaMB( UInt16(memQuota) ); } } generator->setCriDesc(givenCriDesc, Generator::DOWN); generator->setCriDesc(returnCriDesc, Generator::UP); generator->setGenObj(this, sequenceTdb); return 0; }
void RangePartitioningFunction::generatePivLayout( Generator *generator, Lng32 &partitionInputDataLength, Lng32 atp, Lng32 atpIndex, Attributes ***pivAttrs) { // Make a layout of the partition input data record such that // begin and end key are aligned in the same way. // (layout = ((beg. key) (filler1) (end key) (filler2) (exclusion flag))) ExpGenerator *expGen = generator->getExpGenerator(); CollIndex numPartInputs = getPartitionInputValuesLayout().entries(); CollIndex numPartKeyCols = (numPartInputs - 1) / 2; // the number of partition input variables must be odd GenAssert(2*numPartKeyCols+1 == numPartInputs, "NOT 2*numPartKeyCols+1 == numPartInputs"); // --------------------------------------------------------------------- // Start by processing the begin key PIVs // --------------------------------------------------------------------- ValueIdList partialPivs; Attributes **returnedAttrs = NULL; Attributes **localPartialAttrs; Lng32 maxAlignment = 1; Lng32 alignedPartKeyLen; if (pivAttrs) { returnedAttrs = new(generator->wHeap()) Attributes *[numPartInputs]; } CollIndex i = 0; for (i = 0; i < numPartKeyCols; i++) partialPivs.insert(getPartitionInputValuesLayout()[i]); expGen->processValIdList( partialPivs, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, (ULng32 &) partitionInputDataLength, atp, atpIndex, NULL, ExpTupleDesc::SHORT_FORMAT, 0, &localPartialAttrs); if (returnedAttrs) for (i = 0; i < numPartKeyCols; i++) returnedAttrs[i] = localPartialAttrs[i]; // --------------------------------------------------------------------- // Now find out the max. alignment that is needed in the begin key, // make sure that the end key starts on an offset that is a // multiple of the max. alignment in the partition input values // --------------------------------------------------------------------- for (i = 0; i < numPartKeyCols; i++) { if (localPartialAttrs[i]->getDataAlignmentSize() > maxAlignment) maxAlignment = localPartialAttrs[i]->getDataAlignmentSize(); if (localPartialAttrs[i]->getVCIndicatorLength() > maxAlignment) maxAlignment = localPartialAttrs[i]->getVCIndicatorLength(); if (localPartialAttrs[i]->getNullIndicatorLength() > maxAlignment) maxAlignment = localPartialAttrs[i]->getNullIndicatorLength(); } alignedPartKeyLen = partitionInputDataLength; while (alignedPartKeyLen % maxAlignment != 0) alignedPartKeyLen++; // --------------------------------------------------------------------- // Now that we are starting on a good offset, process the end key // --------------------------------------------------------------------- partialPivs.clear(); for (i = numPartKeyCols; i < numPartInputs-1; i++) partialPivs.insert(getPartitionInputValuesLayout()[i]); expGen->processValIdList( partialPivs, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, (ULng32 &) partitionInputDataLength, atp, atpIndex, NULL, ExpTupleDesc::SHORT_FORMAT, alignedPartKeyLen, &localPartialAttrs); if (returnedAttrs) for (i = numPartKeyCols; i < numPartInputs-1; i++) returnedAttrs[i] = localPartialAttrs[i-numPartKeyCols]; // --------------------------------------------------------------------- // Process the exclusion flag at offset 2*alignedPartKeyLen // --------------------------------------------------------------------- partialPivs.clear(); partialPivs.insert(getPartitionInputValuesLayout()[numPartInputs-1]); expGen->processValIdList( partialPivs, ExpTupleDesc::SQLARK_EXPLODED_FORMAT, (ULng32 &) partitionInputDataLength, atp, atpIndex, NULL, ExpTupleDesc::SHORT_FORMAT, 2*alignedPartKeyLen, &localPartialAttrs); // set up return values if (returnedAttrs) returnedAttrs[numPartInputs-1] = localPartialAttrs[0]; partitionInputDataLength += 2*alignedPartKeyLen; if (pivAttrs) { *pivAttrs = returnedAttrs; } else { NADELETEBASIC(returnedAttrs, generator->wHeap()); } }
// ItmDoWhileFunction::codeGen // // The DoWhile function executes the code represented by child(0) until // the condition represented by child(1) becomes false. The result of // the DoWhile is the final value of child(0). // // The looping is accomplished by inserting a NOOP/BRANCH pair. The NOOP // is inserted before generating the code for either child and serves as a // branch target. The BRANCH is inserted after generating the code for // both children and is targeted at the NOOP clause based on the result of // child(1). Between the NOOP and the BRANCH the body of the loop (child(0)) // and the termination condition (child(1)) are repeatedly evaluated. After // the branch the final result of the loop body is assigned as the result // of the DoWhile. // short ItmDoWhileFunction::codeGen(Generator * generator) { // Get local handles... // Attributes **attr; Space* space = generator->getSpace(); CollHeap *wHeap = generator->wHeap(); ExpGenerator *exp = generator->getExpGenerator(); // If this DoWhile has already been codeGenned, then bug out... // Otherwise, allocate space for the result if necessary and set // attr[0] to point to the result attribute data. Also, mark this // node as codeGenned. // if (exp->genItemExpr(this, &attr, 2, 0) == 1) return 0; // Insert the NOOP clause to use as the branch target for the // start of the loop body. // ex_clause * branchTarget = new(space) ex_noop_clause(); exp->linkClause(this, branchTarget); // CodeGen the body of the loop. // child(0)->codeGen(generator); // The result of the DoWhile is the result of the body of the loop. Set // the src attribute for the convert (added below) to be the body of // the while loop. The dst attribute has already been set in genItemExpr(). // attr[1] = generator->getMapInfo (child(0)->castToItemExpr()->getValueId())->getAttr(); // CodeGen the loop termination condition. // child(1)->codeGen(generator); // Construct a BRANCH clause to loop back and repeat the expression // and condition if the condition evaluates to TRUE. // Attributes ** branchAttrs = new(wHeap) Attributes*[2]; Attributes *boolAttr = generator->getMapInfo (child(1)->castToItemExpr()->getValueId())->getAttr(); branchAttrs[0] = boolAttr->newCopy(wHeap); branchAttrs[1] = boolAttr->newCopy(wHeap); // branchAttrs[0]->copyLocationAttrs(boolAttr); // branchAttrs[1]->copyLocationAttrs(boolAttr); branchAttrs[0]->resetShowplan(); ex_branch_clause * branchClause = new(space) ex_branch_clause(ITM_OR, branchAttrs, space); branchClause->set_branch_clause(branchTarget); // Insert the branch clause into the expression. // exp->linkClause(this, branchClause); // Allocate a convert clause to move the result from child(0) to the // result of this node. This move is necessary so that future // side-effects of the result of child(0) -- if it is a local variable, // for instance -- will not change the result of the DoWhile. // ex_conv_clause * convClause = new(generator->getSpace()) ex_conv_clause (getOperatorType(), attr, space); exp->linkClause(this, convClause); return 0; }
short PhysSample::codeGen(Generator *generator) { // Get a local handle on some of the generator objects. // CollHeap *wHeap = generator->wHeap(); Space *space = generator->getSpace(); MapTable *mapTable = generator->getMapTable(); ExpGenerator *expGen = generator->getExpGenerator(); // Allocate a new map table for this node. This must be done // before generating the code for my child so that this local // map table will be sandwiched between the map tables already // generated and the map tables generated by my offspring. // // Only the items available as output from this node will // be put in the local map table. Before exiting this function, all of // my offsprings map tables will be removed. Thus, none of the outputs // from nodes below this node will be visible to nodes above it except // those placed in the local map table and those that already exist in // my ancestors map tables. This is the standard mechanism used in the // generator for managing the access to item expressions. // MapTable *localMapTable = generator->appendAtEnd(); // Since this operation doesn't modify the row on the way down the tree, // go ahead and generate the child subtree. Capture the given composite row // descriptor and the child's returned TDB and composite row descriptor. // ex_cri_desc * givenCriDesc = generator->getCriDesc(Generator::DOWN); child(0)->codeGen(generator); ComTdb *childTdb = (ComTdb*)generator->getGenObj(); ex_cri_desc * childCriDesc = generator->getCriDesc(Generator::UP); ExplainTuple *childExplainTuple = generator->getExplainTuple(); // Geneate the sampling expression. // ex_expr *balExpr = NULL; Int32 returnFactorOffset = 0; ValueId val; val = balanceExpr().init(); if(balanceExpr().next(val)) expGen->generateSamplingExpr(val, &balExpr, returnFactorOffset); // Alias the sampleColumns() so that they reference the underlying // expressions directly. This is done to avoid having to generate and // execute a project expression that simply moves the columns from // one tupp to another to reflect the application of the sampledCol // function. // // ValueId valId; // for(valId = sampledColumns().init(); // sampledColumns().next(valId); // sampledColumns().advance(valId)) // { // MapInfo *mapInfoChild = localMapTable->getMapInfoAsIs // (valId.getItemExpr()->child(0)->castToItemExpr()->getValueId()); // GenAssert(mapInfoChild, "Sample::codeGen -- no child map info."); // Attributes *attr = mapInfoChild->getAttr(); // MapInfo *mapInfo = localMapTable->addMapInfoToThis(valId, attr); // mapInfo->codeGenerated(); // } // check if any of the columns inthe sampled columns are lob columns. If so, return an error. ValueId valId; for(valId = sampledColumns().init(); sampledColumns().next(valId); sampledColumns().advance(valId)) { const NAType &colType = valId.getType(); if ((colType.getFSDatatype() == REC_BLOB) || (colType.getFSDatatype() == REC_CLOB)) { *CmpCommon::diags() << DgSqlCode(-4322); GenExit(); } } // Now, remove all attributes from the map table except the // the stuff in the local map table -- the result of this node. // // localMapTable->removeAll(); // Generate the expression to evaluate predicate on the sampled row. // ex_expr *postPred = 0; if (!selectionPred().isEmpty()) { ItemExpr * newPredTree = selectionPred().rebuildExprTree(ITM_AND,TRUE,TRUE); expGen->generateExpr(newPredTree->getValueId(), ex_expr::exp_SCAN_PRED, &postPred); } // Construct the Sample TDB. // ComTdbSample *sampleTdb = new(space) ComTdbSample(NULL, balExpr, returnFactorOffset, postPred, childTdb, givenCriDesc, childCriDesc, (queue_index)getDefault(GEN_SAMPLE_SIZE_DOWN), (queue_index)getDefault(GEN_SAMPLE_SIZE_UP)); generator->initTdbFields(sampleTdb); if(!generator->explainDisabled()) { generator-> setExplainTuple(addExplainInfo(sampleTdb, childExplainTuple, 0, generator)); } generator->setCriDesc(givenCriDesc, Generator::DOWN); generator->setCriDesc(childCriDesc, Generator::UP); generator->setGenObj(this, sampleTdb); return 0; }