greenplumn CCTEMap 源码
greenplumn CCTEMap 代码
文件路径:/src/backend/gporca/libgpopt/src/base/CCTEMap.cpp
//---------------------------------------------------------------------------
// Greenplum Database
// Copyright (C) 2012 EMC Corp.
//
// @filename:
// CCTEMap.cpp
//
// @doc:
// Implementation of CTE map
//---------------------------------------------------------------------------
#include "gpopt/base/CCTEMap.h"
#include "gpos/base.h"
#include "gpopt/base/CCTEReq.h"
using namespace gpopt;
FORCE_GENERATE_DBGSTR(CCTEMap);
FORCE_GENERATE_DBGSTR(CCTEMap::CCTEMapEntry);
//---------------------------------------------------------------------------
// @function:
// CCTEMap::CCTEMap
//
// @doc:
// Ctor
//
//---------------------------------------------------------------------------
CCTEMap::CCTEMap(CMemoryPool *mp) : m_mp(mp), m_phmcm(nullptr)
{
GPOS_ASSERT(nullptr != mp);
m_phmcm = GPOS_NEW(m_mp) UlongToCTEMapEntryMap(m_mp);
}
//---------------------------------------------------------------------------
// @function:
// CCTEMap::~CCTEMap
//
// @doc:
// Dtor
//
//---------------------------------------------------------------------------
CCTEMap::~CCTEMap()
{
m_phmcm->Release();
}
//---------------------------------------------------------------------------
// @function:
// CCTEMap::Insert
//
// @doc:
// Insert a new map entry. No entry with the same id can already exist
//
//---------------------------------------------------------------------------
void
CCTEMap::Insert(ULONG ulCteId, ECteType ect, CDrvdPropPlan *pdpplan)
{
GPOS_ASSERT(EctSentinel > ect);
if (nullptr != pdpplan)
{
pdpplan->AddRef();
}
CCTEMapEntry *pcme = GPOS_NEW(m_mp) CCTEMapEntry(ulCteId, ect, pdpplan);
BOOL fSuccess GPOS_ASSERTS_ONLY =
m_phmcm->Insert(GPOS_NEW(m_mp) ULONG(ulCteId), pcme);
GPOS_ASSERT(fSuccess);
}
//---------------------------------------------------------------------------
// @function:
// CCTEMap::PdpplanProducer
//
// @doc:
// At any point in a query plan, derived plan properties must contain
// at most one CTE producer;
// this function returns plan properties of that producer if found, otherwise
// return NULL;
// the function also asserts that map has no other producer entries
//
//
//---------------------------------------------------------------------------
CDrvdPropPlan *
CCTEMap::PdpplanProducer(
ULONG *
pulId // output: CTE producer Id, set to gpos::ulong_max if no producer found
) const
{
GPOS_ASSERT(nullptr != pulId);
CDrvdPropPlan *pdpplanProducer = nullptr;
*pulId = gpos::ulong_max;
UlongToCTEMapEntryMapIter hmcmi(m_phmcm);
while (nullptr == pdpplanProducer && hmcmi.Advance())
{
const CCTEMapEntry *pcme = hmcmi.Value();
CCTEMap::ECteType ect = pcme->Ect();
CDrvdPropPlan *pdpplan = pcme->Pdpplan();
if (CCTEMap::EctProducer == ect)
{
GPOS_ASSERT(nullptr != pdpplan);
pdpplanProducer = pdpplan;
*pulId = pcme->Id();
}
}
#ifdef GPOS_DEBUG
while (hmcmi.Advance())
{
const CCTEMapEntry *pcme = hmcmi.Value();
CCTEMap::ECteType ect = pcme->Ect();
GPOS_ASSERT(CCTEMap::EctConsumer == ect &&
"CTE map has properties of more than one producer");
}
#endif // GPOS_DEBUG
return pdpplanProducer;
}
//---------------------------------------------------------------------------
// @function:
// CCTEMap::AddUnresolved
//
// @doc:
// Helper to add entries found in the first map and are
// unresolved based on the second map
//
//---------------------------------------------------------------------------
void
CCTEMap::AddUnresolved(const CCTEMap &cmFirst, const CCTEMap &cmSecond,
CCTEMap *pcmResult)
{
GPOS_ASSERT(nullptr != pcmResult);
// iterate on first map and lookup entries in second map
UlongToCTEMapEntryMapIter hmcmi(cmFirst.m_phmcm);
while (hmcmi.Advance())
{
const CCTEMapEntry *pcme = hmcmi.Value();
ULONG id = pcme->Id();
ECteType ectFirst = pcme->Ect();
CDrvdPropPlan *pdpplanFirst = pcme->Pdpplan();
if (nullptr != pcmResult->PcmeLookup(id))
{
// skip entries already in the result map
continue;
}
// check if entry exists in second map
CCTEMapEntry *pcmeSecond = cmSecond.PcmeLookup(id);
// if entry does not exist in second map, or exists with the same cte type
// then it should be in the result
if (nullptr == pcmeSecond || ectFirst == pcmeSecond->Ect())
{
pcmResult->Insert(id, ectFirst, pdpplanFirst);
}
}
}
//---------------------------------------------------------------------------
// @function:
// CCTEMap::PcmeLookup
//
// @doc:
// Lookup info for given cte id
//
//---------------------------------------------------------------------------
CCTEMap::CCTEMapEntry *
CCTEMap::PcmeLookup(ULONG ulCteId) const
{
return m_phmcm->Find(&ulCteId);
}
//---------------------------------------------------------------------------
// @function:
// CCTEMap::FSubset
//
// @doc:
// Check if the current map is a subset of the given one
//
//---------------------------------------------------------------------------
BOOL
CCTEMap::FSubset(const CCTEMap *pcm) const
{
GPOS_ASSERT(nullptr != pcm);
if (m_phmcm->Size() > pcm->m_phmcm->Size())
{
return false;
}
UlongToCTEMapEntryMapIter hmcmi(m_phmcm);
while (hmcmi.Advance())
{
const CCTEMapEntry *pcme = hmcmi.Value();
CCTEMapEntry *pcmeOther = pcm->PcmeLookup(pcme->Id());
if (nullptr == pcmeOther || pcmeOther->Ect() != pcme->Ect())
{
return false;
}
}
return true;
}
//---------------------------------------------------------------------------
// @function:
// CCTEMap::HashValue
//
// @doc:
// Hash of components
//
//---------------------------------------------------------------------------
ULONG
CCTEMap::HashValue() const
{
ULONG ulHash = 0;
// how many map entries to use for hash computation
ULONG ulMaxEntries = 5;
ULONG ul = 0;
UlongToCTEMapEntryMapIter hmcmi(m_phmcm);
while (hmcmi.Advance() && ul < ulMaxEntries)
{
const CCTEMapEntry *pcme = hmcmi.Value();
ulHash = gpos::CombineHashes(ulHash, pcme->HashValue());
ul++;
}
return ulHash;
}
//---------------------------------------------------------------------------
// @function:
// CCTEMap::Ect
//
// @doc:
// Return the CTE type associated with the given ID in the derived map
//
//---------------------------------------------------------------------------
CCTEMap::ECteType
CCTEMap::Ect(const ULONG id) const
{
CCTEMapEntry *pcme = PcmeLookup(id);
if (nullptr == pcme)
{
return EctSentinel;
}
return pcme->Ect();
}
//---------------------------------------------------------------------------
// @function:
// CCTEMap::PcmCombine
//
// @doc:
// Combine the two given maps and return the result
//
//---------------------------------------------------------------------------
CCTEMap *
CCTEMap::PcmCombine(CMemoryPool *mp, const CCTEMap &cmFirst,
const CCTEMap &cmSecond)
{
CCTEMap *pcmResult = GPOS_NEW(mp) CCTEMap(mp);
// add entries from first map that are not resolvable based on second map
AddUnresolved(cmFirst, cmSecond, pcmResult);
// add entries from second map that are not resolvable based on first map
AddUnresolved(cmSecond, cmFirst, pcmResult);
return pcmResult;
}
//---------------------------------------------------------------------------
// @function:
// CCTEMap::FSatisfies
//
// @doc:
// Check whether the current CTE map satisfies the given CTE requirements
//
//---------------------------------------------------------------------------
BOOL
CCTEMap::FSatisfies(const CCTEReq *pcter) const
{
GPOS_ASSERT(nullptr != pcter);
// every CTE marked as "Required" must be in the current map
ULongPtrArray *pdrgpul = pcter->PdrgpulRequired();
const ULONG ulReqd = pdrgpul->Size();
for (ULONG ul = 0; ul < ulReqd; ul++)
{
ULONG *pulId = (*pdrgpul)[ul];
ECteType ect = pcter->Ect(*pulId);
CCTEMapEntry *pcme = this->PcmeLookup(*pulId);
if (nullptr == pcme || pcme->Ect() != ect)
{
return false;
}
}
// every CTE consumer in the current map must be in the requirements (does not
// matter whether it is marked as required or optional)
UlongToCTEMapEntryMapIter hmcmi(m_phmcm);
while (hmcmi.Advance())
{
const CCTEMapEntry *pcme = hmcmi.Value();
ECteType ect = pcme->Ect();
if (CCTEMap::EctConsumer == ect &&
!pcter->FContainsRequirement(pcme->Id(), ect))
{
return false;
}
}
return true;
}
//---------------------------------------------------------------------------
// @function:
// CCTEMap::PdrgpulAdditionalProducers
//
// @doc:
// Return producer ids that are in this map but not in the given requirement
//
//---------------------------------------------------------------------------
ULongPtrArray *
CCTEMap::PdrgpulAdditionalProducers(CMemoryPool *mp, const CCTEReq *pcter) const
{
GPOS_ASSERT(nullptr != pcter);
ULongPtrArray *pdrgpul = GPOS_NEW(mp) ULongPtrArray(mp);
UlongToCTEMapEntryMapIter hmcmi(m_phmcm);
while (hmcmi.Advance())
{
const CCTEMapEntry *pcme = hmcmi.Value();
ULONG id = pcme->Id();
ECteType ect = pcme->Ect();
if (CCTEMap::EctProducer == ect &&
!pcter->FContainsRequirement(id, ect))
{
pdrgpul->Append(GPOS_NEW(mp) ULONG(id));
}
}
return pdrgpul;
}
//---------------------------------------------------------------------------
// @function:
// CCTEMap::OsPrint
//
// @doc:
// debug print
//
//---------------------------------------------------------------------------
IOstream &
CCTEMap::OsPrint(IOstream &os) const
{
UlongToCTEMapEntryMapIter hmcmi(m_phmcm);
while (hmcmi.Advance())
{
CCTEMapEntry *pcme = const_cast<CCTEMapEntry *>(hmcmi.Value());
pcme->OsPrint(os);
os << " ";
}
return os;
}
namespace gpopt
{
IOstream &
operator<<(IOstream &os, CCTEMap &cm)
{
return cm.OsPrint(os);
}
} // namespace gpopt
// EOF
相关信息
相关文章
greenplumn CColConstraintsArrayMapper 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦