//--------------------------------------------------------------------------- // @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: // 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: // 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: // 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(); }