//--------------------------------------------------------------------------- // @function: // CNormalizer::PexprNormalize // // @doc: // Main driver // //--------------------------------------------------------------------------- CExpression * CNormalizer::PexprNormalize ( IMemoryPool *pmp, CExpression *pexpr ) { GPOS_CHECK_STACK_SIZE; GPOS_ASSERT(NULL != pexpr); if (0 == pexpr->UlArity()) { // end recursion early for leaf patterns extracted from memo pexpr->AddRef(); return pexpr; } CExpression *pexprResult = NULL; COperator *pop = pexpr->Pop(); if (pop->FLogical() && CLogical::PopConvert(pop)->FSelectionOp()) { if (FPushThruOuterChild(pexpr)) { CExpression *pexprConstTrue = CUtils::PexprScalarConstBool(pmp, true /*fVal*/); PushThru(pmp, pexpr, pexprConstTrue, &pexprResult); pexprConstTrue->Release(); } else { // add-ref all children except scalar predicate const ULONG ulArity = pexpr->UlArity(); DrgPexpr *pdrgpexpr = GPOS_NEW(pmp) DrgPexpr(pmp); for (ULONG ul = 0; ul < ulArity - 1; ul++) { CExpression *pexprChild = (*pexpr)[ul]; pexprChild->AddRef(); pdrgpexpr->Append(pexprChild); } // normalize scalar predicate and construct a new expression CExpression *pexprPred = (*pexpr)[pexpr->UlArity() - 1]; CExpression *pexprPredNormalized = PexprRecursiveNormalize(pmp, pexprPred); pdrgpexpr->Append(pexprPredNormalized); COperator *pop = pexpr->Pop(); pop->AddRef(); CExpression *pexprNew = GPOS_NEW(pmp) CExpression(pmp, pop, pdrgpexpr); // push normalized predicate through PushThru(pmp, pexprNew, pexprPredNormalized, &pexprResult); pexprNew->Release(); } } else { pexprResult = PexprRecursiveNormalize(pmp, pexpr); } GPOS_ASSERT(NULL != pexprResult); return pexprResult; }
//--------------------------------------------------------------------------- // @function: // CNormalizer::PushThruSetOp // // @doc: // Push a conjunct through set operation // //--------------------------------------------------------------------------- void CNormalizer::PushThruSetOp ( IMemoryPool *pmp, CExpression *pexprSetOp, CExpression *pexprConj, CExpression **ppexprResult ) { GPOS_ASSERT(NULL != pexprSetOp); GPOS_ASSERT(CUtils::FLogicalSetOp(pexprSetOp->Pop())); GPOS_ASSERT(NULL != pexprConj); GPOS_ASSERT(NULL != ppexprResult); CLogicalSetOp *popSetOp = CLogicalSetOp::PopConvert(pexprSetOp->Pop()); DrgPcr *pdrgpcrOutput = popSetOp->PdrgpcrOutput(); CColRefSet *pcrsOutput = GPOS_NEW(pmp) CColRefSet(pmp, pdrgpcrOutput); DrgDrgPcr *pdrgpdrgpcrInput = popSetOp->PdrgpdrgpcrInput(); DrgPexpr *pdrgpexprNewChildren = GPOS_NEW(pmp) DrgPexpr(pmp); const ULONG ulArity = pexprSetOp->UlArity(); for (ULONG ul = 0; ul < ulArity; ul++) { CExpression *pexprChild = (*pexprSetOp)[ul]; DrgPcr *pdrgpcrChild = (*pdrgpdrgpcrInput)[ul]; CColRefSet *pcrsChild = GPOS_NEW(pmp) CColRefSet(pmp, pdrgpcrChild); pexprConj->AddRef(); CExpression *pexprRemappedConj = pexprConj; if (!pcrsChild->FEqual(pcrsOutput)) { // child columns are different from SetOp output columns, // we need to fix conjunct by mapping output columns to child columns, // columns that are not in the output of SetOp child need also to be re-mapped // to new columns, // // for example, if the conjunct looks like 'x > (select max(y) from T)' // and the SetOp child produces only column x, we need to create a new // conjunct that looks like 'x1 > (select max(y1) from T)' // where x1 is a copy of x, and y1 is a copy of y // // this is achieved by passing (fMustExist = True) flag below, which enforces // creating column copies for columns not already in the given map HMUlCr *phmulcr = CUtils::PhmulcrMapping(pmp, pdrgpcrOutput, pdrgpcrChild); pexprRemappedConj->Release(); pexprRemappedConj = pexprConj->PexprCopyWithRemappedColumns(pmp, phmulcr, true /*fMustExist*/); phmulcr->Release(); } CExpression *pexprNewChild = NULL; PushThru(pmp, pexprChild, pexprRemappedConj, &pexprNewChild); pdrgpexprNewChildren->Append(pexprNewChild); pexprRemappedConj->Release(); pcrsChild->Release(); } pcrsOutput->Release(); popSetOp->AddRef(); *ppexprResult = GPOS_NEW(pmp) CExpression(pmp, popSetOp, pdrgpexprNewChildren); }
//--------------------------------------------------------------------------- // @function: // CCNFConverterTest::EresUnittest_Basic // // @doc: // Basic test // //--------------------------------------------------------------------------- GPOS_RESULT CCNFConverterTest::EresUnittest_Basic() { CAutoMemoryPool amp; IMemoryPool *pmp = amp.Pmp(); // setup a file-based provider CMDProviderMemory *pmdp = CTestUtils::m_pmdpf; pmdp->AddRef(); CMDAccessor mda(pmp, CMDCache::Pcache(), CTestUtils::m_sysidDefault, pmdp); typedef CExpression *(*Pfpexpr)(IMemoryPool*); Pfpexpr rgpf[] = { CTestUtils::PexprLogicalSelectWithNestedAnd, CTestUtils::PexprLogicalSelectWithNestedOr, CTestUtils::PexprLogicalSelectWithEvenNestedNot, CTestUtils::PexprLogicalSelectWithOddNestedNot, CTestUtils::PexprLogicalSelectWithNestedAndOrNot }; for (ULONG i = 0; i < GPOS_ARRAY_SIZE(rgpf); i++) { // install opt context in TLS CAutoOptCtxt aoc ( pmp, &mda, NULL, /* pceeval */ CTestUtils::Pcm(pmp) ); // generate expression CExpression *pexpr = rgpf[i](pmp); CExpression *pexprPreprocessed = CExpressionPreprocessor::PexprPreprocess(pmp, pexpr); CWStringDynamic str(pmp); COstreamString oss(&str); oss << std::endl << "SCALAR EXPR:" << std::endl << *(*pexpr)[1] << std::endl; GPOS_TRACE(str.Wsz()); str.Reset(); if (1 < pexprPreprocessed->UlArity()) { CExpression *pexprCNF = CCNFConverter::Pexpr2CNF(pmp, (*pexprPreprocessed)[1]); oss << std::endl << "CNF REPRESENTATION:" << std::endl << *pexprCNF << std::endl; GPOS_TRACE(str.Wsz()); str.Reset(); pexprCNF->Release(); } pexpr->Release(); pexprPreprocessed->Release(); } return GPOS_OK; }
// test cardinality for predicates of the form: a + c = b // for such predicates, NDV based cardinality estimation is not applicable GPOS_RESULT CJoinCardinalityNDVBasedEqPredTest::EresUnittest_NDVCardEstimationNotApplicableMultipleIdents() { // cartesian product / 2.5 // 2.5 = 1/.4 -- where .4 is default selectivity CDouble dRowsExpected(76004000); Fixture f(file_name); IMemoryPool *mp = f.Pmp(); IStatisticsArray *statistics_array = f.PdrgPstat(); CExpression *pexprLgGet = CTestUtils::PexprLogicalGet(mp); CLogicalGet *popGet = CLogicalGet::PopConvert(pexprLgGet->Pop()); CColRefArray *colref_array = popGet->PdrgpcrOutput(); // use the colid available in the input xml file CColRef *pcrLeft1 = (*colref_array)[2]; CColRef *pcrLeft2 = (*colref_array)[1]; CColRef *pcrRight = (*colref_array)[0]; // create a scalar ident // CScalarIdent "column_0000" (0) CExpression *pexprScalarIdentRight = CUtils::PexprScalarIdent(mp, pcrRight); CExpression *pexprScalarIdentLeft2 = CUtils::PexprScalarIdent(mp, pcrLeft2); // create a scalar op expression column_0002 + column_0001 // CScalarOp (+) // |--CScalarIdent "column_0002" (2) // +--CScalarIdent "column_0001" (1) CExpression *pexprScOp = CUtils::PexprScalarOp(mp, pcrLeft1, pexprScalarIdentLeft2, CWStringConst(GPOS_WSZ_LIT("+")), GPOS_NEW(mp) CMDIdGPDB(GPDB_INT4_ADD_OP)); // create a scalar comparision operator // +--CScalarCmp (=) // |--CScalarOp (+) // | |--CScalarIdent "column_0002" (2) // | +--CScalarIdent "column_0001" (1) // +--CScalarIdent "column_0000" (0) CExpression *pScalarCmp = CUtils::PexprScalarEqCmp(mp, pexprScOp, pexprScalarIdentRight); IStatistics *join_stats = CJoinStatsProcessor::CalcAllJoinStats(mp, statistics_array, pScalarCmp, IStatistics::EsjtInnerJoin); GPOS_ASSERT(NULL != join_stats); CDouble dRowsActual(join_stats->Rows()); GPOS_RESULT eres = GPOS_OK; if (floor(dRowsActual.Get()) != dRowsExpected) { eres = GPOS_FAILED; } join_stats->Release(); pexprLgGet->Release(); pScalarCmp->Release(); return eres; }
//--------------------------------------------------------------------------- // @function: // CNormalizer::PushThruSelect // // @doc: // Push a conjunct through a select // //--------------------------------------------------------------------------- void CNormalizer::PushThruSelect ( IMemoryPool *pmp, CExpression *pexprSelect, CExpression *pexprConj, CExpression **ppexprResult ) { GPOS_ASSERT(NULL != pexprConj); GPOS_ASSERT(NULL != ppexprResult); CExpression *pexprLogicalChild = (*pexprSelect)[0]; CExpression *pexprScalarChild = (*pexprSelect)[1]; CExpression *pexprPred = CPredicateUtils::PexprConjunction(pmp, pexprScalarChild, pexprConj); if (CUtils::FScalarConstTrue(pexprPred)) { pexprPred->Release(); *ppexprResult = PexprNormalize(pmp, pexprLogicalChild); return; } COperator::EOperatorId eopid = pexprLogicalChild->Pop()->Eopid(); if (COperator::EopLogicalLeftOuterJoin == eopid) { CExpression *pexprSimplified = NULL; if (FSimplifySelectOnOuterJoin(pmp, pexprLogicalChild, pexprPred, &pexprSimplified)) { // simplification succeeded, normalize resulting expression *ppexprResult = PexprNormalize(pmp, pexprSimplified); pexprPred->Release(); pexprSimplified->Release(); return; } } if (FPushThruOuterChild(pexprLogicalChild)) { PushThruOuterChild(pmp, pexprLogicalChild, pexprPred, ppexprResult); } else { // logical child may not pass all predicates through, we need to collect // unpushable predicates, if any, into a top Select node DrgPexpr *pdrgpexprConjuncts = CPredicateUtils::PdrgpexprConjuncts(pmp, pexprPred); DrgPexpr *pdrgpexprRemaining = NULL; CExpression *pexpr = NULL; PushThru(pmp, pexprLogicalChild, pdrgpexprConjuncts, &pexpr, &pdrgpexprRemaining); *ppexprResult = PexprSelect(pmp, pexpr, pdrgpexprRemaining); pdrgpexprConjuncts->Release(); } pexprPred->Release(); }
// test cardinality for predicates of the form: a + 1 = b // for such predicates, NDV based cardinality estimation is applicable GPOS_RESULT CJoinCardinalityNDVBasedEqPredTest::EresUnittest_NDVEqCardEstimation() { CDouble dRowsExpected(10000); // the minimum cardinality is min(NDV a, NDV b) Fixture f(file_name); IMemoryPool *mp = f.Pmp(); IStatisticsArray *statistics_array = f.PdrgPstat(); CExpression *pexprLgGet = CTestUtils::PexprLogicalGet(mp); CLogicalGet *popGet = CLogicalGet::PopConvert(pexprLgGet->Pop()); CColRefArray *colref_array = popGet->PdrgpcrOutput(); // use the colid available in the input xml file CColRef *pcrLeft = (*colref_array)[2]; CColRef *pcrRight = (*colref_array)[0]; // create a scalar ident // CScalarIdent "column_0000" (0) CExpression *pexprScalarIdentRight = CUtils::PexprScalarIdent(mp, pcrRight); // create a scalar op expression column_0002 + 10 // CScalarOp (+) // |--CScalarIdent "column_0002" (2) // +--CScalarConst (10) CExpression *pexprScConst = CUtils::PexprScalarConstInt4(mp, 10 /* val */); CExpression *pexprScOp = CUtils::PexprScalarOp(mp, pcrLeft, pexprScConst, CWStringConst(GPOS_WSZ_LIT("+")), GPOS_NEW(mp) CMDIdGPDB(GPDB_INT4_ADD_OP)); // create a scalar comparision operator // +--CScalarCmp (=) // |--CScalarOp (+) // | |--CScalarIdent "column_0002" (2) // | +--CScalarConst (10) // +--CScalarIdent "column_0000" (0) CExpression *pScalarCmp = CUtils::PexprScalarEqCmp(mp, pexprScOp, pexprScalarIdentRight); IStatistics *join_stats = CJoinStatsProcessor::CalcAllJoinStats(mp, statistics_array, pScalarCmp, IStatistics::EsjtInnerJoin); GPOS_ASSERT(NULL != join_stats); CDouble dRowsActual(join_stats->Rows()); GPOS_RESULT eres = GPOS_OK; if (std::floor(dRowsActual.Get()) != dRowsExpected) { eres = GPOS_FAILED; } join_stats->Release(); pexprLgGet->Release(); pScalarCmp->Release(); return eres; }
//--------------------------------------------------------------------------- // @function: // CNormalizer::PexprSelect // // @doc: // Return a Select expression, if needed, with a scalar condition made of // given array of conjuncts // //--------------------------------------------------------------------------- CExpression * CNormalizer::PexprSelect ( IMemoryPool *pmp, CExpression *pexpr, DrgPexpr *pdrgpexpr ) { GPOS_ASSERT(NULL != pexpr); GPOS_ASSERT(NULL != pdrgpexpr); if (0 == pdrgpexpr->UlLength()) { // no predicate, return given expression pdrgpexpr->Release(); return pexpr; } // result expression is a select over predicates CExpression *pexprConjunction = CPredicateUtils::PexprConjunction(pmp, pdrgpexpr); CExpression *pexprSelect = CUtils::PexprSafeSelect(pmp, pexpr, pexprConjunction); if (COperator::EopLogicalSelect != pexprSelect->Pop()->Eopid()) { // Select node was pruned, return created expression return pexprSelect; } CExpression *pexprLogicalChild = (*pexprSelect)[0]; COperator::EOperatorId eopidChild = pexprLogicalChild->Pop()->Eopid(); if (COperator::EopLogicalLeftOuterJoin != eopidChild) { // child of Select is not an outer join, return created Select expression return pexprSelect; } // we have a Select on top of Outer Join expression, attempt simplifying expression into InnerJoin CExpression *pexprSimplified = NULL; if (FSimplifySelectOnOuterJoin(pmp, pexprLogicalChild, (*pexprSelect)[1], &pexprSimplified)) { // simplification succeeded, normalize resulting expression pexprSelect->Release(); CExpression *pexprResult = PexprNormalize(pmp, pexprSimplified); pexprSimplified->Release(); return pexprResult; } // simplification failed, return created Select expression return pexprSelect; }
//--------------------------------------------------------------------------- // @function: // CXformExpandNAryJoin::AddSpecifiedJoinOrder // // @doc: // Expand NAry join in the specified order of inputs // //--------------------------------------------------------------------------- void CXformExpandNAryJoin::AddSpecifiedJoinOrder ( IMemoryPool *pmp, CExpression *pexpr, CXformResult *pxfres ) { GPOS_ASSERT(COperator::EopLogicalNAryJoin == pexpr->Pop()->Eopid()); const ULONG ulArity = pexpr->UlArity(); if (4 > ulArity) { return; } // create a join order with same order of given relations (*pexpr)[0]->AddRef(); (*pexpr)[1]->AddRef(); CExpression *pexprJoin = CUtils::PexprLogicalJoin<CLogicalInnerJoin>(pmp, (*pexpr)[0], (*pexpr)[1], CPredicateUtils::PexprConjunction(pmp, NULL)); for (ULONG ul = 2; ul < ulArity - 1; ul++) { (*pexpr)[ul]->AddRef(); pexprJoin = CUtils::PexprLogicalJoin<CLogicalInnerJoin>(pmp, pexprJoin, (*pexpr)[ul], CPredicateUtils::PexprConjunction(pmp, NULL)); } CExpression *pexprScalar = (*pexpr)[ulArity - 1]; pexprScalar->AddRef(); CExpression *pexprSelect = CUtils::PexprLogicalSelect(pmp, pexprJoin, pexprScalar); CExpression *pexprNormalized = CNormalizer::PexprNormalize(pmp, pexprSelect); pexprSelect->Release(); pxfres->Add(pexprNormalized); }
//--------------------------------------------------------------------------- // @function: // CXformGbAggWithMDQA2Join::PexprExpandMDQAs // // @doc: // Expand GbAgg with multiple distinct aggregates into a join of single // distinct aggregates, // return NULL if expansion is not done // //--------------------------------------------------------------------------- CExpression * CXformGbAggWithMDQA2Join::PexprExpandMDQAs ( IMemoryPool *pmp, CExpression *pexpr ) { GPOS_ASSERT(NULL != pexpr); GPOS_ASSERT(COperator::EopLogicalGbAgg == pexpr->Pop()->Eopid()); COperator *pop = pexpr->Pop(); if (CLogicalGbAgg::PopConvert(pop)->FGlobal()) { BOOL fHasMultipleDistinctAggs = CDrvdPropScalar::Pdpscalar((*pexpr)[1]->PdpDerive())->FHasMultipleDistinctAggs(); if (fHasMultipleDistinctAggs) { CExpression *pexprExpanded = PexprMDQAs2Join(pmp, pexpr); // recursively process the resulting expression CExpression *pexprResult = PexprTransform(pmp, pexprExpanded); pexprExpanded->Release(); return pexprResult; } } return NULL; }
CValue* CParser::GetValue(STR_String& txt, bool bFallbackToText) { // returns parsed text into a value, // empty string returns NULL value ! // if bFallbackToText then unparsed stuff is put into text CValue* result=NULL; CExpression* expr = ProcessText(txt); if (expr) { result = expr->Calculate(); expr->Release(); } if (result) { // if the parsed stuff lead to an errorvalue, don't return errors, just NULL if (result->IsError()) { result->Release(); result=NULL; if (bFallbackToText) { if (txt.Length()>0) { result = new CStringValue(txt,""); } } } } return result; }
//--------------------------------------------------------------------------- // @function: // CNormalizer::PexprPullUpProjections // // @doc: // Pulls up logical projects as far as possible, and combines consecutive // projects if possible // //--------------------------------------------------------------------------- CExpression * CNormalizer::PexprPullUpProjections ( IMemoryPool *pmp, CExpression *pexpr ) { GPOS_ASSERT(NULL != pexpr); BOOL fPullUp = true; pexpr->AddRef(); CExpression *pexprOutput = pexpr; while (fPullUp) { fPullUp = false; CExpression *pexprOutputNew = PexprPullUpAndCombineProjects(pmp, pexprOutput, &fPullUp); pexprOutput->Release(); pexprOutput = pexprOutputNew; } GPOS_ASSERT(FLocalColsSubsetOfInputCols(pmp, pexprOutput)); return pexprOutput; }
//--------------------------------------------------------------------------- // @function: // CStatsPredUtils::Pdrgpstatsjoin // // @doc: // Helper function to extract array of statistics join filter from // an expression //--------------------------------------------------------------------------- DrgPstatsjoin * CStatsPredUtils::Pdrgpstatsjoin ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CExpression *pexprScalarInput, DrgPcrs *pdrgpcrsOutput, // array of output columns of join's relational inputs CColRefSet *pcrsOuterRefs ) { GPOS_ASSERT(NULL != pdrgpcrsOutput); // remove implied predicates from join condition to avoid cardinality under-estimation CExpression *pexprScalar = CPredicateUtils::PexprRemoveImpliedConjuncts(pmp, pexprScalarInput, exprhdl); // extract all the conjuncts CStatsPred *pstatspredUnsupported = NULL; DrgPstatsjoin *pdrgpstatsjoin = PdrgpstatsjoinExtract ( pmp, pexprScalar, pdrgpcrsOutput, pcrsOuterRefs, &pstatspredUnsupported ); // TODO: May 15 2014, handle unsupported predicates for LASJ, LOJ and LS joins // clean up CRefCount::SafeRelease(pstatspredUnsupported); pexprScalar->Release(); return pdrgpstatsjoin; }
//--------------------------------------------------------------------------- // @function: // CStatsPredUtils::PdrgpstatsjoinExtract // // @doc: // Helper function to extract array of statistics join filter // from an array of join predicates // //--------------------------------------------------------------------------- DrgPstatsjoin * CStatsPredUtils::PdrgpstatsjoinExtract ( IMemoryPool *pmp, CExpression *pexprScalar, DrgPcrs *pdrgpcrsOutput, // array of output columns of join's relational inputs CColRefSet *pcrsOuterRefs, CStatsPred **ppstatspredUnsupported ) { GPOS_ASSERT(NULL != pexprScalar); GPOS_ASSERT(NULL != pdrgpcrsOutput); DrgPstatsjoin *pdrgpstatsjoin = GPOS_NEW(pmp) DrgPstatsjoin(pmp); DrgPexpr *pdrgpexprUnsupported = GPOS_NEW(pmp) DrgPexpr(pmp); // extract all the conjuncts DrgPexpr *pdrgpexprConjuncts = CPredicateUtils::PdrgpexprConjuncts(pmp, pexprScalar); const ULONG ulSize = pdrgpexprConjuncts->UlLength(); for (ULONG ul = 0; ul < ulSize; ul++) { CExpression *pexprPred = (*pdrgpexprConjuncts) [ul]; CStatisticsJoin *pstatsjoin = PstatsjoinExtract ( pmp, pexprPred, pdrgpcrsOutput, pcrsOuterRefs, pdrgpexprUnsupported ); if (NULL != pstatsjoin) { pdrgpstatsjoin->Append(pstatsjoin); } } const ULONG ulUnsupported = pdrgpexprUnsupported->UlLength(); if (1 == ulUnsupported) { *ppstatspredUnsupported = CStatsPredUtils::PstatspredExtract(pmp, (*pdrgpexprUnsupported)[0], pcrsOuterRefs); } else if (1 < ulUnsupported) { pdrgpexprUnsupported->AddRef(); CExpression *pexprConj = CPredicateUtils::PexprConjDisj(pmp, pdrgpexprUnsupported, true /* fConjunction */); *ppstatspredUnsupported = CStatsPredUtils::PstatspredExtract(pmp, pexprConj, pcrsOuterRefs); pexprConj->Release(); } // clean up pdrgpexprUnsupported->Release(); pdrgpexprConjuncts->Release(); return pdrgpstatsjoin; }
//--------------------------------------------------------------------------- // @function: // CDecorrelator::FProcessGbAgg // // @doc: // Decorrelate GbAgg operator // //--------------------------------------------------------------------------- BOOL CDecorrelator::FProcessGbAgg ( IMemoryPool *pmp, CExpression *pexpr, BOOL, // fEqualityOnly CExpression **ppexprDecorrelated, DrgPexpr *pdrgpexprCorrelations ) { CLogicalGbAgg *popAggOriginal = CLogicalGbAgg::PopConvert(pexpr->Pop()); // fail if agg has outer references if (CUtils::FHasOuterRefs(pexpr) && !CUtils::FHasOuterRefs((*pexpr)[0])) { return false; } // TODO: 12/20/2012 - ; check for strictness of agg function // decorrelate relational child CExpression *pexprRelational = NULL; if (!FProcess(pmp, (*pexpr)[0], true /*fEqualityOnly*/, &pexprRelational, pdrgpexprCorrelations)) { GPOS_ASSERT(NULL == pexprRelational); return false; } // get the output columns of decorrelated child CColRefSet *pcrsOutput = CDrvdPropRelational::Pdprel(pexprRelational->PdpDerive())->PcrsOutput(); // create temp expression of correlations to determine inner columns pdrgpexprCorrelations->AddRef(); CExpression *pexprTemp = CPredicateUtils::PexprConjunction(pmp, pdrgpexprCorrelations); CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp, *(CDrvdPropScalar::Pdpscalar(pexprTemp->PdpDerive())->PcrsUsed())); pcrs->Intersection(pcrsOutput); pexprTemp->Release(); // add grouping columns from original agg pcrs->Include(popAggOriginal->Pdrgpcr()); // assemble grouping columns DrgPcr *pdrgpcr = pcrs->Pdrgpcr(pmp); pcrs->Release(); // assemble agg CExpression *pexprProjList = (*pexpr)[1]; pexprProjList->AddRef(); CLogicalGbAgg *popAgg = GPOS_NEW(pmp) CLogicalGbAgg(pmp, pdrgpcr, popAggOriginal->Egbaggtype()); *ppexprDecorrelated = GPOS_NEW(pmp) CExpression(pmp, popAgg, pexprRelational, pexprProjList); return true; }
//--------------------------------------------------------------------------- // @function: // CLogicalSelect::PstatsDerive // // @doc: // Derive statistics based on filter predicates // //--------------------------------------------------------------------------- IStatistics * CLogicalSelect::PstatsDerive ( IMemoryPool *pmp, CExpressionHandle &exprhdl, DrgPstat *pdrgpstatCtxt ) const { GPOS_ASSERT(Esp(exprhdl) > EspNone); IStatistics *pstatsChild = exprhdl.Pstats(0); if (exprhdl.Pdpscalar(1 /*ulChildIndex*/)->FHasSubquery()) { // in case of subquery in select predicate, we return child stats pstatsChild->AddRef(); return pstatsChild; } // remove implied predicates from selection condition to avoid cardinality under-estimation CExpression *pexprScalar = exprhdl.PexprScalarChild(1 /*ulChildIndex*/); CExpression *pexprPredicate = CPredicateUtils::PexprRemoveImpliedConjuncts(pmp, pexprScalar, exprhdl); // split selection predicate into local predicate and predicate involving outer references CExpression *pexprLocal = NULL; CExpression *pexprOuterRefs = NULL; // get outer references from expression handle CColRefSet *pcrsOuter = exprhdl.Pdprel()->PcrsOuter(); CPredicateUtils::SeparateOuterRefs(pmp, pexprPredicate, pcrsOuter, &pexprLocal, &pexprOuterRefs); pexprPredicate->Release(); IStatistics *pstats = CStatisticsUtils::PstatsFilter(pmp, exprhdl, pstatsChild, pexprLocal, pexprOuterRefs, pdrgpstatCtxt); pexprLocal->Release(); pexprOuterRefs->Release(); return pstats; }
//--------------------------------------------------------------------------- // @function: // CLogicalDifferenceAll::PstatsDerive // // @doc: // Derive statistics // //--------------------------------------------------------------------------- IStatistics * CLogicalDifferenceAll::PstatsDerive ( IMemoryPool *pmp, CExpressionHandle &exprhdl, DrgPstat * // not used ) const { GPOS_ASSERT(Esp(exprhdl) > EspNone); // difference all is transformed into a LASJ, // we follow the same route to compute statistics DrgPcrs *pdrgpcrsOutput = GPOS_NEW(pmp) DrgPcrs(pmp); const ULONG ulSize = m_pdrgpdrgpcrInput->UlLength(); for (ULONG ul = 0; ul < ulSize; ul++) { CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp, (*m_pdrgpdrgpcrInput)[ul]); pdrgpcrsOutput->Append(pcrs); } IStatistics *pstatsOuter = exprhdl.Pstats(0); IStatistics *pstatsInner = exprhdl.Pstats(1); // construct the scalar condition for the LASJ CExpression *pexprScCond = CUtils::PexprConjINDFCond(pmp, m_pdrgpdrgpcrInput); // compute the statistics for LASJ CColRefSet *pcrsOuterRefs = exprhdl.Pdprel()->PcrsOuter(); DrgPstatsjoin *pdrgpstatsjoin = CStatsPredUtils::Pdrgpstatsjoin ( pmp, exprhdl, pexprScCond, pdrgpcrsOutput, pcrsOuterRefs ); IStatistics *pstatsLASJ = pstatsOuter->PstatsLASJoin ( pmp, pstatsInner, pdrgpstatsjoin, true /* fIgnoreLasjHistComputation*/ ); // clean up pexprScCond->Release(); pdrgpstatsjoin->Release(); pdrgpcrsOutput->Release(); return pstatsLASJ; }
//--------------------------------------------------------------------------- // @function: // CCNFConverter::PexprNot2CNF // // @doc: // Convert a NOT tree into CNF // //--------------------------------------------------------------------------- CExpression * CCNFConverter::PexprNot2CNF ( IMemoryPool *pmp, CExpression *pexpr ) { GPOS_ASSERT(NULL != pmp); GPOS_ASSERT(NULL != pexpr); GPOS_ASSERT(1 == pexpr->UlArity()); CExpression *pexprNotChild = (*pexpr)[0]; if (!FScalarBoolOp(pexprNotChild)) { pexpr->AddRef(); return pexpr; } CScalarBoolOp::EBoolOperator eboolopChild = CScalarBoolOp::PopConvert(pexprNotChild->Pop())->Eboolop(); // apply DeMorgan laws // NOT(NOT(A)) ==> A if (CScalarBoolOp::EboolopNot == eboolopChild) { return Pexpr2CNF(pmp, (*pexprNotChild)[0]); } // Not child must be either an AND or an OR // NOT(A AND B) ==> NOT(A) OR NOT(B) // NOT(A OR B) ==> NOT(A) AND NOT(B) DrgPexpr *pdrgpexpr = GPOS_NEW(pmp) DrgPexpr(pmp); const ULONG ulArity = pexprNotChild->UlArity(); for (ULONG ul = 0; ul < ulArity; ul++) { (*pexprNotChild)[ul]->AddRef(); pdrgpexpr->Append(CUtils::PexprNegate(pmp, (*pexprNotChild)[ul])); } CScalarBoolOp::EBoolOperator eboolop = CScalarBoolOp::EboolopAnd; if (CScalarBoolOp::EboolopAnd == eboolopChild) { eboolop = CScalarBoolOp::EboolopOr; } CExpression *pexprScalarBoolOp = CUtils::PexprScalarBoolOp(pmp, eboolop, pdrgpexpr); CExpression *pexprResult = Pexpr2CNF(pmp, pexprScalarBoolOp); pexprScalarBoolOp->Release(); return pexprResult; }
//--------------------------------------------------------------------------- // @function: // CXformGbAggWithMDQA2Join::PexprMDQAs2Join // // @doc: // Converts GbAgg with multiple distinct aggregates into a join of single // distinct aggregates, // // distinct aggregates that share the same argument are grouped together // in one leaf of the generated join expression, // // non-distinct aggregates are also grouped together in one leaf of the // generated join expression // //--------------------------------------------------------------------------- CExpression * CXformGbAggWithMDQA2Join::PexprMDQAs2Join ( IMemoryPool *pmp, CExpression *pexpr ) { GPOS_ASSERT(NULL != pexpr); GPOS_ASSERT(COperator::EopLogicalGbAgg == pexpr->Pop()->Eopid()); GPOS_ASSERT(CDrvdPropScalar::Pdpscalar((*pexpr)[1]->PdpDerive())->FHasMultipleDistinctAggs()); // extract components CExpression *pexprChild = (*pexpr)[0]; CColRefSet *pcrsChildOutput = CDrvdPropRelational::Pdprel(pexprChild->PdpDerive())->PcrsOutput(); DrgPcr *pdrgpcrChildOutput = pcrsChildOutput->Pdrgpcr(pmp); // create a CTE producer based on child expression CCTEInfo *pcteinfo = COptCtxt::PoctxtFromTLS()->Pcteinfo(); const ULONG ulCTEId = pcteinfo->UlNextId(); (void) CXformUtils::PexprAddCTEProducer(pmp, ulCTEId, pdrgpcrChildOutput, pexprChild); // create a CTE consumer with child output columns CExpression *pexprConsumer = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CLogicalCTEConsumer(pmp, ulCTEId, pdrgpcrChildOutput) ); pcteinfo->IncrementConsumers(ulCTEId); // finalize GbAgg expression by replacing its child with CTE consumer pexpr->Pop()->AddRef(); (*pexpr)[1]->AddRef(); CExpression *pexprGbAggWithConsumer = GPOS_NEW(pmp) CExpression(pmp, pexpr->Pop(), pexprConsumer, (*pexpr)[1]); CExpression *pexprJoinDQAs = CXformUtils::PexprGbAggOnCTEConsumer2Join(pmp, pexprGbAggWithConsumer); GPOS_ASSERT(NULL != pexprJoinDQAs); pexprGbAggWithConsumer->Release(); return GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CLogicalCTEAnchor(pmp, ulCTEId), pexprJoinDQAs ); }
//--------------------------------------------------------------------------- // @function: // CDecorrelator::FProcessSelect // // @doc: // Decorrelate select operator // //--------------------------------------------------------------------------- BOOL CDecorrelator::FProcessSelect ( IMemoryPool *pmp, CExpression *pexpr, BOOL fEqualityOnly, CExpression **ppexprDecorrelated, DrgPexpr *pdrgpexprCorrelations ) { GPOS_ASSERT(COperator::EopLogicalSelect == pexpr->Pop()->Eopid()); // decorrelate relational child CExpression *pexprRelational = NULL; if (!FProcess(pmp, (*pexpr)[0], fEqualityOnly, &pexprRelational, pdrgpexprCorrelations)) { GPOS_ASSERT(NULL == pexprRelational); return false; } // process predicate CExpression *pexprPredicate = NULL; CColRefSet *pcrsOutput = CDrvdPropRelational::Pdprel(pexpr->PdpDerive())->PcrsOutput(); BOOL fSuccess = FProcessPredicate(pmp, pexpr, (*pexpr)[1], fEqualityOnly, pcrsOutput, &pexprPredicate, pdrgpexprCorrelations); // build substitute if (fSuccess) { if (NULL != pexprPredicate) { CLogicalSelect *popSelect = CLogicalSelect::PopConvert(pexpr->Pop()); popSelect->AddRef(); *ppexprDecorrelated = GPOS_NEW(pmp) CExpression(pmp, popSelect, pexprRelational, pexprPredicate); } else { *ppexprDecorrelated = pexprRelational; } } else { pexprRelational->Release(); } return fSuccess; }
//--------------------------------------------------------------------------- // @function: // CNormalizer::PushThruSeqPrj // // @doc: // Push a conjunct through a sequence project expression // //--------------------------------------------------------------------------- void CNormalizer::PushThruSeqPrj ( IMemoryPool *pmp, CExpression *pexprSeqPrj, CExpression *pexprConj, CExpression **ppexprResult ) { GPOS_ASSERT(NULL != pexprSeqPrj); GPOS_ASSERT(CLogical::EopLogicalSequenceProject == pexprSeqPrj->Pop()->Eopid()); GPOS_ASSERT(NULL != pexprConj); GPOS_ASSERT(NULL != ppexprResult); // get logical and scalar children CExpression *pexprLogicalChild = (*pexprSeqPrj)[0]; CExpression *pexprScalarChild = (*pexprSeqPrj)[1]; // break scalar expression to pushable and unpushable conjuncts DrgPexpr *pdrgpexprPushable = NULL; DrgPexpr *pdrgpexprUnpushable = NULL; SplitConjunctForSeqPrj(pmp, pexprSeqPrj, pexprConj, &pdrgpexprPushable, &pdrgpexprUnpushable); CExpression *pexprNewLogicalChild = NULL; if (0 < pdrgpexprPushable->UlLength()) { CExpression *pexprPushableConj = CPredicateUtils::PexprConjunction(pmp, pdrgpexprPushable); PushThru(pmp, pexprLogicalChild, pexprPushableConj, &pexprNewLogicalChild); pexprPushableConj->Release(); } else { // no pushable predicates on top of sequence project, // we still need to process child recursively to push-down child's own predicates pdrgpexprPushable->Release(); pexprNewLogicalChild = PexprNormalize(pmp, pexprLogicalChild); } // create a new logical expression based on recursion results COperator *pop = pexprSeqPrj->Pop(); pop->AddRef(); pexprScalarChild->AddRef(); CExpression *pexprNewLogical = GPOS_NEW(pmp) CExpression(pmp, pop, pexprNewLogicalChild, pexprScalarChild); // create a select node for remaining predicates, if any *ppexprResult = PexprSelect(pmp, pexprNewLogical, pdrgpexprUnpushable); }
//--------------------------------------------------------------------------- // @function: // CNormalizer::PushThru // // @doc: // Push an array of conjuncts through a logical expression; // compute an array of unpushable conjuncts // //--------------------------------------------------------------------------- void CNormalizer::PushThru ( IMemoryPool *pmp, CExpression *pexprLogical, DrgPexpr *pdrgpexprConjuncts, CExpression **ppexprResult, DrgPexpr **ppdrgpexprRemaining ) { GPOS_ASSERT(NULL != pexprLogical); GPOS_ASSERT(NULL != pdrgpexprConjuncts); GPOS_ASSERT(NULL != ppexprResult); DrgPexpr *pdrgpexprPushable = GPOS_NEW(pmp) DrgPexpr(pmp); DrgPexpr *pdrgpexprUnpushable = GPOS_NEW(pmp) DrgPexpr(pmp); const ULONG ulSize = pdrgpexprConjuncts->UlLength(); for (ULONG ul = 0; ul < ulSize; ul++) { CExpression *pexprConj = (*pdrgpexprConjuncts)[ul]; pexprConj->AddRef(); if (FPushable(pexprLogical, pexprConj)) { pdrgpexprPushable->Append(pexprConj); } else { pdrgpexprUnpushable->Append(pexprConj); } } // push through a conjunction of all pushable predicates CExpression *pexprPred = CPredicateUtils::PexprConjunction(pmp, pdrgpexprPushable); if (FPushThruOuterChild(pexprLogical)) { PushThruOuterChild(pmp, pexprLogical, pexprPred, ppexprResult); } else { PushThru(pmp, pexprLogical, pexprPred, ppexprResult); } pexprPred->Release(); *ppdrgpexprRemaining = pdrgpexprUnpushable; }
/* calculate expression from inputtext */ EXP_ValueHandle EXP_ParseInput(const char* inputtext) { CValue* resultval=NULL; CParser parser; CExpression* expr = parser.ProcessText(inputtext); if (expr) { resultval = expr->Calculate(); expr->Release(); } else { resultval = new CErrorValue("couldn't parsetext"); } return (EXP_ValueHandle) resultval; }
//--------------------------------------------------------------------------- // @function: // CStatsPredUtils::PstatspredDisj // // @doc: // Create disjunctive statistics filter composed of the extracted // components of the disjunction //--------------------------------------------------------------------------- CStatsPred * CStatsPredUtils::PstatspredDisj ( IMemoryPool *pmp, CExpression *pexprPred, CColRefSet *pcrsOuterRefs ) { GPOS_ASSERT(NULL != pexprPred); GPOS_ASSERT(CPredicateUtils::FOr(pexprPred)); DrgPstatspred *pdrgpstatspredDisjChild = GPOS_NEW(pmp) DrgPstatspred(pmp); // remove duplicate components of the OR tree CExpression *pexprNew = CExpressionUtils::PexprDedupChildren(pmp, pexprPred); // extract the components of the OR tree DrgPexpr *pdrgpexpr = CPredicateUtils::PdrgpexprDisjuncts(pmp, pexprNew); const ULONG ulLen = pdrgpexpr->UlLength(); for (ULONG ul = 0; ul < ulLen; ul++) { CExpression *pexpr = (*pdrgpexpr)[ul]; CColRefSet *pcrsUsed = CDrvdPropScalar::Pdpscalar(pexpr->PdpDerive())->PcrsUsed(); if (NULL != pcrsOuterRefs && pcrsOuterRefs->FSubset(pcrsUsed)) { // skip predicate with outer references continue; } AddSupportedStatsFilters(pmp, pdrgpstatspredDisjChild, pexpr, pcrsOuterRefs); } // clean up pexprNew->Release(); pdrgpexpr->Release(); if (0 < pdrgpstatspredDisjChild->UlLength()) { return GPOS_NEW(pmp) CStatsPredDisj(pdrgpstatspredDisjChild); } pdrgpstatspredDisjChild->Release(); return NULL; }
//--------------------------------------------------------------------------- // @function: // CXformExpandNAryJoin::Transform // // @doc: // Actual transformation of n-ary join to cluster of inner joins // //--------------------------------------------------------------------------- void CXformExpandNAryJoin::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(NULL != pxfres); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); IMemoryPool *pmp = pxfctxt->Pmp(); const ULONG ulArity = pexpr->UlArity(); GPOS_ASSERT(ulArity >= 3); DrgPexpr *pdrgpexpr = GPOS_NEW(pmp) DrgPexpr(pmp); for (ULONG ul = 0; ul < ulArity - 1; ul++) { CExpression *pexprChild = (*pexpr)[ul]; pexprChild->AddRef(); pdrgpexpr->Append(pexprChild); } CExpression *pexprScalar = (*pexpr)[ulArity - 1]; DrgPexpr *pdrgpexprPreds = CPredicateUtils::PdrgpexprConjuncts(pmp, pexprScalar); // create a join order based on query-specified order of joins CJoinOrder jo(pmp, pdrgpexpr, pdrgpexprPreds); CExpression *pexprResult = jo.PexprExpand(); // normalize resulting expression CExpression *pexprNormalized = CNormalizer::PexprNormalize(pmp, pexprResult); pexprResult->Release(); pxfres->Add(pexprNormalized); AddSpecifiedJoinOrder(pmp, pexpr, pxfres); }
//--------------------------------------------------------------------------- // @function: // CXformInnerJoinWithInnerSelect2IndexGetApply::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformInnerJoinWithInnerSelect2IndexGetApply::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); IMemoryPool *pmp = pxfctxt->Pmp(); // extract components CExpression *pexprOuter = (*pexpr)[0]; CExpression *pexprInner = (*pexpr)[1]; CExpression *pexprScalar = (*pexpr)[2]; GPOS_ASSERT(COperator::EopLogicalSelect == pexprInner->Pop()->Eopid()); CExpression *pexprGet = (*pexprInner)[0]; GPOS_ASSERT(COperator::EopLogicalGet == pexprGet->Pop()->Eopid()); CTableDescriptor *ptabdescInner = CLogicalGet::PopConvert (pexprGet->Pop ())->Ptabdesc(); CExpression *pexprAllPredicates = CPredicateUtils::PexprConjunction(pmp, pexprScalar, (*pexprInner)[1]); CreateHomogeneousIndexApplyAlternatives ( pmp, pexpr->Pop()->UlOpId(), pexprOuter, pexprGet, pexprAllPredicates, ptabdescInner, NULL, // popDynamicGet pxfres, IMDIndex::EmdindBtree ); pexprAllPredicates->Release(); }
//--------------------------------------------------------------------------- // @function: // CXformLeftAntiSemiJoin2CrossProduct::Transform // // @doc: // Anti semi join whose join predicate does not use columns from // join's inner child is equivalent to a Cross Product between outer // child (after pushing negated join predicate), and one tuple from // inner child // // //--------------------------------------------------------------------------- void CXformLeftAntiSemiJoin2CrossProduct::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); IMemoryPool *pmp = pxfctxt->Pmp(); // extract components CExpression *pexprOuter = (*pexpr)[0]; CExpression *pexprInner = (*pexpr)[1]; CExpression *pexprScalar = (*pexpr)[2]; pexprOuter->AddRef(); pexprInner->AddRef(); pexprScalar->AddRef(); CExpression *pexprNegatedScalar = CUtils::PexprNegate(pmp, pexprScalar); // create a (limit 1) on top of inner child CExpression *pexprLimitOffset = CUtils::PexprScalarConstInt8(pmp, 0 /*iVal*/); CExpression *pexprLimitCount = CUtils::PexprScalarConstInt8(pmp, 1 /*iVal*/); COrderSpec *pos = GPOS_NEW(pmp) COrderSpec(pmp); CLogicalLimit *popLimit = GPOS_NEW(pmp) CLogicalLimit(pmp, pos, true /*fGlobal*/, true /*fHasCount*/, false /*fNonRemovableLimit*/); CExpression *pexprLimit = GPOS_NEW(pmp) CExpression(pmp, popLimit, pexprInner, pexprLimitOffset, pexprLimitCount); // create cross product CExpression *pexprJoin = CUtils::PexprLogicalJoin<CLogicalInnerJoin>(pmp, pexprOuter, pexprLimit, pexprNegatedScalar); CExpression *pexprNormalized = CNormalizer::PexprNormalize(pmp, pexprJoin); pexprJoin->Release(); pxfres->Add(pexprNormalized); }
//--------------------------------------------------------------------------- // @function: // CPartitionPropagationSpec::PexprResidualFilter // // @doc: // Return a residual filter given an array of predicates and a bitset // indicating which predicates have already been used // //--------------------------------------------------------------------------- CExpression * CPartitionPropagationSpec::PexprResidualFilter ( IMemoryPool *mp, CExpressionArray *pdrgpexpr, CBitSet *pbsUsed ) { GPOS_ASSERT(NULL != pdrgpexpr); GPOS_ASSERT(NULL != pbsUsed); CExpressionArray *pdrgpexprUnused = GPOS_NEW(mp) CExpressionArray(mp); const ULONG length = pdrgpexpr->Size(); for (ULONG ul = 0; ul < length; ul++) { if (pbsUsed->Get(ul)) { // predicate already considered continue; } CExpression *pexpr = (*pdrgpexpr)[ul]; pexpr->AddRef(); pdrgpexprUnused->Append(pexpr); } CExpression *pexprResult = CPredicateUtils::PexprConjunction(mp, pdrgpexprUnused); if (CUtils::FScalarConstTrue(pexprResult)) { pexprResult->Release(); pexprResult = NULL; } return pexprResult; }
float CParser::GetFloat(STR_String& txt) { // returns parsed text into a float // empty string returns -1 // AfxMessageBox("parsed string="+txt); CValue* val=NULL; float result=-1; // String tmpstr; CExpression* expr = ProcessText(txt); if (expr) { val = expr->Calculate(); result=(float)val->GetNumber(); val->Release(); expr->Release(); } // tmpstr.Format("parseresult=%g",result); // AfxMessageBox(tmpstr); return result; }
//--------------------------------------------------------------------------- // @function: // CConstraint::PdrgpcnstrDeduplicate // // @doc: // Simplify an array of constraints to be used as children for a conjunction // or disjunction. If there are two or more elements that reference only one // particular column, these constraints are combined into one // //--------------------------------------------------------------------------- DrgPcnstr * CConstraint::PdrgpcnstrDeduplicate ( IMemoryPool *pmp, DrgPcnstr *pdrgpcnstr, EConstraintType ect ) const { DrgPcnstr *pdrgpcnstrNew = GPOS_NEW(pmp) DrgPcnstr(pmp); CColRefSet *pcrsDeduped = GPOS_NEW(pmp) CColRefSet(pmp); const ULONG ulLen = pdrgpcnstr->UlLength(); for (ULONG ul = 0; ul < ulLen; ul++) { CConstraint *pcnstrChild = (*pdrgpcnstr)[ul]; CColRefSet *pcrs = pcnstrChild->PcrsUsed(); // we only simplify constraints that reference a single column, otherwise // we add constraint as is if (1 < pcrs->CElements()) { pcnstrChild->AddRef(); pdrgpcnstrNew->Append(pcnstrChild); continue; } CColRef *pcr = pcrs->PcrFirst(); if (pcrsDeduped->FMember(pcr)) { // current constraint has already been combined with a previous one continue; } // get all constraints from the input array that reference this column DrgPcnstr *pdrgpcnstrCol = PdrgpcnstrOnColumn(pmp, pdrgpcnstr, pcr, true /*fExclusive*/); if (1 == pdrgpcnstrCol->UlLength()) { // if there is only one such constraint, then no simplification // for this column pdrgpcnstrCol->Release(); pcnstrChild->AddRef(); pdrgpcnstrNew->Append(pcnstrChild); continue; } CExpression *pexpr = NULL; if (EctConjunction == ect) { pexpr = PexprScalarConjDisj(pmp, pdrgpcnstrCol, true /*fConj*/); } else { GPOS_ASSERT(EctDisjunction == ect); pexpr = PexprScalarConjDisj(pmp, pdrgpcnstrCol, false /*fConj*/); } pdrgpcnstrCol->Release(); GPOS_ASSERT(NULL != pexpr); CConstraint *pcnstrNew = CConstraintInterval::PciIntervalFromScalarExpr(pmp, pexpr, pcr); GPOS_ASSERT(NULL != pcnstrNew); pexpr->Release(); pdrgpcnstrNew->Append(pcnstrNew); pcrsDeduped->Include(pcr); } pcrsDeduped->Release(); pdrgpcnstr->Release(); return pdrgpcnstrNew; }
//--------------------------------------------------------------------------- // @function: // COptimizer::PdxlnOptimize // // @doc: // Optimize given query // the function is oblivious of trace flags setting/resetting which // must happen at the caller side if needed // //--------------------------------------------------------------------------- CDXLNode * COptimizer::PdxlnOptimize ( IMemoryPool *pmp, CMDAccessor *pmda, const CDXLNode *pdxlnQuery, const DrgPdxln *pdrgpdxlnQueryOutput, const DrgPdxln *pdrgpdxlnCTE, IConstExprEvaluator *pceeval, ULONG ulHosts, // actual number of data nodes in the system ULONG ulSessionId, ULONG ulCmdId, DrgPss *pdrgpss, COptimizerConfig *poconf, const CHAR *szMinidumpFileName // name of minidump file to be created ) { GPOS_ASSERT(NULL != pmda); GPOS_ASSERT(NULL != pdxlnQuery); GPOS_ASSERT(NULL != pdrgpdxlnQueryOutput); GPOS_ASSERT(NULL != poconf); BOOL fMinidump = GPOS_FTRACE(EopttraceMinidump); CMiniDumperDXL mdmp(pmp); if (fMinidump) { mdmp.Init(); } CDXLNode *pdxlnPlan = NULL; CErrorHandlerStandard errhdl; GPOS_TRY_HDL(&errhdl) { CSerializableStackTrace serStack; CSerializableOptimizerConfig serOptConfig(poconf); CSerializableMDAccessor serMDA(pmda); CSerializableQuery serQuery(pdxlnQuery, pdrgpdxlnQueryOutput, pdrgpdxlnCTE); if (fMinidump) { // pre-serialize query and optimizer configurations serStack.AllocateBuffer(pmp); serOptConfig.Serialize(pmp); serQuery.Serialize(pmp); } { poconf->AddRef(); if (NULL != pceeval) { pceeval->AddRef(); } // install opt context in TLS CAutoOptCtxt aoc(pmp, pmda, pceeval, poconf); // translate DXL Tree -> Expr Tree CTranslatorDXLToExpr dxltr(pmp, pmda); CExpression *pexprTranslated = dxltr.PexprTranslateQuery(pdxlnQuery, pdrgpdxlnQueryOutput, pdrgpdxlnCTE); GPOS_CHECK_ABORT; gpdxl::DrgPul *pdrgpul = dxltr.PdrgpulOutputColRefs(); gpmd::DrgPmdname *pdrgpmdname = dxltr.Pdrgpmdname(); CQueryContext *pqc = CQueryContext::PqcGenerate(pmp, pexprTranslated, pdrgpul, pdrgpmdname, true /*fDeriveStats*/); GPOS_CHECK_ABORT; PrintQueryOrPlan(pmp, pexprTranslated, pqc); CWStringDynamic strTrace(pmp); COstreamString oss(&strTrace); // if the number of inlinable CTEs is greater than the cutoff, then // disable inlining for this query if (!GPOS_FTRACE(EopttraceEnableCTEInlining) || CUtils::UlInlinableCTEs(pexprTranslated) > poconf->Pcteconf()->UlCTEInliningCutoff()) { COptCtxt::PoctxtFromTLS()->Pcteinfo()->DisableInlining(); } GPOS_CHECK_ABORT; // optimize logical expression tree into physical expression tree. CExpression *pexprPlan = PexprOptimize(pmp, pqc, pdrgpss); GPOS_CHECK_ABORT; PrintQueryOrPlan(pmp, pexprPlan); // translate plan into DXL pdxlnPlan = Pdxln(pmp, pmda, pexprPlan, pqc->PdrgPcr(), pdrgpmdname, ulHosts); GPOS_CHECK_ABORT; if (fMinidump) { CSerializablePlan serPlan(pdxlnPlan, poconf->Pec()->UllPlanId(), poconf->Pec()->UllPlanSpaceSize()); serPlan.Serialize(pmp); CMinidumperUtils::Finalize(&mdmp, true /* fSerializeErrCtxt*/, ulSessionId, ulCmdId, szMinidumpFileName); GPOS_CHECK_ABORT; } if (GPOS_FTRACE(EopttraceSamplePlans)) { DumpSamples(pmp, poconf->Pec(), ulSessionId, ulCmdId); GPOS_CHECK_ABORT; } // cleanup pexprTranslated->Release(); pexprPlan->Release(); GPOS_DELETE(pqc); } } GPOS_CATCH_EX(ex) { if (fMinidump) { CMinidumperUtils::Finalize(&mdmp, false /* fSerializeErrCtxt*/, ulSessionId, ulCmdId, szMinidumpFileName); HandleExceptionAfterFinalizingMinidump(ex); } GPOS_RETHROW(ex); } GPOS_CATCH_END; return pdxlnPlan; }