//--------------------------------------------------------------------------- // @function: // CExpressionHandle::PcrsUsedColumns // // @doc: // Return the columns used by a logical operator and all its scalar children // //--------------------------------------------------------------------------- CColRefSet * CExpressionHandle::PcrsUsedColumns ( IMemoryPool *pmp ) { COperator *pop = Pop(); GPOS_ASSERT(pop->FLogical()); CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp); // get columns used by the operator itself pcrs->Include(CLogical::PopConvert(pop)->PcrsLocalUsed()); // get columns used by the scalar children const ULONG ulArity = UlArity(); for (ULONG ul = 0; ul < ulArity; ul++) { if (FScalarChild(ul)) { pcrs->Include(Pdpscalar(ul)->PcrsUsed()); } } return pcrs; }
//--------------------------------------------------------------------------- // @function: // CNormalizer::PexprNormalize // // @doc: // Main driver // //--------------------------------------------------------------------------- CExpression * CNormalizer::PexprNormalize ( IMemoryPool *pmp, CExpression *pexpr ) { GPOS_CHECK_STACK_SIZE; GPOS_ASSERT(NULL != pexpr); if (0 == pexpr->UlArity()) { // end recursion early for leaf patterns extracted from memo pexpr->AddRef(); return pexpr; } CExpression *pexprResult = NULL; COperator *pop = pexpr->Pop(); if (pop->FLogical() && CLogical::PopConvert(pop)->FSelectionOp()) { if (FPushThruOuterChild(pexpr)) { CExpression *pexprConstTrue = CUtils::PexprScalarConstBool(pmp, true /*fVal*/); PushThru(pmp, pexpr, pexprConstTrue, &pexprResult); pexprConstTrue->Release(); } else { // add-ref all children except scalar predicate const ULONG ulArity = pexpr->UlArity(); DrgPexpr *pdrgpexpr = GPOS_NEW(pmp) DrgPexpr(pmp); for (ULONG ul = 0; ul < ulArity - 1; ul++) { CExpression *pexprChild = (*pexpr)[ul]; pexprChild->AddRef(); pdrgpexpr->Append(pexprChild); } // normalize scalar predicate and construct a new expression CExpression *pexprPred = (*pexpr)[pexpr->UlArity() - 1]; CExpression *pexprPredNormalized = PexprRecursiveNormalize(pmp, pexprPred); pdrgpexpr->Append(pexprPredNormalized); COperator *pop = pexpr->Pop(); pop->AddRef(); CExpression *pexprNew = GPOS_NEW(pmp) CExpression(pmp, pop, pdrgpexpr); // push normalized predicate through PushThru(pmp, pexprNew, pexprPredNormalized, &pexprResult); pexprNew->Release(); } } else { pexprResult = PexprRecursiveNormalize(pmp, pexpr); } GPOS_ASSERT(NULL != pexprResult); return pexprResult; }
//--------------------------------------------------------------------------- // @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); }