greenplumn CLogical 代码
文件路径:/src/backend/gporca/libgpopt/src/operators/CLogical.cpp
/---------------------------------------------------------------------------
/ Greenplum Database
/ Copyright (C) 2009 Greenplum, Inc.
/
/ @filename:
/ CLogical.cpp
/
/ @doc:
/ Implementation of base class of logical operators
/---------------------------------------------------------------------------
#include "gpopt/operators/CLogical.h"
#include "gpos/base.h"
#include "gpopt/base/CColRef.h"
#include "gpopt/base/CColRefSet.h"
#include "gpopt/base/CColRefSetIter.h"
#include "gpopt/base/CConstraintConjunction.h"
#include "gpopt/base/CConstraintInterval.h"
#include "gpopt/base/CDrvdPropRelational.h"
#include "gpopt/base/CKeyCollection.h"
#include "gpopt/base/COptCtxt.h"
#include "gpopt/base/CReqdPropRelational.h"
#include "gpopt/operators/CExpression.h"
#include "gpopt/operators/CExpressionHandle.h"
#include "gpopt/operators/CLogicalApply.h"
#include "gpopt/operators/CLogicalBitmapTableGet.h"
#include "gpopt/operators/CLogicalDynamicBitmapTableGet.h"
#include "gpopt/operators/CLogicalDynamicGet.h"
#include "gpopt/operators/CLogicalGet.h"
#include "gpopt/operators/CLogicalNAryJoin.h"
#include "gpopt/operators/CLogicalSelect.h"
#include "gpopt/operators/CPredicateUtils.h"
#include "gpopt/operators/CScalarIdent.h"
#include "gpopt/optimizer/COptimizerConfig.h"
#include "naucrates/md/IMDCheckConstraint.h"
#include "naucrates/md/IMDColumn.h"
#include "naucrates/md/IMDIndex.h"
#include "naucrates/statistics/CStatistics.h"
#include "naucrates/statistics/CStatisticsUtils.h"
using namespace gpnaucrates;
using namespace gpopt;
using namespace gpmd;
/---------------------------------------------------------------------------
/ @function:
/ CLogical::CLogical
/
/ @doc:
/ Ctor
/
/---------------------------------------------------------------------------
CLogical::CLogical(CMemoryPool *mp) : COperator(mp)
{
GPOS_ASSERT(nullptr != mp);
m_pcrsLocalUsed = GPOS_NEW(mp) CColRefSet(mp);
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::~CLogical
/
/ @doc:
/ Dtor
/
/---------------------------------------------------------------------------
CLogical::~CLogical()
{
m_pcrsLocalUsed->Release();
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PdrgpcrCreateMapping
/
/ @doc:
/ Create output column mapping given a list of column descriptors and
/ a pointer to the operator creating that column
/
/---------------------------------------------------------------------------
CColRefArray *
CLogical::PdrgpcrCreateMapping(CMemoryPool *mp,
const CColumnDescriptorArray *pdrgpcoldesc,
ULONG ulOpSourceId, IMDId *mdid_table)
{
/ get column factory from optimizer context object
CColumnFactory *col_factory = COptCtxt::PoctxtFromTLS()->Pcf();
ULONG num_cols = pdrgpcoldesc->Size();
CColRefArray *colref_array = GPOS_NEW(mp) CColRefArray(mp, num_cols);
for (ULONG ul = 0; ul < num_cols; ul++)
{
CColumnDescriptor *pcoldesc = (*pdrgpcoldesc)[ul];
CName name(mp, pcoldesc->Name());
CColRef *colref = col_factory->PcrCreate(
pcoldesc, name, ulOpSourceId, false /* mark_as_used */, mdid_table);
colref_array->Append(colref);
}
return colref_array;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PdrgpdrgpcrCreatePartCols
/
/ @doc:
/ Initialize array of partition columns from the array with their indexes
/
/---------------------------------------------------------------------------
CColRef2dArray *
CLogical::PdrgpdrgpcrCreatePartCols(CMemoryPool *mp, CColRefArray *colref_array,
const ULongPtrArray *pdrgpulPart)
{
GPOS_ASSERT(nullptr != colref_array && "Output columns cannot be NULL");
GPOS_ASSERT(nullptr != pdrgpulPart);
CColRef2dArray *pdrgpdrgpcrPart = GPOS_NEW(mp) CColRef2dArray(mp);
const ULONG ulPartCols = pdrgpulPart->Size();
GPOS_ASSERT(0 < ulPartCols);
for (ULONG ul = 0; ul < ulPartCols; ul++)
{
ULONG ulCol = *((*pdrgpulPart)[ul]);
CColRef *colref = (*colref_array)[ulCol];
CColRefArray *pdrgpcrCurr = GPOS_NEW(mp) CColRefArray(mp);
/ The partition columns are not explicity referenced in the query but we
/ still need to mark them as used since they are required during partition
/ elimination
colref->MarkAsUsed();
pdrgpcrCurr->Append(colref);
pdrgpdrgpcrPart->Append(pdrgpcrCurr);
}
return pdrgpdrgpcrPart;
}
/ Compute an order spec based on an index
COrderSpec *
CLogical::PosFromIndex(CMemoryPool *mp, const IMDIndex *pmdindex,
CColRefArray *colref_array,
const CTableDescriptor *ptabdesc)
{
/ compute the order spec after getting the current position of the index key
/ from the table descriptor. Index keys are relative to the
/ relation. So consider a case where we had 20 columns in a table. We
/ create an index that covers col # 20 as one of its keys. Then we drop
/ columns 10 through 15. Now the index key still points to col #20 but the
/ column ref list in colref_array will only have 15 elements in it.
/
COrderSpec *pos = GPOS_NEW(mp) COrderSpec(mp);
/ GiST, GIN and BRIN indexes have no order, so return an empty order spec
if (pmdindex->IndexType() == IMDIndex::EmdindGist ||
pmdindex->IndexType() == IMDIndex::EmdindGin ||
pmdindex->IndexType() == IMDIndex::EmdindBrin)
{
return pos;
}
const ULONG ulLenKeys = pmdindex->Keys();
/ get relation from the metadata accessor using metadata id
CMDAccessor *md_accessor = COptCtxt::PoctxtFromTLS()->Pmda();
const IMDRelation *pmdrel = md_accessor->RetrieveRel(ptabdesc->MDId());
for (ULONG ul = 0; ul < ulLenKeys; ul++)
{
/ This is the postion of the index key column relative to the relation
const ULONG ulPosRel = pmdindex->KeyAt(ul);
/ get the column and it's attno from the relation
const IMDColumn *pmdcol = pmdrel->GetMdCol(ulPosRel);
INT attno = pmdcol->AttrNum();
/ get the position of the index key column relative to the table descriptor
const ULONG ulPosTabDesc = ptabdesc->GetAttributePosition(attno);
CColRef *colref = (*colref_array)[ulPosTabDesc];
IMDId *mdid =
colref->RetrieveType()->GetMdidForCmpType(IMDType::EcmptL);
mdid->AddRef();
/ TODO: March 27th 2012; we hard-code NULL treatment
/ need to revisit
pos->Append(mdid, colref, COrderSpec::EntLast);
}
return pos;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PcrsDeriveOutputPassThru
/
/ @doc:
/ Common case of output derivation for unary operators or operators
/ that pass through the schema of only the outer child
/
/---------------------------------------------------------------------------
CColRefSet *
CLogical::PcrsDeriveOutputPassThru(CExpressionHandle &exprhdl)
{
/ may have additional children that are ignored, e.g., scalar children
GPOS_ASSERT(1 <= exprhdl.Arity());
CColRefSet *pcrs = exprhdl.DeriveOutputColumns(0);
pcrs->AddRef();
return pcrs;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PcrsDeriveNotNullPassThruOuter
/
/ @doc:
/ Common case of deriving not null columns by passing through
/ not null columns from the outer child
/
/---------------------------------------------------------------------------
CColRefSet *
CLogical::PcrsDeriveNotNullPassThruOuter(CExpressionHandle &exprhdl)
{
/ may have additional children that are ignored, e.g., scalar children
GPOS_ASSERT(1 <= exprhdl.Arity());
CColRefSet *pcrs = exprhdl.DeriveNotNullColumns(0);
pcrs->AddRef();
return pcrs;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PcrsDeriveOutputCombineLogical
/
/ @doc:
/ Common case of output derivation by combining the schemas of all
/ children
/
/---------------------------------------------------------------------------
CColRefSet *
CLogical::PcrsDeriveOutputCombineLogical(CMemoryPool *mp,
CExpressionHandle &exprhdl)
{
CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp);
/ union columns from the first N-1 children
ULONG arity = exprhdl.Arity();
for (ULONG ul = 0; ul < arity - 1; ul++)
{
CColRefSet *pcrsChild = exprhdl.DeriveOutputColumns(ul);
GPOS_ASSERT(pcrs->IsDisjoint(pcrsChild) &&
"Input columns are not disjoint");
pcrs->Union(pcrsChild);
}
return pcrs;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PcrsDeriveNotNullCombineLogical
/
/ @doc:
/ Common case of combining not null columns from all logical
/ children
/
/---------------------------------------------------------------------------
CColRefSet *
CLogical::PcrsDeriveNotNullCombineLogical(CMemoryPool *mp,
CExpressionHandle &exprhdl)
{
CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp);
/ union not nullable columns from the first N-1 children
ULONG arity = exprhdl.Arity();
for (ULONG ul = 0; ul < arity - 1; ul++)
{
CColRefSet *pcrsChild = exprhdl.DeriveNotNullColumns(ul);
GPOS_ASSERT(pcrs->IsDisjoint(pcrsChild) &&
"Input columns are not disjoint");
pcrs->Union(pcrsChild);
}
return pcrs;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PpartinfoPassThruOuter
/
/ @doc:
/ Common case of common case of passing through partition consumer array
/
/---------------------------------------------------------------------------
CPartInfo *
CLogical::PpartinfoPassThruOuter(CExpressionHandle &exprhdl)
{
CPartInfo *ppartinfo = exprhdl.DerivePartitionInfo(0);
GPOS_ASSERT(nullptr != ppartinfo);
ppartinfo->AddRef();
return ppartinfo;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PkcCombineKeys
/
/ @doc:
/ Common case of combining keys from first n - 1 children
/
/---------------------------------------------------------------------------
CKeyCollection *
CLogical::PkcCombineKeys(CMemoryPool *mp, CExpressionHandle &exprhdl)
{
CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp);
const ULONG arity = exprhdl.Arity();
for (ULONG ul = 0; ul < arity - 1; ul++)
{
CKeyCollection *pkc = exprhdl.DeriveKeyCollection(ul);
if (nullptr == pkc)
{
/ if a child has no key, the operator has no key
pcrs->Release();
return nullptr;
}
CColRefArray *colref_array = pkc->PdrgpcrKey(mp);
pcrs->Include(colref_array);
colref_array->Release();
}
return GPOS_NEW(mp) CKeyCollection(mp, pcrs);
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PkcKeysBaseTable
/
/ @doc:
/ Helper function for computing the keys in a base table
/
/---------------------------------------------------------------------------
CKeyCollection *
CLogical::PkcKeysBaseTable(CMemoryPool *mp, const CBitSetArray *pdrgpbsKeys,
const CColRefArray *pdrgpcrOutput)
{
const ULONG ulKeys = pdrgpbsKeys->Size();
if (0 == ulKeys)
{
return nullptr;
}
CKeyCollection *pkc = GPOS_NEW(mp) CKeyCollection(mp);
for (ULONG ul = 0; ul < ulKeys; ul++)
{
CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp);
CBitSet *pbs = (*pdrgpbsKeys)[ul];
CBitSetIter bsiter(*pbs);
while (bsiter.Advance())
{
pcrs->Include((*pdrgpcrOutput)[bsiter.Bit()]);
}
pkc->Add(pcrs);
}
return pkc;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PpartinfoDeriveCombine
/
/ @doc:
/ Common case of combining partition info of all logical children
/
/---------------------------------------------------------------------------
CPartInfo *
CLogical::PpartinfoDeriveCombine(CMemoryPool *mp, CExpressionHandle &exprhdl)
{
const ULONG arity = exprhdl.Arity();
GPOS_ASSERT(0 < arity);
CPartInfo *ppartinfo = GPOS_NEW(mp) CPartInfo(mp);
for (ULONG ul = 0; ul < arity; ul++)
{
CPartInfo *ppartinfoChild = nullptr;
if (exprhdl.FScalarChild(ul))
{
ppartinfoChild = exprhdl.DeriveScalarPartitionInfo(ul);
}
else
{
ppartinfoChild = exprhdl.DerivePartitionInfo(ul);
}
GPOS_ASSERT(nullptr != ppartinfoChild);
CPartInfo *ppartinfoCombined =
CPartInfo::PpartinfoCombine(mp, ppartinfo, ppartinfoChild);
ppartinfo->Release();
ppartinfo = ppartinfoCombined;
}
return ppartinfo;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::DeriveOuterReferences
/
/ @doc:
/ Derive outer references
/
/---------------------------------------------------------------------------
CColRefSet *
CLogical::DeriveOuterReferences(CMemoryPool *mp, CExpressionHandle &exprhdl,
CColRefSet *pcrsUsedAdditional)
{
ULONG arity = exprhdl.Arity();
CColRefSet *outer_refs = GPOS_NEW(mp) CColRefSet(mp);
/ collect output columns from relational children
/ and used columns from scalar children
CColRefSet *pcrsOutput = GPOS_NEW(mp) CColRefSet(mp);
CColRefSet *pcrsUsed = GPOS_NEW(mp) CColRefSet(mp);
for (ULONG i = 0; i < arity; i++)
{
if (exprhdl.FScalarChild(i))
{
pcrsUsed->Union(exprhdl.DeriveUsedColumns(i));
}
else
{
/ add outer references from relational children
outer_refs->Union(exprhdl.DeriveOuterReferences(i));
pcrsOutput->Union(exprhdl.DeriveOutputColumns(i));
}
}
if (nullptr != pcrsUsedAdditional)
{
pcrsUsed->Include(pcrsUsedAdditional);
}
/ outer references are columns used by scalar child
/ but are not included in the output columns of relational children
outer_refs->Union(pcrsUsed);
outer_refs->Exclude(pcrsOutput);
pcrsOutput->Release();
pcrsUsed->Release();
return outer_refs;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PcrsDeriveOuterIndexGet
/
/ @doc:
/ Derive outer references for index get and dynamic index get operators
/
/---------------------------------------------------------------------------
CColRefSet *
CLogical::PcrsDeriveOuterIndexGet(CMemoryPool *mp, CExpressionHandle &exprhdl)
{
ULONG arity = exprhdl.Arity();
CColRefSet *outer_refs = GPOS_NEW(mp) CColRefSet(mp);
CColRefSet *pcrsOutput = DeriveOutputColumns(mp, exprhdl);
CColRefSet *pcrsUsed = GPOS_NEW(mp) CColRefSet(mp);
for (ULONG i = 0; i < arity; i++)
{
GPOS_ASSERT(exprhdl.FScalarChild(i));
pcrsUsed->Union(exprhdl.DeriveUsedColumns(i));
}
/ outer references are columns used by scalar children
/ but are not included in the output columns of relational children
outer_refs->Union(pcrsUsed);
outer_refs->Exclude(pcrsOutput);
pcrsOutput->Release();
pcrsUsed->Release();
return outer_refs;
}
/---------------------------------------------------------------------------
/ @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::DeriveCorrelatedApplyColumns(CMemoryPool *mp,
CExpressionHandle &exprhdl) const
{
GPOS_ASSERT(this == exprhdl.Pop());
ULONG arity = exprhdl.Arity();
CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp);
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 < arity; ul++)
{
if (!exprhdl.FScalarChild(ul))
{
CDrvdPropRelational *pdprel = exprhdl.GetRelationalProperties(ul);
pcrs->Union(pdprel->GetCorrelatedApplyColumns());
}
}
return pcrs;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PkcDeriveKeysPassThru
/
/ @doc:
/ Addref and return keys of n-th child
/
/---------------------------------------------------------------------------
CKeyCollection *
CLogical::PkcDeriveKeysPassThru(CExpressionHandle &exprhdl, ULONG ulChild)
{
CKeyCollection *pkcLeft =
exprhdl.GetRelationalProperties(ulChild)->GetKeyCollection();
/ key collection may be NULL
if (nullptr != pkcLeft)
{
pkcLeft->AddRef();
}
return pkcLeft;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PkcDeriveKeys
/
/ @doc:
/ Derive key collections
/
/---------------------------------------------------------------------------
CKeyCollection *
CLogical::DeriveKeyCollection(CMemoryPool *, / mp
CExpressionHandle & / exprhdl
) const
{
/ no keys found by default
return nullptr;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PpcDeriveConstraintFromPredicates
/
/ @doc:
/ Derive constraint property when expression has relational children and
/ scalar children (predicates)
/
/---------------------------------------------------------------------------
CPropConstraint *
CLogical::PpcDeriveConstraintFromPredicates(CMemoryPool *mp,
CExpressionHandle &exprhdl)
{
CColRefSetArray *pdrgpcrs = GPOS_NEW(mp) CColRefSetArray(mp);
CConstraintArray *pdrgpcnstr = GPOS_NEW(mp) CConstraintArray(mp);
/ collect constraint properties from relational children
/ and predicates from scalar children
const ULONG arity = exprhdl.Arity();
for (ULONG ul = 0; ul < arity; ul++)
{
if (exprhdl.FScalarChild(ul))
{
CExpression *pexprScalar = exprhdl.PexprScalarExactChild(ul);
/ make sure it is a predicate... boolop, cmp, nulltest,
/ or a list of join predicates for an NAry join
if (nullptr == pexprScalar || !CUtils::FPredicate(pexprScalar))
{
continue;
}
GPOS_ASSERT(COperator::EopScalarNAryJoinPredList !=
pexprScalar->Pop()->Eopid());
CColRefSetArray *pdrgpcrsChild = nullptr;
CConstraint *pcnstr = CConstraint::PcnstrFromScalarExpr(
mp, pexprScalar, &pdrgpcrsChild);
if (nullptr != pcnstr)
{
pdrgpcnstr->Append(pcnstr);
/ merge with the equivalence classes we have so far
CColRefSetArray *pdrgpcrsMerged =
CUtils::PdrgpcrsMergeEquivClasses(mp, pdrgpcrs,
pdrgpcrsChild);
pdrgpcrs->Release();
pdrgpcrs = pdrgpcrsMerged;
}
CRefCount::SafeRelease(pdrgpcrsChild);
}
else
{
CPropConstraint *ppc = exprhdl.DerivePropertyConstraint(ul);
/ equivalence classes coming from child
CColRefSetArray *pdrgpcrsChild = ppc->PdrgpcrsEquivClasses();
/ merge with the equivalence classes we have so far
CColRefSetArray *pdrgpcrsMerged =
CUtils::PdrgpcrsMergeEquivClasses(mp, pdrgpcrs, pdrgpcrsChild);
pdrgpcrs->Release();
pdrgpcrs = pdrgpcrsMerged;
/ constraint coming from child
CConstraint *pcnstr = ppc->Pcnstr();
if (nullptr != pcnstr)
{
pcnstr->AddRef();
pdrgpcnstr->Append(pcnstr);
}
}
}
CConstraint *pcnstrNew = CConstraint::PcnstrConjunction(mp, pdrgpcnstr);
return GPOS_NEW(mp) CPropConstraint(mp, pdrgpcrs, pcnstrNew);
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PpcDeriveConstraintFromTable
/
/ @doc:
/ Derive constraint property from a table/index get
/
/---------------------------------------------------------------------------
CPropConstraint *
CLogical::PpcDeriveConstraintFromTable(CMemoryPool *mp,
const CTableDescriptor *ptabdesc,
const CColRefArray *pdrgpcrOutput)
{
CColRefSetArray *pdrgpcrs = GPOS_NEW(mp) CColRefSetArray(mp);
CConstraintArray *pdrgpcnstr = GPOS_NEW(mp) CConstraintArray(mp);
const CColumnDescriptorArray *pdrgpcoldesc = ptabdesc->Pdrgpcoldesc();
const ULONG num_cols = pdrgpcoldesc->Size();
CColRefArray *pdrgpcrNonSystem = GPOS_NEW(mp) CColRefArray(mp);
for (ULONG ul = 0; ul < num_cols; ul++)
{
CColumnDescriptor *pcoldesc = (*pdrgpcoldesc)[ul];
CColRef *colref = (*pdrgpcrOutput)[ul];
/ we are only interested in non-system columns that are defined as
/ being NOT NULL
if (pcoldesc->IsSystemColumn())
{
continue;
}
pdrgpcrNonSystem->Append(colref);
if (pcoldesc->IsNullable() || colref->GetUsage() == CColRef::EUnused)
{
continue;
}
/ add a "not null" constraint and an equivalence class
CConstraint *pcnstr = CConstraintInterval::PciUnbounded(
mp, colref, false /*fIncludesNull*/);
if (pcnstr == nullptr)
{
continue;
}
pdrgpcnstr->Append(pcnstr);
CColRefSet *pcrsEquiv = GPOS_NEW(mp) CColRefSet(mp);
pcrsEquiv->Include(colref);
pdrgpcrs->Append(pcrsEquiv);
}
CMDAccessor *md_accessor = COptCtxt::PoctxtFromTLS()->Pmda();
const IMDRelation *pmdrel = md_accessor->RetrieveRel(ptabdesc->MDId());
const ULONG ulCheckConstraint = pmdrel->CheckConstraintCount();
for (ULONG ul = 0; ul < ulCheckConstraint; ul++)
{
IMDId *pmdidCheckConstraint = pmdrel->CheckConstraintMDidAt(ul);
const IMDCheckConstraint *pmdCheckConstraint =
md_accessor->RetrieveCheckConstraints(pmdidCheckConstraint);
/ extract the check constraint expression
CExpression *pexprCheckConstraint =
pmdCheckConstraint->GetCheckConstraintExpr(mp, md_accessor,
pdrgpcrNonSystem);
GPOS_ASSERT(nullptr != pexprCheckConstraint);
GPOS_ASSERT(CUtils::FPredicate(pexprCheckConstraint));
CColRefSetArray *pdrgpcrsChild = nullptr;
/ Check constraints are satisfied if the check expression evaluates to
/ true or NULL, so infer NULLs as true here.
CConstraint *pcnstr = CConstraint::PcnstrFromScalarExpr(
mp, pexprCheckConstraint, &pdrgpcrsChild,
true /* infer_nulls_as */);
if (nullptr != pcnstr)
{
pdrgpcnstr->Append(pcnstr);
/ merge with the equivalence classes we have so far
CColRefSetArray *pdrgpcrsMerged =
CUtils::PdrgpcrsMergeEquivClasses(mp, pdrgpcrs, pdrgpcrsChild);
pdrgpcrs->Release();
pdrgpcrs = pdrgpcrsMerged;
}
CRefCount::SafeRelease(pdrgpcrsChild);
pexprCheckConstraint->Release();
}
pdrgpcrNonSystem->Release();
return GPOS_NEW(mp) CPropConstraint(
mp, pdrgpcrs, CConstraint::PcnstrConjunction(mp, pdrgpcnstr));
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PpcDeriveConstraintFromTableWithPredicates
/
/ @doc:
/ Derive constraint property from a table/index get with predicates
/
/---------------------------------------------------------------------------
CPropConstraint *
CLogical::PpcDeriveConstraintFromTableWithPredicates(
CMemoryPool *mp, CExpressionHandle &exprhdl,
const CTableDescriptor *ptabdesc, const CColRefArray *pdrgpcrOutput)
{
CConstraintArray *pdrgpcnstr = GPOS_NEW(mp) CConstraintArray(mp);
CPropConstraint *ppcTable =
PpcDeriveConstraintFromTable(mp, ptabdesc, pdrgpcrOutput);
CConstraint *pcnstrTable = ppcTable->Pcnstr();
if (nullptr != pcnstrTable)
{
pcnstrTable->AddRef();
pdrgpcnstr->Append(pcnstrTable);
}
CColRefSetArray *pdrgpcrsEquivClassesTable =
ppcTable->PdrgpcrsEquivClasses();
CPropConstraint *ppcnstrCond =
PpcDeriveConstraintFromPredicates(mp, exprhdl);
CConstraint *pcnstrCond = ppcnstrCond->Pcnstr();
if (nullptr != pcnstrCond)
{
pcnstrCond->AddRef();
pdrgpcnstr->Append(pcnstrCond);
}
else if (nullptr == pcnstrTable)
{
ppcTable->Release();
pdrgpcnstr->Release();
return ppcnstrCond;
}
CColRefSetArray *pdrgpcrsCond = ppcnstrCond->PdrgpcrsEquivClasses();
CColRefSetArray *pdrgpcrs = CUtils::PdrgpcrsMergeEquivClasses(
mp, pdrgpcrsEquivClassesTable, pdrgpcrsCond);
CPropConstraint *ppc = GPOS_NEW(mp) CPropConstraint(
mp, pdrgpcrs, CConstraint::PcnstrConjunction(mp, pdrgpcnstr));
ppcnstrCond->Release();
ppcTable->Release();
return ppc;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PpcDeriveConstraintPassThru
/
/ @doc:
/ Shorthand to addref and pass through constraint from a given child
/
/---------------------------------------------------------------------------
CPropConstraint *
CLogical::PpcDeriveConstraintPassThru(CExpressionHandle &exprhdl, ULONG ulChild)
{
/ return constraint property of child
CPropConstraint *ppc = exprhdl.DerivePropertyConstraint(ulChild);
if (nullptr != ppc)
{
ppc->AddRef();
}
return ppc;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PpcDeriveConstraintRestrict
/
/ @doc:
/ Derive constraint property only on the given columns
/
/---------------------------------------------------------------------------
CPropConstraint *
CLogical::PpcDeriveConstraintRestrict(CMemoryPool *mp,
CExpressionHandle &exprhdl,
CColRefSet *pcrsOutput)
{
/ constraint property from relational child
CPropConstraint *ppc = exprhdl.DerivePropertyConstraint(0);
CColRefSetArray *pdrgpcrs = ppc->PdrgpcrsEquivClasses();
/ construct new array of equivalence classes
CColRefSetArray *pdrgpcrsNew = GPOS_NEW(mp) CColRefSetArray(mp);
const ULONG length = pdrgpcrs->Size();
for (ULONG ul = 0; ul < length; ul++)
{
CColRefSet *pcrsEquiv = GPOS_NEW(mp) CColRefSet(mp);
pcrsEquiv->Include((*pdrgpcrs)[ul]);
pcrsEquiv->Intersection(pcrsOutput);
if (0 < pcrsEquiv->Size())
{
pdrgpcrsNew->Append(pcrsEquiv);
}
else
{
pcrsEquiv->Release();
}
}
CConstraint *pcnstrChild = ppc->Pcnstr();
if (nullptr == pcnstrChild)
{
return GPOS_NEW(mp) CPropConstraint(mp, pdrgpcrsNew, nullptr);
}
CConstraintArray *pdrgpcnstr = GPOS_NEW(mp) CConstraintArray(mp);
/ include only constraints on given columns
CColRefSetIter crsi(*pcrsOutput);
while (crsi.Advance())
{
CColRef *colref = crsi.Pcr();
CConstraint *pcnstrCol = pcnstrChild->Pcnstr(mp, colref);
if (nullptr == pcnstrCol)
{
continue;
}
if (pcnstrCol->IsConstraintUnbounded())
{
pcnstrCol->Release();
continue;
}
pdrgpcnstr->Append(pcnstrCol);
}
CConstraint *pcnstr = CConstraint::PcnstrConjunction(mp, pdrgpcnstr);
return GPOS_NEW(mp) CPropConstraint(mp, pdrgpcrsNew, pcnstr);
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::DeriveFunctionProperties
/
/ @doc:
/ Derive function properties
/
/---------------------------------------------------------------------------
CFunctionProp *
CLogical::DeriveFunctionProperties(CMemoryPool *mp,
CExpressionHandle &exprhdl) const
{
IMDFunction::EFuncStbl efs =
EfsDeriveFromChildren(exprhdl, IMDFunction::EfsImmutable);
return GPOS_NEW(mp) CFunctionProp(
efs, exprhdl.FChildrenHaveVolatileFuncScan(), false /*fScan*/);
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::DeriveTableDescriptor
/
/ @doc:
/ Derive table descriptor for tables used by operator
/
/---------------------------------------------------------------------------
CTableDescriptor *
CLogical::DeriveTableDescriptor(CMemoryPool *, CExpressionHandle &) const
{
/currently return null unless there is a single table being used. Later we may want
/to make this return a set of table descriptors and pass them up all operators
return nullptr;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PfpDeriveFromScalar
/
/ @doc:
/ Derive function properties using data access property of scalar child
/
/---------------------------------------------------------------------------
CFunctionProp *
CLogical::PfpDeriveFromScalar(CMemoryPool *mp, CExpressionHandle &exprhdl)
{
GPOS_CHECK_ABORT;
/ collect stability from all children
IMDFunction::EFuncStbl efs =
EfsDeriveFromChildren(exprhdl, IMDFunction::EfsImmutable);
return GPOS_NEW(mp) CFunctionProp(
efs, exprhdl.FChildrenHaveVolatileFuncScan(), false /*fScan*/);
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::DeriveMaxCard
/
/ @doc:
/ Derive max card
/
/---------------------------------------------------------------------------
CMaxCard
CLogical::DeriveMaxCard(CMemoryPool *, / mp
CExpressionHandle & / exprhdl
) const
{
/ unbounded by default
return CMaxCard();
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::DeriveJoinDepth
/
/ @doc:
/ Derive join depth
/
/---------------------------------------------------------------------------
ULONG
CLogical::DeriveJoinDepth(CMemoryPool *, / mp
CExpressionHandle &exprhdl) const
{
const ULONG arity = exprhdl.Arity();
/ sum-up join depth of all relational children
ULONG ulDepth = 0;
for (ULONG ul = 0; ul < arity; ul++)
{
if (!exprhdl.FScalarChild(ul))
{
ulDepth = ulDepth + exprhdl.DeriveJoinDepth(ul);
}
}
return ulDepth;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::MaxcardDef
/
/ @doc:
/ Default max card for join and apply operators
/
/---------------------------------------------------------------------------
CMaxCard
CLogical::MaxcardDef(CExpressionHandle &exprhdl)
{
const ULONG arity = exprhdl.Arity();
CMaxCard maxcard = exprhdl.DeriveMaxCard(0);
for (ULONG ul = 1; ul < arity - 1; ul++)
{
if (!exprhdl.FScalarChild(ul))
{
maxcard *= exprhdl.DeriveMaxCard(ul);
}
}
return maxcard;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::DeriveMaxCard
/
/ @doc:
/ Derive max card given scalar child and constraint property. If a
/ contradiction is detected then return maxcard of zero, otherwise
/ use the given default maxcard
/
/---------------------------------------------------------------------------
CMaxCard
CLogical::Maxcard(CExpressionHandle &exprhdl, ULONG ulScalarIndex,
CMaxCard maxcard)
{
/ in case of a false condition (when the operator is not Full / Left Outer Join) or a contradiction, maxcard should be zero
CExpression *pexprScalar = exprhdl.PexprScalarExactChild(ulScalarIndex);
if (nullptr != pexprScalar)
{
if (COperator::EopScalarNAryJoinPredList == pexprScalar->Pop()->Eopid())
{
/ look at the inner join predicates only
pexprScalar = (*pexprScalar)[0];
}
if ((CUtils::FScalarConstFalse(pexprScalar) &&
COperator::EopLogicalFullOuterJoin != exprhdl.Pop()->Eopid() &&
COperator::EopLogicalLeftOuterJoin != exprhdl.Pop()->Eopid() &&
COperator::EopLogicalRightOuterJoin != exprhdl.Pop()->Eopid()) ||
exprhdl.DerivePropertyConstraint()->FContradiction())
{
return CMaxCard(0 /*ull*/);
}
}
return maxcard;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PcrsReqdChildStats
/
/ @doc:
/ Helper for compute required stat columns of the n-th child
/
/---------------------------------------------------------------------------
CColRefSet *
CLogical::PcrsReqdChildStats(
CMemoryPool *mp, CExpressionHandle &exprhdl, CColRefSet *pcrsInput,
CColRefSet *pcrsUsed, / columns used by scalar child(ren)
ULONG child_index)
{
GPOS_ASSERT(child_index < exprhdl.Arity() - 1);
GPOS_CHECK_ABORT;
CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp);
pcrs->Union(pcrsInput);
pcrs->Union(pcrsUsed);
/ intersect with the output columns of relational child
pcrs->Intersection(exprhdl.DeriveOutputColumns(child_index));
return pcrs;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PcrsStatsPassThru
/
/ @doc:
/ Helper for common case of passing through required stat columns
/
/---------------------------------------------------------------------------
CColRefSet *
CLogical::PcrsStatsPassThru(CColRefSet *pcrsInput)
{
GPOS_ASSERT(nullptr != pcrsInput);
GPOS_CHECK_ABORT;
pcrsInput->AddRef();
return pcrsInput;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PstatsPassThruOuter
/
/ @doc:
/ Helper for common case of passing through derived stats
/
/---------------------------------------------------------------------------
IStatistics *
CLogical::PstatsPassThruOuter(CExpressionHandle &exprhdl)
{
GPOS_CHECK_ABORT;
IStatistics *stats = exprhdl.Pstats(0);
stats->AddRef();
return stats;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PstatsBaseTable
/
/ @doc:
/ Helper for deriving statistics on a base table
/
/---------------------------------------------------------------------------
IStatistics *
CLogical::PstatsBaseTable(
CMemoryPool *mp, CExpressionHandle &exprhdl, CTableDescriptor *ptabdesc,
CColRefSet *
pcrsHistExtra / additional columns required for stats, not required by parent
)
{
CReqdPropRelational *prprel =
CReqdPropRelational::GetReqdRelationalProps(exprhdl.Prp());
CColRefSet *pcrsHist = GPOS_NEW(mp) CColRefSet(mp);
pcrsHist->Include(prprel->PcrsStat());
if (nullptr != pcrsHistExtra)
{
pcrsHist->Include(pcrsHistExtra);
}
CColRefSet *pcrsOutput = exprhdl.DeriveOutputColumns();
CColRefSet *pcrsWidth = GPOS_NEW(mp) CColRefSet(mp);
pcrsWidth->Include(pcrsOutput);
pcrsWidth->Exclude(pcrsHist);
const COptCtxt *poctxt = COptCtxt::PoctxtFromTLS();
CMDAccessor *md_accessor = poctxt->Pmda();
CStatisticsConfig *stats_config =
poctxt->GetOptimizerConfig()->GetStatsConf();
IStatistics *stats = md_accessor->Pstats(mp, ptabdesc->MDId(), pcrsHist,
pcrsWidth, stats_config);
/ clean up
pcrsWidth->Release();
pcrsHist->Release();
return stats;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PstatsDeriveDummy
/
/ @doc:
/ Derive dummy statistics
/
/---------------------------------------------------------------------------
IStatistics *
CLogical::PstatsDeriveDummy(CMemoryPool *mp, CExpressionHandle &exprhdl,
CDouble rows) const
{
GPOS_CHECK_ABORT;
/ return a dummy stats object that has a histogram for every
/ required-stats column
GPOS_ASSERT(Esp(exprhdl) > EspNone);
CReqdPropRelational *prprel =
CReqdPropRelational::GetReqdRelationalProps(exprhdl.Prp());
CColRefSet *pcrs = prprel->PcrsStat();
ULongPtrArray *colids = GPOS_NEW(mp) ULongPtrArray(mp);
pcrs->ExtractColIds(mp, colids);
IStatistics *stats = CStatistics::MakeDummyStats(mp, colids, rows);
/ clean up
colids->Release();
return stats;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PexprPartPred
/
/ @doc:
/ Compute partition predicate to pass down to n-th child
/
/---------------------------------------------------------------------------
CExpression *
CLogical::PexprPartPred(CMemoryPool *, /mp,
CExpressionHandle &, /exprhdl,
CExpression *, /pexprInput,
ULONG /child_index
) const
{
GPOS_CHECK_ABORT;
/ the default behavior is to never pass down any partition predicates
return nullptr;
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PdpCreate
/
/ @doc:
/ Create base container of derived properties
/
/---------------------------------------------------------------------------
CDrvdProp *
CLogical::PdpCreate(CMemoryPool *mp) const
{
return GPOS_NEW(mp) CDrvdPropRelational(mp);
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PrpCreate
/
/ @doc:
/ Create base container of required properties
/
/---------------------------------------------------------------------------
CReqdProp *
CLogical::PrpCreate(CMemoryPool *mp) const
{
return GPOS_NEW(mp) CReqdPropRelational();
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PtabdescFromTableGet
/
/ @doc:
/ Returns the table descriptor for (Dynamic)(BitmapTable)Get operators
/
/---------------------------------------------------------------------------
CTableDescriptor *
CLogical::PtabdescFromTableGet(COperator *pop)
{
GPOS_ASSERT(nullptr != pop);
switch (pop->Eopid())
{
case CLogical::EopLogicalGet:
return CLogicalGet::PopConvert(pop)->Ptabdesc();
case CLogical::EopLogicalDynamicGet:
return CLogicalDynamicGet::PopConvert(pop)->Ptabdesc();
case CLogical::EopLogicalBitmapTableGet:
return CLogicalBitmapTableGet::PopConvert(pop)->Ptabdesc();
case CLogical::EopLogicalDynamicBitmapTableGet:
return CLogicalDynamicBitmapTableGet::PopConvert(pop)->Ptabdesc();
case CLogical::EopLogicalSelect:
return CLogicalSelect::PopConvert(pop)->Ptabdesc();
default:
return nullptr;
}
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PdrgpcrOutputFromLogicalGet
/
/ @doc:
/ Extract the output columns from a logical get or dynamic get operator
/
/---------------------------------------------------------------------------
CColRefArray *
CLogical::PdrgpcrOutputFromLogicalGet(CLogical *pop)
{
GPOS_ASSERT(nullptr != pop);
GPOS_ASSERT(COperator::EopLogicalGet == pop->Eopid() ||
COperator::EopLogicalDynamicGet == pop->Eopid());
if (COperator::EopLogicalGet == pop->Eopid())
{
return CLogicalGet::PopConvert(pop)->PdrgpcrOutput();
}
return CLogicalDynamicGet::PopConvert(pop)->PdrgpcrOutput();
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::NameFromLogicalGet
/
/ @doc:
/ Extract the name from a logical get or dynamic get operator
/
/---------------------------------------------------------------------------
const CName &
CLogical::NameFromLogicalGet(CLogical *pop)
{
GPOS_ASSERT(nullptr != pop);
GPOS_ASSERT(COperator::EopLogicalGet == pop->Eopid() ||
COperator::EopLogicalDynamicGet == pop->Eopid());
if (COperator::EopLogicalGet == pop->Eopid())
{
return CLogicalGet::PopConvert(pop)->Name();
}
return CLogicalDynamicGet::PopConvert(pop)->Name();
}
/---------------------------------------------------------------------------
/ @function:
/ CLogical::PcrsDist
/
/ @doc:
/ Return the set of distribution columns
/
/---------------------------------------------------------------------------
CColRefSet *
CLogical::PcrsDist(CMemoryPool *mp, const CTableDescriptor *ptabdesc,
const CColRefArray *pdrgpcrOutput)
{
GPOS_ASSERT(nullptr != ptabdesc);
GPOS_ASSERT(nullptr != pdrgpcrOutput);
const CColumnDescriptorArray *pdrgpcoldesc = ptabdesc->Pdrgpcoldesc();
const CColumnDescriptorArray *pdrgpcoldescDist =
ptabdesc->PdrgpcoldescDist();
GPOS_ASSERT(nullptr != pdrgpcoldesc);
GPOS_ASSERT(nullptr != pdrgpcoldescDist);
GPOS_ASSERT(pdrgpcrOutput->Size() == pdrgpcoldesc->Size());
/ mapping base table columns to corresponding column references
IntToColRefMap *phmicr = GPOS_NEW(mp) IntToColRefMap(mp);
const ULONG num_cols = pdrgpcoldesc->Size();
for (ULONG ul = 0; ul < num_cols; ul++)
{
CColumnDescriptor *pcoldesc = (*pdrgpcoldesc)[ul];
CColRef *colref = (*pdrgpcrOutput)[ul];
phmicr->Insert(GPOS_NEW(mp) INT(pcoldesc->AttrNum()), colref);
}
CColRefSet *pcrsDist = GPOS_NEW(mp) CColRefSet(mp);
const ULONG ulDistCols = pdrgpcoldescDist->Size();
for (ULONG ul2 = 0; ul2 < ulDistCols; ul2++)
{
CColumnDescriptor *pcoldesc = (*pdrgpcoldescDist)[ul2];
const INT attno = pcoldesc->AttrNum();
CColRef *pcrMapped = phmicr->Find(&attno);
GPOS_ASSERT(nullptr != pcrMapped);
pcrsDist->Include(pcrMapped);
}
/ clean up
phmicr->Release();
return pcrsDist;
}
/ EOF
相关信息
相关文章
greenplumn CExpressionFactorizer 源码
greenplumn CExpressionHandle 源码
greenplumn CExpressionPreprocessor 源码
greenplumn CExpressionUtils 源码
greenplumn CHashedDistributions 源码