//--------------------------------------------------------------------------- // @function: // CCNFConverter::Pdrgpdrgpexpr // // @doc: // Create an array of arrays each holding the children of an expression // from the given array // // //--------------------------------------------------------------------------- DrgPdrgPexpr * CCNFConverter::Pdrgpdrgpexpr ( IMemoryPool *pmp, DrgPexpr *pdrgpexpr ) { GPOS_ASSERT(NULL != pmp); GPOS_ASSERT(NULL != pdrgpexpr); DrgPdrgPexpr *pdrgpdrgpexpr = GPOS_NEW(pmp) DrgPdrgPexpr(pmp); const ULONG ulArity = pdrgpexpr->UlLength(); for (ULONG ul = 0; ul < ulArity; ul++) { CExpression *pexpr = (*pdrgpexpr)[ul]; DrgPexpr *pdrgpexprChild = NULL; if (CPredicateUtils::FAnd(pexpr)) { pdrgpexprChild = pexpr->PdrgPexpr(); pdrgpexprChild->AddRef(); } else { pdrgpexprChild = GPOS_NEW(pmp) DrgPexpr(pmp); pexpr->AddRef(); pdrgpexprChild->Append(pexpr); } pdrgpdrgpexpr->Append(pdrgpexprChild); } return pdrgpdrgpexpr; }
//--------------------------------------------------------------------------- // @function: // CNormalizer::PexprPullUpAndCombineProjects // // @doc: // Pulls up logical projects as far as possible, and combines consecutive // projects if possible // //--------------------------------------------------------------------------- CExpression * CNormalizer::PexprPullUpAndCombineProjects ( IMemoryPool *pmp, CExpression *pexpr, BOOL *pfSuccess // output to indicate whether anything was pulled up ) { GPOS_ASSERT(NULL != pexpr); GPOS_ASSERT(NULL != pfSuccess); COperator *pop = pexpr->Pop(); const ULONG ulArity = pexpr->UlArity(); if (!pop->FLogical() || 0 == ulArity) { pexpr->AddRef(); return pexpr; } DrgPexpr *pdrgpexprChildren = GPOS_NEW(pmp) DrgPexpr(pmp); DrgPexpr *pdrgpexprPrElPullUp = GPOS_NEW(pmp) DrgPexpr(pmp); CExpressionHandle exprhdl(pmp); exprhdl.Attach(pexpr); CColRefSet *pcrsOutput = CDrvdPropRelational::Pdprel(pexpr->PdpDerive())->PcrsOutput(); // extract the columns used by the scalar expression and the operator itself (for grouping, sorting, etc.) CColRefSet *pcrsUsed = exprhdl.PcrsUsedColumns(pmp); for (ULONG ul = 0; ul < ulArity; ul++) { CExpression *pexprChild = PexprPullUpAndCombineProjects(pmp, (*pexpr)[ul], pfSuccess); if (pop->FLogical() && CLogical::PopConvert(pop)->FCanPullProjectionsUp(ul) && COperator::EopLogicalProject == pexprChild->Pop()->Eopid()) { // this child is a project - see if any project elements can be pulled up CExpression *pexprNewChild = PexprPullUpProjectElements ( pmp, pexprChild, pcrsUsed, pcrsOutput, &pdrgpexprPrElPullUp ); pexprChild->Release(); pexprChild = pexprNewChild; } pdrgpexprChildren->Append(pexprChild); } pcrsUsed->Release(); pop->AddRef(); if (0 < pdrgpexprPrElPullUp->UlLength() && COperator::EopLogicalProject == pop->Eopid()) { // some project elements have been pulled up and the original expression // was a project - combine its project list with the pulled up project elements GPOS_ASSERT(2 == pdrgpexprChildren->UlLength()); *pfSuccess = true; CExpression *pexprRelational = (*pdrgpexprChildren)[0]; CExpression *pexprPrLOld = (*pdrgpexprChildren)[1]; pexprRelational->AddRef(); CUtils::AddRefAppend(pdrgpexprPrElPullUp, pexprPrLOld->PdrgPexpr()); pdrgpexprChildren->Release(); CExpression *pexprPrjList = GPOS_NEW(pmp) CExpression(pmp, GPOS_NEW(pmp) CScalarProjectList(pmp), pdrgpexprPrElPullUp); GPOS_ASSERT(CDrvdPropRelational::Pdprel(pexprRelational->PdpDerive())->PcrsOutput()->FSubset(CDrvdPropScalar::Pdpscalar(pexprPrjList->PdpDerive())->PcrsUsed())); return GPOS_NEW(pmp) CExpression(pmp, pop, pexprRelational, pexprPrjList); } CExpression *pexprOutput = GPOS_NEW(pmp) CExpression(pmp, pop, pdrgpexprChildren); if (0 == pdrgpexprPrElPullUp->UlLength()) { // no project elements were pulled up pdrgpexprPrElPullUp->Release(); return pexprOutput; } // some project elements were pulled - add a project on top of output expression *pfSuccess = true; CExpression *pexprPrjList = GPOS_NEW(pmp) CExpression(pmp, GPOS_NEW(pmp) CScalarProjectList(pmp), pdrgpexprPrElPullUp); GPOS_ASSERT(CDrvdPropRelational::Pdprel(pexprOutput->PdpDerive())->PcrsOutput()->FSubset(CDrvdPropScalar::Pdpscalar(pexprPrjList->PdpDerive())->PcrsUsed())); return GPOS_NEW(pmp) CExpression(pmp, GPOS_NEW(pmp) CLogicalProject(pmp), pexprOutput, pexprPrjList); }