//--------------------------------------------------------------------------- // @function: // CDrvdPropScalar::Derive // // @doc: // Derive scalar props // //--------------------------------------------------------------------------- void CDrvdPropScalar::Derive ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CDrvdPropCtxt * // pdpctxt ) { CScalar *popScalar = CScalar::PopConvert(exprhdl.Pop()); // call derivation functions on the operator GPOS_ASSERT(NULL == m_pcrsDefined); m_pcrsDefined = popScalar->PcrsDefined(pmp, exprhdl); GPOS_ASSERT(NULL == m_pcrsSetReturningFunction); m_pcrsSetReturningFunction = popScalar->PcrsSetReturningFunction(pmp, exprhdl); GPOS_ASSERT(NULL == m_pcrsUsed); m_pcrsUsed = popScalar->PcrsUsed(pmp, exprhdl); // derive function properties m_pfp = popScalar->PfpDerive(pmp, exprhdl); // add defined and used columns of children const ULONG ulArity = exprhdl.UlArity(); for (ULONG i = 0; i < ulArity; i++) { // only propagate properties from scalar children if (exprhdl.FScalarChild(i)) { m_pcrsDefined->Union(exprhdl.Pdpscalar(i)->PcrsDefined()); m_pcrsUsed->Union(exprhdl.Pdpscalar(i)->PcrsUsed()); m_pcrsSetReturningFunction->Union(exprhdl.Pdpscalar(i)->PcrsSetReturningFunction()); } else { GPOS_ASSERT(CUtils::FSubquery(popScalar)); // parent operator is a subquery, add outer references // from its relational child as used columns m_pcrsUsed->Union(exprhdl.Pdprel(0)->PcrsOuter()); } } // derive existence of subqueries GPOS_ASSERT(!m_fHasSubquery); m_fHasSubquery = popScalar->FHasSubquery(exprhdl); if (m_fHasSubquery) { m_ppartinfo = popScalar->PpartinfoDerive(pmp, exprhdl); } else { m_ppartinfo = GPOS_NEW(pmp) CPartInfo(pmp); } m_fHasNonScalarFunction = popScalar->FHasNonScalarFunction(exprhdl); if (COperator::EopScalarProjectList == exprhdl.Pop()->Eopid()) { m_ulDistinctAggs = CScalarProjectList::UlDistinctAggs(exprhdl); m_fHasMultipleDistinctAggs = CScalarProjectList::FHasMultipleDistinctAggs(exprhdl); } if (COperator::EopScalarProjectElement == exprhdl.Pop()->Eopid()) { if (m_fHasNonScalarFunction) { CScalarProjectElement *pspeProject = (CScalarProjectElement *)(exprhdl.Pop()); m_pcrsSetReturningFunction->Include(pspeProject->Pcr()); } } }
//--------------------------------------------------------------------------- // @function: // CNormalizer::PexprPullUpProjectElements // // @doc: // Pull up project elements from the given projection expression that do not // exist in the given used columns set. The pulled up project elements must only // use columns that are in the output columns of the parent operator. Returns // a new expression that does not have the pulled up project elements. These // project elements are appended to the given array. // //--------------------------------------------------------------------------- CExpression * CNormalizer::PexprPullUpProjectElements ( IMemoryPool *pmp, CExpression *pexpr, CColRefSet *pcrsUsed, CColRefSet *pcrsOutput, DrgPexpr **ppdrgpexprPrElPullUp // output: the pulled-up project elements ) { GPOS_ASSERT(NULL != pexpr); GPOS_ASSERT(COperator::EopLogicalProject == pexpr->Pop()->Eopid()); GPOS_ASSERT(NULL != pcrsUsed); GPOS_ASSERT(NULL != ppdrgpexprPrElPullUp); GPOS_ASSERT(NULL != *ppdrgpexprPrElPullUp); if (2 != pexpr->UlArity()) { // the project's children were not extracted as part of the pattern in this xform GPOS_ASSERT(0 == pexpr->UlArity()); pexpr->AddRef(); return pexpr; } DrgPexpr *pdrgpexprPrElNoPullUp = GPOS_NEW(pmp) DrgPexpr(pmp); CExpression *pexprPrL = (*pexpr)[1]; const ULONG ulProjElements = pexprPrL->UlArity(); for (ULONG ul = 0; ul < ulProjElements; ul++) { CExpression *pexprPrEl = (*pexprPrL)[ul]; CScalarProjectElement *popPrEl = CScalarProjectElement::PopConvert(pexprPrEl->Pop()); CColRef *pcrDefined = popPrEl->Pcr(); CColRefSet *pcrsUsedByProjElem = CDrvdPropScalar::Pdpscalar(pexprPrEl->PdpDerive())->PcrsUsed(); // a proj elem can be pulled up only if the defined column is not in // pcrsUsed and its used columns are in pcrOutput pexprPrEl->AddRef(); if (!pcrsUsed->FMember(pcrDefined) && pcrsOutput->FSubset(pcrsUsedByProjElem)) { (*ppdrgpexprPrElPullUp)->Append(pexprPrEl); } else { pdrgpexprPrElNoPullUp->Append(pexprPrEl); } } CExpression *pexprNew = (*pexpr)[0]; pexprNew->AddRef(); if (0 == pdrgpexprPrElNoPullUp->UlLength()) { pdrgpexprPrElNoPullUp->Release(); } else { // some project elements could not be pulled up - need a project here CExpression *pexprPrjList = GPOS_NEW(pmp) CExpression(pmp, GPOS_NEW(pmp) CScalarProjectList(pmp), pdrgpexprPrElNoPullUp); pexprNew = GPOS_NEW(pmp) CExpression(pmp, GPOS_NEW(pmp) CLogicalProject(pmp), pexprNew, pexprPrjList); } return pexprNew; }