// -------------------------------------------------------------------- // Create a MultiJoin that is joining a subset of this MultiJoin children. // Note: We assume JBBCs are already primed before calling this method. // THis is a fine assumption at the analysis and post analysis stage. // -------------------------------------------------------------------- MultiJoin* MultiJoin::createSubsetMultiJoin(const JBBSubset & subset, NABoolean reUseMJ) const { MultiJoin * result = NULL; if(reUseMJ) result = subset.getSubsetMJ(); if(result) return result; CMPASSERT (subset.getGB() == NULL_CA_ID); // no GBs for now CMPASSERT (subset.getJBBCs().entries() > 1); // everything here goes to statement heap CollHeap* outHeap = CmpCommon::statementHeap(); result = new (outHeap) MultiJoin(subset, outHeap); result->setChildren(childrenMap_); result->setGroupAttr(new (outHeap) GroupAttributes()); // Assign my Characteristic Inputs to the newly created subset multi-join. result->getGroupAttr()->addCharacteristicInputs (getGroupAttr()->getCharacteristicInputs()); // The following call primes the result Characteristic Outputs. // It ensures that the inputs are minimal and outputs are maximal. result->primeGroupAttributes(); // Now compute the GroupAnalysis fields result->primeGroupAnalysis(); return result; }
// only used when triggers are allocated from the cntext heap. // Currently triggers are allocated from the statement heap. // See method Trigger::Heap() in file Triggers.h for more details // LCOV_EXCL_START void TriggerDB::clearAndDestroy() { NAHashDictionaryIterator<TableOp,BeforeAndAfterTriggers> iter(*this); TableOp * key = NULL; BeforeAndAfterTriggers* value = NULL; // iterate over all entries and destroy them #pragma warning (disable : 4018) //warning elimination for (Int32 i=0; i < iter.entries(); i++) #pragma warning (default : 4018) //warning elimination { iter.getNext(key, value); CMPASSERT(key != NULL); CMPASSERT(value != NULL); value->clearAndDestroy(); delete value; value = NULL; delete key; key = NULL; } this->clear(FALSE); // now, TriggerDB should be empty CMPASSERT(this->entries() == 0); }
// ----------------------------------------------------------------------- // Given a column list providing identifiers for columns of this table, // this method returns a list of VEG expressions and/or base columns that // show the equivalence of base columns with index columns. // ----------------------------------------------------------------------- void TableDesc::getEquivVEGCols (const ValueIdList& columnList, ValueIdList &VEGColumnList) const { for (CollIndex i=0; i < columnList.entries(); i++) { ItemExpr *ie = columnList[i].getItemExpr(); BaseColumn *bc = NULL; switch (ie->getOperatorType()) { case ITM_BASECOLUMN: bc = (BaseColumn *) ie; break; case ITM_INDEXCOLUMN: bc = (BaseColumn *) ((IndexColumn *) ie)->getDefinition(). getItemExpr(); CMPASSERT(bc->getOperatorType() == ITM_BASECOLUMN); break; default: ABORT("Invalid argument to TableDesc::getEquivVEGCols()\n"); } CMPASSERT(bc->getTableDesc() == this); VEGColumnList.insert(getColumnVEGList()[bc->getColNumber()]); } }
// --------------------------------------------------------------- // Compute the Group Analysis for this multi join based on its // children. Verify its consistent with its jbbSubset_ // --------------------------------------------------------------- void MultiJoin::primeGroupAnalysis() { // Analysis must have passed now that we have a MultiJoin. Otherwise // we must have cleanup problem. CMPASSERT (QueryAnalysis::Instance()->isAnalysisON()); // no GB in multi-joins for now CMPASSERT (jbbSubset_.getGB() == NULL_CA_ID); GroupAnalysis* groupAnalysis = getGroupAnalysis(); // recursively call the children appending their subtreeTables // and parentJBBViews JBBSubset* localView = new (groupAnalysis->outHeap()) JBBSubset(groupAnalysis->outHeap()); CANodeIdSet allSubtreeTables; Int32 arity = getArity(); for (Lng32 i = 0; i < arity; i++) { GroupAnalysis* childAnalysis = child(i).getPtr()->getGroupAnalysis(); // use children parentViews to build this join local view localView->addSubset(*(childAnalysis->getParentJBBView())); allSubtreeTables += childAnalysis->getAllSubtreeTables(); } groupAnalysis->setLocalJBBView(localView); groupAnalysis->setSubtreeTables(allSubtreeTables); // The computed localJBBView should be the same as the MultiJoin subset. CMPASSERT (jbbSubset_ == *localView); return; }
static NABoolean ISPFetchPut(CmpInternalSP* storedProc, // to fetch data CmpISPDataObject* ispData) // to put data { NABoolean bufferFull = FALSE; // fetch until there is no more data #pragma nowarn(770) // warning elimination CmpStoredProc::ExecStatus execStatus; short putStatus; while ( !bufferFull && (execStatus=storedProc->fetch(*ispData)) == CmpStoredProc::MOREDATA ) { if ( (putStatus = ispData->output()->AddARow()) == 1 ) bufferFull = TRUE; CMPASSERT(putStatus != -1); } // close the ISP if ( !bufferFull ) { storedProc->close(*ispData); if ( (putStatus = ispData->output()->AddEOR() ) == 1 ) bufferFull = TRUE; CMPASSERT(putStatus != -1); } return bufferFull; }
CmpStatement::ReturnStatus CmpStatementISP::process (CmpMessageISPRequest& isp) { #pragma nowarn(262) // warning elimination ReturnStatus ret = CmpStatement_ERROR; #ifdef _DEBUG if (getenv("DEBUG_SP2")) DebugBreak(); #endif CmpCommon::context()->sqlSession()->setParentQid(isp.getParentQid()); // Instantiate a CmpInternalSP CmpInternalSP* storedProc = new(heap_) CmpInternalSP(isp.procName(), context_); CMPASSERT(storedProc); setStoredProc(storedProc); reply_ = new(outHeap_) CmpMessageReplyISP(outHeap_, isp.id(), 0, 0, outHeap_); // prepare the data for execution // Make sure the pointer that ispData owns won't be deleted until ispData is // out of scope. Because of the performance reason, the pointers are copied, // not the contents. // The procedure flow is : // .CmpContext contains CmpStatements // .one CmpStatementISP is created per CmpMessageISPRequest, there might be many CmpMessageGetNext to fetch more data, // but they all share the same CmpStatementISP. This CmpStatementISP will be deleted when the execution of ISP is finished. // .CmpStatementISP owns a CmpInternalSP, the interface to stored procedure execution. CmpInternalSP will be deleted in // CmpStatement::~CmpStatement // . CmpInternalSP owns a CmpISPDataObject which contains data passed from executor for ISP execution. this // CmpISPDataObject will only be deleted when CmpInternalSP is out of scope. // .CmpISPDataObject is constructed from the CmpMessageISPRequest, for better performance // the data pointers are copied instead of duplicating the data, so it should own the // data member and only delete them when CmpISPDataObject is out of scope. // storedProc_ owns this ispData, it should be deleted in storedProc is out of scope. CmpISPDataObject* ispData = new(heap_) CmpISPDataObject(&isp, storedProc, context_->heap(), context_); ISPReqId_ = isp.id(); // open ISP short inputStatus = 0; NABoolean bufferFull = FALSE; for (; !bufferFull && (inputStatus = ispData->input()->next() ) == 0; ) { if (storedProc->open(*ispData) == CmpStoredProc::SUCCESS) bufferFull = ISPFetchPut(storedProc, ispData); else { if ( ispData->output()->AddEOR() == 1 ) bufferFull = TRUE; } } CMPASSERT(inputStatus != -1); // fail for retrieving input data // prepare to send the data back to executor ISPPrepareReply(ispData, reply_, bufferFull); return CmpStatement_SUCCESS; }
////////////////////////////////////////////////////////////////////////////// // Get all the ref constraints from this NATable, filter the ones that are to // tables in this graph, and mark them on both tables. For example, use the // RI on Orderes and Customers: O->C ( O is referencing C ). Because of the // semantics of the order of the tables in the join graph, in order for RI // optimization to be utilized, C must appear in the graph solution AFTER O. // The result is that C has an incoming bit for table O, and O has an // outgoing bit for table C. // Other conditions that must be met for the RI to be usable: // 1. C must have non-empty, insert only delta. // 2. O must not be inner tables of left joins. // 3. Each of the columns of the RI constraint must be covered by a predicate. // So if O(a,b) is referencing C(x,y) the join should use these two equal // predicates: (O.a = C.x) AND (O.b = C.y). // In this method, this table is O, and otherTable is C. Lng32 MVJoinTable::markRiConstraints(BindWA *bindWA, MVInfo *mvInfo) { LIST (MVUsedObjectInfo*)& usedObjects = mvInfo->getUsedObjectsList(); if (usedObjects[tableIndex_]->isInnerTableOfLeftJoin()) return 0; // O must not be inner table of a left join. Lng32 howManyRIs=0; const AbstractRIConstraintList& refConstraints = naTable_->getRefConstraints(); for (CollIndex i=0; i<refConstraints.entries(); i++) { RefConstraint *const ref = (RefConstraint *const)(refConstraints[i]); CMPASSERT(ref->getOperatorType() == ITM_REF_CONSTRAINT); // Ignore self referencing RIs. if (ref->selfRef()) continue; // Find the table the RI is referencing. const NAString& otherTableName = ref->getOtherTableName().getQualifiedNameAsString(); MVJoinTable *otherTable = mvInfo->getJoinGraph()->getTableObjectFor(&otherTableName); if (otherTable == NULL) continue; // The other table must be on the graph. if (otherTable->deltaType_ != INSERTONLY_DELTA) continue; // C must be insert only. Lng32 otherTableIndex = otherTable->getTableIndex(); // The RI must be covered by equal predicates on the same columns LIST(Lng32) myCols; LIST(Lng32) otherCols; ref->getMyKeyColumns(myCols); ref->getOtherTableKeyColumns(bindWA, otherCols); CMPASSERT(myCols.entries() == otherCols.entries()); NABoolean matchingPredicatesExist=TRUE; for (CollIndex currentCol=0; currentCol<myCols.entries(); currentCol++) { if (!mvInfo->isEqPredicateBetween(naTable_->getTableName(), myCols[currentCol], ref->getOtherTableName(), otherCols[currentCol])) matchingPredicatesExist = FALSE; } if (!matchingPredicatesExist) continue; // OK - we found a qualifying RI that we can use for optimization. // Now mark the bits. markRiTo(otherTableIndex); otherTable->markRiFrom(getTableIndex()); howManyRIs++; } return howManyRIs; }
void MultiJoin::synthLogPropWithMJReuse(NormWA * normWAPtr) { // Check to see whether this GA has already been associated // with a logExpr for synthesis. If so, no need to resynthesize // for this equivalent log. expression. if (getGroupAttr()->existsLogExprForSynthesis()) { Join * joinExprForSynth = (Join *) getGroupAttr()->getLogExprForSynthesis(); if(joinExprForSynth->isJoinFromMJSynthLogProp()) return; } NABoolean reUseMJ = TRUE; CMPASSERT ( (jbbSubset_.getGB() == NULL_CA_ID)); const CANodeIdSet & jbbcs = jbbSubset_.getJBBCs(); // Instead of always picking the first JBBC as the right child // pick the one with minimum JBBC connections. This will avoid // all unnecessary crossproducts CANodeId jbbcRight; jbbcRight = jbbcs.getJBBCwithMinConnectionsToThisJBBSubset(); CANodeIdSet right(jbbcRight); CANodeIdSet left(jbbcs); left -= jbbcRight; Join* join = splitSubset(*(left.jbbcsToJBBSubset()), *(right.jbbcsToJBBSubset()), reUseMJ); //if the left is a MultiJoin, synthesize it using reUse //this has to be done before join->synthLogProp to avoid //calling MultiJoin::synthLogProp on the left MultiJoin //because that does not reUse if(left.entries() > 1) { RelExpr * leftRelExpr = join->child(0)->castToRelExpr(); if(leftRelExpr && leftRelExpr->getOperator() == REL_MULTI_JOIN) ((MultiJoin *) leftRelExpr)->synthLogPropWithMJReuse(normWAPtr); } join->synthLogProp(normWAPtr); join->setJoinFromMJSynthLogProp(); getGroupAttr()->setLogExprForSynthesis(join); jbbSubset_.setSubsetMJ(this); CMPASSERT ( getGroupAttr()->getNumJoinedTables() >= getArity()); }
////////////////////////////////////////////////////////////////////////////// // Determine the correct MvRefreshBuilder sub-class to handle the refresh job, // construct, and return it. // This method is called from two places in the code: // 1) From Refresh::bindNode() with isPipelined = FALSE, for a non-pipelined // refresh job. // 2) From PipelinedMavBuilder::buildRefreshTree() with isPipelined = TRUE, // for the lowest level of a pipelined refresh job. ////////////////////////////////////////////////////////////////////////////// MvRefreshBuilder *Refresh::constructRefreshBuilder(BindWA *bindWA, MVInfoForDML *mvInfo) { CollHeap *heap = bindWA->wHeap(); CorrName mvCorrName(mvName_); mvCorrName.setSpecialType(ExtendedQualName::MV_TABLE); MvRefreshBuilder *treeBuilder = NULL; switch (refreshType_) { case RECOMPUTE: { treeBuilder = new(heap) MvRecomputeBuilder(mvCorrName, mvInfo, noDeleteOnRecompute_, bindWA); break; } case SINGLEDELTA: // Verify no Multidelta in SINGLEDELTA definition. CMPASSERT(deltaDefList_->entries() == 1); // Fall through to multidelta. case MULTIDELTA: CMPASSERT(mvInfo->getRefreshType() == COM_ON_REQUEST); switch (mvInfo->getMVType()) { case COM_MAV: case COM_MAJV: { treeBuilder = constructMavSpecifichBuilder(bindWA, mvCorrName, mvInfo); break; } case COM_MJV: { treeBuilder = constructMjvSpecifichBuilder(bindWA, mvCorrName, mvInfo); break; } default: CMPASSERT(FALSE); } break; default: // Unknown refresh type CMPASSERT(FALSE); } CMPASSERT(treeBuilder!=NULL); return treeBuilder; } // Refresh::constructRefreshBuilder()
short CmpSeabaseDDL::buildViewColInfo(StmtDDLCreateView * createViewParseNode, ElemDDLColDefArray *colDefArray) { // Builds the list of ElemDDLColDef parse nodes from the list of // NAType parse nodes derived from the query expression parse sub-tree // and the list of ElemDDLColViewDef parse nodes from the parse tree. // This extra step is needed to invoke (reuse) global func CatBuildColumnList. CMPASSERT(createViewParseNode->getQueryExpression()-> getOperatorType() EQU REL_ROOT); RelRoot * pQueryExpr = (RelRoot *)createViewParseNode->getQueryExpression(); const ValueIdList &valIdList = pQueryExpr->compExpr(); // select-list CMPASSERT(valIdList.entries() > 0); CollIndex numOfCols(createViewParseNode->getViewColDefArray().entries()); if (numOfCols NEQ valIdList.entries()) { *CmpCommon::diags() << DgSqlCode(-1108) //CAT_NUM_OF_VIEW_COLS_NOT_MATCHED << DgInt0(numOfCols) << DgInt1(valIdList.entries()); return -1; } const ElemDDLColViewDefArray &viewColDefArray = createViewParseNode-> getViewColDefArray(); for (CollIndex i = 0; i < numOfCols; i++) { // ANSI 11.19 SR8 if (viewColDefArray[i]->getColumnName().isNull()) { *CmpCommon::diags() << DgSqlCode(-1099) //CAT_VIEW_COLUMN_UNNAMED << DgInt0(i+1); return -1; } colDefArray->insert(new (STMTHEAP) ElemDDLColDef ( viewColDefArray[i]->getColumnName() , (NAType *)&valIdList[i].getType() , NULL // default value (n/a for view def) , NULL // col attr list (not needed) , STMTHEAP)); if (viewColDefArray[i]->isHeadingSpecified()) { (*colDefArray)[i]->setIsHeadingSpecified(TRUE); (*colDefArray)[i]->setHeading(viewColDefArray[i]->getHeading()); } } return 0; }
// LCOV_EXCL_START // Used for other RelExpr but not MultiJoin void MultiJoin::synthEstLogProp(const EstLogPropSharedPtr& inputEstLogProp) { CMPASSERT(inputEstLogProp->getNodeSet()); Join * preferredJoin = jbbSubset_.getPreferredJoin(); CMPASSERT(preferredJoin->isJoinFromMJSynthLogProp()); EstLogPropSharedPtr myEstLogProp = preferredJoin->getGroupAttr()->outputLogProp(inputEstLogProp); getGroupAttr()->addInputOutputLogProp (inputEstLogProp, myEstLogProp, NULL); } // MultiJoin::synthEstLogProp
// Constructor that parses a 1-, 2-, or 3-part external (Ansi) name string // and optionally applies default catalog and schema to it. // Use this on a string gotten from a trusted source (Sql Catalog), because // if it doesn't parse, the ctor cannot return an error so it CMPASSERTs. // // This code cloned for CorrName::applyPrototype below. // QualifiedName::QualifiedName(const NAString &ansiString, Int32 minNameParts, CollHeap * h, BindWA *bindWA) : SchemaName(h), objectName_(h), objectNameSpace_(COM_UNKNOWN_NAME), flagbits_(0) { if (HasMPLocPrefix(ansiString.data())) { ComMPLoc loc(ansiString); catalogName_ = loc.getSysDotVol(); schemaName_ = loc.getSubvolName(); objectName_ = loc.getFileName(); } else { CmpContext *cmpContext = bindWA ? bindWA->currentCmpContext() : NULL; Parser parser(cmpContext); NAString ns("TABLE " + ansiString + ";", CmpCommon::statementHeap()); #pragma nowarn(1506) // warning elimination // save the current parserflags setting ULng32 savedParserFlags = Get_SqlParser_Flags (0xFFFFFFFF); StmtQuery *stmt = (StmtQuery *)parser.parseDML(ns, ns.length(), GetAnsiNameCharSet()); // Restore parser flags settings Set_SqlParser_Flags (savedParserFlags); #pragma warn(1506) // warning elimination if (stmt) { CMPASSERT(stmt->getOperatorType() == STM_QUERY); *this = stmt->getQueryExpression()->getScanNode()->getTableName().getQualifiedNameObj(); delete stmt; } else { // It is possible for the parser to get errors when parsing SQL/MP // stored text. The caller is expected to check the contents of // this QualifiedName. // return; } } Int32 nameParts = 0; if (minNameParts > 0) { nameParts = getCatalogName() != "" ? 3 : getSchemaName() != "" ? 2 : getObjectName() != "" ? 1 : 0; CMPASSERT(nameParts >= minNameParts); } if (bindWA && nameParts < 3) applyDefaults(bindWA->getDefaultSchema()); } // end of QualifiedName::QualifiedName
CmpStatement::ReturnStatus CmpStatementISP::process (const CmpMessageISPGetNext& getNext) { // This routine is to process the getNext request // 1. It first allocate the output data with size specified. // 2. it then fetched the remaining data from previous ISP execution. // 3. continue open/fetch/close for ISP execution. CmpCommon::context()->sqlSession()->setParentQid(getNext.getParentQid()); CmpInternalSP& internalSP= *((CmpInternalSP*)storedProc_); CmpISPDataObject& ispData = *(CmpISPDataObject*)(internalSP.ispData()); ispData.output()->allocateData(getNext.bufSize()); NABoolean bufferFull = FALSE; short putStatus; if (ispData.output()->rowExist()) { if ( (putStatus = ispData.output()->AddARow()) == 1 ) bufferFull = TRUE; CMPASSERT(putStatus != -1); if ( !bufferFull) bufferFull = ISPFetchPut(&internalSP, &ispData); } else if (ispData.output()->EORExist()) { if ( (putStatus = ispData.output()->AddEOR()) == 1 ) bufferFull = TRUE; CMPASSERT(putStatus != -1); } // open ISP again for remaining input. short inputStatus = 0; for (; !bufferFull && (inputStatus = ispData.input()->next() ) == 0; ) { if (internalSP.open(ispData) == CmpStoredProc::SUCCESS) bufferFull = ISPFetchPut(&internalSP, &ispData); else { if ( ispData.output()->AddEOR() == 1 ) bufferFull = TRUE; } } CMPASSERT(inputStatus != -1); // fail for retrieving input data ISPPrepareReply(&ispData, reply_, bufferFull); return CmpStatement_SUCCESS; }
CmpSPExecDataItemInput::CmpSPExecDataItemInput(ULng32 exprSize, void* expr, ULng32 dataSize, void* data, CmpContext* context) : CmpSPExecDataItem(exprSize, expr, dataSize, data, context) { CMPASSERT(ExSPPrepareInputBuffer(data_) == 0); CMPASSERT(ExSPPosition(data_) == 0); currentRow_ = 0; rowLength_ = 0; control_ = 0; }
////////////////////////////////////////////////////////////////////////////// // This is the MDL version of the algorithm, used during a multi-delta refresh. // - RIs are used to determine the BEST order of the tables. // - We compute a solution from each and every table in the graph, and use // the number of usable RIs on the solution to determine which one wins. void MVJoinGraph::findBestOrder() { CMPASSERT(nofTables_>1); #ifndef NDEBUG display(); #endif // start with one group of all tables. for (Lng32 i=0; i<nofTables_; i++) reorderGroupSet_.insert(i); notStartedSet_ = reorderGroupSet_; MVJoinGraphState state(nofTables_, nofRI_, reorderGroupSet_, heap_); NABoolean done = FALSE; while (!done && notStartedSet_.entries()>0) { // Choose a table to start from Lng32 firstTable = state.pickNextTable(*this, TRUE); CMPASSERT(firstTable != -1); state.nextTableIs(firstTable, FALSE); notStartedSet_.remove(firstTable); // Find a solution from this table. if (findSolutionFrom(state)) { state.chooseBestSolution(); if (state.getBestRoute().getScore() == nofRI_) done = TRUE; // This is as good as it gets. } else { // If we get here the graph is not fully connected! CMPASSERT(FALSE); } if (!done) state.reset(reorderGroupSet_); } CMPASSERT(!state.getBestRoute().isEmpty()); // The state object will be gone when we exit this method, so save // the solution for later. theSolution_ = state.getBestRoute(); #ifndef NDEBUG theSolution_.display(); #endif }
Int32 UniqueConstraint::getRefConstraints(BindWA *bindWA, const ColSignature &updateCols, RefConstraintList &resultList) { if (!constraintOverlapsUpdateCols(bindWA, updateCols)) return 0; CollIndex constraintCnt = refConstraintsReferencingMe_.entries(); // Loop over FKs referencing this UC. // Find one FK // Tell it that it is the "other table" relative to me // Set the FK's UC's column list pointer to my list of cols // Append the FK to the result list for (CollIndex i = 0; i < constraintCnt; i++) { RefConstraint *rc = (RefConstraint *)findConstraint(bindWA, *refConstraintsReferencingMe_[i]); if (!rc) return 0; // If Binder fails because of preivilege error, QI logic removes // NATable marked for deletion and retries the same query. If the deleted // NATable (T1) had RefConstraint on other table T2, then T2's NATable // RefConstraint contains the address of T1 UniqueConstraint keyColumn_. // Since T1 has been removed from the cache, T2's // RefConstraint->uniqueConstraintReferencedByMe_.keyColumns_ could contain // invalid address. If this situation occurs, keyColumns_ will be reset // instead of asserting. if ( bindWA->shouldLogAccessViolations() ) rc->uniqueConstraintReferencedByMe_.resetAfterStatement(); rc->setOtherTableName(); CMPASSERT((rc->getOtherTableName() == rc->getDefiningTableName()) || (rc->getOtherTableName() == getDefiningTableName())); if (!rc->uniqueConstraintReferencedByMe_.keyColumns_) rc->uniqueConstraintReferencedByMe_.keyColumns_ = &keyColumns(); // assignment else { CMPASSERT(rc->uniqueConstraintReferencedByMe_.keyColumns_ == &keyColumns()); // equality operator } resultList.insert(rc); } return (Int32)constraintCnt; } // UniqueConstraint::getRefConstraints
CharInfo::Collation CollationDB::insert(QualifiedName &qn, const SchemaName *defaultSchema, CollationInfo::CollationFlags flags) { Int32 defaultMatchCount = 0; if (defaultSchema) defaultMatchCount = qn.applyDefaults(*defaultSchema); CMPASSERT(!qn.getCatalogName().isNull()); // fully qualified w/ all defaults size_t siz[CollationInfo::SIZEARRAY_SIZE]; NAString nam(qn.getQualifiedNameAsAnsiString(siz)); CMPASSERT(siz[0] == 3); // fully qualified w/ all defaults return insert(nam, siz, flags, defaultMatchCount); }
CostScalar IndexDesc::getEstimatedRecordsPerBlock() const { // We don't have "spanning rows" so the fractional part // is "garbage" and wasted space, therefore // we take the floor of the following measure since // a fractional "rows per block" does not make sense: const CostScalar blockSize = getNAFileSet()->getBlockSize(); const CostScalar recordLength = getNAFileSet()->getRecordLength(); const CostScalar recordsPerBlock = (blockSize / recordLength).getFloor(); if ((CmpCommon::getDefault(MODE_SEABASE) != DF_ON) || (NOT getPrimaryTableDesc()->getNATable()->isHbaseTable())) { // A row can never be larger than a block: CMPASSERT( recordsPerBlock > csZero ); } else { // For an hbase table, there is no concept of a SQ like blocksize and // the record size can be very large. // For now, make recordsPerBlock as 1 if it becomes 0 or less. // TBD TBD if (recordsPerBlock <= csZero) return (CostScalar)1; } return recordsPerBlock; }
UInt32 ValidateCollationList::insertIntoCDB(SchemaDB *sdb, CollationDB *cdb, const char *value, NABoolean nsk) { NABoolean savformatNSK = formatNSK_; formatNSK_ = nsk; lastCoInserted_ = CharInfo::UNKNOWN_COLLATION; cntCoParsed_ = 0; CMPASSERT(!cdb_ && !sdb_); // our kludgy/dodgy passing mechanism... cdb_ = cdb; sdb_ = sdb; validate(value, NULL, 0, 0/*silent*/); cdb_ = NULL; sdb_ = NULL; formatNSK_ = savformatNSK; #ifndef NDEBUG if (getenv("NCHAR_DEBUG")) CollationDB::Display(); #endif return cntCoParsed_; }
short CmpSPExecDataItemInput::next() { short status = 0; status = ExSPGetInputRow(data_, control_, currentRow_, rowLength_); CMPASSERT(status != -1); return status; }
CharInfo::Collation CollationDB::insert(ComMPLoc &loc, const ComMPLoc *defaultMPLoc, CollationInfo::CollationFlags flags) { Int32 defaultMatchCount = 0; if (defaultMPLoc) defaultMatchCount = loc.applyDefaults(*defaultMPLoc); CMPASSERT(loc.isValid(ComMPLoc::FILE)); size_t siz[CollationInfo::SIZEARRAY_SIZE]; NAString nam(loc.getMPName(siz)); CMPASSERT(siz[0] == 3 || siz[0] == 4); // was defaulted out to $vol or \sys return insert(nam, siz, flags, defaultMatchCount); }
/************************************************************************ method CompilerTrackingInfo::hCacheLookups The current histogram cache lookups counter is calculated by subtracting the total from the last time we marked an interval (see CompilerTrackingInfo::resetInterval and resetMetadataCacheCounters for interval marking) ************************************************************************/ inline ULng32 CompilerTrackingInfo::hCacheLookups() { CMPASSERT(NULL!=CURRCONTEXT_HISTCACHE); return CURRCONTEXT_HISTCACHE->lookups() - hCacheLookups_; }
//CmpStoredProc::Status CmpInternalSP::open(CmpISPDataObject& data) CmpStoredProc::ExecStatus CmpInternalSP::open(CmpISPDataObject& data) { CMPASSERT(state_ == NONE); procFuncs_ = procFuncsLookupTable_[procName()]; if (!procFuncsLookupTable_.ValidPFuncs(procFuncs_)) { *(cmpContext()->diags()) << DgSqlCode(arkcmpErrorISPNotFound) << DgString0(procName().data()); return FAIL; } initSP_ERROR_STRUCT(); SP_STATUS spStatus = (*(procFuncs_.procFunc_))( SP_PROC_OPEN, (SP_ROW_DATA)data.input(), CmpSPExtractFunc, (SP_ROW_DATA)data.output(), CmpSPFormatFunc, (SP_KEY_VALUE)data.key(), CmpSPKeyValueFunc, &procHandle_, procFuncs_.spHandle_, &spError_[0]); if (spStatus == SP_FAIL || spStatus == SP_SUCCESS_WARNING) { // Errors or warnings, go get them data.output()->MoveDiags(spError_, spStatus); if (spStatus == SP_FAIL) return FAIL; } state_ = PROCESS; return SUCCESS; }
NABoolean HHDFSTableStats::connectHDFS(const NAString &host, Int32 port) { NABoolean result = TRUE; // establish connection to HDFS if needed if (fs_ == NULL || currHdfsHost_ != host || currHdfsPort_ != port) { if (fs_) { hdfsDisconnect(fs_); fs_ = NULL; } fs_ = hdfsConnect(host, port); if (fs_ == NULL) { CMPASSERT(fs_); // TBD:DIAGS result = FALSE; } currHdfsHost_ = host; currHdfsPort_ = port; } return result; }
MultiJoin::MultiJoin(const JBBSubset & jbbSubset, CollHeap *oHeap) : RelExpr(REL_MULTI_JOIN, NULL, NULL, oHeap) , jbbSubset_(jbbSubset) , childrenMap_(oHeap) , scheduledLSRs_(oHeap) { // Need to initialize the childrenMap // This will set all children to NULL CANodeIdSet jbbcs = jbbSubset_.getJBBCs(); Lng32 index = 0; for (CANodeId x= jbbcs.init(); jbbcs.next(x); jbbcs.advance(x) ) { JBBCExprGroupEntry* entry = new (oHeap) JBBCExprGroupEntry(x, (RelExpr*)NULL, oHeap); childrenMap_.insertAt(index, entry); index++; } lsrC_ = new (oHeap) LSRConfidence(oHeap); #pragma warning (disable : 4018) //warning elimination CMPASSERT (getArity() == jbbcs.entries()); #pragma warning (default : 4018) //warning elimination }
void PhysSequence::transformOlapFunctions(CollHeap *wHeap) { for(ValueId valId = sequenceFunctions().init(); sequenceFunctions().next(valId); sequenceFunctions().advance(valId)) { ItemExpr * itmExpr = valId.getItemExpr(); //NAType *itmType = itmExpr->getValueId().getType().newCopy(wHeap); if (itmExpr->isOlapFunction()) { NAType *itmType = itmExpr->getValueId().getType().newCopy(wHeap); itmExpr = ((ItmSeqOlapFunction*)itmExpr)->transformOlapFunction(wHeap); CMPASSERT(itmExpr); if(itmExpr->getValueId() != valId) { itmExpr = new (wHeap) Cast(itmExpr, itmType); itmExpr->synthTypeAndValueId(TRUE); valId.replaceItemExpr(itmExpr); itmExpr->getValueId().changeType(itmType);//???? } } itmExpr->transformOlapFunctions(wHeap); } }
// First, always calls applyPrototype -- so may fill in one or more of // this's name parts -- hence this method is not const. // // Second, delegates to QualifiedName::extractAndDefaultNameParts // to fill in the return name parts -- // *EXCEPT* in the case that this CorrName contains a correlation name, // masking a qualified name like "c.s.t", -- then we always return 0 // and the name parts are *not* filled in with defaults (they're meaningless). // Int32 CorrName::extractAndDefaultNameParts(BindWA *bindWA, const SchemaName& defCatSch, NAString& catName, // OUT NAString& schName, // OUT NAString& objName) // OUT { // For performance, avoid redoing work if we've done it before if (defaultMatchCount_ < 0) { // initially -1 applyPrototype(bindWA); // if (!nodeIsBound()) return -1; // caller will check bindWA-errStatus() if (getCorrNameAsString() == "") { // CorrName is "qual", not "corr" CMPASSERT(NOT isFabricated()); // only corr names can be fabricated defaultMatchCount_ = getQualifiedNameObj().applyDefaults(defCatSch); // override schema, if default schema is "from" schema // increase count so columns like t.a will be valid if ( bindWA->overrideSchemaEnabled() && (bindWA->getOsFromSchema() == defCatSch.getSchemaName()) && (bindWA->getOsToSchema() == getQualifiedNameObj().getSchemaName()) ) defaultMatchCount_++; } else defaultMatchCount_ = 0; // "corr" masks "qual", always return 0 } catName = getQualifiedNameObj().getCatalogName(); // OUT schName = getQualifiedNameObj().getSchemaName(); // OUT objName = getQualifiedNameObj().getObjectName(); // OUT return defaultMatchCount_; }
// // --TriggerDB::getValidEntry // // return the BeforeAndAfterTriggers (ptr) given the key. // NULL is returned if no entry was found. In case of working across statements // (Trigger::heap() == CmpCommon::contextHeap()) then this method // VALIDATES (timestamp check) the return value before returning. // Note: a non-valid entry is first removed from the DB and a NULL is returned. // BeforeAndAfterTriggers* TriggerDB::getValidEntry(const TableOp * key, BindWA * bindWA) { BeforeAndAfterTriggers* result = NAHashDictionary<TableOp, BeforeAndAfterTriggers>::getFirstValue(key); if ((result != NULL) && (Trigger::Heap() == CmpCommon::contextHeap())) { // only used when triggers are allocated from the cntext heap. // Currently triggers are allocated from the statement heap. // See method Trigger::Heap() in file Triggers.h for more details // LCOV_EXCL_START // entry exist in TriggerDB and we work ACROSS statements => // validate the entry: compare the entry's subject table timestamp // against the actual subject table's timestamp // convert to ExtendedQualName ExtendedQualName exSubjectTable = ExtendedQualName(key->subjectTable_, CmpCommon::statementHeap()); // fetch the subject table from the NATableDB NATable *subjectTable = bindWA->getSchemaDB()->getNATableDB()->get(&exSubjectTable); // the subject table MUST appear in the TableTB because it must have // been fetched earlier by the binder (also in the case of cascaded // triggers) CMPASSERT(subjectTable != NULL); ComTimestamp trigsTS = result->getSubjectTableTimeStamp(); CMPASSERT(trigsTS != 0); // must have been initialized by the catman if (subjectTable->getRedefTime() != trigsTS) { // no match => invalidate this->remove((TableOp*) key); result->clearAndDestroy(); delete result; // destroy the entry return NULL; } // LCOV_EXCL_STOP } // end of validation // at this point, if result != NULL, then it is valid. Otherwise it is // not in the TriggerDB return result; }
const NAString SchemaName::getSchemaNameAsAnsiString() const { QualifiedName q("X", getSchemaName(), getCatalogName()); NAString result(q.getQualifiedNameAsAnsiString(), CmpCommon::statementHeap()); CMPASSERT(result[result.length()-1] == 'X'); result.remove(result.length()-2); // remove the '.X' return result; }
RelExpr *Refresh::buildCompleteRefreshTree(BindWA *bindWA, MVInfoForDML *mvInfo) { CollHeap *heap = bindWA->wHeap(); MvRefreshBuilder *firstBuilder = constructRefreshBuilder(bindWA, mvInfo); if (bindWA->errStatus()) return NULL; RelExpr *topTree = firstBuilder->buildRefreshTree(); // For recompute the refresh tree does not scan the log. // For MJV, it sometimes does, and when it does, it handles it itself. // So, for these types, the refresh tree is ready. if (refreshType_ == RECOMPUTE || mvInfo->getMVType() == COM_MJV) { delete firstBuilder; return topTree; } MvBindContext *bindContext = new(heap) MvBindContext(heap); bindContext->setRefreshBuilder(firstBuilder); // In multi-delta, this is done inside the refresh tree. if (refreshType_ == SINGLEDELTA) { CMPASSERT(deltaDefList_->entries() == 1); DeltaDefinition *deltaDef = deltaDefList_->at(0); const QualifiedName *baseTableName = deltaDef->getTableName(); RelExpr *scanLogBlock = firstBuilder->buildLogsScanningBlock(*baseTableName); if (bindWA->errStatus() || scanLogBlock == NULL) return NULL; bindContext->setReplacementFor(baseTableName, scanLogBlock); } if (pipelineClause_ != NULL) topTree = constructPipelinedBuilders(bindWA, bindContext, topTree); if (topTree == NULL) return NULL; // Make sure no data is projected out. RelRoot *rootNode = new(heap) RelRoot(topTree); #ifndef NDEBUG if (!getenv("DEBUG_DCB")) #endif rootNode->setEmptySelectList(); rootNode->setMvBindContext(bindContext); RelExpr *topNode = rootNode; // Save the bind context for cleanup. bindContext_ = bindContext; return topNode; } // Refresh::buildCompleteRefreshTree()