greenplumn CLogicalProject 源码
greenplumn CLogicalProject 代码
文件路径:/src/backend/gporca/libgpopt/src/operators/CLogicalProject.cpp
//---------------------------------------------------------------------------
// Greenplum Database
// Copyright (C) 2011 EMC Corp.
//
// @filename:
// CLogicalProject.cpp
//
// @doc:
// Implementation of project operator
//---------------------------------------------------------------------------
#include "gpopt/operators/CLogicalProject.h"
#include "gpos/base.h"
#include "gpopt/base/CColRefSet.h"
#include "gpopt/base/CColRefTable.h"
#include "gpopt/base/CConstraintInterval.h"
#include "gpopt/base/CDefaultComparator.h"
#include "gpopt/base/CKeyCollection.h"
#include "gpopt/base/COptCtxt.h"
#include "gpopt/operators/CExpression.h"
#include "gpopt/operators/CExpressionHandle.h"
#include "gpopt/operators/CScalarIdent.h"
#include "gpopt/operators/CScalarProjectElement.h"
using namespace gpopt;
using namespace gpnaucrates;
//---------------------------------------------------------------------------
// @function:
// CLogicalProject::CLogicalProject
//
// @doc:
// Ctor
//
//---------------------------------------------------------------------------
CLogicalProject::CLogicalProject(CMemoryPool *mp) : CLogicalUnary(mp)
{
}
//---------------------------------------------------------------------------
// @function:
// CLogicalProject::DeriveOutputColumns
//
// @doc:
// Derive output columns
//
//---------------------------------------------------------------------------
CColRefSet *
CLogicalProject::DeriveOutputColumns(CMemoryPool *mp,
CExpressionHandle &exprhdl)
{
GPOS_ASSERT(2 == exprhdl.Arity());
CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp);
// the scalar child defines additional columns
pcrs->Union(exprhdl.DeriveOutputColumns(0));
pcrs->Union(exprhdl.DeriveDefinedColumns(1));
return pcrs;
}
//---------------------------------------------------------------------------
// @function:
// CLogicalProject::PkcDeriveKeys
//
// @doc:
// Derive key collection
//
//---------------------------------------------------------------------------
CKeyCollection *
CLogicalProject::DeriveKeyCollection(CMemoryPool *, // mp
CExpressionHandle &exprhdl) const
{
return PkcDeriveKeysPassThru(exprhdl, 0 /* ulChild */);
}
//---------------------------------------------------------------------------
// @function:
// CLogicalProject::PdrgpcrsEquivClassFromScIdent
//
// @doc:
// Return equivalence class from scalar ident project element
//
//---------------------------------------------------------------------------
CColRefSetArray *
CLogicalProject::PdrgpcrsEquivClassFromScIdent(CMemoryPool *mp,
CExpression *pexprPrEl,
CColRefSet *not_null_columns)
{
GPOS_ASSERT(nullptr != pexprPrEl);
CScalarProjectElement *popPrEl =
CScalarProjectElement::PopConvert(pexprPrEl->Pop());
CColRef *pcrPrEl = popPrEl->Pcr();
CExpression *pexprScalar = (*pexprPrEl)[0];
if (EopScalarIdent != pexprScalar->Pop()->Eopid())
{
return nullptr;
}
CScalarIdent *popScIdent = CScalarIdent::PopConvert(pexprScalar->Pop());
const CColRef *pcrScIdent = popScIdent->Pcr();
GPOS_ASSERT(pcrPrEl->Id() != pcrScIdent->Id());
GPOS_ASSERT(pcrPrEl->RetrieveType()->MDId()->Equals(
pcrScIdent->RetrieveType()->MDId()));
if (!CUtils::FConstrainableType(pcrPrEl->RetrieveType()->MDId()))
{
return nullptr;
}
BOOL non_nullable = not_null_columns->FMember(pcrScIdent);
// only add renamed columns to equivalent class if the column is not null-able
// this is because equality predicates will be inferred from the equivalent class
// during preprocessing
if (CColRef::EcrtTable == pcrScIdent->Ecrt() && non_nullable)
{
// equivalence class
CColRefSetArray *pdrgpcrs = GPOS_NEW(mp) CColRefSetArray(mp);
CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp);
pcrs->Include(pcrPrEl);
pcrs->Include(pcrScIdent);
pdrgpcrs->Append(pcrs);
return pdrgpcrs;
}
return nullptr;
}
//---------------------------------------------------------------------------
// @function:
// CLogicalProject::ExtractConstraintFromScConst
//
// @doc:
// Extract constraint from scalar constant project element
//
//---------------------------------------------------------------------------
void
CLogicalProject::ExtractConstraintFromScConst(
CMemoryPool *mp, CExpression *pexprPrEl,
CConstraintArray *pdrgpcnstr, // array of range constraints
CColRefSetArray *pdrgpcrs // array of equivalence class
)
{
GPOS_ASSERT(nullptr != pexprPrEl);
GPOS_ASSERT(nullptr != pdrgpcnstr);
GPOS_ASSERT(nullptr != pdrgpcrs);
CScalarProjectElement *popPrEl =
CScalarProjectElement::PopConvert(pexprPrEl->Pop());
CColRef *colref = popPrEl->Pcr();
CExpression *pexprScalar = (*pexprPrEl)[0];
IMDId *mdid_type = colref->RetrieveType()->MDId();
if (EopScalarConst != pexprScalar->Pop()->Eopid() ||
!CUtils::FConstrainableType(mdid_type))
{
return;
}
CScalarConst *popConst = CScalarConst::PopConvert(pexprScalar->Pop());
IDatum *datum = popConst->GetDatum();
CRangeArray *pdrgprng = GPOS_NEW(mp) CRangeArray(mp);
BOOL is_null = datum->IsNull();
if (!is_null)
{
datum->AddRef();
pdrgprng->Append(GPOS_NEW(mp) CRange(COptCtxt::PoctxtFromTLS()->Pcomp(),
IMDType::EcmptEq, datum));
}
pdrgpcnstr->Append(GPOS_NEW(mp)
CConstraintInterval(mp, colref, pdrgprng, is_null));
CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp);
pcrs->Include(colref);
pdrgpcrs->Append(pcrs);
}
//---------------------------------------------------------------------------
// @function:
// CLogicalProject::DerivePropertyConstraint
//
// @doc:
// Derive constraint property
//
//---------------------------------------------------------------------------
CPropConstraint *
CLogicalProject::DerivePropertyConstraint(CMemoryPool *mp,
CExpressionHandle &exprhdl) const
{
CExpression *pexprPrL = exprhdl.PexprScalarExactChild(1);
if (nullptr == pexprPrL)
{
return PpcDeriveConstraintPassThru(exprhdl, 0 /*ulChild*/);
}
CConstraintArray *pdrgpcnstr = GPOS_NEW(mp) CConstraintArray(mp);
CColRefSetArray *pdrgpcrs = GPOS_NEW(mp) CColRefSetArray(mp);
const ULONG ulProjElems = pexprPrL->Arity();
for (ULONG ul = 0; ul < ulProjElems; ul++)
{
CExpression *pexprPrEl = (*pexprPrL)[ul];
CExpression *pexprProjected = (*pexprPrEl)[0];
if (EopScalarConst == pexprProjected->Pop()->Eopid())
{
ExtractConstraintFromScConst(mp, pexprPrEl, pdrgpcnstr, pdrgpcrs);
}
else
{
CColRefSet *not_null_columns =
exprhdl.DeriveNotNullColumns(0 /*ulChild*/);
CColRefSetArray *pdrgpcrsChild =
PdrgpcrsEquivClassFromScIdent(mp, pexprPrEl, not_null_columns);
if (nullptr != pdrgpcrsChild)
{
// merge with the equivalence classes we have so far
CColRefSetArray *pdrgpcrsMerged =
CUtils::PdrgpcrsMergeEquivClasses(mp, pdrgpcrs,
pdrgpcrsChild);
// clean up
pdrgpcrs->Release();
pdrgpcrsChild->Release();
pdrgpcrs = pdrgpcrsMerged;
}
}
}
if (0 == pdrgpcnstr->Size() && 0 == pdrgpcrs->Size())
{
// no constants or equivalence classes found, so just return the same constraint property of the child
pdrgpcnstr->Release();
pdrgpcrs->Release();
return PpcDeriveConstraintPassThru(exprhdl, 0 /*ulChild*/);
}
CPropConstraint *ppcChild =
exprhdl.DerivePropertyConstraint(0 /* ulChild */);
// equivalence classes coming from child
CColRefSetArray *pdrgpcrsChild = ppcChild->PdrgpcrsEquivClasses();
if (nullptr != pdrgpcrsChild)
{
// merge with the equivalence classes we have so far
CColRefSetArray *pdrgpcrsMerged =
CUtils::PdrgpcrsMergeEquivClasses(mp, pdrgpcrs, pdrgpcrsChild);
// clean up
pdrgpcrs->Release();
pdrgpcrs = pdrgpcrsMerged;
}
// constraint coming from child
CConstraint *pcnstr = ppcChild->Pcnstr();
if (nullptr != pcnstr)
{
pcnstr->AddRef();
pdrgpcnstr->Append(pcnstr);
}
CConstraint *pcnstrNew = CConstraint::PcnstrConjunction(mp, pdrgpcnstr);
return GPOS_NEW(mp) CPropConstraint(mp, pdrgpcrs, pcnstrNew);
}
//---------------------------------------------------------------------------
// @function:
// CLogicalProject::DeriveMaxCard
//
// @doc:
// Derive max card
//
//---------------------------------------------------------------------------
CMaxCard
CLogicalProject::DeriveMaxCard(CMemoryPool *, // mp
CExpressionHandle &exprhdl) const
{
if (exprhdl.DeriveHasNonScalarFunction(1))
{
// unbounded by default
return CMaxCard();
}
// pass on max card of first child
return exprhdl.DeriveMaxCard(0);
}
//---------------------------------------------------------------------------
// @function:
// CLogicalProject::PxfsCandidates
//
// @doc:
// Get candidate xforms
//
//---------------------------------------------------------------------------
CXformSet *
CLogicalProject::PxfsCandidates(CMemoryPool *mp) const
{
CXformSet *xform_set = GPOS_NEW(mp) CXformSet(mp);
(void) xform_set->ExchangeSet(CXform::ExfSimplifyProjectWithSubquery);
(void) xform_set->ExchangeSet(CXform::ExfProject2Apply);
(void) xform_set->ExchangeSet(CXform::ExfProject2ComputeScalar);
(void) xform_set->ExchangeSet(CXform::ExfCollapseProject);
return xform_set;
}
//---------------------------------------------------------------------------
// @function:
// CLogicalProject::PstatsDerive
//
// @doc:
// Derive statistics
//
//---------------------------------------------------------------------------
IStatistics *
CLogicalProject::PstatsDerive(CMemoryPool *mp, CExpressionHandle &exprhdl,
IStatisticsArray * // stats_ctxt
) const
{
UlongToIDatumMap *phmuldatum = GPOS_NEW(mp) UlongToIDatumMap(mp);
// extract scalar constant expression that can be used for
// statistics calculation
CExpression *pexprPrList = exprhdl.PexprScalarRepChild(1 /*child_index*/);
const ULONG arity = pexprPrList->Arity();
for (ULONG ul = 0; ul < arity; ul++)
{
CExpression *pexprPrElem = (*pexprPrList)[ul];
GPOS_ASSERT(1 == pexprPrElem->Arity());
CColRef *colref =
CScalarProjectElement::PopConvert(pexprPrElem->Pop())->Pcr();
CExpression *pexprScalar = (*pexprPrElem)[0];
COperator *pop = pexprScalar->Pop();
if (COperator::EopScalarConst == pop->Eopid())
{
IDatum *datum = CScalarConst::PopConvert(pop)->GetDatum();
if (datum->StatsMappable())
{
datum->AddRef();
BOOL fInserted GPOS_ASSERTS_ONLY =
phmuldatum->Insert(GPOS_NEW(mp) ULONG(colref->Id()), datum);
GPOS_ASSERT(fInserted);
}
}
}
IStatistics *stats = PstatsDeriveProject(mp, exprhdl, phmuldatum);
// clean up
phmuldatum->Release();
return stats;
}
// EOF
相关信息
相关文章
greenplumn CExpressionFactorizer 源码
greenplumn CExpressionHandle 源码
greenplumn CExpressionPreprocessor 源码
greenplumn CExpressionUtils 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
7、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦