greenplumn CCTEReq 源码
greenplumn CCTEReq 代码
文件路径:/src/backend/gporca/libgpopt/src/base/CCTEReq.cpp
//---------------------------------------------------------------------------
// Greenplum Database
// Copyright (C) 2013 EMC Corp.
//
// @filename:
// CCTEReq.cpp
//
// @doc:
// Implementation of CTE requirements
//---------------------------------------------------------------------------
#include "gpopt/base/CCTEReq.h"
#include "gpos/base.h"
#include "gpopt/base/COptCtxt.h"
using namespace gpopt;
FORCE_GENERATE_DBGSTR(CCTEReq);
FORCE_GENERATE_DBGSTR(CCTEReq::CCTEReqEntry);
//---------------------------------------------------------------------------
// @function:
// CCTEReq::CCTEReqEntry::CCTEReqEntry
//
// @doc:
// Ctor
//
//---------------------------------------------------------------------------
CCTEReq::CCTEReqEntry::CCTEReqEntry(ULONG id, CCTEMap::ECteType ect,
BOOL fRequired, CDrvdPropPlan *pdpplan)
: m_id(id), m_ect(ect), m_fRequired(fRequired), m_pdpplan(pdpplan)
{
GPOS_ASSERT(CCTEMap::EctSentinel > ect);
GPOS_ASSERT_IMP(nullptr == pdpplan, CCTEMap::EctProducer == ect);
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::CCTEReqEntry::~CCTEReqEntry
//
// @doc:
// Dtor
//
//---------------------------------------------------------------------------
CCTEReq::CCTEReqEntry::~CCTEReqEntry()
{
CRefCount::SafeRelease(m_pdpplan);
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::CCTEReqEntry::HashValue
//
// @doc:
// Hash function
//
//---------------------------------------------------------------------------
ULONG
CCTEReq::CCTEReqEntry::HashValue() const
{
ULONG ulHash =
gpos::CombineHashes(gpos::HashValue<ULONG>(&m_id),
gpos::HashValue<CCTEMap::ECteType>(&m_ect));
ulHash = gpos::CombineHashes(ulHash, gpos::HashValue<BOOL>(&m_fRequired));
if (nullptr != m_pdpplan)
{
ulHash = gpos::CombineHashes(ulHash, m_pdpplan->HashValue());
}
return ulHash;
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::CCTEReqEntry::Equals
//
// @doc:
// Equality function
//
//---------------------------------------------------------------------------
BOOL
CCTEReq::CCTEReqEntry::Equals(CCTEReqEntry *pcre) const
{
GPOS_ASSERT(nullptr != pcre);
if (m_id != pcre->Id() || m_ect != pcre->Ect() ||
m_fRequired != pcre->FRequired())
{
return false;
}
CDrvdPropPlan *pdpplan = pcre->PdpplanProducer();
if (nullptr == m_pdpplan && nullptr == pdpplan)
{
return true;
}
if (nullptr != m_pdpplan && nullptr != pdpplan)
{
return m_pdpplan->Equals(pdpplan);
}
return false;
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::CCTEReqEntry::OsPrint
//
// @doc:
// Print function
//
//---------------------------------------------------------------------------
IOstream &
CCTEReq::CCTEReqEntry::OsPrint(IOstream &os) const
{
os << m_id << (CCTEMap::EctProducer == m_ect ? ":p" : ":c")
<< (m_fRequired ? " " : "(opt) ");
if (nullptr != m_pdpplan)
{
os << "Plan Props: " << *m_pdpplan;
}
return os;
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::CCTEReq
//
// @doc:
// Ctor
//
//---------------------------------------------------------------------------
CCTEReq::CCTEReq(CMemoryPool *mp)
: m_mp(mp), m_phmcter(nullptr), m_pdrgpulRequired(nullptr)
{
GPOS_ASSERT(nullptr != mp);
m_phmcter = GPOS_NEW(m_mp) UlongToCTEReqEntryMap(m_mp);
m_pdrgpulRequired = GPOS_NEW(m_mp) ULongPtrArray(m_mp);
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::~CCTEReq
//
// @doc:
// Dtor
//
//---------------------------------------------------------------------------
CCTEReq::~CCTEReq()
{
m_phmcter->Release();
m_pdrgpulRequired->Release();
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::Insert
//
// @doc:
// Insert a new map entry. No entry with the same id can already exist
//
//---------------------------------------------------------------------------
void
CCTEReq::Insert(ULONG ulCteId, CCTEMap::ECteType ect, BOOL fRequired,
CDrvdPropPlan *pdpplan)
{
GPOS_ASSERT(CCTEMap::EctSentinel > ect);
CCTEReqEntry *pcre =
GPOS_NEW(m_mp) CCTEReqEntry(ulCteId, ect, fRequired, pdpplan);
BOOL fSuccess GPOS_ASSERTS_ONLY =
m_phmcter->Insert(GPOS_NEW(m_mp) ULONG(ulCteId), pcre);
GPOS_ASSERT(fSuccess);
if (fRequired)
{
m_pdrgpulRequired->Append(GPOS_NEW(m_mp) ULONG(ulCteId));
}
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::InsertConsumer
//
// @doc:
// Insert a new consumer entry. with the given id. The plan properties are
// taken from the given context
//
//---------------------------------------------------------------------------
void
CCTEReq::InsertConsumer(ULONG id, CDrvdPropArray *pdrgpdpCtxt)
{
ULONG ulProducerId = gpos::ulong_max;
CDrvdPropPlan *pdpplan = CDrvdPropPlan::Pdpplan((*pdrgpdpCtxt)[0])
->GetCostModel()
->PdpplanProducer(&ulProducerId);
GPOS_ASSERT(nullptr != pdpplan);
GPOS_ASSERT(ulProducerId == id &&
"unexpected CTE producer plan properties");
pdpplan->AddRef();
Insert(id, CCTEMap::EctConsumer, true /*fRequired*/, pdpplan);
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::PcreLookup
//
// @doc:
// Lookup info for given cte id
//
//---------------------------------------------------------------------------
CCTEReq::CCTEReqEntry *
CCTEReq::PcreLookup(ULONG ulCteId) const
{
return m_phmcter->Find(&ulCteId);
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::FSubset
//
// @doc:
// Check if the current requirement is a subset of the given one
//
//---------------------------------------------------------------------------
BOOL
CCTEReq::FSubset(const CCTEReq *pcter) const
{
GPOS_ASSERT(nullptr != pcter);
// compare number of entries first
if (m_phmcter->Size() > pcter->m_phmcter->Size())
{
return false;
}
if (0 == m_phmcter->Size())
{
// empty subset
return true;
}
// iterate over map entries
UlongToCTEReqEntryMapIter hmcri(m_phmcter);
while (hmcri.Advance())
{
const CCTEReqEntry *pcre = hmcri.Value();
CCTEReqEntry *pcreOther = pcter->PcreLookup(pcre->Id());
if (nullptr == pcreOther || !pcre->Equals(pcreOther))
{
return false;
}
}
return true;
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::FContainsRequirement
//
// @doc:
// Check if the given CTE is in the requirements
//
//---------------------------------------------------------------------------
BOOL
CCTEReq::FContainsRequirement(const ULONG id, const CCTEMap::ECteType ect) const
{
CCTEReqEntry *pcre = PcreLookup(id);
return (nullptr != pcre && pcre->Ect() == ect);
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::Ect
//
// @doc:
// Return the CTE type associated with the given ID in the requirements
//
//---------------------------------------------------------------------------
CCTEMap::ECteType
CCTEReq::Ect(const ULONG id) const
{
CCTEReqEntry *pcre = PcreLookup(id);
GPOS_ASSERT(nullptr != pcre);
return pcre->Ect();
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::HashValue
//
// @doc:
// Hash of components
//
//---------------------------------------------------------------------------
ULONG
CCTEReq::HashValue() const
{
ULONG ulHash = 0;
// how many map entries to use for hash computation
const ULONG ulMaxEntries = 5;
ULONG ul = 0;
UlongToCTEReqEntryMapIter hmcri(m_phmcter);
while (hmcri.Advance() && ul < ulMaxEntries)
{
const CCTEReqEntry *pcre = hmcri.Value();
ulHash = gpos::CombineHashes(ulHash, pcre->HashValue());
ul++;
}
return ulHash;
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::PcterUnresolved
//
// @doc:
// Unresolved CTE requirements given a derived CTE map
//
//---------------------------------------------------------------------------
CCTEReq *
CCTEReq::PcterUnresolved(CMemoryPool *mp, CCTEMap *pcm)
{
GPOS_ASSERT(nullptr != pcm);
CCTEReq *pcterUnresolved = GPOS_NEW(mp) CCTEReq(mp);
UlongToCTEReqEntryMapIter hmcri(m_phmcter);
while (hmcri.Advance())
{
// if a cte is marked as required and it is not found in the given map
// then keep it as required, else make it optional
const CCTEReqEntry *pcre = hmcri.Value();
ULONG id = pcre->Id();
BOOL fRequired =
pcre->FRequired() && CCTEMap::EctSentinel == pcm->Ect(id);
CDrvdPropPlan *pdpplan = pcre->PdpplanProducer();
if (nullptr != pdpplan)
{
pdpplan->AddRef();
}
pcterUnresolved->Insert(id, pcre->Ect(), fRequired, pdpplan);
}
return pcterUnresolved;
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::PcterUnresolvedSequence
//
// @doc:
// Unresolved CTE requirements given a derived CTE map for a sequence
// operator
//
//---------------------------------------------------------------------------
CCTEReq *
CCTEReq::PcterUnresolvedSequence(
CMemoryPool *mp, CCTEMap *pcm,
CDrvdPropArray *
pdrgpdpCtxt // context contains derived plan properties of producer tree
)
{
GPOS_ASSERT(nullptr != pcm);
CCTEReq *pcterUnresolved = GPOS_NEW(mp) CCTEReq(mp);
UlongToCTEReqEntryMapIter hmcri(m_phmcter);
while (hmcri.Advance())
{
const CCTEReqEntry *pcre = hmcri.Value();
ULONG id = pcre->Id();
CCTEMap::ECteType ect = pcre->Ect();
BOOL fRequired = pcre->FRequired();
CCTEMap::ECteType ectDrvd = pcm->Ect(id);
if (fRequired && CCTEMap::EctSentinel != ectDrvd)
{
GPOS_ASSERT(CCTEMap::EctConsumer == ect);
GPOS_ASSERT(CCTEMap::EctConsumer == ectDrvd);
// already found, so mark it as optional
CDrvdPropPlan *pdpplan = pcre->PdpplanProducer();
GPOS_ASSERT(nullptr != pdpplan);
pdpplan->AddRef();
pcterUnresolved->Insert(id, ect, false /*fReqiored*/, pdpplan);
}
else if (!fRequired && CCTEMap::EctProducer == ect &&
CCTEMap::EctSentinel != ectDrvd)
{
GPOS_ASSERT(CCTEMap::EctProducer == ectDrvd);
// found a producer. require the corresponding consumer and
// extract producer plan properties from passed context
pcterUnresolved->InsertConsumer(id, pdrgpdpCtxt);
}
else
{
// either required and not found yet, or optional
// in both cases, pass it down as is
CDrvdPropPlan *pdpplan = pcre->PdpplanProducer();
GPOS_ASSERT_IMP(nullptr == pdpplan, CCTEMap::EctProducer == ect);
if (nullptr != pdpplan)
{
pdpplan->AddRef();
}
pcterUnresolved->Insert(id, ect, fRequired, pdpplan);
}
}
// if something is in pcm and not in the requirments, it has to be a producer
// in which case, add the corresponding consumer as unresolved
ULongPtrArray *pdrgpulProducers = pcm->PdrgpulAdditionalProducers(mp, this);
const ULONG length = pdrgpulProducers->Size();
for (ULONG ul = 0; ul < length; ul++)
{
ULONG *pulId = (*pdrgpulProducers)[ul];
pcterUnresolved->InsertConsumer(*pulId, pdrgpdpCtxt);
}
pdrgpulProducers->Release();
return pcterUnresolved;
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::PcterAllOptional
//
// @doc:
// Create a copy of the current requirement where all the entries are marked optional
//
//---------------------------------------------------------------------------
CCTEReq *
CCTEReq::PcterAllOptional(CMemoryPool *mp)
{
CCTEReq *pcter = GPOS_NEW(mp) CCTEReq(mp);
UlongToCTEReqEntryMapIter hmcri(m_phmcter);
while (hmcri.Advance())
{
const CCTEReqEntry *pcre = hmcri.Value();
CDrvdPropPlan *pdpplan = pcre->PdpplanProducer();
if (nullptr != pdpplan)
{
pdpplan->AddRef();
}
pcter->Insert(pcre->Id(), pcre->Ect(), false /*fRequired*/, pdpplan);
}
return pcter;
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::Pdpplan
//
// @doc:
// Lookup plan properties for given cte id
//
//---------------------------------------------------------------------------
CDrvdPropPlan *
CCTEReq::Pdpplan(ULONG ulCteId) const
{
const CCTEReqEntry *pcre = PcreLookup(ulCteId);
if (nullptr != pcre)
{
return pcre->PdpplanProducer();
}
return nullptr;
}
//---------------------------------------------------------------------------
// @function:
// CCTEReq::OsPrint
//
// @doc:
// debug print
//
//---------------------------------------------------------------------------
IOstream &
CCTEReq::OsPrint(IOstream &os) const
{
UlongToCTEReqEntryMapIter hmcri(m_phmcter);
while (hmcri.Advance())
{
CCTEReqEntry *pcre = const_cast<CCTEReqEntry *>(hmcri.Value());
pcre->OsPrint(os);
}
return os;
}
namespace gpopt
{
IOstream &
operator<<(IOstream &os, CCTEReq &cter)
{
return cter.OsPrint(os);
}
} // namespace gpopt
// EOF
相关信息
相关文章
greenplumn CColConstraintsArrayMapper 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦