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