//--------------------------------------------------------------------------- // @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; }