//--------------------------------------------------------------------------- // @function: // CLogical::PcrsDeriveCorrelatedApply // // @doc: // Derive columns from the inner child of a correlated-apply expression // that can be used above the apply expression // //--------------------------------------------------------------------------- CColRefSet * CLogical::PcrsDeriveCorrelatedApply ( IMemoryPool *pmp, CExpressionHandle &exprhdl ) const { GPOS_ASSERT(this == exprhdl.Pop()); ULONG ulArity = exprhdl.UlArity(); CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp); if (CUtils::FCorrelatedApply(exprhdl.Pop())) { // add inner columns of correlated-apply expression pcrs->Include(CLogicalApply::PopConvert(exprhdl.Pop())->PdrgPcrInner()); } // combine correlated-apply columns from logical children for (ULONG ul = 0; ul < ulArity; ul++) { if (!exprhdl.FScalarChild(ul)) { CDrvdPropRelational *pdprel = exprhdl.Pdprel(ul); pcrs->Union(pdprel->PcrsCorrelatedApply()); } } return pcrs; }
//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelector::PdsRequired // // @doc: // Compute required distribution of the n-th child // //--------------------------------------------------------------------------- CDistributionSpec * CPhysicalPartitionSelector::PdsRequired ( IMemoryPool *mp, CExpressionHandle &exprhdl, CDistributionSpec *pdsInput, ULONG child_index, CDrvdProp2dArray *, // pdrgpdpCtxt ULONG // ulOptReq ) const { GPOS_ASSERT(0 == child_index); CDrvdPropRelational *pdprelDrvd = exprhdl.GetRelationalProperties(); CPartInfo *ppartinfo = pdprelDrvd->Ppartinfo(); BOOL fCovered = ppartinfo->FContainsScanId(m_scan_id); if (fCovered) { // if partition consumer is defined below, do not pass distribution // requirements down as this will cause the consumer and enforcer to be // in separate slices return GPOS_NEW(mp) CDistributionSpecAny(this->Eopid()); } return PdsPassThru(mp, exprhdl, pdsInput, child_index); }
//--------------------------------------------------------------------------- // @function: // CXformTest::PexprStarJoinTree // // @doc: // Generate a randomized star join tree // //--------------------------------------------------------------------------- CExpression * CXformTest::PexprStarJoinTree ( IMemoryPool *pmp, ULONG ulTabs ) { CExpression *pexprLeft = CTestUtils::PexprLogicalGet(pmp); for (ULONG ul = 1; ul < ulTabs; ul++) { CDrvdPropRelational *pdprelLeft = CDrvdPropRelational::Pdprel(pexprLeft->PdpDerive()); CColRef *pcrLeft = pdprelLeft->PcrsOutput()->PcrAny(); CExpression *pexprRight = CTestUtils::PexprLogicalGet(pmp); CDrvdPropRelational *pdprelRight = CDrvdPropRelational::Pdprel(pexprRight->PdpDerive()); CColRef *pcrRight = pdprelRight->PcrsOutput()->PcrAny(); CExpression *pexprPred = CUtils::PexprScalarEqCmp(pmp, pcrLeft, pcrRight); pexprLeft = CUtils::PexprLogicalJoin<CLogicalInnerJoin>(pmp, pexprLeft, pexprRight, pexprPred); } return pexprLeft; }
//--------------------------------------------------------------------------- // @function: // CLogical::PcrsDeriveOuter // // @doc: // Derive outer references // //--------------------------------------------------------------------------- CColRefSet * CLogical::PcrsDeriveOuter ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CColRefSet *pcrsUsedAdditional ) { ULONG ulArity = exprhdl.UlArity(); CColRefSet *pcrsOuter = GPOS_NEW(pmp) CColRefSet(pmp); // collect output columns from relational children // and used columns from scalar children CColRefSet *pcrsOutput = GPOS_NEW(pmp) CColRefSet(pmp); CColRefSet *pcrsUsed = GPOS_NEW(pmp) CColRefSet(pmp); for (ULONG i = 0; i < ulArity; i++) { if (exprhdl.FScalarChild(i)) { CDrvdPropScalar *pdpscalar = exprhdl.Pdpscalar(i); pcrsUsed->Union(pdpscalar->PcrsUsed()); } else { CDrvdPropRelational *pdprel = exprhdl.Pdprel(i); pcrsOutput->Union(pdprel->PcrsOutput()); // add outer references from relational children pcrsOuter->Union(pdprel->PcrsOuter()); } } if (NULL != pcrsUsedAdditional) { pcrsUsed->Include(pcrsUsedAdditional); } // outer references are columns used by scalar child // but are not included in the output columns of relational children pcrsOuter->Union(pcrsUsed); pcrsOuter->Exclude(pcrsOutput); pcrsOutput->Release(); pcrsUsed->Release(); return pcrsOuter; }
//--------------------------------------------------------------------------- // @function: // CLogical::PstatsBaseTable // // @doc: // Helper for deriving statistics on a base table // //--------------------------------------------------------------------------- IStatistics * CLogical::PstatsBaseTable ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CTableDescriptor *ptabdesc, CColRefSet *pcrsHistExtra // additional columns required for stats, not required by parent ) { CReqdPropRelational *prprel = CReqdPropRelational::Prprel(exprhdl.Prp()); CColRefSet *pcrsHist = GPOS_NEW(pmp) CColRefSet(pmp); pcrsHist->Include(prprel->PcrsStat()); if (NULL != pcrsHistExtra) { pcrsHist->Include(pcrsHistExtra); } CDrvdPropRelational *pdprel = exprhdl.Pdprel(); CColRefSet *pcrsOutput = pdprel->PcrsOutput(); CColRefSet *pcrsWidth = GPOS_NEW(pmp) CColRefSet(pmp); pcrsWidth->Include(pcrsOutput); pcrsWidth->Exclude(pcrsHist); const COptCtxt *poctxt = COptCtxt::PoctxtFromTLS(); CMDAccessor *pmda = poctxt->Pmda(); CStatisticsConfig *pstatsconf = poctxt->Poconf()->Pstatsconf(); IStatistics *pstats = pmda->Pstats ( pmp, ptabdesc->Pmdid(), pcrsHist, pcrsWidth, pstatsconf ); // clean up pcrsWidth->Release(); pcrsHist->Release(); return pstats; }
//--------------------------------------------------------------------------- // @function: // CLogical::PstatsBaseTable // // @doc: // Helper for deriving statistics on a base table // //--------------------------------------------------------------------------- IStatistics * CLogical::PstatsBaseTable ( IMemoryPool *pmp, CExpressionHandle &exprhdl, CTableDescriptor *ptabdesc, CColRefSet *pcrsStatExtra // additional columns required for stats, not required by parent ) { // extract colids and attribute for which detailed stats are necessary CReqdPropRelational *prprel = CReqdPropRelational::Prprel(exprhdl.Prp()); CColRefSet *pcrsStat = GPOS_NEW(pmp) CColRefSet(pmp); pcrsStat->Include(prprel->PcrsStat()); if (NULL != pcrsStatExtra) { pcrsStat->Include(pcrsStatExtra); } DrgPul *pdrgpulHistColIds = GPOS_NEW(pmp) DrgPul(pmp); DrgPul *pdrgpulHistPos = GPOS_NEW(pmp) DrgPul(pmp); CUtils::ExtractColIdsAttno(pmp, ptabdesc, pcrsStat, pdrgpulHistColIds, pdrgpulHistPos); // extract colids and attribute for which widths are necessary CDrvdPropRelational *pdprel = exprhdl.Pdprel(); CColRefSet *pcrsWidth = pdprel->PcrsOutput(); DrgPul *pdrgpulWidthColIds = GPOS_NEW(pmp) DrgPul(pmp); DrgPul *pdrgpulWidthPos = GPOS_NEW(pmp) DrgPul(pmp); CUtils::ExtractColIdsAttno(pmp, ptabdesc, pcrsWidth, pdrgpulWidthColIds, pdrgpulWidthPos); CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); IStatistics *pstats = pmda->Pstats(pmp, ptabdesc->Pmdid(), pdrgpulHistPos, pdrgpulHistColIds, pdrgpulWidthPos, pdrgpulWidthColIds); if (!GPOS_FTRACE(EopttraceDonotCollectMissingStatsCols) && !pstats->FEmpty()) { CStatisticsUtils::RecordMissingStatisticsColumns(pmp, ptabdesc, pcrsStat, pstats); } pcrsStat->Release(); return pstats; }
//--------------------------------------------------------------------------- // @function: // CDecorrelator::FProcess // // @doc: // Main driver for decorrelation of expression // //--------------------------------------------------------------------------- BOOL CDecorrelator::FProcess ( IMemoryPool *pmp, CExpression *pexpr, BOOL fEqualityOnly, CExpression **ppexprDecorrelated, DrgPexpr *pdrgpexprCorrelations ) { GPOS_CHECK_STACK_SIZE; // only correlated Apply can be encountered here GPOS_ASSERT_IMP(CUtils::FApply(pexpr->Pop()), CUtils::FCorrelatedApply(pexpr->Pop()) && "Apply expression is encountered by decorrelator"); CDrvdPropRelational *pdprel = CDrvdPropRelational::Pdprel(pexpr->PdpDerive()); // no outer references? if (0 == pdprel->PcrsOuter()->CElements()) { pexpr->AddRef(); *ppexprDecorrelated = pexpr; return true; } BOOL fSuccess = FProcessOperator(pmp, pexpr, fEqualityOnly, ppexprDecorrelated, pdrgpexprCorrelations); // in case of success make sure there are no outer references left GPOS_ASSERT_IMP ( fSuccess, 0 == CDrvdPropRelational::Pdprel((*ppexprDecorrelated)->PdpDerive())->PcrsOuter()->CElements() ); return fSuccess; }
//--------------------------------------------------------------------------- // @function: // CLogical::PpcDeriveConstraintFromPredicates // // @doc: // Derive constraint property when expression has relational children and // scalar children (predicates) // //--------------------------------------------------------------------------- CPropConstraint * CLogical::PpcDeriveConstraintFromPredicates ( IMemoryPool *pmp, CExpressionHandle &exprhdl ) { DrgPcrs *pdrgpcrs = GPOS_NEW(pmp) DrgPcrs(pmp); DrgPcnstr *pdrgpcnstr = GPOS_NEW(pmp) DrgPcnstr(pmp); // collect constraint properties from relational children // and predicates from scalar children const ULONG ulArity = exprhdl.UlArity(); for (ULONG ul = 0; ul < ulArity; ul++) { if (exprhdl.FScalarChild(ul)) { CExpression *pexprScalar = exprhdl.PexprScalarChild(ul); // make sure it is a predicate... boolop, cmp, nulltest if (NULL == pexprScalar || !CUtils::FPredicate(pexprScalar)) { continue; } DrgPcrs *pdrgpcrsChild = NULL; CConstraint *pcnstr = CConstraint::PcnstrFromScalarExpr(pmp, pexprScalar, &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); } else { CDrvdPropRelational *pdprel = exprhdl.Pdprel(ul); CPropConstraint *ppc = pdprel->Ppc(); // equivalence classes coming from child DrgPcrs *pdrgpcrsChild = ppc->PdrgpcrsEquivClasses(); // merge with the equivalence classes we have so far DrgPcrs *pdrgpcrsMerged = CUtils::PdrgpcrsMergeEquivClasses(pmp, pdrgpcrs, pdrgpcrsChild); pdrgpcrs->Release(); pdrgpcrs = pdrgpcrsMerged; // constraint coming from child CConstraint *pcnstr = ppc->Pcnstr(); if (NULL != pcnstr) { pcnstr->AddRef(); pdrgpcnstr->Append(pcnstr); } } } CConstraint *pcnstrNew = CConstraint::PcnstrConjunction(pmp, pdrgpcnstr); return GPOS_NEW(pmp) CPropConstraint(pmp, pdrgpcrs, pcnstrNew); }
//--------------------------------------------------------------------------- // @function: // CNormalizer::FLocalColsSubsetOfInputCols // // @doc: // Check if the columns used by the operator are a subset of its input columns // //--------------------------------------------------------------------------- BOOL CNormalizer::FLocalColsSubsetOfInputCols ( IMemoryPool *pmp, CExpression *pexpr ) { GPOS_ASSERT(NULL != pexpr); GPOS_CHECK_STACK_SIZE; CExpressionHandle exprhdl(pmp); if (NULL != pexpr->Pgexpr()) { exprhdl.Attach(pexpr->Pgexpr()); } else { exprhdl.Attach(pexpr); } exprhdl.DeriveProps(NULL /*pdpctxt*/); BOOL fValid = true; if (pexpr->Pop()->FLogical()) { if (0 == exprhdl.UlNonScalarChildren()) { return true; } CColRefSet *pcrsInput = GPOS_NEW(pmp) CColRefSet(pmp); const ULONG ulArity = exprhdl.UlArity(); for (ULONG ul = 0; ul < ulArity; ul++) { if (!exprhdl.FScalarChild(ul)) { CDrvdPropRelational *pdprelChild = exprhdl.Pdprel(ul); pcrsInput->Include(pdprelChild->PcrsOutput()); } } // check if the operator's locally used columns are a subset of the input columns CColRefSet *pcrsUsedOp = exprhdl.PcrsUsedColumns(pmp); pcrsUsedOp->Exclude(exprhdl.Pdprel()->PcrsOuter()); fValid = pcrsInput->FSubset(pcrsUsedOp); // release pcrsInput->Release(); pcrsUsedOp->Release(); } // check if its children are valid const ULONG ulExprArity = pexpr->UlArity(); for (ULONG ulChildIdx = 0; ulChildIdx < ulExprArity && fValid; ulChildIdx++) { CExpression *pexprChild = (*pexpr)[ulChildIdx]; fValid = FLocalColsSubsetOfInputCols(pmp, pexprChild); } return fValid; }