//--------------------------------------------------------------------------- // @function: // CLogicalSequenceProject::Matches // // @doc: // Matching function // //--------------------------------------------------------------------------- BOOL CLogicalSequenceProject::Matches ( COperator *pop ) const { GPOS_ASSERT(NULL != pop); if (Eopid() == pop->Eopid()) { CLogicalSequenceProject *popLogicalSequenceProject = CLogicalSequenceProject::PopConvert(pop); return m_pds->Matches(popLogicalSequenceProject->Pds()) && CWindowFrame::Equals(m_pdrgpwf, popLogicalSequenceProject->Pdrgpwf()) && COrderSpec::Equals(m_pdrgpos, popLogicalSequenceProject->Pdrgpos()); } return false; }
//--------------------------------------------------------------------------- // @function: // CXformSubqueryUnnest::PexprSubqueryUnnest // // @doc: // Helper for unnesting subquery under a given context // //--------------------------------------------------------------------------- CExpression * CXformSubqueryUnnest::PexprSubqueryUnnest ( IMemoryPool *pmp, CExpression *pexpr, BOOL fEnforceCorrelatedApply ) { GPOS_ASSERT(NULL != pexpr); if (GPOS_FTRACE(EopttraceEnforceCorrelatedExecution) && !fEnforceCorrelatedApply) { // if correlated execution is enforced, we cannot generate an expression // that does not use correlated Apply return NULL; } // extract components CExpression *pexprOuter = (*pexpr)[0]; CExpression *pexprScalar = (*pexpr)[1]; // we add-ref the logical child since the resulting expression must re-use it pexprOuter->AddRef(); CExpression *pexprNewOuter = NULL; CExpression *pexprResidualScalar = NULL; CSubqueryHandler::ESubqueryCtxt esqctxt = CSubqueryHandler::EsqctxtFilter; if (COperator::EopScalarProjectList == pexprScalar->Pop()->Eopid()) { esqctxt = CSubqueryHandler::EsqctxtValue; } // calling the handler removes subqueries and sets new logical and scalar expressions CSubqueryHandler sh(pmp, fEnforceCorrelatedApply); if (!CSubqueryHandler::FProcess ( sh, pexprOuter, pexprScalar, false /* fDisjunctionOrNegation */, esqctxt, &pexprNewOuter, &pexprResidualScalar ) ) { CRefCount::SafeRelease(pexprNewOuter); CRefCount::SafeRelease(pexprResidualScalar); return NULL; } // create a new alternative using the new logical and scalar expressions CExpression *pexprResult = NULL; if (CSubqueryHandler::EsqctxtFilter == esqctxt) { pexprResult = CUtils::PexprLogicalSelect(pmp, pexprNewOuter, pexprResidualScalar); } else { GPOS_ASSERT(CSubqueryHandler::EsqctxtValue == esqctxt); CLogicalSequenceProject *popSeqPrj = NULL; CLogicalGbAgg *popGbAgg = NULL; COperator::EOperatorId eopid = pexpr->Pop()->Eopid(); switch (eopid) { case COperator::EopLogicalProject: pexprResult = CUtils::PexprLogicalProject(pmp, pexprNewOuter, pexprResidualScalar, false /*fNewComputedCol*/); break; case COperator::EopLogicalGbAgg: popGbAgg = CLogicalGbAgg::PopConvert(pexpr->Pop()); popGbAgg->Pdrgpcr()->AddRef(); pexprResult = CUtils::PexprLogicalGbAgg(pmp, popGbAgg->Pdrgpcr(), pexprNewOuter, pexprResidualScalar, popGbAgg->Egbaggtype()); break; case COperator::EopLogicalSequenceProject: popSeqPrj = CLogicalSequenceProject::PopConvert(pexpr->Pop()); popSeqPrj->Pds()->AddRef(); popSeqPrj->Pdrgpos()->AddRef(); popSeqPrj->Pdrgpwf()->AddRef(); pexprResult = CUtils::PexprLogicalSequenceProject(pmp, popSeqPrj->Pds(), popSeqPrj->Pdrgpos(), popSeqPrj->Pdrgpwf(), pexprNewOuter, pexprResidualScalar); break; default: GPOS_ASSERT(!"Unnesting subqueries for an invalid operator"); break; } } // normalize resulting expression CExpression *pexprNormalized = CNormalizer::PexprNormalize(pmp, pexprResult); pexprResult->Release(); // pull up projections CExpression *pexprPullUpProjections = CNormalizer::PexprPullUpProjections(pmp, pexprNormalized); pexprNormalized->Release(); return pexprPullUpProjections; }