//--------------------------------------------------------------------------- // @function: // CPartInfo::CPartInfoEntry::PpartinfoentryAddRemappedKeys // // @doc: // Create a copy of the current object, and add a set of remapped // part keys to this entry, using the existing keys and the given hashmap // //--------------------------------------------------------------------------- CPartInfo::CPartInfoEntry * CPartInfo::CPartInfoEntry::PpartinfoentryAddRemappedKeys ( IMemoryPool *pmp, CColRefSet *pcrs, HMUlCr *phmulcr ) { GPOS_ASSERT(NULL != pcrs); GPOS_ASSERT(NULL != phmulcr); DrgPpartkeys *pdrgppartkeys = CPartKeys::PdrgppartkeysCopy(pmp, m_pdrgppartkeys); const ULONG ulSize = m_pdrgppartkeys->UlLength(); for (ULONG ul = 0; ul < ulSize; ul++) { CPartKeys *ppartkeys = (*m_pdrgppartkeys)[ul]; if (ppartkeys->FOverlap(pcrs)) { pdrgppartkeys->Append(ppartkeys->PpartkeysRemap(pmp, phmulcr)); break; } } m_pmdid->AddRef(); CPartConstraint *ppartcnstrRel = m_ppartcnstrRel->PpartcnstrCopyWithRemappedColumns(pmp, phmulcr, false /*fMustExist*/); return GPOS_NEW(pmp) CPartInfoEntry(m_ulScanId, m_pmdid, pdrgppartkeys, ppartcnstrRel); }
//--------------------------------------------------------------------------- // @function: // CPhysicalJoin::PexprJoinPredOnPartKeys // // @doc: // Helper to find join predicates on part keys. Returns NULL if not found // //--------------------------------------------------------------------------- CExpression * CPhysicalJoin::PexprJoinPredOnPartKeys ( IMemoryPool *pmp, CExpression *pexprScalar, CPartIndexMap *ppimSource, ULONG ulPartIndexId, CColRefSet *pcrsAllowedRefs ) { GPOS_ASSERT(NULL != pcrsAllowedRefs); CExpression *pexprPred = NULL; DrgPpartkeys *pdrgppartkeys = ppimSource->Pdrgppartkeys(ulPartIndexId); const ULONG ulKeysets = pdrgppartkeys->UlLength(); for (ULONG ulKey = 0; NULL == pexprPred && ulKey < ulKeysets; ulKey++) { // get partition key DrgDrgPcr *pdrgpdrgpcrPartKeys = (*pdrgppartkeys)[ulKey]->Pdrgpdrgpcr(); // try to generate a request with dynamic partition selection pexprPred = CPredicateUtils::PexprExtractPredicatesOnPartKeys ( pmp, pexprScalar, pdrgpdrgpcrPartKeys, pcrsAllowedRefs, true // fUseConstraints ); } return pexprPred; }
//--------------------------------------------------------------------------- // @function: // CPartInfo::OsPrint // // @doc: // Debug print // //--------------------------------------------------------------------------- IOstream & CPartInfo::OsPrint ( IOstream &os ) const { const ULONG ulLength = m_pdrgppartentries->UlLength(); os << "Part Consumers: "; for (ULONG ul = 0; ul < ulLength; ul++) { CPartInfoEntry *ppartinfoentry = (*m_pdrgppartentries)[ul]; ppartinfoentry->OsPrint(os); // separator os << (ul == ulLength - 1 ? "" : ", "); } os << ", Part Keys: "; for (ULONG ulCons = 0; ulCons < ulLength; ulCons++) { DrgPpartkeys *pdrgppartkeys = Pdrgppartkeys(ulCons); os << "("; const ULONG ulPartKeys = pdrgppartkeys->UlLength();; for (ULONG ulPartKey = 0; ulPartKey < ulPartKeys; ulPartKey++) { os << *(*pdrgppartkeys)[ulPartKey]; os << (ulPartKey == ulPartKeys - 1 ? "" : ", "); } os << ")"; os << (ulCons == ulLength - 1 ? "" : ", "); } return os; }
//--------------------------------------------------------------------------- // @function: // CPhysicalScan::PpimDeriveFromDynamicScan // // @doc: // Derive partition index map from a dynamic scan operator // //--------------------------------------------------------------------------- CPartIndexMap * CPhysicalScan::PpimDeriveFromDynamicScan ( IMemoryPool *pmp, ULONG ulPartIndexId, IMDId *pmdidRel, DrgDrgPcr *pdrgpdrgpcrPart, ULONG ulSecondaryPartIndexId, CPartConstraint *ppartcnstr, CPartConstraint *ppartcnstrRel, ULONG ulExpectedPropagators ) { CPartIndexMap *ppim = GPOS_NEW(pmp) CPartIndexMap(pmp); PartCnstrMap *ppartcnstrmap = GPOS_NEW(pmp) PartCnstrMap(pmp); (void) ppartcnstrmap->FInsert(GPOS_NEW(pmp) ULONG(ulSecondaryPartIndexId), ppartcnstr); DrgPpartkeys *pdrgppartkeys = GPOS_NEW(pmp) DrgPpartkeys(pmp); pdrgppartkeys->Append(GPOS_NEW(pmp) CPartKeys(pdrgpdrgpcrPart)); ppim->Insert(ulPartIndexId, ppartcnstrmap, CPartIndexMap::EpimConsumer, ulExpectedPropagators, pmdidRel, pdrgppartkeys, ppartcnstrRel); return ppim; }
//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelector::PpimDerive // // @doc: // Derive partition index map // //--------------------------------------------------------------------------- CPartIndexMap * CPhysicalPartitionSelector::PpimDerive ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CDrvdPropCtxt *pdpctxt ) const { GPOS_ASSERT(NULL != pdpctxt); CDrvdPropPlan *pdpplan = exprhdl.Pdpplan(0 /*ulChildIndex*/); CPartIndexMap *ppimInput = pdpplan->Ppim(); GPOS_ASSERT(NULL != ppimInput); ULONG ulExpectedPartitionSelectors = CDrvdPropCtxtPlan::PdpctxtplanConvert(pdpctxt)->UlExpectedPartitionSelectors(); CPartIndexMap *ppim = ppimInput->PpimPartitionSelector(pmp, m_ulScanId, ulExpectedPartitionSelectors); if (!ppim->FContains(m_ulScanId)) { // the consumer of this scan id does not come from the child, i.e. it // is on the other side of a join Pmdid()->AddRef(); m_pdrgpdrgpcr->AddRef(); m_ppartcnstrmap->AddRef(); m_ppartcnstr->AddRef(); DrgPpartkeys *pdrgppartkeys = GPOS_NEW(pmp) DrgPpartkeys(pmp); pdrgppartkeys->Append(GPOS_NEW(pmp) CPartKeys(m_pdrgpdrgpcr)); ppim->Insert(m_ulScanId, m_ppartcnstrmap, CPartIndexMap::EpimPropagator, 0 /*ulExpectedPropagators*/, Pmdid(), pdrgppartkeys, m_ppartcnstr); } return ppim; }
//--------------------------------------------------------------------------- // @function: // CLogicalSelect::PexprPartPred // // @doc: // Compute partition predicate to pass down to n-th child // //--------------------------------------------------------------------------- CExpression * CLogicalSelect::PexprPartPred ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CExpression *, //pexprInput ULONG #ifdef GPOS_DEBUG ulChildIndex #endif //GPOS_DEBUG ) const { GPOS_ASSERT(0 == ulChildIndex); // in case of subquery in select predicate, we cannot extract the whole // predicate, and it would not be helpful anyway, so return NULL if (exprhdl.Pdpscalar(1 /*ulChildIndex*/)->FHasSubquery()) { return NULL; } CExpression *pexprScalar = exprhdl.PexprScalarChild(1 /*ulChildIndex*/); GPOS_ASSERT(NULL != pexprScalar); // get partition keys CPartInfo *ppartinfo = exprhdl.Pdprel()->Ppartinfo(); GPOS_ASSERT(NULL != ppartinfo); // we assume that the select is right on top of the dynamic get, so there // should be only one part consumer. If there is more, then we are higher up so // we do not push down any predicates if (1 != ppartinfo->UlConsumers()) { return NULL; } CExpression *pexprPredOnPartKey = NULL; DrgPpartkeys *pdrgppartkeys = ppartinfo->Pdrgppartkeys(0 /*ulPos*/); const ULONG ulKeySets = pdrgppartkeys->UlLength(); for (ULONG ul = 0; NULL == pexprPredOnPartKey && ul < ulKeySets; ul++) { pexprPredOnPartKey = CPredicateUtils::PexprExtractPredicatesOnPartKeys ( pmp, pexprScalar, (*pdrgppartkeys)[ul]->Pdrgpdrgpcr(), NULL, //pcrsAllowedRefs true //fUseConstraints ); } return pexprPredOnPartKey; }
//--------------------------------------------------------------------------- // @function: // CPartIndexMap::AddUnresolved // // @doc: // Helper to add part-index id's found in the first map and are // unresolved based on the second map // // For example, if the first and second map contain the following entries: // pimFst: // (partindexid: 1, consumer, part cnstr: 5->[1,3)), // (partindexid: 2, consumer, part cnstr: <>), // pimSnd: // (partindexid: 1, consumer, part cnstr: 6->(4,5))), // (partindexid: 2, producer, part cnstr: <>), // (partindexid: 3, producer, part cnstr: <>) // the result will be: // (partindexid: 1, consumer, part cnstr: 5->[1,3), 6->(4,5)), // part constraint get combined // (partindexid: 2, resolver, part cnstr: <>), // consumer+producer=resolver // (partindexid: 3, producer, part cnstr: <>) // no match for part index id 3: copy out // //--------------------------------------------------------------------------- void CPartIndexMap::AddUnresolved ( IMemoryPool *pmp, const CPartIndexMap &pimFst, const CPartIndexMap &pimSnd, CPartIndexMap* ppimResult ) { // iterate on first map and lookup entries in second map PartIndexMapIter pimiFst(pimFst.m_pim); while (pimiFst.FAdvance()) { const CPartTableInfo *pptiFst = pimiFst.Pt(); ULONG ulScanId = pptiFst->UlScanId(); EPartIndexManipulator epimFst = pptiFst->Epim(); ULONG ulPropagatorsFst = pptiFst->UlExpectedPropagators(); if (NULL != ppimResult->PptiLookup(ulScanId)) { // skip entries already in the result map continue; } // check if entry exists in second map CPartTableInfo *pptiSnd = pimSnd.PptiLookup(ulScanId); EPartIndexManipulator epimResult = epimFst; ULONG ulPropagatorsResult = ulPropagatorsFst; PartCnstrMap *ppartcnstrmapSnd = NULL; if (NULL != pptiSnd) { EPartIndexManipulator epimSnd = pptiSnd->Epim(); ULONG ulPropagatorsSnd = pptiSnd->UlExpectedPropagators(); GPOS_ASSERT_IMP(epimFst == EpimConsumer && epimSnd == EpimConsumer, ulPropagatorsFst == ulPropagatorsSnd); ResolvePropagator(epimFst, ulPropagatorsFst, epimSnd, ulPropagatorsSnd, &epimResult, &ulPropagatorsResult); ppartcnstrmapSnd = pptiSnd->Ppartcnstrmap(); } // copy mdid and partition columns from part index map entry IMDId *pmdid = pptiFst->Pmdid(); DrgPpartkeys *pdrgppartkeys = pptiFst->Pdrgppartkeys(); CPartConstraint *ppartcnstrRel = pptiFst->PpartcnstrRel(); PartCnstrMap *ppartcnstrmap = CPartConstraint::PpartcnstrmapCombine(pmp, pptiFst->Ppartcnstrmap(), ppartcnstrmapSnd); pmdid->AddRef(); pdrgppartkeys->AddRef(); ppartcnstrRel->AddRef(); ppimResult->Insert(ulScanId, ppartcnstrmap, epimResult, ulPropagatorsResult, pmdid, pdrgppartkeys, ppartcnstrRel); } }
//--------------------------------------------------------------------------- // @function: // CPartInfo::AddPartConsumer // // @doc: // Add part table consumer // //--------------------------------------------------------------------------- void CPartInfo::AddPartConsumer ( IMemoryPool *pmp, ULONG ulScanId, IMDId *pmdid, DrgDrgPcr *pdrgpdrgpcrPart, CPartConstraint *ppartcnstrRel ) { DrgPpartkeys *pdrgppartkeys = GPOS_NEW(pmp) DrgPpartkeys(pmp); pdrgppartkeys->Append(GPOS_NEW(pmp) CPartKeys(pdrgpdrgpcrPart)); m_pdrgppartentries->Append(GPOS_NEW(pmp) CPartInfoEntry(ulScanId, pmdid, pdrgppartkeys, ppartcnstrRel)); }
//--------------------------------------------------------------------------- // @function: // CPartIndexMap::PpimPartitionSelector // // @doc: // Return a new part index map for a partition selector with the given // scan id, and the given number of expected selectors above it // //--------------------------------------------------------------------------- CPartIndexMap * CPartIndexMap::PpimPartitionSelector ( IMemoryPool *pmp, ULONG ulScanId, ULONG ulExpectedFromReq ) const { CPartIndexMap *ppimResult = GPOS_NEW(pmp) CPartIndexMap(pmp); PartIndexMapIter pimi(m_pim); while (pimi.FAdvance()) { const CPartTableInfo *ppti = pimi.Pt(); PartCnstrMap *ppartcnstrmap = ppti->Ppartcnstrmap(); IMDId *pmdid = ppti->Pmdid(); DrgPpartkeys *pdrgppartkeys = ppti->Pdrgppartkeys(); CPartConstraint *ppartcnstrRel = ppti->PpartcnstrRel(); ppartcnstrmap->AddRef(); pmdid->AddRef(); pdrgppartkeys->AddRef(); ppartcnstrRel->AddRef(); EPartIndexManipulator epim = ppti->Epim(); ULONG ulExpectedPropagators = ppti->UlExpectedPropagators(); if (ppti->UlScanId() == ulScanId) { if (0 == ulExpectedFromReq) { // this are no other expected partition selectors // so this scan id is resolved epim = EpimResolver; ulExpectedPropagators = 0; } else { // this is not resolved yet epim = EpimConsumer; ulExpectedPropagators = ulExpectedFromReq; } } ppimResult->Insert(ppti->UlScanId(), ppartcnstrmap, epim, ulExpectedPropagators, pmdid, pdrgppartkeys, ppartcnstrRel); } return ppimResult; }
//--------------------------------------------------------------------------- // @function: // CPartKeys::PdrgppartkeysCopy // // @doc: // Copy array of part keys into given memory pool // //--------------------------------------------------------------------------- DrgPpartkeys * CPartKeys::PdrgppartkeysCopy ( IMemoryPool *pmp, const DrgPpartkeys *pdrgppartkeys ) { GPOS_ASSERT(NULL != pdrgppartkeys); DrgPpartkeys *pdrgppartkeysCopy = GPOS_NEW(pmp) DrgPpartkeys(pmp); const ULONG ulLength = pdrgppartkeys->UlLength(); for (ULONG ul = 0; ul < ulLength; ul++) { pdrgppartkeysCopy->Append((*pdrgppartkeys)[ul]->PpartkeysCopy(pmp)); } return pdrgppartkeysCopy; }
//--------------------------------------------------------------------------- // @function: // CPartInfo::PpartinfoCombine // // @doc: // Combine two part info objects // //--------------------------------------------------------------------------- CPartInfo * CPartInfo::PpartinfoCombine ( IMemoryPool *pmp, CPartInfo *ppartinfoFst, CPartInfo *ppartinfoSnd ) { GPOS_ASSERT(NULL != ppartinfoFst); GPOS_ASSERT(NULL != ppartinfoSnd); DrgPpartentries *pdrgppartentries = GPOS_NEW(pmp) DrgPpartentries(pmp); // copy part entries from first part info object CUtils::AddRefAppend(pdrgppartentries, ppartinfoFst->m_pdrgppartentries); // copy part entries from second part info object, except those which already exist const ULONG ulLen = ppartinfoSnd->m_pdrgppartentries->UlLength(); for (ULONG ul = 0; ul < ulLen; ul++) { CPartInfoEntry *ppartinfoentry = (*(ppartinfoSnd->m_pdrgppartentries))[ul]; DrgPpartkeys *pdrgppartkeys = ppartinfoFst->PdrgppartkeysByScanId(ppartinfoentry->UlScanId()); if (NULL != pdrgppartkeys) { // there is already an entry with the same scan id; need to add to it // the keys from the current entry DrgPpartkeys *pdrgppartkeysCopy = CPartKeys::PdrgppartkeysCopy(pmp, ppartinfoentry->Pdrgppartkeys()); CUtils::AddRefAppend(pdrgppartkeys, pdrgppartkeysCopy); pdrgppartkeysCopy->Release(); } else { CPartInfoEntry *ppartinfoentryCopy = ppartinfoentry->PpartinfoentryCopy(pmp); pdrgppartentries->Append(ppartinfoentryCopy); } } return GPOS_NEW(pmp) CPartInfo(pdrgppartentries); }
//--------------------------------------------------------------------------- // @function: // CPartitionPropagationSpec::FRequiresPartitionPropagation // // @doc: // Check if given part index id needs to be enforced on top of the given // expression // //--------------------------------------------------------------------------- BOOL CPartitionPropagationSpec::FRequiresPartitionPropagation ( IMemoryPool *pmp, CExpression *pexpr, CExpressionHandle &exprhdl, ULONG ulPartIndexId ) const { GPOS_ASSERT(m_ppim->FContains(ulPartIndexId)); // construct partition propagation spec with the given id only, and check if it needs to be // enforced on top CPartIndexMap *ppim = GPOS_NEW(pmp) CPartIndexMap(pmp); IMDId *pmdid = m_ppim->PmdidRel(ulPartIndexId); DrgPpartkeys *pdrgppartkeys = m_ppim->Pdrgppartkeys(ulPartIndexId); CPartConstraint *ppartcnstr = m_ppim->PpartcnstrRel(ulPartIndexId); PartCnstrMap *ppartcnstrmap = m_ppim->Ppartcnstrmap(ulPartIndexId); pmdid->AddRef(); pdrgppartkeys->AddRef(); ppartcnstr->AddRef(); ppartcnstrmap->AddRef(); ppim->Insert(ulPartIndexId, ppartcnstrmap, m_ppim->Epim(ulPartIndexId), m_ppim->UlExpectedPropagators(ulPartIndexId), pmdid, pdrgppartkeys, ppartcnstr); CPartitionPropagationSpec *ppps = GPOS_NEW(pmp) CPartitionPropagationSpec(ppim, GPOS_NEW(pmp) CPartFilterMap(pmp)); CEnfdPartitionPropagation *pepp = GPOS_NEW(pmp) CEnfdPartitionPropagation(ppps, CEnfdPartitionPropagation::EppmSatisfy, GPOS_NEW(pmp) CPartFilterMap(pmp)); CEnfdProp::EPropEnforcingType epetPartitionPropagation = pepp->Epet(exprhdl, CPhysical::PopConvert(pexpr->Pop()), true /*fPartitionPropagationRequired*/); pepp->Release(); return CEnfdProp::FEnforce(epetPartitionPropagation); }
//--------------------------------------------------------------------------- // @function: // CPartitionPropagationSpec::AppendEnforcers // // @doc: // Add required enforcers to dynamic array // //--------------------------------------------------------------------------- void CPartitionPropagationSpec::AppendEnforcers ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CReqdPropPlan * #ifdef GPOS_DEBUG prpp #endif // GPOS_DEBUG , DrgPexpr *pdrgpexpr, CExpression *pexpr ) { GPOS_ASSERT(NULL != prpp); GPOS_ASSERT(NULL != pmp); GPOS_ASSERT(NULL != pdrgpexpr); GPOS_ASSERT(NULL != pexpr); DrgPul *pdrgpul = m_ppim->PdrgpulScanIds(pmp); const ULONG ulSize = pdrgpul->UlLength(); for (ULONG ul = 0; ul < ulSize; ul++) { ULONG ulScanId = *((*pdrgpul)[ul]); GPOS_ASSERT(m_ppim->FContains(ulScanId)); if (CPartIndexMap::EpimConsumer != m_ppim->Epim(ulScanId) || 0 < m_ppim->UlExpectedPropagators(ulScanId)) { continue; } if (!FRequiresPartitionPropagation(pmp, pexpr, exprhdl, ulScanId)) { continue; } CExpression *pexprResolver = NULL; IMDId *pmdid = m_ppim->PmdidRel(ulScanId); DrgDrgPcr *pdrgpdrgpcrKeys = NULL; DrgPpartkeys *pdrgppartkeys = m_ppim->Pdrgppartkeys(ulScanId); CPartConstraint *ppartcnstr = m_ppim->PpartcnstrRel(ulScanId); PartCnstrMap *ppartcnstrmap = m_ppim->Ppartcnstrmap(ulScanId); pmdid->AddRef(); ppartcnstr->AddRef(); ppartcnstrmap->AddRef(); pexpr->AddRef(); // check if there is a predicate on this part index id HMUlExpr *phmulexprEqFilter = GPOS_NEW(pmp) HMUlExpr(pmp); HMUlExpr *phmulexprFilter = GPOS_NEW(pmp) HMUlExpr(pmp); CExpression *pexprResidual = NULL; if (m_ppfm->FContainsScanId(ulScanId)) { CExpression *pexprScalar = PexprFilter(pmp, ulScanId); // find out which keys are used in the predicate, in case there are multiple // keys at this point (e.g. from a union of multiple CTE consumers) CColRefSet *pcrsUsed = CDrvdPropScalar::Pdpscalar(pexprScalar->PdpDerive())->PcrsUsed(); const ULONG ulKeysets = pdrgppartkeys->UlLength(); for (ULONG ulKey = 0; NULL == pdrgpdrgpcrKeys && ulKey < ulKeysets; ulKey++) { // get partition key CPartKeys *ppartkeys = (*pdrgppartkeys)[ulKey]; if (ppartkeys->FOverlap(pcrsUsed)) { pdrgpdrgpcrKeys = ppartkeys->Pdrgpdrgpcr(); } } // if we cannot find partition keys mapping the partition predicates, fall back to planner if (NULL == pdrgpdrgpcrKeys) { GPOS_RAISE(gpopt::ExmaGPOPT, gpopt::ExmiUnsatisfiedRequiredProperties); } pdrgpdrgpcrKeys->AddRef(); // split predicates and put them in the appropriate hashmaps SplitPartPredicates(pmp, pexprScalar, pdrgpdrgpcrKeys, phmulexprEqFilter, phmulexprFilter, &pexprResidual); pexprScalar->Release(); } else { // doesn't matter which keys we use here since there is no filter GPOS_ASSERT(1 <= pdrgppartkeys->UlLength()); pdrgpdrgpcrKeys = (*pdrgppartkeys)[0]->Pdrgpdrgpcr(); pdrgpdrgpcrKeys->AddRef(); } pexprResolver = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CPhysicalPartitionSelector ( pmp, ulScanId, pmdid, pdrgpdrgpcrKeys, ppartcnstrmap, ppartcnstr, phmulexprEqFilter, phmulexprFilter, pexprResidual ), pexpr ); pdrgpexpr->Append(pexprResolver); } pdrgpul->Release(); }
//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelector::PppsRequired // // @doc: // Compute required partition propagation of the n-th child // //--------------------------------------------------------------------------- CPartitionPropagationSpec * CPhysicalPartitionSelector::PppsRequired ( IMemoryPool *pmp, CExpressionHandle & exprhdl, CPartitionPropagationSpec *pppsRequired, ULONG #ifdef GPOS_DEBUG ulChildIndex #endif // GPOS_DEBUG , DrgPdp *, //pdrgpdpCtxt, ULONG //ulOptReq ) { GPOS_ASSERT(0 == ulChildIndex); GPOS_ASSERT(NULL != pppsRequired); CPartIndexMap *ppimInput = pppsRequired->Ppim(); CPartFilterMap *ppfmInput = pppsRequired->Ppfm(); DrgPul *pdrgpulInputScanIds = ppimInput->PdrgpulScanIds(pmp); CPartIndexMap *ppim = GPOS_NEW(pmp) CPartIndexMap(pmp); CPartFilterMap *ppfm = GPOS_NEW(pmp) CPartFilterMap(pmp); CPartInfo *ppartinfo = exprhdl.Pdprel(0)->Ppartinfo(); const ULONG ulScanIds = pdrgpulInputScanIds->UlLength(); for (ULONG ul = 0; ul < ulScanIds; ul++) { ULONG ulScanId = *((*pdrgpulInputScanIds)[ul]); ULONG ulExpectedPropagators = ppimInput->UlExpectedPropagators(ulScanId); if (ulScanId == m_ulScanId) { // partition propagation resolved - do not need to require from children continue; } if (!ppartinfo->FContainsScanId(ulScanId) && ppartinfo->FContainsScanId(m_ulScanId)) { // dynamic scan for the required id not defined below, but the current one is: do not push request down continue; } IMDId *pmdid = ppimInput->PmdidRel(ulScanId); DrgPpartkeys *pdrgppartkeys = ppimInput->Pdrgppartkeys(ulScanId); PartCnstrMap *ppartcnstrmap = ppimInput->Ppartcnstrmap(ulScanId); CPartConstraint *ppartcnstr = ppimInput->PpartcnstrRel(ulScanId); CPartIndexMap::EPartIndexManipulator epim = ppimInput->Epim(ulScanId); pmdid->AddRef(); pdrgppartkeys->AddRef(); ppartcnstrmap->AddRef(); ppartcnstr->AddRef(); ppim->Insert(ulScanId, ppartcnstrmap, epim, ulExpectedPropagators, pmdid, pdrgppartkeys, ppartcnstr); (void) ppfm->FCopyPartFilter(m_pmp, ulScanId, ppfmInput); } // cleanup pdrgpulInputScanIds->Release(); return GPOS_NEW(pmp) CPartitionPropagationSpec(ppim, ppfm); }
//--------------------------------------------------------------------------- // @function: // CPhysicalNLJoin::PppsRequiredNLJoinChild // // @doc: // Compute required partition propagation of the n-th child // //--------------------------------------------------------------------------- CPartitionPropagationSpec * CPhysicalNLJoin::PppsRequiredNLJoinChild ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CPartitionPropagationSpec *pppsRequired, ULONG ulChildIndex, DrgPdp *, //pdrgpdpCtxt, ULONG ulOptReq ) { GPOS_ASSERT(NULL != pppsRequired); if (1 == ulOptReq) { // request (1): push partition propagation requests to join's children, // do not consider possible dynamic partition elimination using join predicate here, // this is handled by optimization request (0) below return CPhysical::PppsRequiredPushThruNAry(pmp, exprhdl, pppsRequired, ulChildIndex); } GPOS_ASSERT(0 == ulOptReq); CPartIndexMap *ppim = pppsRequired->Ppim(); CPartFilterMap *ppfm = pppsRequired->Ppfm(); DrgPul *pdrgpul = ppim->PdrgpulScanIds(pmp); CPartIndexMap *ppimResult = GPOS_NEW(pmp) CPartIndexMap(pmp); CPartFilterMap *ppfmResult = GPOS_NEW(pmp) CPartFilterMap(pmp); CPartInfo *ppartinfoOuter = exprhdl.Pdprel(0)->Ppartinfo(); CColRefSet *pcrsOutputOuter = exprhdl.Pdprel(0)->PcrsOutput(); CColRefSet *pcrsOutputInner = exprhdl.Pdprel(1)->PcrsOutput(); const ULONG ulPartIndexIds = pdrgpul->UlLength(); for (ULONG ul = 0; ul < ulPartIndexIds; ul++) { ULONG ulPartIndexId = *((*pdrgpul)[ul]); if (ppfm->FContainsScanId(ulPartIndexId)) { GPOS_ASSERT(NULL != ppfm->Pexpr(ulPartIndexId)); // a selection-based propagation request pushed from above: do not propagate any // further as the join will reduce cardinality and thus may select more partitions // for scanning continue; } BOOL fOuterPartConsumer = ppartinfoOuter->FContainsScanId(ulPartIndexId); // in order to find interesting join predicates that can be used for DPE, // one side of the predicate must be the partition key, while the other side must only contain // references from the join child that does not have the partition consumer CColRefSet *pcrsAllowedRefs = pcrsOutputOuter; if (fOuterPartConsumer) { pcrsAllowedRefs = pcrsOutputInner; } if (0 == ulChildIndex && fOuterPartConsumer) { // always push through required partition propagation for consumers on the // outer side of the nested loop join DrgPpartkeys *pdrgppartkeys = ppartinfoOuter->PdrgppartkeysByScanId(ulPartIndexId); GPOS_ASSERT(NULL != pdrgppartkeys); pdrgppartkeys->AddRef(); ppimResult->AddRequiredPartPropagation(ppim, ulPartIndexId, CPartIndexMap::EppraPreservePropagators, pdrgppartkeys); } else { // check if there is an interesting condition involving the partition key CExpression *pexprScalar = exprhdl.PexprScalarChild(2 /*ulChildIndex*/); AddFilterOnPartKey(pmp, true /*fNLJoin*/, pexprScalar, ppim, ppfm, ulChildIndex, ulPartIndexId, fOuterPartConsumer, ppimResult, ppfmResult, pcrsAllowedRefs); } } pdrgpul->Release(); return GPOS_NEW(pmp) CPartitionPropagationSpec(ppimResult, ppfmResult); }
//--------------------------------------------------------------------------- // @function: // CPhysicalHashJoin::PppsRequiredCompute // // @doc: // Compute required partition propagation of the n-th child // //--------------------------------------------------------------------------- CPartitionPropagationSpec * CPhysicalHashJoin::PppsRequiredCompute ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CPartitionPropagationSpec *pppsRequired, ULONG ulChildIndex ) { CPartIndexMap *ppim = pppsRequired->Ppim(); CPartFilterMap *ppfm = pppsRequired->Ppfm(); DrgPul *pdrgpul = ppim->PdrgpulScanIds(pmp); CPartIndexMap *ppimResult = GPOS_NEW(pmp) CPartIndexMap(pmp); CPartFilterMap *ppfmResult = GPOS_NEW(pmp) CPartFilterMap(pmp); // get outer partition consumers CPartInfo *ppartinfo = exprhdl.Pdprel(0)->Ppartinfo(); CColRefSet *pcrsOutputOuter = exprhdl.Pdprel(0)->PcrsOutput(); CColRefSet *pcrsOutputInner = exprhdl.Pdprel(1)->PcrsOutput(); const ULONG ulPartIndexIds = pdrgpul->UlLength(); for (ULONG ul = 0; ul < ulPartIndexIds; ul++) { ULONG ulPartIndexId = *((*pdrgpul)[ul]); if (ppfm->FContainsScanId(ulPartIndexId)) { GPOS_ASSERT(NULL != ppfm->Pexpr(ulPartIndexId)); // a selection-based propagation request pushed from above: do not propagate any // further as the join will reduce cardinality and thus may select more partitions // for scanning continue; } BOOL fOuterPartConsumer = ppartinfo->FContainsScanId(ulPartIndexId); // in order to find interesting join predicates that can be used for DPE, // one side of the predicate must be the partition key, while the other side must only contain // references from the join child that does not have the partition consumer CColRefSet *pcrsAllowedRefs = pcrsOutputOuter; if (fOuterPartConsumer) { pcrsAllowedRefs = pcrsOutputInner; } if (1 == ulChildIndex && !fOuterPartConsumer) { // always push through required partition propagation for consumers on the // inner side of the hash join DrgPpartkeys *pdrgppartkeys = exprhdl.Pdprel(1 /*ulChildIndex*/)->Ppartinfo()->PdrgppartkeysByScanId(ulPartIndexId); GPOS_ASSERT(NULL != pdrgppartkeys); pdrgppartkeys->AddRef(); ppimResult->AddRequiredPartPropagation(ppim, ulPartIndexId, CPartIndexMap::EppraPreservePropagators, pdrgppartkeys); } else { // look for a filter on the part key CExpression *pexprScalar = exprhdl.PexprScalarChild(2 /*ulChildIndex*/); AddFilterOnPartKey(pmp, false /*fNLJoin*/, pexprScalar, ppim, ppfm, ulChildIndex, ulPartIndexId, fOuterPartConsumer, ppimResult, ppfmResult, pcrsAllowedRefs); } } pdrgpul->Release(); return GPOS_NEW(pmp) CPartitionPropagationSpec(ppimResult, ppfmResult); }