//--------------------------------------------------------------------------- // @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: // CPhysicalPartitionSelector::PpimDerive // // @doc: // Derive partition index map // //--------------------------------------------------------------------------- CPartIndexMap * CPhysicalPartitionSelector::PpimDerive ( IMemoryPool *mp, CExpressionHandle &exprhdl, CDrvdPropCtxt *pdpctxt ) const { GPOS_ASSERT(NULL != pdpctxt); CDrvdPropPlan *pdpplan = exprhdl.Pdpplan(0 /*child_index*/); CPartIndexMap *ppimInput = pdpplan->Ppim(); GPOS_ASSERT(NULL != ppimInput); ULONG ulExpectedPartitionSelectors = CDrvdPropCtxtPlan::PdpctxtplanConvert(pdpctxt)->UlExpectedPartitionSelectors(); CPartIndexMap *ppim = ppimInput->PpimPartitionSelector(mp, m_scan_id, ulExpectedPartitionSelectors); if (!ppim->Contains(m_scan_id)) { // the consumer of this scan id does not come from the child, i.e. it // is on the other side of a join MDId()->AddRef(); m_pdrgpdrgpcr->AddRef(); m_ppartcnstrmap->AddRef(); m_part_constraint->AddRef(); CPartKeysArray *pdrgppartkeys = GPOS_NEW(mp) CPartKeysArray(mp); pdrgppartkeys->Append(GPOS_NEW(mp) CPartKeys(m_pdrgpdrgpcr)); ppim->Insert(m_scan_id, m_ppartcnstrmap, CPartIndexMap::EpimPropagator, 0 /*ulExpectedPropagators*/, MDId(), pdrgppartkeys, m_part_constraint); } return ppim; }
//--------------------------------------------------------------------------- // @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; }
BOOL CPhysicalSpool::FValidContext ( IMemoryPool *, COptimizationContext *poc, COptimizationContextArray *pdrgpocChild ) const { GPOS_ASSERT(NULL != pdrgpocChild); GPOS_ASSERT(1 == pdrgpocChild->Size()); COptimizationContext *pocChild = (*pdrgpocChild)[0]; CCostContext *pccBest = pocChild->PccBest(); GPOS_ASSERT(NULL != pccBest); // partition selections that happen outside of a physical spool does not do // any good on rescan: a physical spool blocks the rescan from the entire // subtree (in particular, any dynamic scan) underneath it. That means when // we have a dynamic scan under a spool, and a corresponding partition // selector outside the spool, we run the risk of materializing the wrong // results. // For example, the following plan is invalid because the partition selector // won't be able to influence inner side of the nested loop join as intended // ("blocked" by the spool): // +--CPhysicalMotionGather(master) // +--CPhysicalInnerNLJoin // |--CPhysicalPartitionSelector // | +--CPhysicalMotionBroadcast // | +--CPhysicalTableScan "foo" ("foo") // |--CPhysicalSpool // | +--CPhysicalLeftOuterHashJoin // | |--CPhysicalDynamicTableScan "pt" ("pt") // | |--CPhysicalMotionHashDistribute // | | +--CPhysicalTableScan "bar" ("bar") // | +--CScalarCmp (=) // | |--CScalarIdent "d" (19) // | +--CScalarIdent "dk" (9) // +--CScalarCmp (<) // |--CScalarIdent "a" (0) // +--CScalarIdent "partkey" (10) CDrvdPropPlan *pdpplanChild = pccBest->Pdpplan(); if (pdpplanChild->Ppim()->FContainsUnresolved()) { return false; } // Discard any context that is requesting for rewindability with motion hazard handling and // the physical spool is streaming with a motion underneath it. // We do not want to add a blocking spool over a spool as spooling twice will be expensive, // hence invalidate this context. CEnfdRewindability *per = poc->Prpp()->Per(); if(per->PrsRequired()->HasMotionHazard() && pdpplanChild->Prs()->HasMotionHazard()) { return FEager(); } return true; }