greenplumn CReqdPropPlan 源码
greenplumn CReqdPropPlan 代码
文件路径:/src/backend/gporca/libgpopt/src/base/CReqdPropPlan.cpp
//---------------------------------------------------------------------------
//	Greenplum Database
//	Copyright (C) 2009 - 2011 EMC CORP.
//
//	@filename:
//		CReqdPropPlan.cpp
//
//	@doc:
//		Required plan properties;
//---------------------------------------------------------------------------
#include "gpopt/base/CReqdPropPlan.h"
#include "gpos/base.h"
#include "gpos/common/CPrintablePointer.h"
#include "gpos/error/CAutoTrace.h"
#include "gpopt/base/CCTEReq.h"
#include "gpopt/base/CColRefSet.h"
#include "gpopt/base/CColRefSetIter.h"
#include "gpopt/base/CDistributionSpecAny.h"
#include "gpopt/base/CDistributionSpecSingleton.h"
#include "gpopt/base/CEnfdDistribution.h"
#include "gpopt/base/CEnfdOrder.h"
#include "gpopt/base/CEnfdPartitionPropagation.h"
#include "gpopt/base/CEnfdRewindability.h"
#include "gpopt/base/CPartInfo.h"
#include "gpopt/base/CUtils.h"
#include "gpopt/operators/CExpressionHandle.h"
#include "gpopt/operators/CLogical.h"
#include "gpopt/operators/CPhysical.h"
#include "gpopt/search/CGroupExpression.h"
using namespace gpopt;
//---------------------------------------------------------------------------
//     @function:
//             CReqdPropPlan::CReqdPropPlan
//
//     @doc:
//             Ctor
//
//---------------------------------------------------------------------------
CReqdPropPlan::CReqdPropPlan(CColRefSet *pcrs, CEnfdOrder *peo,
							 CEnfdDistribution *ped, CEnfdRewindability *per,
							 CEnfdPartitionPropagation *pepp, CCTEReq *pcter)
	: m_pcrs(pcrs),
	  m_peo(peo),
	  m_ped(ped),
	  m_per(per),
	  m_pepp(pepp),
	  m_pcter(pcter)
{
	GPOS_ASSERT(nullptr != pcrs);
	GPOS_ASSERT(nullptr != peo);
	GPOS_ASSERT(nullptr != ped);
	GPOS_ASSERT(nullptr != per);
	GPOS_ASSERT(nullptr != pepp);
	GPOS_ASSERT(nullptr != pcter);
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::~CReqdPropPlan
//
//	@doc:
//		Dtor
//
//---------------------------------------------------------------------------
CReqdPropPlan::~CReqdPropPlan()
{
	CRefCount::SafeRelease(m_pcrs);
	CRefCount::SafeRelease(m_peo);
	CRefCount::SafeRelease(m_ped);
	CRefCount::SafeRelease(m_per);
	CRefCount::SafeRelease(m_pepp);
	CRefCount::SafeRelease(m_pcter);
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::ComputeReqdCols
//
//	@doc:
//		Compute required columns
//
//---------------------------------------------------------------------------
void
CReqdPropPlan::ComputeReqdCols(CMemoryPool *mp, CExpressionHandle &exprhdl,
							   CReqdProp *prpInput, ULONG child_index,
							   CDrvdPropArray *pdrgpdpCtxt)
{
	GPOS_ASSERT(nullptr == m_pcrs);
	CReqdPropPlan *prppInput = CReqdPropPlan::Prpp(prpInput);
	CPhysical *popPhysical = CPhysical::PopConvert(exprhdl.Pop());
	m_pcrs =
		popPhysical->PcrsRequired(mp, exprhdl, prppInput->PcrsRequired(),
								  child_index, pdrgpdpCtxt, 0 /*ulOptReq*/);
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::ComputeReqdCTEs
//
//	@doc:
//		Compute required CTEs
//
//---------------------------------------------------------------------------
void
CReqdPropPlan::ComputeReqdCTEs(CMemoryPool *mp, CExpressionHandle &exprhdl,
							   CReqdProp *prpInput, ULONG child_index,
							   CDrvdPropArray *pdrgpdpCtxt)
{
	GPOS_ASSERT(nullptr == m_pcter);
	CReqdPropPlan *prppInput = CReqdPropPlan::Prpp(prpInput);
	CPhysical *popPhysical = CPhysical::PopConvert(exprhdl.Pop());
	m_pcter =
		popPhysical->PcteRequired(mp, exprhdl, prppInput->Pcter(), child_index,
								  pdrgpdpCtxt, 0 /*ulOptReq*/);
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::Compute
//
//	@doc:
//		Compute required props
//
//---------------------------------------------------------------------------
void
CReqdPropPlan::Compute(CMemoryPool *mp, CExpressionHandle &exprhdl,
					   CReqdProp *prpInput, ULONG child_index,
					   CDrvdPropArray *pdrgpdpCtxt, ULONG ulOptReq)
{
	GPOS_CHECK_ABORT;
	CReqdPropPlan *prppInput = CReqdPropPlan::Prpp(prpInput);
	CPhysical *popPhysical = CPhysical::PopConvert(exprhdl.Pop());
	ComputeReqdCols(mp, exprhdl, prpInput, child_index, pdrgpdpCtxt);
	ComputeReqdCTEs(mp, exprhdl, prpInput, child_index, pdrgpdpCtxt);
	ULONG ulOrderReq = 0;
	ULONG ulDistrReq = 0;
	ULONG ulRewindReq = 0;
	ULONG ulPartPropagateReq = 0;
	popPhysical->LookupRequest(ulOptReq, &ulOrderReq, &ulDistrReq, &ulRewindReq,
							   &ulPartPropagateReq);
	m_peo = GPOS_NEW(mp) CEnfdOrder(
		popPhysical->PosRequired(mp, exprhdl, prppInput->Peo()->PosRequired(),
								 child_index, pdrgpdpCtxt, ulOrderReq),
		popPhysical->Eom(prppInput, child_index, pdrgpdpCtxt, ulOrderReq));
	m_ped = popPhysical->Ped(mp, exprhdl, prppInput, child_index, pdrgpdpCtxt,
							 ulDistrReq);
	GPOS_ASSERT(
		CDistributionSpec::EdtUniversal != m_ped->PdsRequired()->Edt() &&
		"CDistributionSpecUniversal is a derive-only, cannot be required");
	m_per = GPOS_NEW(mp) CEnfdRewindability(
		popPhysical->PrsRequired(mp, exprhdl, prppInput->Per()->PrsRequired(),
								 child_index, pdrgpdpCtxt, ulRewindReq),
		popPhysical->Erm(prppInput, child_index, pdrgpdpCtxt, ulRewindReq));
	m_pepp = GPOS_NEW(mp) CEnfdPartitionPropagation(
		popPhysical->PppsRequired(mp, exprhdl,
								  prppInput->Pepp()->PppsRequired(),
								  child_index, pdrgpdpCtxt, ulPartPropagateReq),
		CEnfdPartitionPropagation::EppmSatisfy);
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::Pps
//
//	@doc:
//		Given a property spec type, return the corresponding property spec
//		member
//
//---------------------------------------------------------------------------
CPropSpec *
CReqdPropPlan::Pps(ULONG ul) const
{
	CPropSpec::EPropSpecType epst = (CPropSpec::EPropSpecType) ul;
	switch (epst)
	{
		case CPropSpec::EpstOrder:
			return m_peo->PosRequired();
		case CPropSpec::EpstDistribution:
			return m_ped->PdsRequired();
		case CPropSpec::EpstRewindability:
			return m_per->PrsRequired();
		case CPropSpec::EpstPartPropagation:
			return m_pepp->PppsRequired();
		default:
			GPOS_ASSERT(!"Invalid property spec index");
	}
	return nullptr;
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::Equals
//
//	@doc:
//		Check if expression attached to handle provides required columns
//		by all plan properties
//
//---------------------------------------------------------------------------
BOOL
CReqdPropPlan::FProvidesReqdCols(CMemoryPool *mp, CExpressionHandle &exprhdl,
								 ULONG ulOptReq) const
{
	CPhysical *popPhysical = CPhysical::PopConvert(exprhdl.Pop());
	// check if operator provides required columns
	if (!popPhysical->FProvidesReqdCols(exprhdl, m_pcrs, ulOptReq))
	{
		return false;
	}
	CColRefSet *pcrsOutput = exprhdl.DeriveOutputColumns();
	// check if property spec members use columns from operator output
	BOOL fProvidesReqdCols = true;
	for (ULONG ul = 0; fProvidesReqdCols && ul < CPropSpec::EpstSentinel; ul++)
	{
		CPropSpec *pps = Pps(ul);
		if (nullptr == pps)
		{
			continue;
		}
		CColRefSet *pcrsUsed = pps->PcrsUsed(mp);
		fProvidesReqdCols = pcrsOutput->ContainsAll(pcrsUsed);
		pcrsUsed->Release();
	}
	return fProvidesReqdCols;
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::Equals
//
//	@doc:
//		Equality function
//
//---------------------------------------------------------------------------
BOOL
CReqdPropPlan::Equals(const CReqdPropPlan *prpp) const
{
	GPOS_ASSERT(nullptr != prpp);
	BOOL result = PcrsRequired()->Equals(prpp->PcrsRequired()) &&
				  Pcter()->Equals(prpp->Pcter()) &&
				  Peo()->Matches(prpp->Peo()) && Ped()->Matches(prpp->Ped()) &&
				  Per()->Matches(prpp->Per());
	if (result)
	{
		if (nullptr == Pepp() || nullptr == prpp->Pepp())
		{
			result = (nullptr == Pepp() && nullptr == prpp->Pepp());
		}
		else
		{
			result = Pepp()->Matches(prpp->Pepp());
		}
	}
	return result;
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::HashValue
//
//	@doc:
//		Compute hash value using required columns and required sort order
//
//---------------------------------------------------------------------------
ULONG
CReqdPropPlan::HashValue() const
{
	GPOS_ASSERT(nullptr != m_pcrs);
	GPOS_ASSERT(nullptr != m_peo);
	GPOS_ASSERT(nullptr != m_ped);
	GPOS_ASSERT(nullptr != m_per);
	GPOS_ASSERT(nullptr != m_pcter);
	ULONG ulHash = m_pcrs->HashValue();
	ulHash = gpos::CombineHashes(ulHash, m_peo->HashValue());
	ulHash = gpos::CombineHashes(ulHash, m_ped->HashValue());
	ulHash = gpos::CombineHashes(ulHash, m_per->HashValue());
	ulHash = gpos::CombineHashes(ulHash, m_pcter->HashValue());
	return ulHash;
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::FSatisfied
//
//	@doc:
//		Check if plan properties are satisfied by the given derived properties
//
//---------------------------------------------------------------------------
BOOL
CReqdPropPlan::FSatisfied(const CDrvdPropRelational *pdprel,
						  const CDrvdPropPlan *pdpplan) const
{
	GPOS_ASSERT(nullptr != pdprel);
	GPOS_ASSERT(nullptr != pdpplan);
	GPOS_ASSERT(pdprel->IsComplete());
	// first, check satisfiability of relational properties
	if (!pdprel->FSatisfies(this))
	{
		return false;
	}
	// second, check satisfiability of plan properties;
	// if max cardinality <= 1, then any order requirement is already satisfied;
	// we only need to check satisfiability of distribution and rewindability
	if (pdprel->GetMaxCard().Ull() <= 1)
	{
		GPOS_ASSERT(nullptr != pdpplan->Ppps());
		return pdpplan->Pds()->FSatisfies(this->Ped()->PdsRequired()) &&
			   pdpplan->Prs()->FSatisfies(this->Per()->PrsRequired()) &&
			   pdpplan->Ppps()->FSatisfies(this->Pepp()->PppsRequired()) &&
			   pdpplan->GetCostModel()->FSatisfies(this->Pcter());
	}
	// otherwise, check satisfiability of all plan properties
	return pdpplan->FSatisfies(this);
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::FCompatible
//
//	@doc:
//		Check if plan properties are compatible with the given derived properties
//
//---------------------------------------------------------------------------
BOOL
CReqdPropPlan::FCompatible(CExpressionHandle &exprhdl, CPhysical *popPhysical,
						   const CDrvdPropRelational *pdprel,
						   const CDrvdPropPlan *pdpplan) const
{
	GPOS_ASSERT(nullptr != pdpplan);
	GPOS_ASSERT(nullptr != pdprel);
	// first, check satisfiability of relational properties, including required columns
	if (!pdprel->FSatisfies(this))
	{
		return false;
	}
	return m_peo->FCompatible(pdpplan->Pos()) &&
		   m_ped->FCompatible(pdpplan->Pds()) &&
		   m_per->FCompatible(pdpplan->Prs()) &&
		   pdpplan->Ppps()->FSatisfies(m_pepp->PppsRequired()) &&
		   popPhysical->FProvidesReqdCTEs(exprhdl, m_pcter);
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::PrppEmpty
//
//	@doc:
//		Generate empty required properties
//
//---------------------------------------------------------------------------
CReqdPropPlan *
CReqdPropPlan::PrppEmpty(CMemoryPool *mp)
{
	CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp);
	COrderSpec *pos = GPOS_NEW(mp) COrderSpec(mp);
	CDistributionSpec *pds =
		GPOS_NEW(mp) CDistributionSpecAny(COperator::EopSentinel);
	CRewindabilitySpec *prs = GPOS_NEW(mp) CRewindabilitySpec(
		CRewindabilitySpec::ErtNone, CRewindabilitySpec::EmhtNoMotion);
	CPartitionPropagationSpec *pps = GPOS_NEW(mp) CPartitionPropagationSpec(mp);
	CEnfdOrder *peo = GPOS_NEW(mp) CEnfdOrder(pos, CEnfdOrder::EomSatisfy);
	CEnfdDistribution *ped =
		GPOS_NEW(mp) CEnfdDistribution(pds, CEnfdDistribution::EdmExact);
	CEnfdRewindability *per =
		GPOS_NEW(mp) CEnfdRewindability(prs, CEnfdRewindability::ErmSatisfy);
	CEnfdPartitionPropagation *pepp = GPOS_NEW(mp)
		CEnfdPartitionPropagation(pps, CEnfdPartitionPropagation::EppmSatisfy);
	CCTEReq *pcter = GPOS_NEW(mp) CCTEReq(mp);
	return GPOS_NEW(mp) CReqdPropPlan(pcrs, peo, ped, per, pepp, pcter);
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::OsPrint
//
//	@doc:
//		Print function
//
//---------------------------------------------------------------------------
IOstream &
CReqdPropPlan::OsPrint(IOstream &os) const
{
	if (GPOS_FTRACE(EopttracePrintRequiredColumns))
	{
		os << "req cols: [";
		if (nullptr != m_pcrs)
		{
			os << (*m_pcrs);
		}
		os << "], ";
	}
	os << "req CTEs: [";
	if (nullptr != m_pcter)
	{
		os << (*m_pcter);
	}
	os << "], req order: [";
	if (nullptr != m_peo)
	{
		os << (*m_peo);
	}
	os << "], req dist: [";
	if (nullptr != m_ped)
	{
		os << (*m_ped);
	}
	os << "], req rewind: [";
	if (nullptr != m_per)
	{
		os << "], req rewind: [" << (*m_per);
	}
	os << "], req partition propagation: [";
	if (nullptr != m_pepp)
	{
		os << GetPrintablePtr(m_pepp);
	}
	os << "]";
	return os;
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::UlHashForCostBounding
//
//	@doc:
//		Hash function used for cost bounding
//
//---------------------------------------------------------------------------
ULONG
CReqdPropPlan::UlHashForCostBounding(const CReqdPropPlan *prpp)
{
	GPOS_ASSERT(nullptr != prpp);
	ULONG ulHash = prpp->PcrsRequired()->HashValue();
	if (nullptr != prpp->Ped())
	{
		ulHash = CombineHashes(ulHash, prpp->Ped()->HashValue());
	}
	return ulHash;
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::FEqualForCostBounding
//
//	@doc:
//		Equality function used for cost bounding
//
//---------------------------------------------------------------------------
BOOL
CReqdPropPlan::FEqualForCostBounding(const CReqdPropPlan *prppFst,
									 const CReqdPropPlan *prppSnd)
{
	GPOS_ASSERT(nullptr != prppFst);
	GPOS_ASSERT(nullptr != prppSnd);
	if (nullptr == prppFst->Ped() || nullptr == prppSnd->Ped())
	{
		return nullptr == prppFst->Ped() && nullptr == prppSnd->Ped() &&
			   prppFst->PcrsRequired()->Equals(prppSnd->PcrsRequired());
	}
	return prppFst->PcrsRequired()->Equals(prppSnd->PcrsRequired()) &&
		   prppFst->Ped()->Matches(prppSnd->Ped());
}
//---------------------------------------------------------------------------
//	@function:
//		CReqdPropPlan::PrppRemap
//
//	@doc:
//		Map input required and derived plan properties into new required
//		plan properties for the CTE producer
//
//---------------------------------------------------------------------------
CReqdPropPlan *
CReqdPropPlan::PrppRemapForCTE(CMemoryPool *mp, CReqdPropPlan *prppInput,
							   CDrvdPropPlan *pdpplanInput,
							   UlongToColRefMap *colref_mapping)
{
	GPOS_ASSERT(nullptr != colref_mapping);
	GPOS_ASSERT(nullptr != prppInput);
	GPOS_ASSERT(nullptr != pdpplanInput);
	// Remap derived sort order to a required sort order.
	COrderSpec *pos = pdpplanInput->Pos()->PosCopyWithRemappedColumns(
		mp, colref_mapping, false /*must_exist*/);
	CEnfdOrder *peo = GPOS_NEW(mp) CEnfdOrder(pos, prppInput->Peo()->Eom());
	// Remap derived distribution only if it can be used as required distribution.
	// Also, fix distribution specs with equivalent columns, since those may come
	// from different consumers and NOT be equivalent in the producer.
	// For example:
	//     with cte as (select a,b from foo where b<10)
	//     select * from cte x1 join cte x2 on x1.a=x2.b
	// On the query side, columns x1.a and x2.b are equivalent, but we should NOT
	// treat columns a and b of the producer as equivalent.
	CDistributionSpec *pdsDerived = pdpplanInput->Pds();
	CEnfdDistribution *ped = nullptr;
	if (pdsDerived->FRequirable())
	{
		CDistributionSpec *pdsNoEquiv = pdsDerived->StripEquivColumns(mp);
		CDistributionSpec *pds = pdsNoEquiv->PdsCopyWithRemappedColumns(
			mp, colref_mapping, false /*must_exist*/);
		ped = GPOS_NEW(mp) CEnfdDistribution(pds, prppInput->Ped()->Edm());
		pdsNoEquiv->Release();
	}
	else
	{
		prppInput->Ped()->AddRef();
		ped = prppInput->Ped();
	}
	// other properties are copied from input
	prppInput->PcrsRequired()->AddRef();
	CColRefSet *pcrsRequired = prppInput->PcrsRequired();
	prppInput->Per()->AddRef();
	CEnfdRewindability *per = prppInput->Per();
	prppInput->Pepp()->AddRef();
	CEnfdPartitionPropagation *pepp = prppInput->Pepp();
	prppInput->Pcter()->AddRef();
	CCTEReq *pcter = prppInput->Pcter();
	return GPOS_NEW(mp) CReqdPropPlan(pcrsRequired, peo, ped, per, pepp, pcter);
}
// EOF
相关信息
相关文章
greenplumn CColConstraintsArrayMapper 源码
                        
                            0
                        
                        
                             赞
                        
                    
                    
                热门推荐
- 
                        2、 - 优质文章
 - 
                        3、 gate.io
 - 
                        7、 openharmony
 - 
                        9、 golang