Join* MultiJoin::createLeftLinearJoinTree (const NAList<CANodeIdSet> * const leftDeepJoinSequence, NAList<MJJoinDirective *> * joinDirectives) const { Join* result = NULL; Join* currentJoin=NULL; NABoolean reUseMultiJoins = FALSE; //Set of all JBBCs in this multi-join. //This set will be broken up to make the join tree //representing the substitue. //The loop below will construct the join tree, //starting from the top join. CANodeIdSet childSet = getJBBSubset().getJBBCs(); // variables used in loop below MultiJoin * currentMJoin = (MultiJoin *) this; // in an iteration this is the parent join // e.g. when we are create JOIN3, this will // be JOIN2 Join * parentJoin = NULL; #ifdef _DEBUG if ( CmpCommon::getDefault( NSK_DBG ) == DF_ON && CmpCommon::getDefault( NSK_DBG_MJRULES_TRACKING ) == DF_ON ) { // LCOV_EXCL_START - dpm CURRCONTEXT_OPTDEBUG->stream() << "Following is left deep join sequence: " << endl; CURRCONTEXT_OPTDEBUG->stream() << endl; // LCOV_EXCL_STOP } #endif UInt32 numJoinChildren = leftDeepJoinSequence->entries(); CANodeId currentTable = NULL_CA_ID; for (UInt32 i = 0; i < (numJoinChildren-1); i++) { //create JBBSubset representing a comprising component of the //leftDeepJoinSequence. JBBSubset * joinRightChild = ((*leftDeepJoinSequence)[i]).computeJBBSubset(); MJJoinDirective * joinDirective = (*joinDirectives)[i]; //remove all tables that will become right side of join childSet.remove((*leftDeepJoinSequence)[i]); #ifdef _DEBUG //print the right child of the current join if ( CmpCommon::getDefault( NSK_DBG ) == DF_ON && CmpCommon::getDefault( NSK_DBG_MJRULES_TRACKING ) == DF_ON ) { CURRCONTEXT_OPTDEBUG->stream() << ((*leftDeepJoinSequence)[i]).getText() << endl; // LCOV_EXCL_LINE - dpm } #endif //Get JBBSubset for left side of join JBBSubset * joinLeftChild = childSet.computeJBBSubset(); //create the join by doing a split of the multi-join currentJoin = currentMJoin->splitSubset(*joinLeftChild, *joinRightChild, reUseMultiJoins); joinDirective->setupJoin(currentJoin); if ( CmpCommon::getDefault(COMP_BOOL_120) == DF_OFF) currentJoin->updatePotential(-3); // if this is the first iteration // set the result to be the top join if (i == 0) result = currentJoin; //set the current multi-join to the left child of the //join just created //change getChild to child().getPointer currentMJoin = (MultiJoin*) currentJoin->getChild(0); //if there was a parent join, set the left child to //point to the new join we just created i.e. currentJoin. if (parentJoin) parentJoin->setChild(0,currentJoin); //set currentJoin to be the parent for the next iteration parentJoin = currentJoin; } #ifdef _DEBUG //print the left most child if ( CmpCommon::getDefault( NSK_DBG ) == DF_ON && CmpCommon::getDefault( NSK_DBG_MJRULES_TRACKING ) == DF_ON ) { // LCOV_EXCL_START - dpm CURRCONTEXT_OPTDEBUG->stream() << ((*leftDeepJoinSequence)[(numJoinChildren-1)]).getText() << endl; CURRCONTEXT_OPTDEBUG->stream() << endl; // LCOV_EXCL_STOP } #endif // end - construct the join tree // synth the join result->synthLogProp(); //if the right child of the top-most join is a multi-Join, //synthesize_it if(result->child(1)) if(result->child(1)->getOperatorType()==REL_MULTI_JOIN) result->child(1)->synthLogProp(); // synth the left child too result->child(0)->synthLogProp(); return result; } // MultiJoin::createLeftLinearJoinTree()
// LCOV_EXCL_START :cnu EstLogPropSharedPtr AppliedStatMan::joinEstLogProps ( const EstLogPropSharedPtr& leftEstLogProp, const EstLogPropSharedPtr& rightEstLogProp, const EstLogPropSharedPtr& inLP) { EstLogPropSharedPtr outputEstLogProp; NABoolean cacheable = FALSE; CANodeIdSet * inputNodeSet = inLP->getNodeSet(); // These nodesets could be NULL, if the estLogProps to which they // belong are not cacheable CANodeIdSet * leftNodeSet = leftEstLogProp->getNodeSet(); CANodeIdSet * rightNodeSet = rightEstLogProp->getNodeSet(); if ((leftEstLogProp->isCacheable()) && (rightEstLogProp->isCacheable()) && (inLP->isCacheable()) ) { CCMPASSERT(leftNodeSet != NULL); CCMPASSERT(rightNodeSet != NULL); CCMPASSERT(inputNodeSet != NULL); if (leftNodeSet && rightNodeSet && inputNodeSet) { cacheable = TRUE; } } if (cacheable) { // check the ASM cache to see if outputEstLogProp for these // NodeSets appear for the given inputEstLogProp CANodeIdSet combineNodeSet = *leftNodeSet; combineNodeSet.insert(*rightNodeSet); CANodeIdSet combinedWithInputNodeSet = combineNodeSet; combinedWithInputNodeSet.insert(*inputNodeSet); outputEstLogProp = getCachedStatistics(&combinedWithInputNodeSet); if (outputEstLogProp != NULL) return outputEstLogProp; } JBBSubset * newJBBSubset = NULL; ValueIdSet setOfPredicates; if (leftNodeSet && rightNodeSet) { // join predicates can be obtained from EstLogProp, only // if these corresponded to complete set of predicates - // all local or complete join. Also, we need a // combinedJBBSubset to set in the fake join expression // that we will be creating. newJBBSubset = leftNodeSet->computeJBBSubset(); JBBSubset rightJBBSubset = *(rightNodeSet->computeJBBSubset()); setOfPredicates = newJBBSubset->joinPredsWithOther(rightJBBSubset); // Since the properties from this group are cacheable, hence the // group attributes for the new join expression should contain // the combined JBBsubset of the left and the right children newJBBSubset->addSubset(rightJBBSubset); } // inputEstLogProp would be either empty input estLogProp or from the // outer child. If cacheable is TRUE, then newJBBsubset should // contain the combined left and the right JBB subset. But if // cacheable is FALSE, newJBBsubset should be NULL Join * joinExpr = formJoinExprWithEstLogProps( leftEstLogProp, rightEstLogProp, inLP, &setOfPredicates, cacheable, newJBBSubset); // Now do the actual synthesis and cache statistics in the cache outputEstLogProp = joinExpr->getGroupAttr()->outputLogProp(inLP); return outputEstLogProp; }