//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelector::PpfmDerive // // @doc: // Derive partition filter map // //--------------------------------------------------------------------------- CPartFilterMap * CPhysicalPartitionSelector::PpfmDerive ( IMemoryPool *mp, CExpressionHandle &exprhdl ) const { if (!FHasFilter()) { return PpfmPassThruOuter(exprhdl); } CPartFilterMap *ppfm = PpfmDeriveCombineRelational(mp, exprhdl); IStatistics *stats = exprhdl.Pstats(); GPOS_ASSERT(NULL != stats); m_pexprCombinedPredicate->AddRef(); stats->AddRef(); ppfm->AddPartFilter(mp, m_scan_id, m_pexprCombinedPredicate, stats); return ppfm; }
//--------------------------------------------------------------------------- // @function: // CPhysical::PppsRequiredPushThruNAry // // @doc: // Helper for pushing required partition propagation to the children of // an n-ary operator // //--------------------------------------------------------------------------- CPartitionPropagationSpec * CPhysical::PppsRequiredPushThruNAry ( IMemoryPool *mp, CExpressionHandle &exprhdl, CPartitionPropagationSpec *pppsReqd, ULONG child_index ) { GPOS_ASSERT(NULL != pppsReqd); CPartIndexMap *ppimReqd = pppsReqd->Ppim(); CPartFilterMap *ppfmReqd = pppsReqd->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(); const ULONG arity = exprhdl.UlNonScalarChildren(); // iterate over required part index ids and decide which ones to push to the outer // and which to the inner side of the n-ary op for (ULONG ul = 0; ul < ulPartIndexIds; ul++) { ULONG part_idx_id = *((*pdrgpul)[ul]); GPOS_ASSERT(ppimReqd->Contains(part_idx_id)); CBitSet *pbsPartConsumer = GPOS_NEW(mp) CBitSet(mp); for (ULONG ulChildIdx = 0; ulChildIdx < arity; ulChildIdx++) { if (exprhdl.GetRelationalProperties(ulChildIdx)->Ppartinfo()->FContainsScanId(part_idx_id)) { (void) pbsPartConsumer->ExchangeSet(ulChildIdx); } } if (arity == pbsPartConsumer->Size() && COperator::EopPhysicalSequence == exprhdl.Pop()->Eopid() && (*(exprhdl.Pgexpr()))[0]->FHasCTEProducer()) { GPOS_ASSERT(2 == arity); // this is a part index id that comes from both sides of a sequence // with a CTE producer on the outer side, so pretend that part index // id is not defined the inner sides pbsPartConsumer->ExchangeClear(1); } if (!FCanPushPartReqToChild(pbsPartConsumer, child_index)) { // clean up pbsPartConsumer->Release(); continue; } // clean up pbsPartConsumer->Release(); CPartKeysArray *pdrgppartkeys = exprhdl.GetRelationalProperties(child_index)->Ppartinfo()->PdrgppartkeysByScanId(part_idx_id); GPOS_ASSERT(NULL != pdrgppartkeys); pdrgppartkeys->AddRef(); // push requirements to child node ppimResult->AddRequiredPartPropagation(ppimReqd, part_idx_id, CPartIndexMap::EppraPreservePropagators, pdrgppartkeys); // check if there is a filter on the part index id and propagate that further down if (ppfmReqd->FContainsScanId(part_idx_id)) { CExpression *pexpr = ppfmReqd->Pexpr(part_idx_id); // if the current child is inner child and the predicate is IsNull check and the parent is outer join, // don't push IsNull check predicate to the partition filter. // for all the other cases, push the filter down. if (!(1 == child_index && CUtils::FScalarNullTest(pexpr) && CUtils::FPhysicalOuterJoin(exprhdl.Pop())) ) { pexpr->AddRef(); ppfmResult->AddPartFilter(mp, part_idx_id, pexpr, NULL /*stats */); } } } pdrgpul->Release(); return GPOS_NEW(mp) CPartitionPropagationSpec(ppimResult, ppfmResult); }