//--------------------------------------------------------------------------- // @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: // 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: // 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: // 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); }
// *************************************************************************** CBitSet CBitSet::operator~() const { CBitSet ret; ret= *this; ret.flip(); return ret; }
//--------------------------------------------------------------------------- // @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: // CLogicalGet::OsPrint // // @doc: // debug print // //--------------------------------------------------------------------------- IOstream & CLogicalGet::OsPrint ( IOstream &os ) const { if (m_fPattern) { return COperator::OsPrint(os); } else { os << SzId() << " "; // alias of table as referenced in the query m_pnameAlias->OsPrint(os); // actual name of table in catalog and columns os << " ("; m_ptabdesc->Name().OsPrint(os); os << "), Columns: ["; CUtils::OsPrintDrgPcr(os, m_pdrgpcrOutput); os << "] Key sets: {"; const ULONG ulColumns = m_pdrgpcrOutput->Size(); const CBitSetArray *pdrgpbsKeys = m_ptabdesc->PdrgpbsKeys(); for (ULONG ul = 0; ul < pdrgpbsKeys->Size(); ul++) { CBitSet *pbs = (*pdrgpbsKeys)[ul]; if (0 < ul) { os << ", "; } os << "["; ULONG ulPrintedKeys = 0; for (ULONG ulKey = 0; ulKey < ulColumns; ulKey++) { if (pbs->Get(ulKey)) { if (0 < ulPrintedKeys) { os << ","; } os << ulKey; ulPrintedKeys++; } } os << "]"; } os << "}"; } return os; }
//--------------------------------------------------------------------------- // @function: // CPhysicalDML::PosComputeRequired // // @doc: // Compute required sort order based on the key information in the table // descriptor: // 1. If a table has no keys, no sort order is necessary. // // 2. If a table has keys, but they are not modified in the update, no sort // order is necessary. This relies on the fact that Split always produces // Delete tuples before Insert tuples, so we cannot have two versions of the // same tuple on the same time. Consider for example tuple (A: 1, B: 2), where // A is key and an update "set B=B+1". Since there cannot be any other tuple // with A=1, and the tuple (1,2) is deleted before tuple (1,3) gets inserted, // we don't need to enforce specific order of deletes and inserts. // // 3. If the update changes a key column, enforce order on the Action column // to deliver Delete tuples before Insert tuples. This is done to avoid a // conflict between a newly inserted tuple and an old tuple that is about to be // deleted. Consider table with tuples (A: 1),(A: 2), where A is key, and // update "set A=A+1". Split will generate tuples (1,"D"), (2,"I"), (2,"D"), (3,"I"). // If (2,"I") happens before (2,"D") we will have a violation of the key constraint. // Therefore we need to enforce sort order on Action to get all old tuples // tuples deleted before the new ones are inserted. // //--------------------------------------------------------------------------- COrderSpec * CPhysicalDML::PosComputeRequired ( IMemoryPool *pmp, CTableDescriptor *ptabdesc ) { COrderSpec *pos = GPOS_NEW(pmp) COrderSpec(pmp); const DrgPbs *pdrgpbsKeys = ptabdesc->PdrgpbsKeys(); if (1 < pdrgpbsKeys->UlLength() && CLogicalDML::EdmlUpdate == m_edmlop) { // if this is an update on the target table's keys, enforce order on // the action column, see explanation in function's comment const ULONG ulKeySets = pdrgpbsKeys->UlLength(); BOOL fNeedsSort = false; for (ULONG ul = 0; ul < ulKeySets && !fNeedsSort; ul++) { CBitSet *pbs = (*pdrgpbsKeys)[ul]; if (!pbs->FDisjoint(m_pbsModified)) { fNeedsSort = true; break; } } if (fNeedsSort) { IMDId *pmdid = m_pcrAction->Pmdtype()->PmdidCmp(IMDType::EcmptL); pmdid->AddRef(); pos->Append(pmdid, m_pcrAction, COrderSpec::EntAuto); } } else if (m_ptabdesc->FPartitioned()) { COptimizerConfig *poconf = COptCtxt::PoctxtFromTLS()->Poconf(); BOOL fInsertSortOnParquet = FInsertSortOnParquet(); BOOL fInsertSortOnRows = FInsertSortOnRows(poconf); if (fInsertSortOnParquet || fInsertSortOnRows) { GPOS_ASSERT(CLogicalDML::EdmlInsert == m_edmlop); m_fInputSorted = true; // if this is an INSERT over a partitioned Parquet or Row-oriented table, // sort tuples by their table oid IMDId *pmdid = m_pcrTableOid->Pmdtype()->PmdidCmp(IMDType::EcmptL); pmdid->AddRef(); pos->Append(pmdid, m_pcrTableOid, COrderSpec::EntAuto); } } return pos; }
//--------------------------------------------------------------------------- // @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: // CXformImplementDML::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformImplementDML::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); CLogicalDML *popDML = CLogicalDML::PopConvert(pexpr->Pop()); IMemoryPool *mp = pxfctxt->Pmp(); // extract components for alternative CLogicalDML::EDMLOperator edmlop = popDML->Edmlop(); CTableDescriptor *ptabdesc = popDML->Ptabdesc(); ptabdesc->AddRef(); CColRefArray *pdrgpcrSource = popDML->PdrgpcrSource(); pdrgpcrSource->AddRef(); CBitSet *pbsModified = popDML->PbsModified(); pbsModified->AddRef(); CColRef *pcrAction = popDML->PcrAction(); CColRef *pcrTableOid = popDML->PcrTableOid(); CColRef *pcrCtid = popDML->PcrCtid(); CColRef *pcrSegmentId = popDML->PcrSegmentId(); CColRef *pcrTupleOid = popDML->PcrTupleOid(); // child of DML operator CExpression *pexprChild = (*pexpr)[0]; pexprChild->AddRef(); // create physical DML CExpression *pexprAlt = GPOS_NEW(mp) CExpression ( mp, GPOS_NEW(mp) CPhysicalDML(mp, edmlop, ptabdesc, pdrgpcrSource, pbsModified, pcrAction, pcrTableOid, pcrCtid, pcrSegmentId, pcrTupleOid), pexprChild ); // add alternative to transformation result pxfres->Add(pexprAlt); }
//--------------------------------------------------------------------------- // @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: // 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: // 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::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::PbsCovered // // @doc: // Return a subset of the given set covered by one or more edges // //--------------------------------------------------------------------------- CBitSet * CJoinOrderDP::PbsCovered ( CBitSet *pbsInput ) { GPOS_ASSERT(NULL != pbsInput); CBitSet *pbs = GPOS_NEW(m_mp) CBitSet(m_mp); for (ULONG ul = 0; ul < m_ulEdges; ul++) { SEdge *pedge = m_rgpedge[ul]; if (pbsInput->ContainsAll(pedge->m_pbs)) { pbs->Union(pedge->m_pbs); } } return pbs; }
//--------------------------------------------------------------------------- // @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: // 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::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: // 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: // 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: // 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; }
void DecodeISDNMessage(ofstream f, CString message ) { sGlobalDefs gvars; gvars.GlobalCallReference = false; bool decodeOk = true; int bi=0; message.TrimLeft(); message.TrimRight(); BYTE Protocol=0; try { Protocol=GetByte(message,bi++); SetFont(f,ElementType(0,IE_PROTOCOL_DISCRIMINATOR)); decodeOk=DecodeProtocol(f,INDENT_SIZE,Protocol); f<<eFont; f<<Break<<endl; } catch (CPException se) { decodeOk=false; } BYTE crefl; if ( decodeOk ) { try { crefl = GetByte(message,bi++); } catch (CPException se) { decodeOk=false; } } if ( decodeOk ) { SetFont(f,ElementType(0,IE_CALL_REFERENCE)); decodeOk=DecodeCallReferenceLength(f,3,crefl); if (decodeOk) { int callRefLen = (crefl & 0x0f); // should be one or two only if ( callRefLen != 0 ) { BYTE CallRef[2] = { 0,0 }; for (int j=0; j<crefl; j++) try { CallRef[j]=GetByte(message,bi++); } catch (CPException se) { f<<"**Not enough Call Reference data**"<<Break<<endl; decodeOk = false; } if ( decodeOk ) DecodeCallReference(f,INDENT_SIZE,crefl,CallRef[0],CallRef[1]); } } f<<eFont; f<<Break<<endl; } BYTE MessageType; if ( decodeOk ) { try { MessageType = GetByte(message,bi++); } catch (CPException se) { decodeOk=false; } } CBitSet elements; if ( decodeOk ) { SetFont(f,ElementType(MessageType,IE_MESSAGE_TYPE)); DecodeMessageType(f,INDENT_SIZE,Protocol,MessageType); f<<eFont<<endl; } gvars.ActiveCodeSet = 0; int LastActiveCodeSet=0; bool decodeDone=false; while ( decodeOk && !decodeDone) { int ie; try { ie = GetByte(message,bi++); } catch (CPException se) { decodeDone=true; continue; } f << Break << endl; if ( (ie & 0x80) == 0x80 ) { // single octet Information Element SetFont(f,ElementType(MessageType,ie)); if (ie==IE_SENDING_COMPLETE) { f << "ie=" << HexOutput(ie) << Break << "IE="<<IEname(MAKE_FULLIE(gvars.ActiveCodeSet,ie)) << Break << endl; } else if (ie==IE_MORE_DATA) { f << "ie=" << HexOutput(ie) << Break << "IE="<<IEname(MAKE_FULLIE(gvars.ActiveCodeSet,ie)) << Break << endl; } else { BYTE d[1]; switch (ie&0xf0) { case IE_RESERVED: f << "ie=" << HexOutput(ie) << Break << "IE=" << IEname(MAKE_FULLIE(gvars.ActiveCodeSet,ie)) << Break << endl; break; case IE_SHIFT: f << "ie=" << HexOutput(ie) << Break << "IE=" << IEname(MAKE_FULLIE(gvars.ActiveCodeSet,ie)) << Break << endl; d[0]=ie; DecodeShift(f,3,&gvars,d); break; case IE_CONGESTION_LEVEL: f << "ie=" << HexOutput(ie) << Break << "IE=" << IEname(MAKE_FULLIE(gvars.ActiveCodeSet,ie)) << Break << endl; d[0]=ie; DecodeCongestionLevel(f,3,&gvars,d); break; case IE_REPEAT_INDICATOR: f << "ie=" << HexOutput(ie) << Break << "IE=" << IEname(MAKE_FULLIE(gvars.ActiveCodeSet,ie)) << Break << endl; d[0]=ie; DecodeRepeatIndication(f,3,&gvars,d); break; default: f << "**invalid Single Octet IE** (" << HexOutput(ie) << ")" << Break << endl; decodeOk = false; } } f<<eFont<<endl; } else { // multiple octet Information Element SetFont(f,ElementType(MessageType,ie)); int ielen; try { ielen = GetByte(message,bi++); } catch (CPException se ) { // IE is missing its length f << "No IE Length for ie=" << HexOutput(ie) << Break << endl; decodeOk = false; continue; } if ( ielen == 0 ) { f << "IE length cannot be zero for ie=" << HexOutput(ie) << Break << endl; decodeOk = false; continue; } f << "ie=" << HexOutput(ie) << " len=" << HexOutput(ielen) << " data="; int dstat = bi; BYTE iea[64]; memset(iea,0,sizeof(iea)); try { iea[0]=0xff; for (int i=0; i<ielen; i++) { int ieb = GetByte(message,dstat++); f << " " << HexOutput(ieb); iea[i+1]=ieb; iea[0]=i+1; } } catch (CPException se) { f << " **more expected**"; decodeOk=false; } f << Break << endl; if ( decodeOk ) { elements.setBit(ie); f << "IE=" << IEname(MAKE_FULLIE(gvars.ActiveCodeSet,ie)) << Break << endl; psIEDecoderEntry p = &IEDecoders[0]; if ( p != NULL ) { while (p->DecodeFunction!=NULL) { if ((p->CodeSet==gvars.ActiveCodeSet) && ((p->IEid&p->IEidMask)==(ie&p->IEidMask))) { (p->DecodeFunction)(f,INDENT_SIZE,&gvars,iea); break; } p++; } if ( p->DecodeFunction == NULL ) f<<DrawIndent(INDENT_SIZE)<<"!!!NO DECODERS INSTALLED FOR codeset="<<HexOutput(gvars.ActiveCodeSet)<<" ie="<<HexOutput(ie)<<"!!!"<<Break<<endl; } else f<<DrawIndent(INDENT_SIZE)<<"!!!NO DECODERS INSTALLED!!!"<<Break<<endl; } f << eFont; bi = dstat; } // decrement the vars->LockCount. If its zero, restore the ActiveCodeSet if ( gvars.LockCount > 0 ) { gvars.LockCount--; if ( gvars.LockCount == 0 ) gvars.ActiveCodeSet = gvars.LastCodeSet; } } /* if ( decodeOk ) { // Can add some sanity check here to ensure that all the mandatory fields were entered if ( Protocol == PROTOCOL_Q931) { switch (MessageType) { case MESSAGE_ALERTING: break; case MESSAGE_CALL_PROCEEDING: break; case MESSAGE_CONNECT: break; case MESSAGE_CONNECT_ACKNOWLEDGE: break; case MESSAGE_PROGRESS: break; case MESSAGE_SETUP: break; case MESSAGE_SETUP_ACKNOWLEDGE: break; case MESSAGE_RESUME: break; case MESSAGE_RESUME_ACKNOWLEDGE: break; case MESSAGE_RESUME_REJECT: break; case MESSAGE_SUSPEND: break; case MESSAGE_SUSPEND_ACKNOWLEDGE: break; case MESSAGE_SUSPEND_REJECT: break; case MESSAGE_USER_INFORMATION: break; case MESSAGE_DISCONNECT: break; case MESSAGE_RELEASE: break; case MESSAGE_RELEASE_COMPLETE: break; case MESSAGE_RESTART: break; case MESSAGE_RESTART_ACKNOWLEDGE: break; case MESSAGE_SEGMENT: break; case MESSAGE_CONGESTION_CONTROL: break; case MESSAGE_INFORMATION: break; case MESSAGE_FACILITY: break; case MESSAGE_FACILITY_REJECT: break; case MESSAGE_NOTIFY: break; case MESSAGE_STATUS: break; case MESSAGE_STATUS_ENQUIRY: break; default: decodeOk=false; break; } } if ( Protocol == PROTOCOL_MAINTENANCE ) { switch (MessageType) { case MESSAGE_SERVICE: break; case MESSAGE_SERVICE_ACKNOWLEDGE: break; default: decodeOk=false; break; } } } */ }
//--------------------------------------------------------------------------- // @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); }
//--------------------------------------------------------------------------- // @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: // 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: // 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; }