//--------------------------------------------------------------------------- // @function: // CLogical::PpartinfoDeriveCombine // // @doc: // Common case of combining partition info of all logical children // //--------------------------------------------------------------------------- CPartInfo * CLogical::PpartinfoDeriveCombine ( IMemoryPool *pmp, CExpressionHandle &exprhdl ) { const ULONG ulArity = exprhdl.UlArity(); GPOS_ASSERT(0 < ulArity); CPartInfo *ppartinfo = GPOS_NEW(pmp) CPartInfo(pmp); for (ULONG ul = 0; ul < ulArity; ul++) { CPartInfo *ppartinfoChild = NULL; if (exprhdl.FScalarChild(ul)) { ppartinfoChild = exprhdl.Pdpscalar(ul)->Ppartinfo(); } else { ppartinfoChild = exprhdl.Pdprel(ul)->Ppartinfo(); } GPOS_ASSERT(NULL != ppartinfoChild); CPartInfo *ppartinfoCombined = CPartInfo::PpartinfoCombine(pmp, ppartinfo, ppartinfoChild); ppartinfo->Release(); ppartinfo = ppartinfoCombined; } return ppartinfo; }
//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelector::PdsRequired // // @doc: // Compute required distribution of the n-th child // //--------------------------------------------------------------------------- CDistributionSpec * CPhysicalPartitionSelector::PdsRequired ( IMemoryPool *mp, CExpressionHandle &exprhdl, CDistributionSpec *pdsInput, ULONG child_index, CDrvdProp2dArray *, // pdrgpdpCtxt ULONG // ulOptReq ) const { GPOS_ASSERT(0 == child_index); CDrvdPropRelational *pdprelDrvd = exprhdl.GetRelationalProperties(); CPartInfo *ppartinfo = pdprelDrvd->Ppartinfo(); BOOL fCovered = ppartinfo->FContainsScanId(m_scan_id); if (fCovered) { // if partition consumer is defined below, do not pass distribution // requirements down as this will cause the consumer and enforcer to be // in separate slices return GPOS_NEW(mp) CDistributionSpecAny(this->Eopid()); } return PdsPassThru(mp, exprhdl, pdsInput, child_index); }
//--------------------------------------------------------------------------- // @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: // CLogical::PpartinfoPassThruOuter // // @doc: // Common case of common case of passing through partition consumer array // //--------------------------------------------------------------------------- CPartInfo * CLogical::PpartinfoPassThruOuter ( CExpressionHandle &exprhdl ) { CPartInfo *ppartinfo = exprhdl.Pdprel(0 /*ulChildIndex*/)->Ppartinfo(); GPOS_ASSERT(NULL != ppartinfo); ppartinfo->AddRef(); return ppartinfo; }
//--------------------------------------------------------------------------- // @function: // CPhysicalMotion::PppsRequired // // @doc: // Compute required partition propagation of the n-th child // //--------------------------------------------------------------------------- CPartitionPropagationSpec * CPhysicalMotion::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 *ppimReqd = pppsRequired->Ppim(); CPartFilterMap *ppfmReqd = pppsRequired->Ppfm(); DrgPul *pdrgpul = ppimReqd->PdrgpulScanIds(pmp); CPartIndexMap *ppimResult = GPOS_NEW(pmp) CPartIndexMap(pmp); CPartFilterMap *ppfmResult = GPOS_NEW(pmp) CPartFilterMap(pmp); /// get derived part consumers CPartInfo *ppartinfo = exprhdl.Pdprel(0)->Ppartinfo(); const ULONG ulPartIndexSize = pdrgpul->UlLength(); for (ULONG ul = 0; ul < ulPartIndexSize; ul++) { ULONG ulPartIndexId = *((*pdrgpul)[ul]); if (!ppartinfo->FContainsScanId(ulPartIndexId)) { // part index id does not exist in child nodes: do not push it below // the motion continue; } ppimResult->AddRequiredPartPropagation(ppimReqd, ulPartIndexId, CPartIndexMap::EppraPreservePropagators); (void) ppfmResult->FCopyPartFilter(m_pmp, ulPartIndexId, ppfmReqd); } pdrgpul->Release(); return GPOS_NEW(pmp) CPartitionPropagationSpec(ppimResult, ppfmResult); }
//--------------------------------------------------------------------------- // @function: // CPhysical::PppsRequiredPushThruUnresolvedUnary // // @doc: // Helper function for pushing unresolved partition propagation in unary // operators // //--------------------------------------------------------------------------- CPartitionPropagationSpec * CPhysical::PppsRequiredPushThruUnresolvedUnary ( IMemoryPool *mp, CExpressionHandle &exprhdl, CPartitionPropagationSpec *pppsRequired, EPropogatePartConstraint eppcPropogate ) { GPOS_ASSERT(NULL != pppsRequired); CPartInfo *ppartinfo = exprhdl.GetRelationalProperties(0)->Ppartinfo(); CPartIndexMap *ppimReqd = pppsRequired->Ppim(); CPartFilterMap *ppfmReqd = pppsRequired->Ppfm(); ULongPtrArray *pdrgpul = ppimReqd->PdrgpulScanIds(mp); CPartIndexMap *ppimResult = GPOS_NEW(mp) CPartIndexMap(mp); CPartFilterMap *ppfmResult = GPOS_NEW(mp) CPartFilterMap(mp); const ULONG ulPartIndexIds = pdrgpul->Size(); // iterate over required part index ids and decide which ones to push through for (ULONG ul = 0; ul < ulPartIndexIds; ul++) { ULONG part_idx_id = *((*pdrgpul)[ul]); GPOS_ASSERT(ppimReqd->Contains(part_idx_id)); // if part index id is defined in child, push it to the child if (ppartinfo->FContainsScanId(part_idx_id)) { // push requirements to child node ppimResult->AddRequiredPartPropagation(ppimReqd, part_idx_id, CPartIndexMap::EppraPreservePropagators); if (CPhysical::EppcAllowed == eppcPropogate) { // for some logical operators such as limit while we push the part index map, we cannot push the constraints // since they are NOT semantically equivalent. So only push the constraints when the operator asks this // utility function to do so (void) ppfmResult->FCopyPartFilter(mp, part_idx_id, ppfmReqd); } } } pdrgpul->Release(); return GPOS_NEW(mp) CPartitionPropagationSpec(ppimResult, ppfmResult); }
//--------------------------------------------------------------------------- // @function: // CLogicalSetOp::PpartinfoDerive // // @doc: // Derive partition consumer info // //--------------------------------------------------------------------------- CPartInfo * CLogicalSetOp::PpartinfoDerive ( IMemoryPool *pmp, CExpressionHandle &exprhdl ) const { const ULONG ulArity = exprhdl.UlArity(); GPOS_ASSERT(0 < ulArity); // start with the part info of the first child CPartInfo *ppartinfo = exprhdl.Pdprel(0 /*ulChildIndex*/)->Ppartinfo(); ppartinfo->AddRef(); for (ULONG ul = 1; ul < ulArity; ul++) { CPartInfo *ppartinfoChild = exprhdl.Pdprel(ul)->Ppartinfo(); GPOS_ASSERT(NULL != ppartinfoChild); DrgPcr *pdrgpcrInput = (*m_pdrgpdrgpcrInput)[ul]; GPOS_ASSERT(pdrgpcrInput->UlLength() == m_pdrgpcrOutput->UlLength()); CPartInfo *ppartinfoRemapped = ppartinfoChild->PpartinfoWithRemappedKeys(pmp, pdrgpcrInput, m_pdrgpcrOutput); CPartInfo *ppartinfoCombined = CPartInfo::PpartinfoCombine(pmp, ppartinfo, ppartinfoRemapped); ppartinfoRemapped->Release(); ppartinfo->Release(); ppartinfo = ppartinfoCombined; } return ppartinfo; }
//--------------------------------------------------------------------------- // @function: // CLogicalDynamicGetBase::PpartinfoDerive // // @doc: // Derive partition consumer info // //--------------------------------------------------------------------------- CPartInfo * CLogicalDynamicGetBase::PpartinfoDerive ( IMemoryPool *pmp, CExpressionHandle & // exprhdl ) const { IMDId *pmdid = m_ptabdesc->Pmdid(); pmdid->AddRef(); m_pdrgpdrgpcrPart->AddRef(); m_ppartcnstrRel->AddRef(); CPartInfo *ppartinfo = GPOS_NEW(pmp) CPartInfo(pmp); ppartinfo->AddPartConsumer(pmp, m_ulScanId, pmdid, m_pdrgpdrgpcrPart, m_ppartcnstrRel); return ppartinfo; }
//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelector::PppsRequired // // @doc: // Compute required partition propagation of the n-th child // //--------------------------------------------------------------------------- CPartitionPropagationSpec * CPhysicalPartitionSelector::PppsRequired ( IMemoryPool *mp, CExpressionHandle & exprhdl, CPartitionPropagationSpec *pppsRequired, ULONG #ifdef GPOS_DEBUG child_index #endif // GPOS_DEBUG , CDrvdProp2dArray *, //pdrgpdpCtxt, ULONG //ulOptReq ) { GPOS_ASSERT(0 == child_index); GPOS_ASSERT(NULL != pppsRequired); CPartIndexMap *ppimInput = pppsRequired->Ppim(); CPartFilterMap *ppfmInput = pppsRequired->Ppfm(); ULongPtrArray *pdrgpulInputScanIds = ppimInput->PdrgpulScanIds(mp); CPartIndexMap *ppim = GPOS_NEW(mp) CPartIndexMap(mp); CPartFilterMap *ppfm = GPOS_NEW(mp) CPartFilterMap(mp); CPartInfo *ppartinfo = exprhdl.GetRelationalProperties(0)->Ppartinfo(); const ULONG ulScanIds = pdrgpulInputScanIds->Size(); for (ULONG ul = 0; ul < ulScanIds; ul++) { ULONG scan_id = *((*pdrgpulInputScanIds)[ul]); ULONG ulExpectedPropagators = ppimInput->UlExpectedPropagators(scan_id); if (scan_id == m_scan_id) { // partition propagation resolved - do not need to require from children continue; } if (!ppartinfo->FContainsScanId(scan_id) && ppartinfo->FContainsScanId(m_scan_id)) { // dynamic scan for the required id not defined below, but the current one is: do not push request down continue; } IMDId *mdid = ppimInput->GetRelMdId(scan_id); CPartKeysArray *pdrgppartkeys = ppimInput->Pdrgppartkeys(scan_id); UlongToPartConstraintMap *ppartcnstrmap = ppimInput->Ppartcnstrmap(scan_id); CPartConstraint *ppartcnstr = ppimInput->PpartcnstrRel(scan_id); CPartIndexMap::EPartIndexManipulator epim = ppimInput->Epim(scan_id); mdid->AddRef(); pdrgppartkeys->AddRef(); ppartcnstrmap->AddRef(); ppartcnstr->AddRef(); ppim->Insert(scan_id, ppartcnstrmap, epim, ulExpectedPropagators, mdid, pdrgppartkeys, ppartcnstr); (void) ppfm->FCopyPartFilter(m_mp, scan_id, ppfmInput); } // cleanup pdrgpulInputScanIds->Release(); return GPOS_NEW(mp) CPartitionPropagationSpec(ppim, ppfm); }
//--------------------------------------------------------------------------- // @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); }