//--------------------------------------------------------------------------- // @function: // CPhysicalAgg::PdsRequiredIntermediateAgg // // @doc: // Compute required distribution of the n-th child of an intermediate // aggregate operator // //--------------------------------------------------------------------------- CDistributionSpec * CPhysicalAgg::PdsRequiredIntermediateAgg ( IMemoryPool *pmp, ULONG ulOptReq ) const { GPOS_ASSERT(COperator::EgbaggtypeIntermediate == m_egbaggtype); if (0 == ulOptReq) { return PdsMaximalHashed(pmp, m_pdrgpcr); } DrgPcr *pdrgpcr = GPOS_NEW(pmp) DrgPcr(pmp); const ULONG ulLen = m_pdrgpcr->UlLength() - m_pdrgpcrArgDQA->UlLength(); for (ULONG ul = 0; ul < ulLen; ul++) { CColRef *pcr = (*m_pdrgpcr)[ul]; pdrgpcr->Append(pcr); } CDistributionSpec *pds = PdsMaximalHashed(pmp, pdrgpcr); pdrgpcr->Release(); return pds; }
//--------------------------------------------------------------------------- // @function: // CLogical::PdrgpdrgpcrCreatePartCols // // @doc: // Initialize array of partition columns from the array with their indexes // //--------------------------------------------------------------------------- DrgDrgPcr * CLogical::PdrgpdrgpcrCreatePartCols ( IMemoryPool *pmp, DrgPcr *pdrgpcr, const DrgPul *pdrgpulPart ) { GPOS_ASSERT(NULL != pdrgpcr && "Output columns cannot be NULL"); GPOS_ASSERT(NULL != pdrgpulPart); DrgDrgPcr *pdrgpdrgpcrPart = GPOS_NEW(pmp) DrgDrgPcr(pmp); const ULONG ulPartCols = pdrgpulPart->UlLength(); GPOS_ASSERT(0 < ulPartCols); for (ULONG ul = 0; ul < ulPartCols; ul++) { ULONG ulCol = *((*pdrgpulPart)[ul]); CColRef *pcr = (*pdrgpcr)[ulCol]; DrgPcr * pdrgpcrCurr = GPOS_NEW(pmp) DrgPcr(pmp); pdrgpcrCurr->Append(pcr); pdrgpdrgpcrPart->Append(pdrgpcrCurr); } return pdrgpdrgpcrPart; }
//--------------------------------------------------------------------------- // @function: // CXformImplementDynamicBitmapTableGet::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformImplementDynamicBitmapTableGet::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); IMemoryPool *pmp = pxfctxt->Pmp(); CLogicalDynamicBitmapTableGet *popLogical = CLogicalDynamicBitmapTableGet::PopConvert(pexpr->Pop()); CTableDescriptor *ptabdesc = popLogical->Ptabdesc(); ptabdesc->AddRef(); CName *pname = GPOS_NEW(pmp) CName(pmp, popLogical->Name()); DrgPcr *pdrgpcrOutput = popLogical->PdrgpcrOutput(); GPOS_ASSERT(NULL != pdrgpcrOutput); pdrgpcrOutput->AddRef(); DrgDrgPcr *pdrgpdrgpcrPart = popLogical->PdrgpdrgpcrPart(); pdrgpdrgpcrPart->AddRef(); CPartConstraint *ppartcnstr = popLogical->Ppartcnstr(); ppartcnstr->AddRef(); CPartConstraint *ppartcnstrRel = popLogical->PpartcnstrRel(); ppartcnstrRel->AddRef(); CPhysicalDynamicBitmapTableScan *popPhysical = GPOS_NEW(pmp) CPhysicalDynamicBitmapTableScan ( pmp, popLogical->FPartial(), ptabdesc, pexpr->Pop()->UlOpId(), pname, popLogical->UlScanId(), pdrgpcrOutput, pdrgpdrgpcrPart, popLogical->UlSecondaryScanId(), ppartcnstr, ppartcnstrRel ); CExpression *pexprCondition = (*pexpr)[0]; CExpression *pexprIndexPath = (*pexpr)[1]; pexprCondition->AddRef(); pexprIndexPath->AddRef(); CExpression *pexprPhysical = GPOS_NEW(pmp) CExpression(pmp, popPhysical, pexprCondition, pexprIndexPath); pxfres->Add(pexprPhysical); }
//--------------------------------------------------------------------------- // @function: // CLogicalSetOp::PpartinfoDerive // // @doc: // Derive partition consumer info // //--------------------------------------------------------------------------- CPartInfo * CLogicalSetOp::PpartinfoDerive ( IMemoryPool *pmp, CExpressionHandle &exprhdl ) const { const ULONG ulArity = exprhdl.UlArity(); GPOS_ASSERT(0 < ulArity); // start with the part info of the first child CPartInfo *ppartinfo = exprhdl.Pdprel(0 /*ulChildIndex*/)->Ppartinfo(); ppartinfo->AddRef(); for (ULONG ul = 1; ul < ulArity; ul++) { CPartInfo *ppartinfoChild = exprhdl.Pdprel(ul)->Ppartinfo(); GPOS_ASSERT(NULL != ppartinfoChild); DrgPcr *pdrgpcrInput = (*m_pdrgpdrgpcrInput)[ul]; GPOS_ASSERT(pdrgpcrInput->UlLength() == m_pdrgpcrOutput->UlLength()); CPartInfo *ppartinfoRemapped = ppartinfoChild->PpartinfoWithRemappedKeys(pmp, pdrgpcrInput, m_pdrgpcrOutput); CPartInfo *ppartinfoCombined = CPartInfo::PpartinfoCombine(pmp, ppartinfo, ppartinfoRemapped); ppartinfoRemapped->Release(); ppartinfo->Release(); ppartinfo = ppartinfoCombined; } return ppartinfo; }
//--------------------------------------------------------------------------- // @function: // CLogical::PkcCombineKeys // // @doc: // Common case of combining keys from first n - 1 children // //--------------------------------------------------------------------------- CKeyCollection * CLogical::PkcCombineKeys ( IMemoryPool *pmp, CExpressionHandle &exprhdl ) { CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp); const ULONG ulArity = exprhdl.UlArity(); for (ULONG ul = 0; ul < ulArity - 1; ul++) { CKeyCollection *pkc = exprhdl.Pdprel(ul)->Pkc(); if (NULL == pkc) { // if a child has no key, the operator has no key pcrs->Release(); return NULL; } DrgPcr *pdrgpcr = pkc->PdrgpcrKey(pmp); pcrs->Include(pdrgpcr); pdrgpcr->Release(); } return GPOS_NEW(pmp) CKeyCollection(pmp, pcrs); }
//--------------------------------------------------------------------------- // @function: // CLogical::PdrgpcrCreateMapping // // @doc: // Create output column mapping given a list of column descriptors and // a pointer to the operator creating that column // //--------------------------------------------------------------------------- DrgPcr * CLogical::PdrgpcrCreateMapping ( IMemoryPool *pmp, const DrgPcoldesc *pdrgpcoldesc, ULONG ulOpSourceId ) const { // get column factory from optimizer context object CColumnFactory *pcf = COptCtxt::PoctxtFromTLS()->Pcf(); ULONG ulCols = pdrgpcoldesc->UlLength(); DrgPcr *pdrgpcr = GPOS_NEW(pmp) DrgPcr(pmp, ulCols); for(ULONG ul = 0; ul < ulCols; ul++) { CColumnDescriptor *pcoldesc = (*pdrgpcoldesc)[ul]; CName name(pmp, pcoldesc->Name()); CColRef *pcr = pcf->PcrCreate(pcoldesc, name, ulOpSourceId); pdrgpcr->Append(pcr); } return pdrgpcr; }
//--------------------------------------------------------------------------- // @function: // CXformDifferenceAll2LeftAntiSemiJoin::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformDifferenceAll2LeftAntiSemiJoin::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); IMemoryPool *pmp = pxfctxt->Pmp(); // TODO: , Jan 8th 2013, we currently only handle difference all // operators with two children GPOS_ASSERT(2 == pexpr->UlArity()); // extract components CExpression *pexprLeftChild = (*pexpr)[0]; CExpression *pexprRightChild = (*pexpr)[1]; CLogicalDifferenceAll *popDifferenceAll = CLogicalDifferenceAll::PopConvert(pexpr->Pop()); DrgDrgPcr *pdrgpdrgpcrInput = popDifferenceAll->PdrgpdrgpcrInput(); CExpression *pexprLeftWindow = CXformUtils::PexprWindowWithRowNumber(pmp, pexprLeftChild, (*pdrgpdrgpcrInput)[0]); CExpression *pexprRightWindow = CXformUtils::PexprWindowWithRowNumber(pmp, pexprRightChild, (*pdrgpdrgpcrInput)[1]); DrgDrgPcr *pdrgpdrgpcrInputNew = GPOS_NEW(pmp) DrgDrgPcr(pmp); DrgPcr *pdrgpcrLeftNew = CUtils::PdrgpcrExactCopy(pmp, (*pdrgpdrgpcrInput)[0]); pdrgpcrLeftNew->Append(CXformUtils::PcrProjectElement(pexprLeftWindow, 0 /* row_number window function*/)); DrgPcr *pdrgpcrRightNew = CUtils::PdrgpcrExactCopy(pmp, (*pdrgpdrgpcrInput)[1]); pdrgpcrRightNew->Append(CXformUtils::PcrProjectElement(pexprRightWindow, 0 /* row_number window function*/)); pdrgpdrgpcrInputNew->Append(pdrgpcrLeftNew); pdrgpdrgpcrInputNew->Append(pdrgpcrRightNew); // generate the scalar condition for the left anti-semi join CExpression *pexprScCond = CUtils::PexprConjINDFCond(pmp, pdrgpdrgpcrInputNew); // assemble the new left anti-semi join logical operator CExpression *pexprLASJ = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CLogicalLeftAntiSemiJoin(pmp), pexprLeftWindow, pexprRightWindow, pexprScCond ); // clean up pdrgpdrgpcrInputNew->Release(); // add alternative to results pxfres->Add(pexprLASJ); }
//--------------------------------------------------------------------------- // @function: // CXformDynamicGet2DynamicTableScan::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformDynamicGet2DynamicTableScan::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); CLogicalDynamicGet *popGet = CLogicalDynamicGet::PopConvert(pexpr->Pop()); IMemoryPool *pmp = pxfctxt->Pmp(); // create/extract components for alternative CName *pname = GPOS_NEW(pmp) CName(pmp, popGet->Name()); CTableDescriptor *ptabdesc = popGet->Ptabdesc(); ptabdesc->AddRef(); DrgPcr *pdrgpcrOutput = popGet->PdrgpcrOutput(); GPOS_ASSERT(NULL != pdrgpcrOutput); pdrgpcrOutput->AddRef(); DrgDrgPcr *pdrgpdrgpcrPart = popGet->PdrgpdrgpcrPart(); pdrgpdrgpcrPart->AddRef(); popGet->Ppartcnstr()->AddRef(); popGet->PpartcnstrRel()->AddRef(); // create alternative expression CExpression *pexprAlt = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CPhysicalDynamicTableScan ( pmp, popGet->FPartial(), pname, ptabdesc, popGet->UlOpId(), popGet->UlScanId(), pdrgpcrOutput, pdrgpdrgpcrPart, popGet->UlSecondaryScanId(), popGet->Ppartcnstr(), popGet->PpartcnstrRel() ) ); // add alternative to transformation result pxfres->Add(pexprAlt); }
//--------------------------------------------------------------------------- // @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: // CXformGbAggDedup2HashAggDedup::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformGbAggDedup2HashAggDedup::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); IMemoryPool *pmp = pxfctxt->Pmp(); CLogicalGbAggDeduplicate *popAggDedup = CLogicalGbAggDeduplicate::PopConvert(pexpr->Pop()); DrgPcr *pdrgpcr = popAggDedup->Pdrgpcr(); pdrgpcr->AddRef(); DrgPcr *pdrgpcrKeys = popAggDedup->PdrgpcrKeys(); pdrgpcrKeys->AddRef(); // extract components CExpression *pexprRel = (*pexpr)[0]; CExpression *pexprScalar = (*pexpr)[1]; GPOS_ASSERT(0 == pexprScalar->UlArity()); // addref children pexprRel->AddRef(); pexprScalar->AddRef(); // create alternative expression CExpression *pexprAlt = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CPhysicalHashAggDeduplicate ( pmp, pdrgpcr, popAggDedup->PdrgpcrMinimal(), popAggDedup->Egbaggtype(), pdrgpcrKeys, popAggDedup->FGeneratesDuplicates(), CXformUtils::FMultiStageAgg(pexpr) ), pexprRel, pexprScalar ); // add alternative to transformation result pxfres->Add(pexprAlt); }
//--------------------------------------------------------------------------- // @function: // CXformSimplifyGbAgg::FDropGbAgg // // @doc: // Return true if GbAgg operator can be dropped because grouping // columns include a key // //--------------------------------------------------------------------------- BOOL CXformSimplifyGbAgg::FDropGbAgg ( IMemoryPool *pmp, CExpression *pexpr, CXformResult *pxfres ) { CLogicalGbAgg *popAgg = CLogicalGbAgg::PopConvert(pexpr->Pop()); CExpression *pexprRelational = (*pexpr)[0]; CExpression *pexprProjectList = (*pexpr)[1]; if (0 < pexprProjectList->UlArity()) { // GbAgg cannot be dropped if Agg functions are computed return false; } CKeyCollection *pkc = CDrvdPropRelational::Pdprel(pexprRelational->PdpDerive())->Pkc(); if (NULL == pkc) { // relational child does not have key return false; } const ULONG ulKeys = pkc->UlKeys(); BOOL fDrop = false; for (ULONG ul = 0; !fDrop && ul < ulKeys; ul++) { DrgPcr *pdrgpcrKey = pkc->PdrgpcrKey(pmp, ul); CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp, pdrgpcrKey); pdrgpcrKey->Release(); CColRefSet *pcrsGrpCols = GPOS_NEW(pmp) CColRefSet(pmp); pcrsGrpCols->Include(popAgg->Pdrgpcr()); BOOL fGrpColsHasKey = pcrsGrpCols->FSubset(pcrs); pcrs->Release(); pcrsGrpCols->Release(); if (fGrpColsHasKey) { // Gb operator can be dropped pexprRelational->AddRef(); CExpression *pexprResult = CUtils::PexprLogicalSelect(pmp, pexprRelational, CPredicateUtils::PexprConjunction(pmp, NULL)); pxfres->Add(pexprResult); fDrop = true; } } return fDrop; }
//--------------------------------------------------------------------------- // @function: // CXformDelete2DML::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformDelete2DML::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); CLogicalDelete *popDelete = CLogicalDelete::PopConvert(pexpr->Pop()); IMemoryPool *pmp = pxfctxt->Pmp(); // extract components for alternative CTableDescriptor *ptabdesc = popDelete->Ptabdesc(); ptabdesc->AddRef(); DrgPcr *pdrgpcr = popDelete->Pdrgpcr(); pdrgpcr->AddRef(); CColRef *pcrCtid = popDelete->PcrCtid(); CColRef *pcrSegmentId = popDelete->PcrSegmentId(); // child of delete operator CExpression *pexprChild = (*pexpr)[0]; pexprChild->AddRef(); // create logical DML CExpression *pexprAlt = CXformUtils::PexprLogicalDMLOverProject ( pmp, pexprChild, CLogicalDML::EdmlDelete, ptabdesc, pdrgpcr, pcrCtid, pcrSegmentId ); // add alternative to transformation result pxfres->Add(pexprAlt); }
//--------------------------------------------------------------------------- // @function: // CColRefSet::Pdrgpcr // // @doc: // Convert set into array // //--------------------------------------------------------------------------- DrgPcr * CColRefSet::Pdrgpcr ( IMemoryPool *pmp ) const { DrgPcr *pdrgpcr = GPOS_NEW(pmp) DrgPcr(pmp); CColRefSetIter crsi(*this); while(crsi.FAdvance()) { pdrgpcr->Append(crsi.Pcr()); } return pdrgpcr; }
//--------------------------------------------------------------------------- // @function: // CXformImplementSplit::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformImplementSplit::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); CLogicalSplit *popSplit = CLogicalSplit::PopConvert(pexpr->Pop()); IMemoryPool *pmp = pxfctxt->Pmp(); // extract components for alternative DrgPcr *pdrgpcrDelete = popSplit->PdrgpcrDelete(); pdrgpcrDelete->AddRef(); DrgPcr *pdrgpcrInsert = popSplit->PdrgpcrInsert(); pdrgpcrInsert->AddRef(); CColRef *pcrAction = popSplit->PcrAction(); CColRef *pcrCtid = popSplit->PcrCtid(); CColRef *pcrSegmentId = popSplit->PcrSegmentId(); CColRef *pcrTupleOid = popSplit->PcrTupleOid(); // child of Split operator CExpression *pexprChild = (*pexpr)[0]; CExpression *pexprProjList = (*pexpr)[1]; pexprChild->AddRef(); pexprProjList->AddRef(); // create physical Split CExpression *pexprAlt = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CPhysicalSplit(pmp, pdrgpcrDelete, pdrgpcrInsert, pcrCtid, pcrSegmentId, pcrAction, pcrTupleOid), pexprChild, pexprProjList ); // add alternative to transformation result pxfres->Add(pexprAlt); }
//--------------------------------------------------------------------------- // @function: // CXformImplementInnerIndexApply::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformImplementInnerIndexApply::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); IMemoryPool *pmp = pxfctxt->Pmp(); // extract components CExpression *pexprOuter = (*pexpr)[0]; CExpression *pexprInner = (*pexpr)[1]; CExpression *pexprScalar = (*pexpr)[2]; DrgPcr *pdrgpcr = CLogicalInnerIndexApply::PopConvert(pexpr->Pop())->PdrgPcrOuterRefs(); pdrgpcr->AddRef(); // addref all components pexprOuter->AddRef(); pexprInner->AddRef(); pexprScalar->AddRef(); // assemble physical operator CExpression *pexprResult = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CPhysicalInnerIndexNLJoin(pmp, pdrgpcr), pexprOuter, pexprInner, pexprScalar ); // add alternative to results pxfres->Add(pexprResult); }
//--------------------------------------------------------------------------- // @function: // CPhysicalUnionAll::PdrgpulMap // // @doc: // Map given array of scalar identifier expressions to positions of // UnionAll input columns in the given child; // the function returns NULL if no mapping could be constructed // //--------------------------------------------------------------------------- DrgPul * CPhysicalUnionAll::PdrgpulMap ( IMemoryPool *pmp, DrgPexpr *pdrgpexpr, ULONG ulChildIndex ) const { GPOS_ASSERT(NULL != pdrgpexpr); DrgPcr *pdrgpcr = (*m_pdrgpdrgpcrInput)[ulChildIndex]; const ULONG ulExprs = pdrgpexpr->UlLength(); const ULONG ulCols = pdrgpcr->UlLength(); DrgPul *pdrgpul = GPOS_NEW(pmp) DrgPul(pmp); for (ULONG ulExpr = 0; ulExpr < ulExprs; ulExpr++) { CExpression *pexpr = (*pdrgpexpr)[ulExpr]; if (COperator::EopScalarIdent != pexpr->Pop()->Eopid()) { continue; } const CColRef *pcr = CScalarIdent::PopConvert(pexpr->Pop())->Pcr(); for (ULONG ulCol = 0; ulCol < ulCols; ulCol++) { if ((*pdrgpcr)[ulCol] == pcr) { pdrgpul->Append(GPOS_NEW(pmp) ULONG(ulCol)); } } } if (0 == pdrgpul->UlLength()) { // mapping failed pdrgpul->Release(); pdrgpul = NULL; } return pdrgpul; }
//--------------------------------------------------------------------------- // @function: // CKeyCollection::PdrgpcrHashableKey // // @doc: // Extract a hashable key // //--------------------------------------------------------------------------- DrgPcr * CKeyCollection::PdrgpcrHashableKey ( IMemoryPool *pmp ) const { const ULONG ulSets = m_pdrgpcrs->UlLength(); for(ULONG ul = 0; ul < ulSets; ul++) { DrgPcr *pdrgpcrKey = (*m_pdrgpcrs)[ul]->Pdrgpcr(pmp); if (CUtils::FHashable(pdrgpcrKey)) { return pdrgpcrKey; } pdrgpcrKey->Release(); } // no hashable key is found return NULL; }
//--------------------------------------------------------------------------- // @function: // CDistributionSpecHashed::PdshashedMaximal // // @doc: // Return a hashed distribution on the maximal hashable subset of // given columns, // if all columns are not hashable, return NULL // //--------------------------------------------------------------------------- CDistributionSpecHashed * CDistributionSpecHashed::PdshashedMaximal ( IMemoryPool *pmp, DrgPcr *pdrgpcr, BOOL fNullsColocated ) { GPOS_ASSERT(NULL != pdrgpcr); GPOS_ASSERT(0 < pdrgpcr->UlLength()); DrgPcr *pdrgpcrHashable = CUtils::PdrgpcrHashableSubset(pmp, pdrgpcr); CDistributionSpecHashed *pdshashed = NULL; if (0 < pdrgpcrHashable->UlLength()) { DrgPexpr *pdrgpexpr = CUtils::PdrgpexprScalarIdents(pmp, pdrgpcrHashable); pdshashed = GPOS_NEW(pmp) CDistributionSpecHashed(pdrgpexpr, fNullsColocated); } pdrgpcrHashable->Release(); return pdshashed; }
//--------------------------------------------------------------------------- // @function: // CPartKeys::PpartkeysCopy // // @doc: // Copy part key into the given memory pool // //--------------------------------------------------------------------------- CPartKeys * CPartKeys::PpartkeysCopy ( IMemoryPool *pmp ) { DrgDrgPcr *pdrgpdrgpcrCopy = GPOS_NEW(pmp) DrgDrgPcr(pmp); const ULONG ulLength = m_pdrgpdrgpcr->UlLength(); for (ULONG ul = 0; ul < ulLength; ul++) { DrgPcr *pdrgpcr = (*m_pdrgpdrgpcr)[ul]; DrgPcr *pdrgpcrCopy = GPOS_NEW(pmp) DrgPcr(pmp); const ULONG ulCols = pdrgpcr->UlLength(); for (ULONG ulCol = 0; ulCol < ulCols; ulCol++) { pdrgpcrCopy->Append((*pdrgpcr)[ulCol]); } pdrgpdrgpcrCopy->Append(pdrgpcrCopy); } return GPOS_NEW(pmp) CPartKeys(pdrgpdrgpcrCopy); }
//--------------------------------------------------------------------------- // @function: // CTranslatorDXLToExprUtils::Pdrgpcr // // @doc: // Construct a dynamic array of column references corresponding to the // given col ids // //--------------------------------------------------------------------------- DrgPcr * CTranslatorDXLToExprUtils::Pdrgpcr ( IMemoryPool *pmp, HMUlCr *phmulcr, const DrgPul *pdrgpulColIds ) { GPOS_ASSERT(NULL != pdrgpulColIds); DrgPcr *pdrgpcr = GPOS_NEW(pmp) DrgPcr(pmp); for (ULONG ul = 0; ul < pdrgpulColIds->UlLength(); ul++) { ULONG *pulColId = (*pdrgpulColIds)[ul]; const CColRef *pcr = phmulcr->PtLookup(pulColId); GPOS_ASSERT(NULL != pcr); pdrgpcr->Append(const_cast<CColRef*>(pcr)); } return pdrgpcr; }
//--------------------------------------------------------------------------- // @function: // CLogicalUnion::CLogicalUnion // // @doc: // Ctor // //--------------------------------------------------------------------------- CLogicalUnion::CLogicalUnion ( IMemoryPool *pmp, DrgPcr *pdrgpcrOutput, DrgDrgPcr *pdrgpdrgpcrInput ) : CLogicalSetOp(pmp, pdrgpcrOutput, pdrgpdrgpcrInput) { #ifdef GPOS_DEBUG DrgPcr *pdrgpcrInput = (*pdrgpdrgpcrInput)[0]; const ULONG ulCols = pdrgpcrOutput->UlLength(); GPOS_ASSERT(ulCols == pdrgpcrInput->UlLength()); // Ensure that the output columns are the same as first input for(ULONG ul = 0; ul < ulCols; ul++) { GPOS_ASSERT( (*pdrgpcrOutput)[ul] == (*pdrgpcrInput)[ul]); } #endif // GPOS_DEBUG }
//--------------------------------------------------------------------------- // @function: // CPartKeys::PpartkeysRemap // // @doc: // Create a new PartKeys object from the current one by remapping the // keys using the given hashmap // //--------------------------------------------------------------------------- CPartKeys * CPartKeys::PpartkeysRemap ( IMemoryPool *pmp, HMUlCr *phmulcr ) const { GPOS_ASSERT(NULL != phmulcr); DrgDrgPcr *pdrgpdrgpcr = GPOS_NEW(pmp) DrgDrgPcr(pmp); for (ULONG ul = 0; ul < m_ulLevels; ul++) { CColRef *pcr = CUtils::PcrRemap(PcrKey(ul), phmulcr, false /*fMustExist*/); DrgPcr *pdrgpcr = GPOS_NEW(pmp) DrgPcr(pmp); pdrgpcr->Append(pcr); pdrgpdrgpcr->Append(pdrgpcr); } return GPOS_NEW(pmp) CPartKeys(pdrgpdrgpcr); }
//--------------------------------------------------------------------------- // @function: // CXformImplementConstTableGet::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformImplementConstTableGet::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); CLogicalConstTableGet *popConstTableGet = CLogicalConstTableGet::PopConvert(pexpr->Pop()); IMemoryPool *pmp = pxfctxt->Pmp(); // create/extract components for alternative DrgPcoldesc *pdrgpcoldesc = popConstTableGet->Pdrgpcoldesc(); pdrgpcoldesc->AddRef(); DrgPdrgPdatum *pdrgpdrgpdatum = popConstTableGet->Pdrgpdrgpdatum(); pdrgpdrgpdatum->AddRef(); DrgPcr *pdrgpcrOutput = popConstTableGet->PdrgpcrOutput(); pdrgpcrOutput->AddRef(); // create alternative expression CExpression *pexprAlt = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CPhysicalConstTableGet(pmp, pdrgpcoldesc, pdrgpdrgpdatum, pdrgpcrOutput) ); // add alternative to transformation result pxfres->Add(pexprAlt); }
//--------------------------------------------------------------------------- // @function: // CXformSelect2PartialDynamicIndexGet::CreatePartialIndexGetPlan // // @doc: // Create a plan as a union of the given partial index get candidates and // possibly a dynamic table scan // //--------------------------------------------------------------------------- void CXformSelect2PartialDynamicIndexGet::CreatePartialIndexGetPlan ( IMemoryPool *pmp, CExpression *pexpr, DrgPpartdig *pdrgppartdig, const IMDRelation *pmdrel, CXformResult *pxfres ) const { CExpression *pexprRelational = (*pexpr)[0]; CExpression *pexprScalar = (*pexpr)[1]; CLogicalDynamicGet *popGet = CLogicalDynamicGet::PopConvert(pexprRelational->Pop()); DrgPcr *pdrgpcrGet = popGet->PdrgpcrOutput(); const ULONG ulPartialIndexes = pdrgppartdig->UlLength(); DrgDrgPcr *pdrgpdrgpcrInput = GPOS_NEW(pmp) DrgDrgPcr(pmp); DrgPexpr *pdrgpexprInput = GPOS_NEW(pmp) DrgPexpr(pmp); for (ULONG ul = 0; ul < ulPartialIndexes; ul++) { SPartDynamicIndexGetInfo *ppartdig = (*pdrgppartdig)[ul]; const IMDIndex *pmdindex = ppartdig->m_pmdindex; CPartConstraint *ppartcnstr = ppartdig->m_ppartcnstr; DrgPexpr *pdrgpexprIndex = ppartdig->m_pdrgpexprIndex; DrgPexpr *pdrgpexprResidual = ppartdig->m_pdrgpexprResidual; DrgPcr *pdrgpcrNew = pdrgpcrGet; if (0 < ul) { pdrgpcrNew = CUtils::PdrgpcrCopy(pmp, pdrgpcrGet); } else { pdrgpcrNew->AddRef(); } CExpression *pexprDynamicScan = NULL; if (NULL != pmdindex) { pexprDynamicScan = CXformUtils::PexprPartialDynamicIndexGet ( pmp, popGet, pexpr->Pop()->UlOpId(), pdrgpexprIndex, pdrgpexprResidual, pdrgpcrNew, pmdindex, pmdrel, ppartcnstr, NULL, // pcrsAcceptedOuterRefs NULL, // pdrgpcrOuter NULL // pdrgpcrNewOuter ); } else { pexprDynamicScan = PexprSelectOverDynamicGet ( pmp, popGet, pexprScalar, pdrgpcrNew, ppartcnstr ); } GPOS_ASSERT(NULL != pexprDynamicScan); pdrgpdrgpcrInput->Append(pdrgpcrNew); pdrgpexprInput->Append(pexprDynamicScan); } ULONG ulInput = pdrgpexprInput->UlLength(); if (0 < ulInput) { CExpression *pexprResult = NULL; if (1 < ulInput) { pdrgpcrGet->AddRef(); DrgPcr *pdrgpcrOuter = pdrgpcrGet; // construct a new union all operator pexprResult = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CLogicalUnionAll(pmp, pdrgpcrOuter, pdrgpdrgpcrInput, popGet->UlScanId()), pdrgpexprInput ); } else { pexprResult = (*pdrgpexprInput)[0]; pexprResult->AddRef(); // clean up pdrgpexprInput->Release(); pdrgpdrgpcrInput->Release(); } // if scalar expression involves the partitioning key, keep a SELECT node // on top for the purposes of partition selection DrgDrgPcr *pdrgpdrgpcrPartKeys = popGet->PdrgpdrgpcrPart(); CExpression *pexprPredOnPartKey = CPredicateUtils::PexprExtractPredicatesOnPartKeys ( pmp, pexprScalar, pdrgpdrgpcrPartKeys, NULL, /*pcrsAllowedRefs*/ true /*fUseConstraints*/ ); if (NULL != pexprPredOnPartKey) { pexprResult = GPOS_NEW(pmp) CExpression(pmp, GPOS_NEW(pmp) CLogicalSelect(pmp), pexprResult, pexprPredOnPartKey); } pxfres->Add(pexprResult); return; } // clean up pdrgpdrgpcrInput->Release(); pdrgpexprInput->Release(); }
//--------------------------------------------------------------------------- // @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); }
//--------------------------------------------------------------------------- // @function: // CXformInnerApplyWithOuterKey2InnerJoin::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformInnerApplyWithOuterKey2InnerJoin::Transform ( CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexpr ) const { GPOS_ASSERT(NULL != pxfctxt); GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr)); GPOS_ASSERT(FCheckPattern(pexpr)); IMemoryPool *pmp = pxfctxt->Pmp(); // extract components CExpression *pexprOuter = (*pexpr)[0]; CExpression *pexprGb = (*pexpr)[1]; CExpression *pexprScalar = (*pexpr)[2]; if (0 < CLogicalGbAgg::PopConvert(pexprGb->Pop())->Pdrgpcr()->UlLength()) { // xform is not applicable if inner Gb has grouping columns return; } if (CUtils::FHasSubqueryOrApply((*pexprGb)[0])) { // Subquery/Apply must be unnested before reaching here return; } // decorrelate Gb's relational child (*pexprGb)[0]->ResetDerivedProperties(); CExpression *pexprInner = NULL; DrgPexpr *pdrgpexpr = GPOS_NEW(pmp) DrgPexpr(pmp); if (!CDecorrelator::FProcess(pmp, (*pexprGb)[0], false /*fEqualityOnly*/, &pexprInner, pdrgpexpr)) { pdrgpexpr->Release(); return; } GPOS_ASSERT(NULL != pexprInner); CExpression *pexprPredicate = CPredicateUtils::PexprConjunction(pmp, pdrgpexpr); // join outer child with Gb's decorrelated child pexprOuter->AddRef(); CExpression *pexprInnerJoin = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CLogicalInnerJoin(pmp), pexprOuter, pexprInner, pexprPredicate ); // create grouping columns from the output of outer child DrgPcr *pdrgpcrKey = NULL; DrgPcr *pdrgpcr = CUtils::PdrgpcrGroupingKey(pmp, pexprOuter, &pdrgpcrKey); pdrgpcrKey->Release(); // key is not used here CLogicalGbAgg *popGbAgg = GPOS_NEW(pmp) CLogicalGbAgg(pmp, pdrgpcr, COperator::EgbaggtypeGlobal /*egbaggtype*/); CExpression *pexprPrjList = (*pexprGb)[1]; pexprPrjList->AddRef(); CExpression *pexprNewGb = GPOS_NEW(pmp) CExpression (pmp, popGbAgg, pexprInnerJoin, pexprPrjList); // add Apply predicate in a top Select node pexprScalar->AddRef(); CExpression *pexprSelect = CUtils::PexprLogicalSelect(pmp, pexprNewGb, pexprScalar); pxfres->Add(pexprSelect); }
//--------------------------------------------------------------------------- // @function: // CLogical::PpcDeriveConstraintFromTable // // @doc: // Derive constraint property from a table/index get // //--------------------------------------------------------------------------- CPropConstraint * CLogical::PpcDeriveConstraintFromTable ( IMemoryPool *pmp, const CTableDescriptor *ptabdesc, const DrgPcr *pdrgpcrOutput ) { DrgPcrs *pdrgpcrs = GPOS_NEW(pmp) DrgPcrs(pmp); DrgPcnstr *pdrgpcnstr = GPOS_NEW(pmp) DrgPcnstr(pmp); const DrgPcoldesc *pdrgpcoldesc = ptabdesc->Pdrgpcoldesc(); const ULONG ulCols = pdrgpcoldesc->UlLength(); DrgPcr *pdrgpcrNonSystem = GPOS_NEW(pmp) DrgPcr(pmp); for (ULONG ul = 0; ul < ulCols; ul++) { CColumnDescriptor *pcoldesc = (*pdrgpcoldesc)[ul]; CColRef *pcr = (*pdrgpcrOutput)[ul]; // we are only interested in non-system columns that are defined as // being NOT NULL if (pcoldesc->FSystemColumn()) { continue; } pdrgpcrNonSystem->Append(pcr); if (pcoldesc->FNullable()) { continue; } // add a "not null" constraint and an equivalence class CConstraint * pcnstr = CConstraintInterval::PciUnbounded(pmp, pcr, false /*fIncludesNull*/); if (pcnstr == NULL) { continue; } pdrgpcnstr->Append(pcnstr); CColRefSet *pcrsEquiv = GPOS_NEW(pmp) CColRefSet(pmp); pcrsEquiv->Include(pcr); pdrgpcrs->Append(pcrsEquiv); } CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); const IMDRelation *pmdrel = pmda->Pmdrel(ptabdesc->Pmdid()); const ULONG ulCheckConstraint = pmdrel->UlCheckConstraints(); for (ULONG ul = 0; ul < ulCheckConstraint; ul++) { IMDId *pmdidCheckConstraint = pmdrel->PmdidCheckConstraint(ul); const IMDCheckConstraint *pmdCheckConstraint = pmda->Pmdcheckconstraint(pmdidCheckConstraint); // extract the check constraint expression CExpression *pexprCheckConstraint = pmdCheckConstraint->Pexpr(pmp, pmda, pdrgpcrNonSystem); GPOS_ASSERT(NULL != pexprCheckConstraint); GPOS_ASSERT(CUtils::FPredicate(pexprCheckConstraint)); DrgPcrs *pdrgpcrsChild = NULL; CConstraint *pcnstr = CConstraint::PcnstrFromScalarExpr(pmp, pexprCheckConstraint, &pdrgpcrsChild); if (NULL != pcnstr) { pdrgpcnstr->Append(pcnstr); // merge with the equivalence classes we have so far DrgPcrs *pdrgpcrsMerged = CUtils::PdrgpcrsMergeEquivClasses(pmp, pdrgpcrs, pdrgpcrsChild); pdrgpcrs->Release(); pdrgpcrs = pdrgpcrsMerged; } CRefCount::SafeRelease(pdrgpcrsChild); pexprCheckConstraint->Release(); } pdrgpcrNonSystem->Release(); return GPOS_NEW(pmp) CPropConstraint(pmp, pdrgpcrs, CConstraint::PcnstrConjunction(pmp, pdrgpcnstr)); }
//--------------------------------------------------------------------------- // @function: // CQueryContext::PqcGenerate // // @doc: // Generate the query context for the given expression and array of // output column ref ids // //--------------------------------------------------------------------------- CQueryContext * CQueryContext::PqcGenerate ( IMemoryPool *pmp, CExpression * pexpr, DrgPul *pdrgpulQueryOutputColRefId, DrgPmdname *pdrgpmdname, BOOL fDeriveStats ) { GPOS_ASSERT(NULL != pexpr && NULL != pdrgpulQueryOutputColRefId); CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp); DrgPcr *pdrgpcr = GPOS_NEW(pmp) DrgPcr(pmp); COptCtxt *poptctxt = COptCtxt::PoctxtFromTLS(); CColumnFactory *pcf = poptctxt->Pcf(); GPOS_ASSERT(NULL != pcf); const ULONG ulLen = pdrgpulQueryOutputColRefId->UlLength(); for (ULONG ul = 0; ul < ulLen; ul++) { ULONG *pul = (*pdrgpulQueryOutputColRefId)[ul]; GPOS_ASSERT(NULL != pul); CColRef *pcr = pcf->PcrLookup(*pul); GPOS_ASSERT(NULL != pcr); pcrs->Include(pcr); pdrgpcr->Append(pcr); } COrderSpec *pos = NULL; CExpression *pexprResult = pexpr; COperator *popTop = PopTop(pexpr); if (COperator::EopLogicalLimit == popTop->Eopid()) { // top level operator is a limit, copy order spec to query context pos = CLogicalLimit::PopConvert(popTop)->Pos(); pos->AddRef(); } else { // no order required pos = GPOS_NEW(pmp) COrderSpec(pmp); } CDistributionSpec *pds = NULL; BOOL fDML = CUtils::FLogicalDML(pexpr->Pop()); poptctxt->MarkDMLQuery(fDML); if (fDML) { pds = GPOS_NEW(pmp) CDistributionSpecAny(COperator::EopSentinel); } else { pds = GPOS_NEW(pmp) CDistributionSpecSingleton(CDistributionSpecSingleton::EstMaster); } CRewindabilitySpec *prs = GPOS_NEW(pmp) CRewindabilitySpec(CRewindabilitySpec::ErtNone /*ert*/); CEnfdOrder *peo = GPOS_NEW(pmp) CEnfdOrder(pos, CEnfdOrder::EomSatisfy); // we require satisfy matching on distribution since final query results must be sent to master CEnfdDistribution *ped = GPOS_NEW(pmp) CEnfdDistribution(pds, CEnfdDistribution::EdmSatisfy); CEnfdRewindability *per = GPOS_NEW(pmp) CEnfdRewindability(prs, CEnfdRewindability::ErmSatisfy); CCTEReq *pcter = poptctxt->Pcteinfo()->PcterProducers(pmp); CReqdPropPlan *prpp = GPOS_NEW(pmp) CReqdPropPlan(pcrs, peo, ped, per, pcter); pdrgpmdname->AddRef(); return GPOS_NEW(pmp) CQueryContext(pmp, pexprResult, prpp, pdrgpcr, pdrgpmdname, fDeriveStats); }
//--------------------------------------------------------------------------- // @function: // CXformSplitGbAggDedup::Transform // // @doc: // Actual transformation to expand a global aggregate into a pair of // local and global aggregate // //--------------------------------------------------------------------------- void CXformSplitGbAggDedup::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(); CLogicalGbAggDeduplicate *popAggDedup = CLogicalGbAggDeduplicate::PopConvert(pexpr->Pop()); // extract components CExpression *pexprRelational = (*pexpr)[0]; CExpression *pexprProjectList = (*pexpr)[1]; // check if the transformation is applicable if (!FApplicable(pexprProjectList)) { return; } pexprRelational->AddRef(); CExpression *pexprProjectListLocal = NULL; CExpression *pexprProjectListGlobal = NULL; (void) PopulateLocalGlobalProjectList(pmp, pexprProjectList, &pexprProjectListLocal, &pexprProjectListGlobal); GPOS_ASSERT(NULL != pexprProjectListLocal && NULL != pexprProjectListLocal); DrgPcr *pdrgpcr = popAggDedup->Pdrgpcr(); pdrgpcr->AddRef(); pdrgpcr->AddRef(); DrgPcr *pdrgpcrMinimal = popAggDedup->PdrgpcrMinimal(); if (NULL != pdrgpcrMinimal) { pdrgpcrMinimal->AddRef(); pdrgpcrMinimal->AddRef(); } DrgPcr *pdrgpcrKeys = popAggDedup->PdrgpcrKeys(); pdrgpcrKeys->AddRef(); pdrgpcrKeys->AddRef(); CExpression *pexprLocal = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CLogicalGbAggDeduplicate(pmp, pdrgpcr, pdrgpcrMinimal, COperator::EgbaggtypeLocal /*egbaggtype*/, pdrgpcrKeys), pexprRelational, pexprProjectListLocal ); CExpression *pexprGlobal = GPOS_NEW(pmp) CExpression ( pmp, GPOS_NEW(pmp) CLogicalGbAggDeduplicate(pmp, pdrgpcr, pdrgpcrMinimal, COperator::EgbaggtypeGlobal /*egbaggtype*/, pdrgpcrKeys), pexprLocal, pexprProjectListGlobal ); pxfres->Add(pexprGlobal); }