greenplumn CLogicalSelect 源码

  • 2022-08-18
  • 浏览 (309)

greenplumn CLogicalSelect 代码

文件路径:/src/backend/gporca/libgpopt/src/operators/CLogicalSelect.cpp

//---------------------------------------------------------------------------
//	Greenplum Database
//	Copyright (C) 2011 EMC Corp.
//
//	@filename:
//		CLogicalSelect.cpp
//
//	@doc:
//		Implementation of select operator
//---------------------------------------------------------------------------

#include "gpopt/operators/CLogicalSelect.h"

#include "gpos/base.h"

#include "gpopt/base/CColRefSet.h"
#include "gpopt/base/CColRefSetIter.h"
#include "gpopt/base/CColRefTable.h"
#include "gpopt/base/COptCtxt.h"
#include "gpopt/operators/CExpression.h"
#include "gpopt/operators/CExpressionHandle.h"
#include "gpopt/operators/CPatternTree.h"
#include "gpopt/operators/CPredicateUtils.h"
#include "naucrates/statistics/CFilterStatsProcessor.h"
#include "naucrates/statistics/CStatisticsUtils.h"
using namespace gpopt;

//---------------------------------------------------------------------------
//	@function:
//		CLogicalSelect::CLogicalSelect
//
//	@doc:
//		Ctor
//
//---------------------------------------------------------------------------
CLogicalSelect::CLogicalSelect(CMemoryPool *mp)
	: CLogicalUnary(mp), m_ptabdesc(nullptr)
{
	m_phmPexprPartPred = GPOS_NEW(mp) ExprPredToExprPredPartMap(mp);
}

CLogicalSelect::CLogicalSelect(CMemoryPool *mp, CTableDescriptor *ptabdesc)
	: CLogicalUnary(mp), m_ptabdesc(ptabdesc)
{
	m_phmPexprPartPred = GPOS_NEW(mp) ExprPredToExprPredPartMap(mp);
}

CLogicalSelect::~CLogicalSelect()
{
	m_phmPexprPartPred->Release();
}
//---------------------------------------------------------------------------
//	@function:
//		CLogicalSelect::DeriveOutputColumns
//
//	@doc:
//		Derive output columns
//
//---------------------------------------------------------------------------
CColRefSet *
CLogicalSelect::DeriveOutputColumns(CMemoryPool *,	// mp
									CExpressionHandle &exprhdl)
{
	return PcrsDeriveOutputPassThru(exprhdl);
}


//---------------------------------------------------------------------------
//	@function:
//		CLogicalSelect::PkcDeriveKeys
//
//	@doc:
//		Derive key collection
//
//---------------------------------------------------------------------------
CKeyCollection *
CLogicalSelect::DeriveKeyCollection(CMemoryPool *,	// mp
									CExpressionHandle &exprhdl) const
{
	return PkcDeriveKeysPassThru(exprhdl, 0 /* ulChild */);
}


//---------------------------------------------------------------------------
//	@function:
//		CLogicalSelect::PxfsCandidates
//
//	@doc:
//		Get candidate xforms
//
//---------------------------------------------------------------------------
CXformSet *
CLogicalSelect::PxfsCandidates(CMemoryPool *mp) const
{
	CXformSet *xform_set = GPOS_NEW(mp) CXformSet(mp);

	(void) xform_set->ExchangeSet(CXform::ExfSelect2Apply);
	(void) xform_set->ExchangeSet(CXform::ExfRemoveSubqDistinct);
	(void) xform_set->ExchangeSet(CXform::ExfInlineCTEConsumerUnderSelect);
	(void) xform_set->ExchangeSet(CXform::ExfPushGbWithHavingBelowJoin);
	(void) xform_set->ExchangeSet(CXform::ExfSelect2IndexGet);
	(void) xform_set->ExchangeSet(CXform::ExfSelect2DynamicIndexGet);
	(void) xform_set->ExchangeSet(CXform::ExfSelect2BitmapBoolOp);
	(void) xform_set->ExchangeSet(CXform::ExfSelect2DynamicBitmapBoolOp);
	(void) xform_set->ExchangeSet(CXform::ExfSimplifySelectWithSubquery);
	(void) xform_set->ExchangeSet(CXform::ExfSelect2Filter);

	return xform_set;
}

//---------------------------------------------------------------------------
//	@function:
//		CLogicalSelect::DeriveMaxCard
//
//	@doc:
//		Derive max card
//
//---------------------------------------------------------------------------
CMaxCard
CLogicalSelect::DeriveMaxCard(CMemoryPool *,  // mp
							  CExpressionHandle &exprhdl) const
{
	// in case of a false condition or a contradiction, maxcard should be zero
	CExpression *pexprScalar = exprhdl.PexprScalarRepChild(1);
	if ((nullptr != pexprScalar &&
		 (CUtils::FScalarConstFalse(pexprScalar) ||
		  CUtils::FScalarConstBoolNull(pexprScalar))) ||
		exprhdl.DerivePropertyConstraint()->FContradiction())
	{
		return CMaxCard(0 /*ull*/);
	}

	// pass on max card of first child
	return exprhdl.DeriveMaxCard(0);
}


//---------------------------------------------------------------------------
//	@function:
//		CLogicalSelect::PstatsDerive
//
//	@doc:
//		Derive statistics based on filter predicates
//
//---------------------------------------------------------------------------
IStatistics *
CLogicalSelect::PstatsDerive(CMemoryPool *mp, CExpressionHandle &exprhdl,
							 IStatisticsArray *stats_ctxt) const
{
	GPOS_ASSERT(Esp(exprhdl) > EspNone);
	IStatistics *child_stats = exprhdl.Pstats(0);

	if (exprhdl.DeriveHasSubquery(1))
	{
		// in case of subquery in select predicate, we return child stats
		child_stats->AddRef();
		return child_stats;
	}

	// remove implied predicates from selection condition to avoid cardinality under-estimation
	CExpression *pexprScalar = exprhdl.PexprScalarRepChild(1 /*child_index*/);
	CExpression *pexprPredicate =
		CPredicateUtils::PexprRemoveImpliedConjuncts(mp, pexprScalar, exprhdl);


	// split selection predicate into local predicate and predicate involving outer references
	CExpression *local_expr = nullptr;
	CExpression *expr_with_outer_refs = nullptr;

	// get outer references from expression handle
	CColRefSet *outer_refs = exprhdl.DeriveOuterReferences();

	CPredicateUtils::SeparateOuterRefs(mp, pexprPredicate, outer_refs,
									   &local_expr, &expr_with_outer_refs);
	pexprPredicate->Release();

	IStatistics *stats = CFilterStatsProcessor::MakeStatsFilterForScalarExpr(
		mp, exprhdl, child_stats, local_expr, expr_with_outer_refs, stats_ctxt);
	local_expr->Release();
	expr_with_outer_refs->Release();

	return stats;
}

// compute partition predicate to pass down to n-th child.
// given an input scalar expression, find out the predicate
// in the scalar expression which is used for partitioning
//
// clang-format off
// Input Expr:
//	+--CScalarBoolOp (EboolopAnd)
//	|--CScalarArrayCmp Any (=)
//	|  |--CScalarIdent "risk_set_row_id" (2)
//	|  +--CScalarArray: {eleMDId: (23,1.0), arrayMDId: (1007,1.0) CScalarConst (32) CScalarConst (33) CScalarConst (43) CScalarConst (9) CScalarConst (10) CScalarConst (15) CScalarConst (16) CScalarConst (36) CScalarConst (11) CScalarConst (50) CScalarConst (46) CScalarConst (356) CScalarConst (468) CScalarConst (42)}
//	+--CScalarCmp (=)
//	|--CScalarIdent "value_date" (0)
//	+--CScalarConst (559094400000000.000)
//
// Let's say the partition key is on value_date, then the extracted
// predicate is as below:
// Output Expr:
//	+--CScalarCmp (=)
//	|--CScalarIdent "value_date" (0)
//	+--CScalarConst (559094400000000.000)
// clang-format on
CExpression *
CLogicalSelect::PexprPartPred(CMemoryPool *mp, CExpressionHandle &exprhdl,
							  CExpression *,  //pexprInput
							  ULONG
#ifdef GPOS_DEBUG
								  child_index
#endif	//GPOS_DEBUG
) const
{
	GPOS_ASSERT(0 == child_index);

	CExpression *pexprScalar = exprhdl.PexprScalarExactChild(1 /*child_index*/);

	if (nullptr == pexprScalar)
	{
		// no exact predicate is available (e.g. when we have a subquery in the predicate)
		return nullptr;
	}

	// get partition keys
	CPartInfo *ppartinfo = exprhdl.DerivePartitionInfo();
	GPOS_ASSERT(nullptr != ppartinfo);

	// we assume that the select is right on top of the dynamic get, so there
	// should be only one part consumer. If there is more, then we are higher up so
	// we do not push down any predicates
	if (1 != ppartinfo->UlConsumers())
	{
		return nullptr;
	}

	// check if a corresponding predicate has already been cached
	CExpression *pexprPredOnPartKey = m_phmPexprPartPred->Find(pexprScalar);
	if (pexprPredOnPartKey != nullptr)
	{
		// predicate on partition key found in cache
		pexprPredOnPartKey->AddRef();
		return pexprPredOnPartKey;
	}

	CPartKeysArray *pdrgppartkeys = ppartinfo->Pdrgppartkeys(0 /*ulPos*/);
	const ULONG ulKeySets = pdrgppartkeys->Size();
	for (ULONG ul = 0; nullptr == pexprPredOnPartKey && ul < ulKeySets; ul++)
	{
		pexprPredOnPartKey = CPredicateUtils::PexprExtractPredicatesOnPartKeys(
			mp, pexprScalar, (*pdrgppartkeys)[ul]->Pdrgpdrgpcr(),
			nullptr,  //pcrsAllowedRefs
			true	  //fUseConstraints
		);
	}

	if (pexprPredOnPartKey != nullptr)
	{
		// insert the scalar expression and the corresponding partitioning predicate
		// in the hashmap
		pexprPredOnPartKey->AddRef();
		pexprScalar->AddRef();
		m_phmPexprPartPred->Insert(pexprScalar, pexprPredOnPartKey);
	}

	return pexprPredOnPartKey;
}

// EOF

相关信息

greenplumn 源码目录

相关文章

greenplumn CExpression 源码

greenplumn CExpressionFactorizer 源码

greenplumn CExpressionHandle 源码

greenplumn CExpressionPreprocessor 源码

greenplumn CExpressionUtils 源码

greenplumn CHashedDistributions 源码

greenplumn CLogical 源码

greenplumn CLogicalApply 源码

greenplumn CLogicalAssert 源码

greenplumn CLogicalBitmapTableGet 源码

0  赞