//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelector::EpetDistribution // // @doc: // Return the enforcing type for distribution property based on this operator // //--------------------------------------------------------------------------- CEnfdProp::EPropEnforcingType CPhysicalPartitionSelector::EpetDistribution ( CExpressionHandle &exprhdl, const CEnfdDistribution *ped ) const { CDrvdPropPlan *pdpplan = exprhdl.Pdpplan(0 /* child_index */); if (ped->FCompatible(pdpplan->Pds())) { // required distribution established by the operator return CEnfdProp::EpetUnnecessary; } CPartIndexMap *ppimDrvd = pdpplan->Ppim(); if (!ppimDrvd->Contains(m_scan_id)) { // part consumer is defined above: prohibit adding a motion on top of the // part resolver as this will create two slices return CEnfdProp::EpetProhibited; } GPOS_ASSERT(CPartIndexMap::EpimConsumer == ppimDrvd->Epim(m_scan_id)); // part consumer found below: enforce distribution on top of part resolver return CEnfdProp::EpetRequired; }
//--------------------------------------------------------------------------- // @function: // CDrvdPropPlan::CopyCTEProducerPlanProps // // @doc: // Copy CTE producer plan properties from given context to current object // //--------------------------------------------------------------------------- void CDrvdPropPlan::CopyCTEProducerPlanProps ( IMemoryPool *pmp, CDrvdPropCtxt *pdpctxt, COperator *pop ) { CDrvdPropCtxtPlan *pdpctxtplan = CDrvdPropCtxtPlan::PdpctxtplanConvert(pdpctxt); CPhysicalCTEConsumer *popCTEConsumer = CPhysicalCTEConsumer::PopConvert(pop); ULONG ulCTEId = popCTEConsumer->UlCTEId(); HMUlCr *phmulcr = popCTEConsumer->Phmulcr(); CDrvdPropPlan *pdpplan = pdpctxtplan->PdpplanCTEProducer(ulCTEId); if (NULL != pdpplan) { // copy producer plan properties after remapping columns m_pos = pdpplan->Pos()->PosCopyWithRemappedColumns(pmp, phmulcr, true /*fMustExist*/); m_pds = pdpplan->Pds()->PdsCopyWithRemappedColumns(pmp, phmulcr, true /*fMustExist*/); // rewindability and partition filter map do not need column remapping, // we add-ref producer's properties directly pdpplan->Prs()->AddRef(); m_prs = pdpplan->Prs(); pdpplan->Ppfm()->AddRef(); m_ppfm = pdpplan->Ppfm(); // no need to copy the part index map. return an empty one. This is to // distinguish between a CTE consumer and the inlined expression m_ppim = GPOS_NEW(pmp) CPartIndexMap(pmp); GPOS_ASSERT(CDistributionSpec::EdtAny != m_pds->Edt() && "CDistributionAny is a require-only, cannot be derived"); } }
//--------------------------------------------------------------------------- // @function: // CPhysical::FChildrenHaveCompatibleDistributions // // @doc: // Returns true iff the delivered distributions of the children are // compatible among themselves. // //--------------------------------------------------------------------------- BOOL CPhysical::FCompatibleChildrenDistributions ( const CExpressionHandle &exprhdl ) const { GPOS_ASSERT(exprhdl.Pop() == this); BOOL fSingletonOrUniversalChild = false; BOOL fNotSingletonOrUniversalDistributedChild = false; const ULONG arity = exprhdl.Arity(); for (ULONG ul = 0; ul < arity; ul++) { if (!exprhdl.FScalarChild(ul)) { CDrvdPropPlan *pdpplanChild = exprhdl.Pdpplan(ul); // an operator cannot have a singleton or universal distributed child // and one distributed on multiple nodes // this assumption is safe for all current operators, but it can be // too conservative: we could allow for instance the following cases // * LeftOuterJoin (universal, distributed) // * AntiSemiJoin (universal, distributed) // These cases can be enabled if considered necessary by overriding // this function. if (CDistributionSpec::EdtUniversal == pdpplanChild->Pds()->Edt() || pdpplanChild->Pds()->FSingletonOrStrictSingleton()) { fSingletonOrUniversalChild = true; } else { fNotSingletonOrUniversalDistributedChild = true; } if (fSingletonOrUniversalChild && fNotSingletonOrUniversalDistributedChild) { return false; } } } return true; }
//--------------------------------------------------------------------------- // @function: // CPhysicalMotion::FValidContext // // @doc: // Check if optimization context is valid // //--------------------------------------------------------------------------- BOOL CPhysicalMotion::FValidContext ( IMemoryPool *pmp, COptimizationContext *poc, DrgPoc *pdrgpocChild ) const { GPOS_ASSERT(NULL != pdrgpocChild); GPOS_ASSERT(1 == pdrgpocChild->UlLength()); COptimizationContext *pocChild = (*pdrgpocChild)[0]; CCostContext *pccBest = pocChild->PccBest(); GPOS_ASSERT(NULL != pccBest); CDrvdPropPlan *pdpplanChild = pccBest->Pdpplan(); if (pdpplanChild->Ppim()->FContainsUnresolved()) { return false; } CExpressionHandle exprhdl(pmp); exprhdl.Attach(pccBest); exprhdl.DeriveProps(NULL /*CDrvdPropCtxt*/); if (exprhdl.FHasOuterRefs()) { // disallow plans with outer references below motion operator return false; } CEnfdDistribution *ped = poc->Prpp()->Ped(); if (ped->FCompatible(this->Pds()) && ped->FCompatible(pdpplanChild->Pds())) { // required distribution is compatible with the distribution delivered by Motion and its child plan, // in this case, Motion is redundant since child plan delivers the required distribution return false; } return true; }
//--------------------------------------------------------------------------- // @function: // CPhysicalSequence::PdsRequired // // @doc: // Compute required distribution of the n-th child // //--------------------------------------------------------------------------- CDistributionSpec * CPhysicalSequence::PdsRequired ( IMemoryPool *pmp, CExpressionHandle & #ifdef GPOS_DEBUG exprhdl #endif // GPOS_DEBUG , CDistributionSpec *pdsRequired, ULONG ulChildIndex, DrgPdp *pdrgpdpCtxt, ULONG ulOptReq ) const { GPOS_ASSERT(2 == exprhdl.UlArity()); GPOS_ASSERT(ulChildIndex < exprhdl.UlArity()); GPOS_ASSERT(ulOptReq < UlDistrRequests()); if (0 == ulOptReq) { if (CDistributionSpec::EdtSingleton == pdsRequired->Edt() || CDistributionSpec::EdtStrictSingleton == pdsRequired->Edt()) { // incoming request is a singleton, request singleton on all children CDistributionSpecSingleton *pdss = CDistributionSpecSingleton::PdssConvert(pdsRequired); return GPOS_NEW(pmp) CDistributionSpecSingleton(pdss->Est()); } // incoming request is a non-singleton, request non-singleton on all children return GPOS_NEW(pmp) CDistributionSpecNonSingleton(); } GPOS_ASSERT(1 == ulOptReq); if (0 == ulChildIndex) { // no distribution requirement on first child return GPOS_NEW(pmp) CDistributionSpecAny(this->Eopid()); } // get derived plan properties of first child CDrvdPropPlan *pdpplan = CDrvdPropPlan::Pdpplan((*pdrgpdpCtxt)[0]); CDistributionSpec *pds = pdpplan->Pds(); if (pds->FSingletonOrStrictSingleton()) { // first child is singleton, request singleton distribution on second child CDistributionSpecSingleton *pdss = CDistributionSpecSingleton::PdssConvert(pds); return GPOS_NEW(pmp) CDistributionSpecSingleton(pdss->Est()); } if (CDistributionSpec::EdtUniversal == pds->Edt()) { // first child is universal, impose no requirements on second child return GPOS_NEW(pmp) CDistributionSpecAny(this->Eopid()); } // first child is non-singleton, request a non-singleton distribution on second child return GPOS_NEW(pmp) CDistributionSpecNonSingleton(); }