//--------------------------------------------------------------------------- // @function: // CJoinOrderDP::PexprExpand // // @doc: // Create join order // //--------------------------------------------------------------------------- CExpression * CJoinOrderDP::PexprExpand() { CBitSet *pbs = GPOS_NEW(m_pmp) CBitSet(m_pmp); for (ULONG ul = 0; ul < m_ulComps; ul++) { (void) pbs->FExchangeSet(ul); } if (GPOPT_DP_JOIN_ORDERING_SIZE_THRESHOLD < m_ulComps && GPOPT_DP_JOIN_ORDERING_CONNECTEDNESS_THRESHOLD < DMaxConnectedness(pbs)) { // terminate early if computation cost is expected to be large pbs->Release(); return NULL; } CExpression *pexprResult = PexprBestJoinOrder(pbs); if (NULL != pexprResult) { pexprResult->AddRef(); } pbs->Release(); return pexprResult; }
//--------------------------------------------------------------------------- // @function: // CBitSetTest::EresUnittest_Performance // // @doc: // Simple perf test -- simulates xform candidate sets // //--------------------------------------------------------------------------- GPOS_RESULT CBitSetTest::EresUnittest_Performance() { // create memory pool CAutoMemoryPool amp; IMemoryPool *pmp = amp.Pmp(); ULONG cSizeBits = 512; CBitSet *pbsBase = GPOS_NEW(pmp) CBitSet(pmp, cSizeBits); for (ULONG i = 0; i < cSizeBits; i++) { (void) pbsBase->FExchangeSet(i); } CBitSet *pbsTest = GPOS_NEW(pmp) CBitSet(pmp, cSizeBits); for (ULONG j = 0; j < 100000; j++) { ULONG cRandomBits = 16; for (ULONG i = 0; i < cRandomBits; i += ((cSizeBits - 1) / cRandomBits)) { (void) pbsTest->FExchangeSet(i); } pbsTest->Intersection(pbsBase); } pbsTest->Release(); pbsBase->Release(); return GPOS_OK; }
//--------------------------------------------------------------------------- // @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: // CTranslatorDXLToExprUtils::AddKeySets // // @doc: // Add key sets info from the MD relation to the table descriptor // //--------------------------------------------------------------------------- void CTranslatorDXLToExprUtils::AddKeySets ( IMemoryPool *pmp, CTableDescriptor *ptabdesc, const IMDRelation *pmdrel, HMUlUl *phmululColMapping ) { GPOS_ASSERT(NULL != ptabdesc); GPOS_ASSERT(NULL != pmdrel); const ULONG ulKeySets = pmdrel->UlKeySets(); for (ULONG ul = 0; ul < ulKeySets; ul++) { CBitSet *pbs = GPOS_NEW(pmp) CBitSet(pmp, ptabdesc->UlColumns()); const DrgPul *pdrgpulKeys = pmdrel->PdrgpulKeyset(ul); const ULONG ulKeys = pdrgpulKeys->UlLength(); for (ULONG ulKey = 0; ulKey < ulKeys; ulKey++) { // populate current keyset ULONG ulOriginalKey = *((*pdrgpulKeys)[ulKey]); ULONG *pulRemappedKey = phmululColMapping->PtLookup(&ulOriginalKey); GPOS_ASSERT(NULL != pulRemappedKey); pbs->FExchangeSet(*pulRemappedKey); } if (!ptabdesc->FAddKeySet(pbs)) { pbs->Release(); } } }
//--------------------------------------------------------------------------- // @function: // CLogicalGbAggDeduplicate::PstatsDerive // // @doc: // Derive statistics // //--------------------------------------------------------------------------- IStatistics * CLogicalGbAggDeduplicate::PstatsDerive ( IMemoryPool *pmp, CExpressionHandle &exprhdl, DrgPstat * // not used ) const { GPOS_ASSERT(Esp(exprhdl) > EspNone); IStatistics *pstatsChild = exprhdl.Pstats(0); // extract computed columns DrgPul *pdrgpulComputedCols = GPOS_NEW(pmp) DrgPul(pmp); exprhdl.Pdpscalar(1 /*ulChildIndex*/)->PcrsDefined()->ExtractColIds(pmp, pdrgpulComputedCols); // construct bitset with keys of join child CBitSet *pbsKeys = GPOS_NEW(pmp) CBitSet(pmp); const ULONG ulKeys = m_pdrgpcrKeys->UlLength(); for (ULONG ul = 0; ul < ulKeys; ul++) { CColRef *pcr = (*m_pdrgpcrKeys)[ul]; pbsKeys->FExchangeSet(pcr->UlId()); } IStatistics *pstats = CLogicalGbAgg::PstatsDerive(pmp, pstatsChild, Pdrgpcr(), pdrgpulComputedCols, pbsKeys); pbsKeys->Release(); pdrgpulComputedCols->Release(); return pstats; }
//--------------------------------------------------------------------------- // @function: // CBitSetTest::EresUnittest_Basics // // @doc: // Testing ctors/dtor // //--------------------------------------------------------------------------- GPOS_RESULT CBitSetTest::EresUnittest_Basics() { // create memory pool CAutoMemoryPool amp; IMemoryPool *pmp = amp.Pmp(); ULONG cSizeBits = 32; CBitSet *pbs = GPOS_NEW(pmp) CBitSet(pmp, cSizeBits); ULONG cInserts = 10; for (ULONG i = 0; i < cInserts; i += 2) { // forces addition of new link pbs->FExchangeSet(i * cSizeBits); } GPOS_ASSERT(cInserts / 2 == pbs->CElements()); for (ULONG i = 1; i < cInserts; i += 2) { // new link between existing links pbs->FExchangeSet(i * cSizeBits); } GPOS_ASSERT(cInserts == pbs->CElements()); CBitSet *pbsCopy = GPOS_NEW(pmp) CBitSet(pmp, *pbs); GPOS_ASSERT(pbsCopy->FEqual(pbs)); // delete old bitset to make sure we're not accidentally // using any of its memory pbs->Release(); for (ULONG i = 0; i < cInserts; i++) { GPOS_ASSERT(pbsCopy->FBit(i * cSizeBits)); } CWStringDynamic str(pmp); COstreamString os(&str); os << *pbsCopy << std::endl; GPOS_TRACE(str.Wsz()); pbsCopy->Release(); return GPOS_OK; }
//--------------------------------------------------------------------------- // @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: // CBitSetTest::EresUnittest_SetOps // // @doc: // Test for set operations // //--------------------------------------------------------------------------- GPOS_RESULT CBitSetTest::EresUnittest_SetOps() { // create memory pool CAutoMemoryPool amp; IMemoryPool *pmp = amp.Pmp(); ULONG cSizeBits = 32; ULONG cInserts = 10; CBitSet *pbs1 = GPOS_NEW(pmp) CBitSet(pmp, cSizeBits); for (ULONG i = 0; i < cInserts; i += 2) { pbs1->FExchangeSet(i * cSizeBits); } CBitSet *pbs2 = GPOS_NEW(pmp) CBitSet(pmp, cSizeBits); for (ULONG i = 1; i < cInserts; i += 2) { pbs2->FExchangeSet(i * cSizeBits); } CBitSet *pbs = GPOS_NEW(pmp) CBitSet(pmp, cSizeBits); pbs->Union(pbs1); GPOS_ASSERT(pbs->FEqual(pbs1)); pbs->Intersection(pbs1); GPOS_ASSERT(pbs->FEqual(pbs1)); GPOS_ASSERT(pbs->FEqual(pbs)); GPOS_ASSERT(pbs1->FEqual(pbs1)); pbs->Union(pbs2); GPOS_ASSERT(!pbs->FEqual(pbs1) && !pbs->FEqual(pbs2)); GPOS_ASSERT(pbs->FSubset(pbs1) && pbs->FSubset(pbs2)); pbs->Difference(pbs2); GPOS_ASSERT(pbs->FEqual(pbs1)); pbs1->Release(); pbs->Union(pbs2); pbs->Intersection(pbs2); GPOS_ASSERT(pbs->FEqual(pbs2)); GPOS_ASSERT(pbs->FSubset(pbs2)); GPOS_ASSERT(pbs->CElements() == pbs2->CElements()); pbs2->Release(); pbs->Release(); return GPOS_OK; }
//--------------------------------------------------------------------------- // @function: // CSerializableOptimizerConfig::Serialize // // @doc: // Serialize contents into provided stream // //--------------------------------------------------------------------------- void CSerializableOptimizerConfig::Serialize ( COstream &oos ) { CXMLSerializer xml_serializer(m_mp, oos, false /*Indent*/); // Copy traceflags from global state CBitSet *pbs = CTask::Self()->GetTaskCtxt()->copy_trace_flags(m_mp); m_optimizer_config->Serialize(m_mp, &xml_serializer, pbs); pbs->Release(); }
//--------------------------------------------------------------------------- // @function: // CBitSetTest::EresUnittest_Removal // // @doc: // Cleanup test // //--------------------------------------------------------------------------- GPOS_RESULT CBitSetTest::EresUnittest_Removal() { // create memory pool CAutoMemoryPool amp; IMemoryPool *pmp = amp.Pmp(); ULONG cSizeBits = 32; CBitSet *pbs = GPOS_NEW(pmp) CBitSet(pmp, cSizeBits); CBitSet *pbsEmpty = GPOS_NEW(pmp) CBitSet(pmp, cSizeBits); GPOS_ASSERT(pbs->FEqual(pbsEmpty)); GPOS_ASSERT(pbsEmpty->FEqual(pbs)); ULONG cInserts = 10; for (ULONG i = 0; i < cInserts; i++) { pbs->FExchangeSet(i * cSizeBits); GPOS_ASSERT(i + 1 == pbs->CElements()); } for (ULONG i = 0; i < cInserts; i++) { // cleans up empty links pbs->FExchangeClear(i * cSizeBits); GPOS_ASSERT(cInserts - i - 1 == pbs->CElements()); } GPOS_ASSERT(pbs->FEqual(pbsEmpty)); GPOS_ASSERT(pbsEmpty->FEqual(pbs)); pbs->Release(); pbsEmpty->Release(); return GPOS_OK; }
//--------------------------------------------------------------------------- // @function: // CTranslatorDXLToQuery::MarkUnusedColumns // // @doc: // Mark unused target list entries in the setop child // //--------------------------------------------------------------------------- void CTranslatorDXLToQuery::MarkUnusedColumns ( Query *pquery, RangeTblRef *prtref, CStateDXLToQuery *pstatedxltoquery, const DrgPul *pdrgpulColids ) { const ULONG ulRTIndex = prtref->rtindex; RangeTblEntry *prte = (RangeTblEntry*) gpdb::PvListNth(pquery->rtable, ulRTIndex -1); GPOS_ASSERT(RTE_SUBQUERY == prte->rtekind); Query *pqueryDerTbl = prte->subquery; // maintain the list of used columns in a bit set CBitSet *pds = New(m_pmp) CBitSet(m_pmp); const ULONG ulLen = pdrgpulColids->UlLength(); for (ULONG ul = 0; ul < ulLen; ul++) { ULONG ulValue = *((*pdrgpulColids)[ul]); (void) pds->FExchangeSet(ulValue); } // Mark all columns that are not in the list of required input columns as being unused const ULONG ulSize = pstatedxltoquery->UlLength(); for (ULONG ul = 0; ul < ulSize; ul++) { ULONG ulColId = pstatedxltoquery->UlColId(ul); BOOL fSet = pds->FBit(ulColId); if (!fSet) { // mark the column as unused in the query TargetEntry *pte2 = (TargetEntry*) gpdb::PvListNth(pqueryDerTbl->targetList, ul); pte2->resjunk = true; // mark the column as unused in the state TargetEntry *pte = pstatedxltoquery->PteColumn(ul); pte->resjunk = true; } } pds->Release(); }
//--------------------------------------------------------------------------- // @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: // CJoinOrderDP::DConnectedness // // @doc: // Return connectedness measure of given component // //--------------------------------------------------------------------------- CDouble CJoinOrderDP::DConnectedness ( ULONG ulComp ) { CBitSet *pbsConnected = GPOS_NEW(m_pmp) CBitSet(m_pmp); for (ULONG ul = 0; ul < m_ulEdges; ul++) { SEdge *pedge = m_rgpedge[ul]; if (pedge->m_pbs->FBit(ulComp)) { pbsConnected->Union(pedge->m_pbs); } } (void) pbsConnected->FExchangeClear(ulComp); DOUBLE dConnectedness = (DOUBLE) pbsConnected->CElements() / m_ulComps; pbsConnected->Release(); return CDouble(dConnectedness); }
//--------------------------------------------------------------------------- // @function: // CPartitionPropagationSpec::SplitPartPredicates // // @doc: // Split the partition elimination predicates over the various levels // as well as the residual predicate and add them to the appropriate // hashmaps. These are to be used when creating the partition selector // //--------------------------------------------------------------------------- void CPartitionPropagationSpec::SplitPartPredicates ( IMemoryPool *mp, CExpression *pexprScalar, CColRef2dArray *pdrgpdrgpcrKeys, UlongToExprMap *phmulexprEqFilter, // output UlongToExprMap *phmulexprFilter, // output CExpression **ppexprResidual // output ) { GPOS_ASSERT(NULL != pexprScalar); GPOS_ASSERT(NULL != pdrgpdrgpcrKeys); GPOS_ASSERT(NULL != phmulexprEqFilter); GPOS_ASSERT(NULL != phmulexprFilter); GPOS_ASSERT(NULL != ppexprResidual); GPOS_ASSERT(NULL == *ppexprResidual); CExpressionArray *pdrgpexprConjuncts = CPredicateUtils::PdrgpexprConjuncts(mp, pexprScalar); CBitSet *pbsUsed = GPOS_NEW(mp) CBitSet(mp); CColRefSet *pcrsKeys = PcrsKeys(mp, pdrgpdrgpcrKeys); const ULONG ulLevels = pdrgpdrgpcrKeys->Size(); for (ULONG ul = 0; ul < ulLevels; ul++) { CColRef *colref = CUtils::PcrExtractPartKey(pdrgpdrgpcrKeys, ul); // find conjuncts for this key and mark their positions CExpressionArray *pdrgpexprKey = PdrgpexprPredicatesOnKey(mp, pdrgpexprConjuncts, colref, pcrsKeys, &pbsUsed); const ULONG length = pdrgpexprKey->Size(); if (length == 0) { // no predicates on this key pdrgpexprKey->Release(); continue; } if (length == 1 && CPredicateUtils::FIdentCompare((*pdrgpexprKey)[0], IMDType::EcmptEq, colref)) { // EqFilters // one equality predicate (key = expr); take out the expression // and add it to the equality filters map CExpression *pexprPartKey = NULL; CExpression *pexprOther = NULL; IMDType::ECmpType cmp_type = IMDType::EcmptOther; CPredicateUtils::ExtractComponents((*pdrgpexprKey)[0], colref, &pexprPartKey, &pexprOther, &cmp_type); GPOS_ASSERT(NULL != pexprOther); pexprOther->AddRef(); #ifdef GPOS_DEBUG BOOL result = #endif // GPOS_DEBUG phmulexprEqFilter->Insert(GPOS_NEW(mp) ULONG(ul), pexprOther); GPOS_ASSERT(result); pdrgpexprKey->Release(); } else { // Filters // more than one predicate on this key or one non-simple-equality predicate #ifdef GPOS_DEBUG BOOL result = #endif // GPOS_DEBUG phmulexprFilter->Insert(GPOS_NEW(mp) ULONG(ul), CPredicateUtils::PexprConjunction(mp, pdrgpexprKey)); GPOS_ASSERT(result); continue; } } (*ppexprResidual) = PexprResidualFilter(mp, pdrgpexprConjuncts, pbsUsed); pcrsKeys->Release(); pdrgpexprConjuncts->Release(); pbsUsed->Release(); }
//--------------------------------------------------------------------------- // @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: // CPartitionPropagationSpec::SplitPartPredicates // // @doc: // Split the partition elimination predicates over the various levels // as well as the residual predicate and add them to the appropriate // hashmaps. These are to be used when creating the partition selector // //--------------------------------------------------------------------------- void CPartitionPropagationSpec::SplitPartPredicates ( IMemoryPool *pmp, CExpression *pexprScalar, DrgDrgPcr *pdrgpdrgpcrKeys, HMUlExpr *phmulexprEqFilter, // output HMUlExpr *phmulexprFilter, // output CExpression **ppexprResidual // output ) { GPOS_ASSERT(NULL != pexprScalar); GPOS_ASSERT(NULL != pdrgpdrgpcrKeys); GPOS_ASSERT(NULL != phmulexprEqFilter); GPOS_ASSERT(NULL != phmulexprFilter); GPOS_ASSERT(NULL != ppexprResidual); GPOS_ASSERT(NULL == *ppexprResidual); DrgPexpr *pdrgpexprConjuncts = CPredicateUtils::PdrgpexprConjuncts(pmp, pexprScalar); CBitSet *pbsUsed = GPOS_NEW(pmp) CBitSet(pmp); CColRefSet *pcrsKeys = PcrsKeys(pmp, pdrgpdrgpcrKeys); const ULONG ulLevels = pdrgpdrgpcrKeys->UlLength(); for (ULONG ul = 0; ul < ulLevels; ul++) { CColRef *pcr = CUtils::PcrExtractPartKey(pdrgpdrgpcrKeys, ul); // find conjuncts for this key and mark their positions DrgPexpr *pdrgpexprKey = PdrgpexprPredicatesOnKey(pmp, pdrgpexprConjuncts, pcr, pcrsKeys, &pbsUsed); const ULONG ulLen = pdrgpexprKey->UlLength(); if (0 == ulLen) { // no predicates on this key pdrgpexprKey->Release(); continue; } if (1 < ulLen || (!CPredicateUtils::FEquality((*pdrgpexprKey)[0]))) { // more than one predicate on this key or one non-equality predicate #ifdef GPOS_DEBUG BOOL fResult = #endif // GPOS_DEBUG phmulexprFilter->FInsert(GPOS_NEW(pmp) ULONG(ul), CPredicateUtils::PexprConjunction(pmp, pdrgpexprKey)); GPOS_ASSERT(fResult); continue; } // one equality predicate (key = expr); take out the expression // and add it to the equality filters map CExpression *pexprPartKey = NULL; CExpression *pexprOther = NULL; IMDType::ECmpType ecmpt = IMDType::EcmptOther; CPredicateUtils::ExtractComponents((*pdrgpexprKey)[0], pcr, &pexprPartKey, &pexprOther, &ecmpt); GPOS_ASSERT(NULL != pexprOther); pexprOther->AddRef(); #ifdef GPOS_DEBUG BOOL fResult = #endif // GPOS_DEBUG phmulexprEqFilter->FInsert(GPOS_NEW(pmp) ULONG(ul), pexprOther); GPOS_ASSERT(fResult); pdrgpexprKey->Release(); } (*ppexprResidual) = PexprResidualFilter(pmp, pdrgpexprConjuncts, pbsUsed); pcrsKeys->Release(); pdrgpexprConjuncts->Release(); pbsUsed->Release(); }
//--------------------------------------------------------------------------- // @function: // CJoinOrderDP::PexprBestJoinOrder // // @doc: // find best join order for a given set of elements; // //--------------------------------------------------------------------------- CExpression * CJoinOrderDP::PexprBestJoinOrder ( CBitSet *pbs ) { GPOS_CHECK_STACK_SIZE; GPOS_CHECK_ABORT; GPOS_ASSERT(NULL != pbs); // start by looking-up cost in the DP map CExpression *pexpr = PexprLookup(pbs); if (pexpr == m_pexprDummy) { // no join order could be created return NULL; } if (NULL != pexpr) { // join order is found by looking up map return pexpr; } // find maximal covered subset CBitSet *pbsCovered = PbsCovered(pbs); if (0 == pbsCovered->Size()) { // set is not covered, return a cross product pbsCovered->Release(); return PexprCross(pbs); } if (!pbsCovered->Equals(pbs)) { // create a cross product for uncovered subset CBitSet *pbsUncovered = GPOS_NEW(m_mp) CBitSet(m_mp, *pbs); pbsUncovered->Difference(pbsCovered); CExpression *pexprResult = PexprJoinCoveredSubsetWithUncoveredSubset(pbs, pbsCovered, pbsUncovered); pbsCovered->Release(); pbsUncovered->Release(); return pexprResult; } pbsCovered->Release(); // if set has size 2, there is only one possible solution if (2 == pbs->Size()) { return PexprJoin(pbs); } // otherwise, compute best join order using dynamic programming CExpression *pexprBestJoinOrder = PexprBestJoinOrderDP(pbs); if (pexprBestJoinOrder == m_pexprDummy) { // no join order could be created return NULL; } return pexprBestJoinOrder; }
//--------------------------------------------------------------------------- // @function: // CJoinOrderDP::PexprBestJoinOrderDP // // @doc: // Find the best join order of a given set of elements using dynamic // programming; // given a set of elements (e.g., {A, B, C}), we find all possible splits // of the set (e.g., {A}, {B, C}) where at least one edge connects the // two subsets resulting from the split, // for each split, we find the best join orders of left and right subsets // recursively, // the function finds the split with the least cost, and stores the join // of its two subsets as the best join order of the given set // // //--------------------------------------------------------------------------- CExpression * CJoinOrderDP::PexprBestJoinOrderDP ( CBitSet *pbs // set of elements to be joined ) { CDouble dMinCost(0.0); CExpression *pexprResult = NULL; CBitSetArray *pdrgpbsSubsets = PdrgpbsSubsets(m_mp, pbs); const ULONG ulSubsets = pdrgpbsSubsets->Size(); for (ULONG ul = 0; ul < ulSubsets; ul++) { CBitSet *pbsCurrent = (*pdrgpbsSubsets)[ul]; CBitSet *pbsRemaining = GPOS_NEW(m_mp) CBitSet(m_mp, *pbs); pbsRemaining->Difference(pbsCurrent); // check if subsets are connected with one or more edges CExpression *pexprPred = PexprPred(pbsCurrent, pbsRemaining); if (NULL != pexprPred) { // compute solutions of left and right subsets recursively CExpression *pexprLeft = PexprBestJoinOrder(pbsCurrent); CExpression *pexprRight = PexprBestJoinOrder(pbsRemaining); if (NULL != pexprLeft && NULL != pexprRight) { // we found solutions of left and right subsets, we check if // this gives a better solution for the input set CExpression *pexprJoin = PexprJoin(pbsCurrent, pbsRemaining); CDouble dCost = DCost(pexprJoin); if (NULL == pexprResult || dCost < dMinCost) { // this is the first solution, or we found a better solution dMinCost = dCost; CRefCount::SafeRelease(pexprResult); pexprJoin->AddRef(); pexprResult = pexprJoin; } if (m_ulComps == pbs->Size()) { AddJoinOrder(pexprJoin, dCost); } pexprJoin->Release(); } } pbsRemaining->Release(); } pdrgpbsSubsets->Release(); // store solution in DP table if (NULL == pexprResult) { m_pexprDummy->AddRef(); pexprResult = m_pexprDummy; } DeriveStats(pexprResult); pbs->AddRef(); #ifdef GPOS_DEBUG BOOL fInserted = #endif // GPOS_DEBUG m_phmbsexpr->Insert(pbs, pexprResult); GPOS_ASSERT(fInserted); // add expression cost to cost map InsertExpressionCost(pexprResult, dMinCost, false /*fValidateInsert*/); return pexprResult; }
//--------------------------------------------------------------------------- // @function: // CConfigParamMapping::PbsPack // // @doc: // Pack the GPDB config params into a bitset // //--------------------------------------------------------------------------- CBitSet * CConfigParamMapping::PbsPack ( IMemoryPool *pmp, ULONG ulXforms // number of available xforms ) { CBitSet *pbs = New(pmp) CBitSet(pmp, EopttraceSentinel); for (ULONG ul = 0; ul < GPOS_ARRAY_SIZE(m_elem); ul++) { SConfigMappingElem elem = m_elem[ul]; GPOS_ASSERT(!pbs->FBit((ULONG) elem.m_etf) && "trace flag already set"); BOOL fVal = *elem.m_pfParam; if (elem.m_fNegate) { // negate the value of config param fVal = !fVal; } if (fVal) { #ifdef GPOS_DEBUG BOOL fSet = #endif // GPOS_DEBUG pbs->FExchangeSet((ULONG) elem.m_etf); GPOS_ASSERT(!fSet); } } // pack disable flags of xforms for (ULONG ul = 0; ul < ulXforms; ul++) { GPOS_ASSERT(!pbs->FBit(EopttraceDisableXformBase + ul) && "xform trace flag already set"); if (optimizer_xforms[ul]) { #ifdef GPOS_DEBUG BOOL fSet = #endif // GPOS_DEBUG pbs->FExchangeSet(EopttraceDisableXformBase + ul); GPOS_ASSERT(!fSet); } } // disable index-join if the corresponding GUC is turned off if (!optimizer_enable_indexjoin) { CBitSet *pbsIndexJoin = CXform::PbsIndexJoinXforms(pmp); pbs->Union(pbsIndexJoin); pbsIndexJoin->Release(); } // disable bitmap scan if the corresponding GUC is turned off if (!optimizer_enable_bitmapscan) { CBitSet *pbsBitmapScan = CXform::PbsBitmapIndexXforms(pmp); pbs->Union(pbsBitmapScan); pbsBitmapScan->Release(); } // disable outerjoin to unionall transformation if GUC is turned off if (!optimizer_enable_outerjoin_to_unionall_rewrite) { pbs->FExchangeSet(GPOPT_DISABLE_XFORM_TF(CXform::ExfLeftOuter2InnerUnionAllLeftAntiSemiJoin)); } // disable Assert MaxOneRow plans if GUC is turned off if (!optimizer_enable_assert_maxonerow) { pbs->FExchangeSet(GPOPT_DISABLE_XFORM_TF(CXform::ExfMaxOneRow2Assert)); } if (!optimizer_enable_partial_index) { CBitSet *pbsHeterogeneousIndex = CXform::PbsHeterogeneousIndexXforms(pmp); pbs->Union(pbsHeterogeneousIndex); pbsHeterogeneousIndex->Release(); } return pbs; }