//--------------------------------------------------------------------------- // @function: // CGroupProxy::PgexprSkip // // @doc: // Skip group expressions starting from the given expression; // the type of group expressions to skip is determined by the passed // flag // //--------------------------------------------------------------------------- CGroupExpression * CGroupProxy::PgexprSkip ( CGroupExpression *pgexprStart, BOOL fSkipLogical ) { CGroupExpression *pgexpr = pgexprStart; while (NULL != pgexpr && fSkipLogical == pgexpr->Pop()->FLogical()) { pgexpr = PgexprNext(pgexpr); } return pgexpr; }
//--------------------------------------------------------------------------- // @function: // CJobGroupOptimization::FScheduleGroupExpressions // // @doc: // Schedule optimization jobs for all unoptimized group expressions with // the current optimization priority; // the function returns true if it could schedule any new jobs // //--------------------------------------------------------------------------- BOOL CJobGroupOptimization::FScheduleGroupExpressions ( CSchedulerContext *psc ) { CGroupExpression *pgexprLast = m_pgexprLastScheduled; // iterate on expressions and schedule them as needed CGroupExpression *pgexpr = PgexprFirstUnsched(); while (NULL != pgexpr) { // we consider only group expressions matching current optimization level, // other group expressions will be optimized when damping current // optimization level if (psc->Peng()->FOptimizeChild(m_pgexprOrigin, pgexpr, m_poc, EolCurrent())) { const ULONG ulOptRequests = CPhysical::PopConvert(pgexpr->Pop())->UlOptRequests(); for (ULONG ul = 0; ul < ulOptRequests; ul++) { // schedule an optimization job for each request CJobGroupExpressionOptimization::ScheduleJob(psc, pgexpr, m_poc, ul, this); } } pgexprLast = pgexpr; // move to next expression { CGroupProxy gp(m_pgroup); pgexpr = gp.PgexprSkipLogical(pgexpr); } } BOOL fNewJobs = (m_pgexprLastScheduled != pgexprLast); // set last scheduled expression m_pgexprLastScheduled = pgexprLast; return fNewJobs; }
//--------------------------------------------------------------------------- // @function: // CExpressionHandle::DeriveProducerStats // // @doc: // If the child (ulChildIndex) is a CTE consumer, then derive is corresponding // producer statistics. // //--------------------------------------------------------------------------- void CExpressionHandle::DeriveProducerStats ( ULONG ulChildIndex, CColRefSet *pcrsStats ) { // check to see if there are any CTE consumers in the group whose properties have // to be pushed to its corresponding CTE producer CGroupExpression *pgexpr = Pgexpr(); if (NULL != pgexpr) { CGroup *pgroupChild = (*pgexpr)[ulChildIndex]; if (pgroupChild->FHasAnyCTEConsumer()) { CGroupExpression *pgexprCTEConsumer = pgroupChild->PgexprAnyCTEConsumer(); CLogicalCTEConsumer *popConsumer = CLogicalCTEConsumer::PopConvert(pgexprCTEConsumer->Pop()); COptCtxt::PoctxtFromTLS()->Pcteinfo()->DeriveProducerStats(popConsumer, pcrsStats); } return; } // statistics are also derived on expressions representing the producer that may have // multiple CTE consumers. We should ensure that their properties are to pushed to their // corresponding CTE producer CExpression *pexpr = Pexpr(); if (NULL != pexpr) { CExpression *pexprChild = (*pexpr)[ulChildIndex]; if (COperator::EopLogicalCTEConsumer == pexprChild->Pop()->Eopid()) { CLogicalCTEConsumer *popConsumer = CLogicalCTEConsumer::PopConvert(pexprChild->Pop()); COptCtxt::PoctxtFromTLS()->Pcteinfo()->DeriveProducerStats(popConsumer, pcrsStats); } } }
//--------------------------------------------------------------------------- // @function: // COptimizationContext::PrppCTEProducer // // @doc: // Compute required properties to CTE producer based on plan properties // of CTE consumer // //--------------------------------------------------------------------------- CReqdPropPlan * COptimizationContext::PrppCTEProducer ( IMemoryPool *mp, COptimizationContext *poc, ULONG ulSearchStages ) { GPOS_ASSERT(NULL != poc); GPOS_ASSERT(NULL != poc->PccBest()); CCostContext *pccBest = poc->PccBest(); CGroupExpression *pgexpr = pccBest->Pgexpr(); BOOL fOptimizeCTESequence = ( COperator::EopPhysicalSequence == pgexpr->Pop()->Eopid() && (*pgexpr)[0]->FHasCTEProducer() ); if (!fOptimizeCTESequence) { // best group expression is not a CTE sequence return NULL; } COptimizationContext *pocProducer = (*pgexpr)[0]->PocLookupBest(mp, ulSearchStages, (*pccBest->Pdrgpoc())[0]->Prpp()); if (NULL == pocProducer) { return NULL; } CCostContext *pccProducer = pocProducer->PccBest(); if (NULL == pccProducer) { return NULL; } COptimizationContext *pocConsumer = (*pgexpr)[1]->PocLookupBest(mp, ulSearchStages, (*pccBest->Pdrgpoc())[1]->Prpp()); if (NULL == pocConsumer) { return NULL; } CCostContext *pccConsumer = pocConsumer->PccBest(); if (NULL == pccConsumer) { return NULL; } CColRefSet *pcrsInnerOutput = CDrvdPropRelational::GetRelationalProperties((*pgexpr)[1]->Pdp())->PcrsOutput(); CPhysicalCTEProducer *popProducer = CPhysicalCTEProducer::PopConvert(pccProducer->Pgexpr()->Pop()); UlongToColRefMap *colref_mapping = COptCtxt::PoctxtFromTLS()->Pcteinfo()->PhmulcrConsumerToProducer(mp, popProducer->UlCTEId(), pcrsInnerOutput, popProducer->Pdrgpcr()); CReqdPropPlan *prppProducer = CReqdPropPlan::PrppRemap(mp, pocProducer->Prpp(), pccConsumer->Pdpplan(), colref_mapping); colref_mapping->Release(); if (prppProducer->Equals(pocProducer->Prpp())) { prppProducer->Release(); return NULL; } return prppProducer; }