//--------------------------------------------------------------------------- // @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: // CXformGbAgg2StreamAgg::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformGbAgg2StreamAgg::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); CLogicalGbAgg *popAgg = CLogicalGbAgg::PopConvert(pexpr->Pop()); IMemoryPool *pmp = pxfctxt->Pmp(); DrgPcr *pdrgpcr = popAgg->Pdrgpcr(); pdrgpcr->AddRef(); // extract components CExpression *pexprRel = (*pexpr)[0]; CExpression *pexprScalar = (*pexpr)[1]; // addref children pexprRel->AddRef(); pexprScalar->AddRef(); DrgPcr *pdrgpcrArgDQA = popAgg->PdrgpcrArgDQA(); if (0 != pdrgpcrArgDQA->UlSafeLength()) { GPOS_ASSERT(NULL != pdrgpcrArgDQA); pdrgpcrArgDQA->AddRef(); } // create alternative expression CExpression *pexprAlt = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CPhysicalStreamAgg ( pmp, pdrgpcr, popAgg->PdrgpcrMinimal(), popAgg->Egbaggtype(), popAgg->FGeneratesDuplicates(), pdrgpcrArgDQA, CXformUtils::FMultiStageAgg(pexpr) ), pexprRel, pexprScalar ); // add alternative to transformation result pxfres->Add(pexprAlt); }
//--------------------------------------------------------------------------- // @function: // CXformSimplifyGbAgg::Exfp // // @doc: // Compute xform promise for a given expression handle; // aggregate must have grouping columns // //--------------------------------------------------------------------------- CXform::EXformPromise CXformSimplifyGbAgg::Exfp ( CExpressionHandle &exprhdl ) const { CLogicalGbAgg *popAgg = CLogicalGbAgg::PopConvert(exprhdl.Pop()); GPOS_ASSERT(COperator::EgbaggtypeGlobal == popAgg->Egbaggtype()); if (0 == popAgg->Pdrgpcr()->UlLength() || NULL != popAgg->PdrgpcrMinimal()) { return CXform::ExfpNone; } return CXform::ExfpHigh; }
//--------------------------------------------------------------------------- // @function: // CXformGbAggWithMDQA2Join::Exfp // // @doc: // Compute xform promise for a given expression handle; // //--------------------------------------------------------------------------- CXform::EXformPromise CXformGbAggWithMDQA2Join::Exfp ( CExpressionHandle &exprhdl ) const { CAutoMemoryPool amp; CLogicalGbAgg *popAgg = CLogicalGbAgg::PopConvert(exprhdl.Pop()); if (COperator::EgbaggtypeGlobal == popAgg->Egbaggtype() && exprhdl.Pdpscalar(1 /*ulChildIndex*/)->FHasMultipleDistinctAggs()) { return CXform::ExfpHigh; } return CXform::ExfpNone; }
//--------------------------------------------------------------------------- // @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; }
//--------------------------------------------------------------------------- // @function: // CXformSimplifyGbAgg::Transform // // @doc: // Actual transformation to simplify a aggregate expression // //--------------------------------------------------------------------------- void CXformSimplifyGbAgg::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(); if (FDropGbAgg(pmp, pexpr,pxfres)) { // grouping columns could be dropped, GbAgg is transformed to a Select return; } // extract components CLogicalGbAgg *popAgg = CLogicalGbAgg::PopConvert(pexpr->Pop()); CExpression *pexprRelational = (*pexpr)[0]; CExpression *pexprProjectList = (*pexpr)[1]; DrgPcr *pdrgpcr = popAgg->Pdrgpcr(); CColRefSet *pcrsGrpCols = GPOS_NEW(pmp) CColRefSet(pmp); pcrsGrpCols->Include(pdrgpcr); CColRefSet *pcrsCovered = GPOS_NEW(pmp) CColRefSet(pmp); // set of grouping columns covered by FD's CColRefSet *pcrsMinimal = GPOS_NEW(pmp) CColRefSet(pmp); // a set of minimal grouping columns based on FD's DrgPfd *pdrgpfd = CDrvdPropRelational::Pdprel(pexpr->PdpDerive())->Pdrgpfd(); // collect grouping columns FD's const ULONG ulSize = pdrgpfd->UlSafeLength(); for (ULONG ul = 0; ul < ulSize; ul++) { CFunctionalDependency *pfd = (*pdrgpfd)[ul]; if (pfd->FIncluded(pcrsGrpCols)) { pcrsCovered->Include(pfd->PcrsDetermined()); pcrsCovered->Include(pfd->PcrsKey()); pcrsMinimal->Include(pfd->PcrsKey()); } } BOOL fCovered = pcrsCovered->FEqual(pcrsGrpCols); pcrsGrpCols->Release(); pcrsCovered->Release(); if (!fCovered) { // the union of RHS of collected FD's does not cover all grouping columns pcrsMinimal->Release(); return; } // create a new Agg with minimal grouping columns pdrgpcr->AddRef(); CLogicalGbAgg *popAggNew = GPOS_NEW(pmp) CLogicalGbAgg(pmp, pdrgpcr, pcrsMinimal->Pdrgpcr(pmp), popAgg->Egbaggtype()); pcrsMinimal->Release(); GPOS_ASSERT(!popAgg->FMatch(popAggNew) && "Simplified aggregate matches original aggregate"); pexprRelational->AddRef(); pexprProjectList->AddRef(); CExpression *pexprResult = GPOS_NEW(pmp) CExpression(pmp, popAggNew, pexprRelational, pexprProjectList); pxfres->Add(pexprResult); }