greenplumn COrderSpec 源码

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

greenplumn COrderSpec 代码

文件路径:/src/backend/gporca/libgpopt/src/base/COrderSpec.cpp

//---------------------------------------------------------------------------
//	Greenplum Database
//	Copyright (C) 2011 EMC Corp.
//
//	@filename:
//		COrderSpec.cpp
//
//	@doc:
//		Specification of order property
//---------------------------------------------------------------------------

#include "gpopt/base/COrderSpec.h"

#include "gpopt/base/CColRefSet.h"
#include "gpopt/base/COptCtxt.h"
#include "gpopt/operators/CPhysicalSort.h"

#ifdef GPOS_DEBUG
#include "gpos/error/CAutoTrace.h"
#endif	// GPOS_DEBUG

using namespace gpopt;
using namespace gpmd;

// string encoding of null treatment
const CHAR rgszNullCode[][16] = {"Auto", "NULLsFirst", "NULLsLast"};
GPOS_CPL_ASSERT(COrderSpec::EntSentinel == GPOS_ARRAY_SIZE(rgszNullCode));


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::COrderExpression::COrderExpression
//
//	@doc:
//		Ctor
//
//---------------------------------------------------------------------------
COrderSpec::COrderExpression::COrderExpression(gpmd::IMDId *mdid,
											   const CColRef *colref,
											   ENullTreatment ent)
	: m_mdid(mdid), m_pcr(colref), m_ent(ent)
{
	GPOS_ASSERT(nullptr != colref);
	GPOS_ASSERT(mdid->IsValid());
}

//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::COrderExpression::~COrderExpression
//
//	@doc:
//		Dtor
//
//---------------------------------------------------------------------------
COrderSpec::COrderExpression::~COrderExpression()
{
	m_mdid->Release();
}

//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::COrderExpression::Matches
//
//	@doc:
//		Check if order expression equal to given one;
//
//---------------------------------------------------------------------------
BOOL
COrderSpec::COrderExpression::Matches(const COrderExpression *poe) const
{
	GPOS_ASSERT(nullptr != poe);

	return poe->m_mdid->Equals(m_mdid) && poe->m_pcr == m_pcr &&
		   poe->m_ent == m_ent;
}


FORCE_GENERATE_DBGSTR(gpopt::COrderSpec::COrderExpression);

//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::COrderExpression::OsPrint
//
//	@doc:
//		Print order expression
//
//---------------------------------------------------------------------------
IOstream &
COrderSpec::COrderExpression::OsPrint(IOstream &os) const
{
	os << "( ";
	m_mdid->OsPrint(os);
	os << ", ";
	m_pcr->OsPrint(os);
	os << ", " << rgszNullCode[m_ent] << " )";

	return os;
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::COrderSpec
//
//	@doc:
//		Ctor
//
//---------------------------------------------------------------------------
COrderSpec::COrderSpec(CMemoryPool *mp) : m_mp(mp), m_pdrgpoe(nullptr)
{
	m_pdrgpoe = GPOS_NEW(mp) COrderExpressionArray(mp);
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::~COrderSpec
//
//	@doc:
//		Dtor
//
//---------------------------------------------------------------------------
COrderSpec::~COrderSpec()
{
	m_pdrgpoe->Release();
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::Append
//
//	@doc:
//		Append order expression;
//
//---------------------------------------------------------------------------
void
COrderSpec::Append(gpmd::IMDId *mdid, const CColRef *colref, ENullTreatment ent)
{
	COrderExpression *poe = GPOS_NEW(m_mp) COrderExpression(mdid, colref, ent);
	m_pdrgpoe->Append(poe);
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::Matches
//
//	@doc:
//		Check for equality between order specs
//
//---------------------------------------------------------------------------
BOOL
COrderSpec::Matches(const COrderSpec *pos) const
{
	BOOL fMatch =
		m_pdrgpoe->Size() == pos->m_pdrgpoe->Size() && FSatisfies(pos);

	GPOS_ASSERT_IMP(fMatch, pos->FSatisfies(this));

	return fMatch;
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::FSatisfies
//
//	@doc:
//		Check if this order spec satisfies the given one
//
//---------------------------------------------------------------------------
BOOL
COrderSpec::FSatisfies(const COrderSpec *pos) const
{
	const ULONG arity = pos->m_pdrgpoe->Size();
	BOOL fSatisfies = (m_pdrgpoe->Size() >= arity);

	for (ULONG ul = 0; fSatisfies && ul < arity; ul++)
	{
		fSatisfies = (*m_pdrgpoe)[ul]->Matches((*(pos->m_pdrgpoe))[ul]);
	}

	return fSatisfies;
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::AppendEnforcers
//
//	@doc:
//		Add required enforcers enforcers to dynamic array
//
//---------------------------------------------------------------------------
void
COrderSpec::AppendEnforcers(CMemoryPool *mp,
							CExpressionHandle &,  // exprhdl
							CReqdPropPlan *
#ifdef GPOS_DEBUG
								prpp
#endif	// GPOS_DEBUG
							,
							CExpressionArray *pdrgpexpr, CExpression *pexpr)
{
	GPOS_ASSERT(nullptr != prpp);
	GPOS_ASSERT(nullptr != mp);
	GPOS_ASSERT(nullptr != pdrgpexpr);
	GPOS_ASSERT(nullptr != pexpr);
	GPOS_ASSERT(this == prpp->Peo()->PosRequired() &&
				"required plan properties don't match enforced order spec");

	AddRef();
	pexpr->AddRef();
	CExpression *pexprSort = GPOS_NEW(mp)
		CExpression(mp, GPOS_NEW(mp) CPhysicalSort(mp, this), pexpr);
	pdrgpexpr->Append(pexprSort);
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::HashValue
//
//	@doc:
//		Hash of components
//
//---------------------------------------------------------------------------
ULONG
COrderSpec::HashValue() const
{
	ULONG ulHash = 0;
	ULONG arity = m_pdrgpoe->Size();

	for (ULONG ul = 0; ul < arity; ul++)
	{
		COrderExpression *poe = (*m_pdrgpoe)[ul];
		ulHash =
			gpos::CombineHashes(ulHash, gpos::HashPtr<CColRef>(poe->Pcr()));
	}

	return ulHash;
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::PosCopyWithRemappedColumns
//
//	@doc:
//		Return a copy of the order spec with remapped columns
//
//---------------------------------------------------------------------------
COrderSpec *
COrderSpec::PosCopyWithRemappedColumns(CMemoryPool *mp,
									   UlongToColRefMap *colref_mapping,
									   BOOL must_exist)
{
	COrderSpec *pos = GPOS_NEW(mp) COrderSpec(mp);

	const ULONG num_cols = m_pdrgpoe->Size();
	for (ULONG ul = 0; ul < num_cols; ul++)
	{
		COrderExpression *poe = (*m_pdrgpoe)[ul];
		IMDId *mdid = poe->GetMdIdSortOp();
		mdid->AddRef();

		const CColRef *colref = poe->Pcr();
		ULONG id = colref->Id();
		CColRef *pcrMapped = colref_mapping->Find(&id);
		if (nullptr == pcrMapped)
		{
			if (must_exist)
			{
				CColumnFactory *col_factory = COptCtxt::PoctxtFromTLS()->Pcf();
				// not found in hashmap, so create a new colref and add to hashmap
				pcrMapped = col_factory->PcrCopy(colref);

				BOOL result GPOS_ASSERTS_ONLY =
					colref_mapping->Insert(GPOS_NEW(mp) ULONG(id), pcrMapped);
				GPOS_ASSERT(result);
			}
			else
			{
				pcrMapped = const_cast<CColRef *>(colref);
			}
		}

		COrderSpec::ENullTreatment ent = poe->Ent();
		pos->Append(mdid, pcrMapped, ent);
	}

	return pos;
}

//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::PosExcludeColumns
//
//	@doc:
//		Return a copy of the order spec after excluding the given columns
//
//---------------------------------------------------------------------------
COrderSpec *
COrderSpec::PosExcludeColumns(CMemoryPool *mp, CColRefSet *pcrs)
{
	GPOS_ASSERT(nullptr != pcrs);

	COrderSpec *pos = GPOS_NEW(mp) COrderSpec(mp);

	const ULONG num_cols = m_pdrgpoe->Size();
	for (ULONG ul = 0; ul < num_cols; ul++)
	{
		COrderExpression *poe = (*m_pdrgpoe)[ul];
		const CColRef *colref = poe->Pcr();

		if (pcrs->FMember(colref))
		{
			continue;
		}

		IMDId *mdid = poe->GetMdIdSortOp();
		mdid->AddRef();
		pos->Append(mdid, colref, poe->Ent());
	}

	return pos;
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::ExtractCols
//
//	@doc:
//		Extract columns from order spec into the given column set
//
//---------------------------------------------------------------------------
void
COrderSpec::ExtractCols(CColRefSet *pcrs) const
{
	GPOS_ASSERT(nullptr != pcrs);

	const ULONG ulOrderExprs = m_pdrgpoe->Size();
	for (ULONG ul = 0; ul < ulOrderExprs; ul++)
	{
		pcrs->Include((*m_pdrgpoe)[ul]->Pcr());
	}
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::PcrsUsed
//
//	@doc:
//		Extract colref set from order components
//
//---------------------------------------------------------------------------
CColRefSet *
COrderSpec::PcrsUsed(CMemoryPool *mp) const
{
	CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp);
	ExtractCols(pcrs);

	return pcrs;
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::GetColRefSet
//
//	@doc:
//		Extract colref set from order specs in the given array
//
//---------------------------------------------------------------------------
CColRefSet *
COrderSpec::GetColRefSet(CMemoryPool *mp, COrderSpecArray *pdrgpos)
{
	GPOS_ASSERT(nullptr != pdrgpos);

	CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp);
	const ULONG ulOrderSpecs = pdrgpos->Size();
	for (ULONG ulSpec = 0; ulSpec < ulOrderSpecs; ulSpec++)
	{
		COrderSpec *pos = (*pdrgpos)[ulSpec];
		pos->ExtractCols(pcrs);
	}

	return pcrs;
}

//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::PdrgposExclude
//
//	@doc:
//		Filter out array of order specs from order expressions using the
//		passed columns
//
//---------------------------------------------------------------------------
COrderSpecArray *
COrderSpec::PdrgposExclude(CMemoryPool *mp, COrderSpecArray *pdrgpos,
						   CColRefSet *pcrsToExclude)
{
	GPOS_ASSERT(nullptr != pdrgpos);
	GPOS_ASSERT(nullptr != pcrsToExclude);

	if (0 == pcrsToExclude->Size())
	{
		// no columns to exclude
		pdrgpos->AddRef();
		return pdrgpos;
	}

	COrderSpecArray *pdrgposNew = GPOS_NEW(mp) COrderSpecArray(mp);
	const ULONG ulOrderSpecs = pdrgpos->Size();
	for (ULONG ulSpec = 0; ulSpec < ulOrderSpecs; ulSpec++)
	{
		COrderSpec *pos = (*pdrgpos)[ulSpec];
		COrderSpec *posNew = pos->PosExcludeColumns(mp, pcrsToExclude);
		pdrgposNew->Append(posNew);
	}

	return pdrgposNew;
}

//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::OsPrint
//
//	@doc:
//		Print order spec
//
//---------------------------------------------------------------------------
IOstream &
COrderSpec::OsPrint(IOstream &os) const
{
	const ULONG arity = m_pdrgpoe->Size();
	if (0 == arity)
	{
		os << "<empty>";
	}
	else
	{
		for (ULONG ul = 0; ul < arity; ul++)
		{
			(*m_pdrgpoe)[ul]->OsPrint(os) << " ";
		}
	}

	return os;
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::Equals
//
//	@doc:
//		 Matching function over order spec arrays
//
//---------------------------------------------------------------------------
BOOL
COrderSpec::Equals(const COrderSpecArray *pdrgposFirst,
				   const COrderSpecArray *pdrgposSecond)
{
	if (nullptr == pdrgposFirst || nullptr == pdrgposSecond)
	{
		return (nullptr == pdrgposFirst && nullptr == pdrgposSecond);
	}

	if (pdrgposFirst->Size() != pdrgposSecond->Size())
	{
		return false;
	}

	const ULONG size = pdrgposFirst->Size();
	BOOL fMatch = true;
	for (ULONG ul = 0; fMatch && ul < size; ul++)
	{
		fMatch = (*pdrgposFirst)[ul]->Matches((*pdrgposSecond)[ul]);
	}

	return fMatch;
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::HashValue
//
//	@doc:
//		 Combine hash values of a maximum number of entries
//
//---------------------------------------------------------------------------
ULONG
COrderSpec::HashValue(const COrderSpecArray *pdrgpos, ULONG ulMaxSize)
{
	GPOS_ASSERT(nullptr != pdrgpos);
	ULONG size = std::min(ulMaxSize, pdrgpos->Size());

	ULONG ulHash = 0;
	for (ULONG ul = 0; ul < size; ul++)
	{
		ulHash = gpos::CombineHashes(ulHash, (*pdrgpos)[ul]->HashValue());
	}

	return ulHash;
}


//---------------------------------------------------------------------------
//	@function:
//		COrderSpec::OsPrint
//
//	@doc:
//		 Print array of order spec objects
//
//---------------------------------------------------------------------------
IOstream &
COrderSpec::OsPrint(IOstream &os, const COrderSpecArray *pdrgpos)
{
	const ULONG size = pdrgpos->Size();
	os << "[";
	if (0 < size)
	{
		for (ULONG ul = 0; ul < size - 1; ul++)
		{
			(void) (*pdrgpos)[ul]->OsPrint(os);
			os << ", ";
		}

		(void) (*pdrgpos)[size - 1]->OsPrint(os);
	}

	return os << "]";
}


// EOF

相关信息

greenplumn 源码目录

相关文章

greenplumn CAutoOptCtxt 源码

greenplumn CCTEInfo 源码

greenplumn CCTEMap 源码

greenplumn CCTEReq 源码

greenplumn CCastUtils 源码

greenplumn CColConstraintsArrayMapper 源码

greenplumn CColConstraintsHashMapper 源码

greenplumn CColRef 源码

greenplumn CColRefComputed 源码

greenplumn CColRefSet 源码

0  赞