//--------------------------------------------------------------------------- // @function: // CNormalizer::PushThruSetOp // // @doc: // Push a conjunct through set operation // //--------------------------------------------------------------------------- void CNormalizer::PushThruSetOp ( IMemoryPool *pmp, CExpression *pexprSetOp, CExpression *pexprConj, CExpression **ppexprResult ) { GPOS_ASSERT(NULL != pexprSetOp); GPOS_ASSERT(CUtils::FLogicalSetOp(pexprSetOp->Pop())); GPOS_ASSERT(NULL != pexprConj); GPOS_ASSERT(NULL != ppexprResult); CLogicalSetOp *popSetOp = CLogicalSetOp::PopConvert(pexprSetOp->Pop()); DrgPcr *pdrgpcrOutput = popSetOp->PdrgpcrOutput(); CColRefSet *pcrsOutput = GPOS_NEW(pmp) CColRefSet(pmp, pdrgpcrOutput); DrgDrgPcr *pdrgpdrgpcrInput = popSetOp->PdrgpdrgpcrInput(); DrgPexpr *pdrgpexprNewChildren = GPOS_NEW(pmp) DrgPexpr(pmp); const ULONG ulArity = pexprSetOp->UlArity(); for (ULONG ul = 0; ul < ulArity; ul++) { CExpression *pexprChild = (*pexprSetOp)[ul]; DrgPcr *pdrgpcrChild = (*pdrgpdrgpcrInput)[ul]; CColRefSet *pcrsChild = GPOS_NEW(pmp) CColRefSet(pmp, pdrgpcrChild); pexprConj->AddRef(); CExpression *pexprRemappedConj = pexprConj; if (!pcrsChild->FEqual(pcrsOutput)) { // child columns are different from SetOp output columns, // we need to fix conjunct by mapping output columns to child columns, // columns that are not in the output of SetOp child need also to be re-mapped // to new columns, // // for example, if the conjunct looks like 'x > (select max(y) from T)' // and the SetOp child produces only column x, we need to create a new // conjunct that looks like 'x1 > (select max(y1) from T)' // where x1 is a copy of x, and y1 is a copy of y // // this is achieved by passing (fMustExist = True) flag below, which enforces // creating column copies for columns not already in the given map HMUlCr *phmulcr = CUtils::PhmulcrMapping(pmp, pdrgpcrOutput, pdrgpcrChild); pexprRemappedConj->Release(); pexprRemappedConj = pexprConj->PexprCopyWithRemappedColumns(pmp, phmulcr, true /*fMustExist*/); phmulcr->Release(); } CExpression *pexprNewChild = NULL; PushThru(pmp, pexprChild, pexprRemappedConj, &pexprNewChild); pdrgpexprNewChildren->Append(pexprNewChild); pexprRemappedConj->Release(); pcrsChild->Release(); } pcrsOutput->Release(); popSetOp->AddRef(); *ppexprResult = GPOS_NEW(pmp) CExpression(pmp, popSetOp, pdrgpexprNewChildren); }
//--------------------------------------------------------------------------- // @function: // CLogicalSetOp::FMatch // // @doc: // Match function on operator level // //--------------------------------------------------------------------------- BOOL CLogicalSetOp::FMatch ( COperator *pop ) const { if (pop->Eopid() != Eopid()) { return false; } CLogicalSetOp *popSetOp = CLogicalSetOp::PopConvert(pop); DrgDrgPcr *pdrgpdrgpcrInput = popSetOp->PdrgpdrgpcrInput(); const ULONG ulArity = pdrgpdrgpcrInput->UlLength(); if (ulArity != m_pdrgpdrgpcrInput->UlLength() || !m_pdrgpcrOutput->FEqual(popSetOp->PdrgpcrOutput())) { return false; } for (ULONG ul = 0; ul < ulArity; ul++) { if (!(*m_pdrgpdrgpcrInput)[ul]->FEqual((*pdrgpdrgpcrInput)[ul])) { return false; } } return true; }