//--------------------------------------------------------------------------- // @function: // CPartConstraint::PpartcnstrRemaining // // @doc: // Return what remains of the current part constraint after taking out // the given part constraint. Returns NULL is the difference cannot be // performed // //--------------------------------------------------------------------------- CPartConstraint * CPartConstraint::PpartcnstrRemaining ( IMemoryPool *mp, CPartConstraint *ppartcnstr ) { GPOS_ASSERT(!m_fUninterpreted && "Calling PpartcnstrRemaining on uninterpreted partition constraint"); GPOS_ASSERT(NULL != ppartcnstr); if (m_num_of_part_levels != ppartcnstr->m_num_of_part_levels || !ppartcnstr->FCanNegate()) { return NULL; } UlongToConstraintMap *phmulcnstr = GPOS_NEW(mp) UlongToConstraintMap(mp); CBitSet *pbsDefaultParts = GPOS_NEW(mp) CBitSet(mp); // constraint on first level CConstraint *pcnstrCurrent = Pcnstr(0 /*ulLevel*/); CConstraint *pcnstrOther = ppartcnstr->Pcnstr(0 /*ulLevel*/); CConstraint *pcnstrRemaining = PcnstrRemaining(mp, pcnstrCurrent, pcnstrOther); #ifdef GPOS_DEBUG BOOL result = #endif // GPOS_DEBUG phmulcnstr->Insert(GPOS_NEW(mp) ULONG(0), pcnstrRemaining); GPOS_ASSERT(result); if (IsDefaultPartition(0 /*ulLevel*/) && !ppartcnstr->IsDefaultPartition(0 /*ulLevel*/)) { pbsDefaultParts->ExchangeSet(0 /*ulBit*/); } // copy the remaining constraints and default partition flags for (ULONG ul = 1; ul < m_num_of_part_levels; ul++) { CConstraint *pcnstrLevel = Pcnstr(ul); if (NULL != pcnstrLevel) { pcnstrLevel->AddRef(); #ifdef GPOS_DEBUG BOOL result = #endif // GPOS_DEBUG phmulcnstr->Insert(GPOS_NEW(mp) ULONG(ul), pcnstrLevel); GPOS_ASSERT(result); } if (IsDefaultPartition(ul)) { pbsDefaultParts->ExchangeSet(ul); } } m_pdrgpdrgpcr->AddRef(); return GPOS_NEW(mp) CPartConstraint(mp, phmulcnstr, pbsDefaultParts, false /*is_unbounded*/, m_pdrgpdrgpcr); }
//--------------------------------------------------------------------------- // @function: // CJoinOrderDP::GenerateSubsets // // @doc: // Generate all subsets of given array of elements // //--------------------------------------------------------------------------- void CJoinOrderDP::GenerateSubsets ( IMemoryPool *mp, CBitSet *pbsCurrent, ULONG *pulElems, ULONG size, ULONG ulIndex, CBitSetArray *pdrgpbsSubsets ) { GPOS_CHECK_STACK_SIZE; GPOS_CHECK_ABORT; GPOS_ASSERT(ulIndex <= size); GPOS_ASSERT(NULL != pbsCurrent); GPOS_ASSERT(NULL != pulElems); GPOS_ASSERT(NULL != pdrgpbsSubsets); if (ulIndex == size) { pdrgpbsSubsets->Append(pbsCurrent); return; } CBitSet *pbsCopy = GPOS_NEW(mp) CBitSet(mp, *pbsCurrent); #ifdef GPOS_DEBUG BOOL fSet = #endif // GPOS_DEBUG pbsCopy->ExchangeSet(pulElems[ulIndex]); GPOS_ASSERT(!fSet); GenerateSubsets(mp, pbsCopy, pulElems, size, ulIndex + 1, pdrgpbsSubsets); GenerateSubsets(mp, pbsCurrent, pulElems, size, ulIndex + 1, pdrgpbsSubsets); }
//--------------------------------------------------------------------------- // @function: // CJoinOrderDP::PexprJoin // // @doc: // Join expressions in the given set // //--------------------------------------------------------------------------- CExpression * CJoinOrderDP::PexprJoin ( CBitSet *pbs ) { GPOS_ASSERT(2 == pbs->Size()); CBitSetIter bsi(*pbs); (void) bsi.Advance(); ULONG ulCompFst = bsi.Bit(); (void) bsi.Advance(); ULONG ulCompSnd = bsi.Bit(); GPOS_ASSERT(!bsi.Advance()); CBitSet *pbsFst = GPOS_NEW(m_mp) CBitSet(m_mp); (void) pbsFst->ExchangeSet(ulCompFst); CBitSet *pbsSnd = GPOS_NEW(m_mp) CBitSet(m_mp); (void) pbsSnd->ExchangeSet(ulCompSnd); CExpression *pexprScalar = PexprPred(pbsFst, pbsSnd); pbsFst->Release(); pbsSnd->Release(); if (NULL == pexprScalar) { return NULL; } CExpression *pexprLeft = m_rgpcomp[ulCompFst]->m_pexpr; CExpression *pexprRight = m_rgpcomp[ulCompSnd]->m_pexpr; pexprLeft->AddRef(); pexprRight->AddRef(); pexprScalar->AddRef(); CExpression *pexprJoin = CUtils::PexprLogicalJoin<CLogicalInnerJoin>(m_mp, pexprLeft, pexprRight, pexprScalar); DeriveStats(pexprJoin); // store solution in DP table pbs->AddRef(); #ifdef GPOS_DEBUG BOOL fInserted = #endif // GPOS_DEBUG m_phmbsexpr->Insert(pbs, pexprJoin); GPOS_ASSERT(fInserted); return pexprJoin; }
//--------------------------------------------------------------------------- // @function: // CJoinOrderDP::PexprBuildPred // // @doc: // Build predicate connecting the two given sets // //--------------------------------------------------------------------------- CExpression * CJoinOrderDP::PexprBuildPred ( CBitSet *pbsFst, CBitSet *pbsSnd ) { // collect edges connecting the given sets CBitSet *pbsEdges = GPOS_NEW(m_mp) CBitSet(m_mp); CBitSet *pbs = GPOS_NEW(m_mp) CBitSet(m_mp, *pbsFst); pbs->Union(pbsSnd); for (ULONG ul = 0; ul < m_ulEdges; ul++) { SEdge *pedge = m_rgpedge[ul]; if ( pbs->ContainsAll(pedge->m_pbs) && !pbsFst->IsDisjoint(pedge->m_pbs) && !pbsSnd->IsDisjoint(pedge->m_pbs) ) { #ifdef GPOS_DEBUG BOOL fSet = #endif // GPOS_DEBUG pbsEdges->ExchangeSet(ul); GPOS_ASSERT(!fSet); } } pbs->Release(); CExpression *pexprPred = NULL; if (0 < pbsEdges->Size()) { CExpressionArray *pdrgpexpr = GPOS_NEW(m_mp) CExpressionArray(m_mp); CBitSetIter bsi(*pbsEdges); while (bsi.Advance()) { ULONG ul = bsi.Bit(); SEdge *pedge = m_rgpedge[ul]; pedge->m_pexpr->AddRef(); pdrgpexpr->Append(pedge->m_pexpr); } pexprPred = CPredicateUtils::PexprConjunction(m_mp, pdrgpexpr); } pbsEdges->Release(); return pexprPred; }
//--------------------------------------------------------------------------- // @function: // CJoinOrderDP::PexprExpand // // @doc: // Create join order // //--------------------------------------------------------------------------- CExpression * CJoinOrderDP::PexprExpand() { CBitSet *pbs = GPOS_NEW(m_mp) CBitSet(m_mp); for (ULONG ul = 0; ul < m_ulComps; ul++) { (void) pbs->ExchangeSet(ul); } CExpression *pexprResult = PexprBestJoinOrder(pbs); if (NULL != pexprResult) { pexprResult->AddRef(); } pbs->Release(); return pexprResult; }
//--------------------------------------------------------------------------- // @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); }
//--------------------------------------------------------------------------- // @function: // CPartConstraint::PpartcnstrDisjunction // // @doc: // Construct a disjunction of the two part constraints. We can only // construct this disjunction if they differ only on the last level // //--------------------------------------------------------------------------- CPartConstraint * CPartConstraint::PpartcnstrDisjunction ( IMemoryPool *mp, CPartConstraint *ppartcnstrFst, CPartConstraint *ppartcnstrSnd ) { GPOS_ASSERT(NULL != ppartcnstrFst); GPOS_ASSERT(NULL != ppartcnstrSnd); if (ppartcnstrFst->IsConstraintUnbounded()) { ppartcnstrFst->AddRef(); return ppartcnstrFst; } if (ppartcnstrSnd->IsConstraintUnbounded()) { ppartcnstrSnd->AddRef(); return ppartcnstrSnd; } if (!FDisjunctionPossible(ppartcnstrFst, ppartcnstrSnd)) { return NULL; } UlongToConstraintMap *phmulcnstr = GPOS_NEW(mp) UlongToConstraintMap(mp); CBitSet *pbsCombined = GPOS_NEW(mp) CBitSet(mp); const ULONG ulLevels = ppartcnstrFst->m_num_of_part_levels; for (ULONG ul = 0; ul < ulLevels-1; ul++) { CConstraint *pcnstrFst = ppartcnstrFst->Pcnstr(ul); pcnstrFst->AddRef(); #ifdef GPOS_DEBUG BOOL result = #endif // GPOS_DEBUG phmulcnstr->Insert(GPOS_NEW(mp) ULONG(ul), pcnstrFst); GPOS_ASSERT(result); if (ppartcnstrFst->IsDefaultPartition(ul)) { pbsCombined->ExchangeSet(ul); } } // create the disjunction between the constraints of the last level CConstraint *pcnstrFst = ppartcnstrFst->Pcnstr(ulLevels - 1); CConstraint *pcnstrSnd = ppartcnstrSnd->Pcnstr(ulLevels - 1); pcnstrFst->AddRef(); pcnstrSnd->AddRef(); CConstraintArray *pdrgpcnstrCombined = GPOS_NEW(mp) CConstraintArray(mp); pdrgpcnstrCombined->Append(pcnstrFst); pdrgpcnstrCombined->Append(pcnstrSnd); CConstraint *pcnstrDisj = CConstraint::PcnstrDisjunction(mp, pdrgpcnstrCombined); GPOS_ASSERT(NULL != pcnstrDisj); #ifdef GPOS_DEBUG BOOL result = #endif // GPOS_DEBUG phmulcnstr->Insert(GPOS_NEW(mp) ULONG(ulLevels - 1), pcnstrDisj); GPOS_ASSERT(result); if (ppartcnstrFst->IsDefaultPartition(ulLevels - 1) || ppartcnstrSnd->IsDefaultPartition(ulLevels - 1)) { pbsCombined->ExchangeSet(ulLevels - 1); } CColRef2dArray *pdrgpdrgpcr = ppartcnstrFst->Pdrgpdrgpcr(); pdrgpdrgpcr->AddRef(); return GPOS_NEW(mp) CPartConstraint(mp, phmulcnstr, pbsCombined, false /*is_unbounded*/, pdrgpdrgpcr); }