//--------------------------------------------------------------------------- // @function: // CLogicalTVF::CLogicalTVF // // @doc: // Ctor // //--------------------------------------------------------------------------- CLogicalTVF::CLogicalTVF ( IMemoryPool *pmp, IMDId *pmdidFunc, IMDId *pmdidRetType, CWStringConst *pstr, DrgPcoldesc *pdrgpcoldesc, DrgPcr *pdrgpcrOutput ) : CLogical(pmp), m_pmdidFunc(pmdidFunc), m_pmdidRetType(pmdidRetType), m_pstr(pstr), m_pdrgpcoldesc(pdrgpcoldesc), m_pdrgpcrOutput(pdrgpcrOutput) { GPOS_ASSERT(pmdidFunc->FValid()); GPOS_ASSERT(pmdidRetType->FValid()); GPOS_ASSERT(NULL != pstr); GPOS_ASSERT(NULL != pdrgpcoldesc); GPOS_ASSERT(NULL != pdrgpcrOutput); CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); const IMDFunction *pmdfunc = pmda->Pmdfunc(m_pmdidFunc); m_efs = pmdfunc->EfsStability(); m_efda = pmdfunc->EfdaDataAccess(); m_fReturnsSet = pmdfunc->FReturnsSet(); }
//--------------------------------------------------------------------------- // @function: // CScalarAggFunc::PmdidLookupReturnType // // @doc: // Lookup mdid of return type for given Agg function // //--------------------------------------------------------------------------- IMDId * CScalarAggFunc::PmdidLookupReturnType ( IMDId *pmdidAggFunc, BOOL fGlobal, CMDAccessor *pmdaInput ) { GPOS_ASSERT(NULL != pmdidAggFunc); CMDAccessor *pmda = pmdaInput; if (NULL == pmda) { pmda = COptCtxt::PoctxtFromTLS()->Pmda(); } GPOS_ASSERT(NULL != pmda); // get aggregate function return type from the MD cache const IMDAggregate *pmdagg = pmda->Pmdagg(pmdidAggFunc); if (fGlobal) { return pmdagg->PmdidTypeResult(); } return pmdagg->PmdidTypeIntermediate(); }
//--------------------------------------------------------------------------- // @function: // CLogicalTVF::CLogicalTVF // // @doc: // Ctor // //--------------------------------------------------------------------------- CLogicalTVF::CLogicalTVF ( IMemoryPool *pmp, IMDId *pmdidFunc, IMDId *pmdidRetType, CWStringConst *pstr, DrgPcoldesc *pdrgpcoldesc ) : CLogical(pmp), m_pmdidFunc(pmdidFunc), m_pmdidRetType(pmdidRetType), m_pstr(pstr), m_pdrgpcoldesc(pdrgpcoldesc), m_pdrgpcrOutput(NULL) { GPOS_ASSERT(pmdidFunc->FValid()); GPOS_ASSERT(pmdidRetType->FValid()); GPOS_ASSERT(NULL != pstr); GPOS_ASSERT(NULL != pdrgpcoldesc); // generate a default column set for the list of column descriptors m_pdrgpcrOutput = PdrgpcrCreateMapping(pmp, pdrgpcoldesc, UlOpId()); CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); const IMDFunction *pmdfunc = pmda->Pmdfunc(m_pmdidFunc); m_efs = pmdfunc->EfsStability(); m_efda = pmdfunc->EfdaDataAccess(); m_fReturnsSet = pmdfunc->FReturnsSet(); }
//--------------------------------------------------------------------------- // @function: // CPhysicalTVF::CPhysicalTVF // // @doc: // Ctor // //--------------------------------------------------------------------------- CPhysicalTVF::CPhysicalTVF ( IMemoryPool *pmp, IMDId *pmdidFunc, IMDId *pmdidRetType, CWStringConst *pstr, DrgPcoldesc *pdrgpcoldesc, CColRefSet *pcrsOutput ) : CPhysical(pmp), m_pmdidFunc(pmdidFunc), m_pmdidRetType(pmdidRetType), m_pstr(pstr), m_pdrgpcoldesc(pdrgpcoldesc), m_pcrsOutput(pcrsOutput) { GPOS_ASSERT(m_pmdidFunc->FValid()); GPOS_ASSERT(m_pmdidRetType->FValid()); GPOS_ASSERT(NULL != m_pstr); GPOS_ASSERT(NULL != m_pdrgpcoldesc); GPOS_ASSERT(NULL != m_pcrsOutput); CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); m_pmdfunc = pmda->Pmdfunc(m_pmdidFunc); }
//--------------------------------------------------------------------------- // @function: // CScalarOp::PmdidType // // @doc: // Expression type // //--------------------------------------------------------------------------- IMDId * CScalarOp::PmdidType() const { if (NULL != m_pmdidReturnType) { return m_pmdidReturnType; } CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); return pmda->Pmdscop(m_pmdidOp)->PmdidTypeResult(); }
//--------------------------------------------------------------------------- // @function: // CStatsPredUtils::Estatscmpt // // @doc: // For the purpose of statistics computation, what is the comparison // type of an operator. Note that this has different, looser semantics // than CUtils::Ecmpt // //--------------------------------------------------------------------------- CStatsPred::EStatsCmpType CStatsPredUtils::Estatscmpt ( IMDId *pmdid ) { CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); const IMDScalarOp *pmdscop = pmda->Pmdscop(pmdid); // Simply go by operator name. // If the name of the operator is "<", then it is a LessThan etc. const CWStringConst *pstrOpName = pmdscop->Mdname().Pstr(); return Estatscmpt(pstrOpName); }
//--------------------------------------------------------------------------- // @function: // CPhysicalScan::ComputeTableStats // // @doc: // Compute stats of underlying table // //--------------------------------------------------------------------------- void CPhysicalScan::ComputeTableStats ( IMemoryPool *pmp ) { GPOS_ASSERT(NULL == m_pstatsBaseTable); CColRefSet *pcrsHist = GPOS_NEW(pmp) CColRefSet(pmp, m_pdrgpcrOutput); CColRefSet *pcrsWidth = GPOS_NEW(pmp) CColRefSet(pmp); CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); m_pstatsBaseTable = pmda->Pstats(pmp, m_ptabdesc->Pmdid(), pcrsHist, pcrsWidth); GPOS_ASSERT(NULL != m_pstatsBaseTable); pcrsHist->Release(); pcrsWidth->Release(); }
//--------------------------------------------------------------------------- // @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: // CPhysicalJoin::FHashJoinCompatible // // @doc: // Are the given predicate parts hash join compatible? // predicate parts are obtained by splitting equality into outer // and inner expressions // //--------------------------------------------------------------------------- BOOL CPhysicalJoin::FHashJoinCompatible ( CExpression *pexprOuter, // outer child of the join CExpression* pexprInner, // inner child of the join CExpression *pexprPredOuter,// outer part of join predicate CExpression *pexprPredInner // inner part of join predicate ) { GPOS_ASSERT(NULL != pexprOuter); GPOS_ASSERT(NULL != pexprInner); GPOS_ASSERT(NULL != pexprPredOuter); GPOS_ASSERT(NULL != pexprPredInner); IMDId *pmdidTypeOuter = CScalar::PopConvert(pexprPredOuter->Pop())->PmdidType(); IMDId *pmdidTypeInner = CScalar::PopConvert(pexprPredInner->Pop())->PmdidType(); CColRefSet *pcrsUsedPredOuter = CDrvdPropScalar::Pdpscalar(pexprPredOuter->PdpDerive())->PcrsUsed(); CColRefSet *pcrsUsedPredInner = CDrvdPropScalar::Pdpscalar(pexprPredInner->PdpDerive())->PcrsUsed(); CColRefSet *pcrsOuter = CDrvdPropRelational::Pdprel(pexprOuter->Pdp(CDrvdProp::EptRelational))->PcrsOutput(); CColRefSet *pcrsInner = CDrvdPropRelational::Pdprel(pexprInner->Pdp(CDrvdProp::EptRelational))->PcrsOutput(); // make sure that each predicate child uses columns from a different join child // in order to reject predicates of the form 'X Join Y on f(X.a, Y.b) = 5' BOOL fPredOuterUsesJoinOuterChild = (0 < pcrsUsedPredOuter->CElements()) && pcrsOuter->FSubset(pcrsUsedPredOuter); BOOL fPredOuterUsesJoinInnerChild = (0 < pcrsUsedPredOuter->CElements()) && pcrsInner->FSubset(pcrsUsedPredOuter); BOOL fPredInnerUsesJoinOuterChild = (0 < pcrsUsedPredInner->CElements()) && pcrsOuter->FSubset(pcrsUsedPredInner); BOOL fPredInnerUsesJoinInnerChild = (0 < pcrsUsedPredInner->CElements()) && pcrsInner->FSubset(pcrsUsedPredInner); BOOL fHashJoinCompatiblePred = (fPredOuterUsesJoinOuterChild && fPredInnerUsesJoinInnerChild) || (fPredOuterUsesJoinInnerChild && fPredInnerUsesJoinOuterChild); CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); return fHashJoinCompatiblePred && pmda->Pmdtype(pmdidTypeOuter)->FHashable() && pmda->Pmdtype(pmdidTypeInner)->FHashable(); }
//--------------------------------------------------------------------------- // @function: // CScalarCast::CScalarCast // // @doc: // Ctor // //--------------------------------------------------------------------------- CScalarCast::CScalarCast ( IMemoryPool *pmp, IMDId *pmdidReturnType, IMDId *pmdidFunc, BOOL fBinaryCoercible ) : CScalar(pmp), m_pmdidReturnType(pmdidReturnType), m_pmdidFunc(pmdidFunc), m_fBinaryCoercible(fBinaryCoercible), m_fReturnsNullOnNullInput(false), m_fBoolReturnType(false) { if (NULL != m_pmdidFunc && m_pmdidFunc->FValid()) { CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); const IMDFunction *pmdfunc = pmda->Pmdfunc(m_pmdidFunc); m_fReturnsNullOnNullInput = pmdfunc->FStrict(); m_fBoolReturnType = CMDAccessorUtils::FBoolType(pmda, m_pmdidReturnType); } }
//--------------------------------------------------------------------------- // @function: // CScalarWindowFunc::CScalarWindowFunc // // @doc: // Ctor // //--------------------------------------------------------------------------- CScalarWindowFunc::CScalarWindowFunc ( IMemoryPool *pmp, IMDId *pmdidFunc, IMDId *pmdidRetType, const CWStringConst *pstrFunc, EWinStage ewinstage, BOOL fDistinct ) : CScalarFunc(pmp), m_ewinstage(ewinstage), m_fDistinct(fDistinct), m_fAgg(false) { GPOS_ASSERT(pmdidFunc->FValid()); GPOS_ASSERT(pmdidRetType->FValid()); m_pmdidFunc = pmdidFunc; m_pmdidRetType = pmdidRetType; m_pstrFunc = pstrFunc; CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); m_fAgg = pmda->FAggWindowFunc(m_pmdidFunc); if (!m_fAgg) { const IMDFunction *pmdfunc = pmda->Pmdfunc(m_pmdidFunc); m_efs = pmdfunc->EfsStability(); m_efda = pmdfunc->EfdaDataAccess(); } else { // TODO: , Aug 15, 2012; pull out properties of aggregate functions m_efs = IMDFunction::EfsImmutable; m_efda = IMDFunction::EfdaNoSQL; } }
//--------------------------------------------------------------------------- // @function: // CXformSelect2PartialDynamicIndexGet::Transform // // @doc: // Actual transformation // //--------------------------------------------------------------------------- void CXformSelect2PartialDynamicIndexGet::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 *pexprRelational = (*pexpr)[0]; CExpression *pexprScalar = (*pexpr)[1]; // get the indexes on this relation CLogicalDynamicGet *popGet = CLogicalDynamicGet::PopConvert(pexprRelational->Pop()); if (popGet->FPartial()) { // already a partial dynamic get; do not try to split further return; } CTableDescriptor *ptabdesc = popGet->Ptabdesc(); CMDAccessor *pmda = COptCtxt::PoctxtFromTLS()->Pmda(); const IMDRelation *pmdrel = pmda->Pmdrel(ptabdesc->Pmdid()); const ULONG ulIndices = pmdrel->UlIndices(); if (0 == ulIndices) { // no indexes on the table return; } // array of expressions in the scalar expression DrgPexpr *pdrgpexpr = CPredicateUtils::PdrgpexprConjuncts(pmp, pexprScalar); GPOS_ASSERT(0 < pdrgpexpr->UlLength()); // derive the scalar and relational properties to build set of required columns CColRefSet *pcrsOutput = CDrvdPropRelational::Pdprel(pexpr->PdpDerive())->PcrsOutput(); CColRefSet *pcrsScalarExpr = CDrvdPropScalar::Pdpscalar(pexprScalar->PdpDerive())->PcrsUsed(); CColRefSet *pcrsReqd = GPOS_NEW(pmp) CColRefSet(pmp); pcrsReqd->Include(pcrsOutput); pcrsReqd->Include(pcrsScalarExpr); CPartConstraint *ppartcnstr = popGet->Ppartcnstr(); ppartcnstr->AddRef(); // find a candidate set of partial index combinations DrgPdrgPpartdig *pdrgpdrgppartdig = CXformUtils::PdrgpdrgppartdigCandidates ( pmp, pmda, pdrgpexpr, popGet->PdrgpdrgpcrPart(), pmdrel, ppartcnstr, popGet->PdrgpcrOutput(), pcrsReqd, pcrsScalarExpr, NULL // pcrsAcceptedOuterRefs ); // construct alternative partial index scan plans const ULONG ulCandidates = pdrgpdrgppartdig->UlLength(); for (ULONG ul = 0; ul < ulCandidates; ul++) { DrgPpartdig *pdrgppartdig = (*pdrgpdrgppartdig)[ul]; CreatePartialIndexGetPlan(pmp, pexpr, pdrgppartdig, pmdrel, pxfres); } ppartcnstr->Release(); pcrsReqd->Release(); pdrgpexpr->Release(); pdrgpdrgppartdig->Release(); }
//--------------------------------------------------------------------------- // @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)); }