本文整理汇总了C++中CExpression::UlArity方法的典型用法代码示例。如果您正苦于以下问题:C++ CExpression::UlArity方法的具体用法?C++ CExpression::UlArity怎么用?C++ CExpression::UlArity使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类CExpression
的用法示例。
在下文中一共展示了CExpression::UlArity方法的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: CColRefSet
//---------------------------------------------------------------------------
// @function:
// CXformCollapseGbAgg::Transform
//
// @doc:
// Actual transformation to collapse two cascaded group by operators;
// if the top Gb grouping columns are subset of bottom Gb grouping
// columns AND both Gb operators do not define agg functions, we can
// remove the bottom group by operator
//
//
//---------------------------------------------------------------------------
void
CXformCollapseGbAgg::Transform
(
CXformContext *pxfctxt,
CXformResult *pxfres,
CExpression *pexpr
)
const
{
GPOS_ASSERT(NULL != pxfctxt);
GPOS_ASSERT(NULL != pxfres);
GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr));
GPOS_ASSERT(FCheckPattern(pexpr));
IMemoryPool *pmp = pxfctxt->Pmp();
// extract components
CLogicalGbAgg *popTopGbAgg = CLogicalGbAgg::PopConvert(pexpr->Pop());
GPOS_ASSERT(0 < popTopGbAgg->Pdrgpcr()->UlLength());
GPOS_ASSERT(popTopGbAgg->FGlobal());
CExpression *pexprRelational = (*pexpr)[0];
CExpression *pexprTopProjectList = (*pexpr)[1];
CLogicalGbAgg *popBottomGbAgg = CLogicalGbAgg::PopConvert(pexprRelational->Pop());
CExpression *pexprChild = (*pexprRelational)[0];
CExpression *pexprBottomProjectList = (*pexprRelational)[1];
if (!popBottomGbAgg->FGlobal())
{
// bottom GbAgg must be global to prevent xform from getting applied to splitted GbAggs
return;
}
if (0 < pexprTopProjectList->UlArity() || 0 < pexprBottomProjectList->UlArity())
{
// exit if any of the Gb operators has an aggregate function
return;
}
#ifdef GPOS_DEBUG
// for two cascaded GbAgg ops with no agg functions, top grouping
// columns must be a subset of bottom grouping columns
CColRefSet *pcrsTopGrpCols = GPOS_NEW(pmp) CColRefSet(pmp, popTopGbAgg->Pdrgpcr());
CColRefSet *pcrsBottomGrpCols = GPOS_NEW(pmp) CColRefSet(pmp, popBottomGbAgg->Pdrgpcr());
GPOS_ASSERT(pcrsBottomGrpCols->FSubset(pcrsTopGrpCols));
pcrsTopGrpCols->Release();
pcrsBottomGrpCols->Release();
#endif // GPOS_DEBUG
pexprChild->AddRef();
CExpression *pexprSelect = CUtils::PexprLogicalSelect(pmp, pexprChild, CPredicateUtils::PexprConjunction(pmp, NULL /*pdrgpexpr*/));
popTopGbAgg->AddRef();
pexprTopProjectList->AddRef();
CExpression *pexprGbAggNew = GPOS_NEW(pmp) CExpression(pmp, popTopGbAgg, pexprSelect, pexprTopProjectList);
pxfres->Add(pexprGbAggNew);
}
示例2: MapComputedToUsedCols
//---------------------------------------------------------------------------
// @function:
// CQueryContext::MapComputedToUsedCols
//
// @doc:
// Walk the expression and add the mapping between computed column
// and its used columns
//
//---------------------------------------------------------------------------
void
CQueryContext::MapComputedToUsedCols
(
CColumnFactory *pcf,
CExpression *pexpr
)
{
GPOS_ASSERT(NULL != pexpr);
if (COperator::EopLogicalProject == pexpr->Pop()->Eopid())
{
CExpression *pexprPrL = (*pexpr)[1];
const ULONG ulArity = pexprPrL->UlArity();
for (ULONG ul = 0; ul < ulArity; ul++)
{
CExpression *pexprPrEl = (*pexprPrL)[ul];
pcf->AddComputedToUsedColsMap(pexprPrEl);
}
}
// process children
const ULONG ulChildren = pexpr->UlArity();
for (ULONG ul = 0; ul < ulChildren; ul++)
{
MapComputedToUsedCols(pcf, (*pexpr)[ul]);
}
}
示例3: mda
//---------------------------------------------------------------------------
// @function:
// CCNFConverterTest::EresUnittest_Basic
//
// @doc:
// Basic test
//
//---------------------------------------------------------------------------
GPOS_RESULT
CCNFConverterTest::EresUnittest_Basic()
{
CAutoMemoryPool amp;
IMemoryPool *pmp = amp.Pmp();
// setup a file-based provider
CMDProviderMemory *pmdp = CTestUtils::m_pmdpf;
pmdp->AddRef();
CMDAccessor mda(pmp, CMDCache::Pcache(), CTestUtils::m_sysidDefault, pmdp);
typedef CExpression *(*Pfpexpr)(IMemoryPool*);
Pfpexpr rgpf[] =
{
CTestUtils::PexprLogicalSelectWithNestedAnd,
CTestUtils::PexprLogicalSelectWithNestedOr,
CTestUtils::PexprLogicalSelectWithEvenNestedNot,
CTestUtils::PexprLogicalSelectWithOddNestedNot,
CTestUtils::PexprLogicalSelectWithNestedAndOrNot
};
for (ULONG i = 0; i < GPOS_ARRAY_SIZE(rgpf); i++)
{
// install opt context in TLS
CAutoOptCtxt aoc
(
pmp,
&mda,
NULL, /* pceeval */
CTestUtils::Pcm(pmp)
);
// generate expression
CExpression *pexpr = rgpf[i](pmp);
CExpression *pexprPreprocessed = CExpressionPreprocessor::PexprPreprocess(pmp, pexpr);
CWStringDynamic str(pmp);
COstreamString oss(&str);
oss << std::endl << "SCALAR EXPR:" << std::endl << *(*pexpr)[1] << std::endl;
GPOS_TRACE(str.Wsz());
str.Reset();
if (1 < pexprPreprocessed->UlArity())
{
CExpression *pexprCNF = CCNFConverter::Pexpr2CNF(pmp, (*pexprPreprocessed)[1]);
oss << std::endl << "CNF REPRESENTATION:" << std::endl << *pexprCNF << std::endl;
GPOS_TRACE(str.Wsz());
str.Reset();
pexprCNF->Release();
}
pexpr->Release();
pexprPreprocessed->Release();
}
return GPOS_OK;
}
示例4: DrgPexpr
//---------------------------------------------------------------------------
// @function:
// CCNFConverter::PexprNot2CNF
//
// @doc:
// Convert a NOT tree into CNF
//
//---------------------------------------------------------------------------
CExpression *
CCNFConverter::PexprNot2CNF
(
IMemoryPool *pmp,
CExpression *pexpr
)
{
GPOS_ASSERT(NULL != pmp);
GPOS_ASSERT(NULL != pexpr);
GPOS_ASSERT(1 == pexpr->UlArity());
CExpression *pexprNotChild = (*pexpr)[0];
if (!FScalarBoolOp(pexprNotChild))
{
pexpr->AddRef();
return pexpr;
}
CScalarBoolOp::EBoolOperator eboolopChild = CScalarBoolOp::PopConvert(pexprNotChild->Pop())->Eboolop();
// apply DeMorgan laws
// NOT(NOT(A)) ==> A
if (CScalarBoolOp::EboolopNot == eboolopChild)
{
return Pexpr2CNF(pmp, (*pexprNotChild)[0]);
}
// Not child must be either an AND or an OR
// NOT(A AND B) ==> NOT(A) OR NOT(B)
// NOT(A OR B) ==> NOT(A) AND NOT(B)
DrgPexpr *pdrgpexpr = GPOS_NEW(pmp) DrgPexpr(pmp);
const ULONG ulArity = pexprNotChild->UlArity();
for (ULONG ul = 0; ul < ulArity; ul++)
{
(*pexprNotChild)[ul]->AddRef();
pdrgpexpr->Append(CUtils::PexprNegate(pmp, (*pexprNotChild)[ul]));
}
CScalarBoolOp::EBoolOperator eboolop = CScalarBoolOp::EboolopAnd;
if (CScalarBoolOp::EboolopAnd == eboolopChild)
{
eboolop = CScalarBoolOp::EboolopOr;
}
CExpression *pexprScalarBoolOp = CUtils::PexprScalarBoolOp(pmp, eboolop, pdrgpexpr);
CExpression *pexprResult = Pexpr2CNF(pmp, pexprScalarBoolOp);
pexprScalarBoolOp->Release();
return pexprResult;
}
示例5: GPOS_NEW
//---------------------------------------------------------------------------
// @function:
// CConstraint::PcnstrFromScalarArrayCmp
//
// @doc:
// Create constraint from scalar array comparison expression
//
//---------------------------------------------------------------------------
CConstraint *
CConstraint::PcnstrFromScalarArrayCmp
(
IMemoryPool *pmp,
CExpression *pexpr,
CColRef *pcr
)
{
GPOS_ASSERT(NULL != pexpr);
GPOS_ASSERT(CUtils::FScalarArrayCmp(pexpr));
CScalarArrayCmp *popScArrayCmp = CScalarArrayCmp::PopConvert(pexpr->Pop());
CScalarArrayCmp::EArrCmpType earrccmpt = popScArrayCmp->Earrcmpt();
if ((CScalarArrayCmp::EarrcmpAny == earrccmpt || CScalarArrayCmp::EarrcmpAll == earrccmpt) &&
CPredicateUtils::FCompareIdentToConstArray(pexpr))
{
// column
#ifdef GPOS_DEBUG
CScalarIdent *popScId = CScalarIdent::PopConvert((*pexpr)[0]->Pop());
GPOS_ASSERT (pcr == (CColRef *) popScId->Pcr());
#endif // GPOS_DEBUG
// get comparison type
IMDType::ECmpType ecmpt = CUtils::Ecmpt(popScArrayCmp->PmdidOp());
CExpression *pexprArray = (*pexpr)[1];
DrgPcnstr *pdrgpcnstr = GPOS_NEW(pmp) DrgPcnstr(pmp);
const ULONG ulArity = pexprArray->UlArity();
for (ULONG ul = 0; ul < ulArity; ul++)
{
GPOS_ASSERT(CUtils::FScalarConst((*pexprArray)[ul]) && "expecting a constant");
CScalarConst *popScConst = CScalarConst::PopConvert((*pexprArray)[ul]->Pop());
CConstraintInterval *pci = CConstraintInterval::PciIntervalFromColConstCmp(pmp, pcr, ecmpt, popScConst);
pdrgpcnstr->Append(pci);
}
if (earrccmpt == CScalarArrayCmp::EarrcmpAny)
{
// predicate is of the form 'A IN (1,2,3)'
// return a disjunction of ranges {[1,1], [2,2], [3,3]}
return GPOS_NEW(pmp) CConstraintDisjunction(pmp, pdrgpcnstr);
}
// predicate is of the form 'A NOT IN (1,2,3)'
// return a conjunctive negation on {[1,1], [2,2], [3,3]}
return GPOS_NEW(pmp) CConstraintConjunction(pmp, pdrgpcnstr);
}
return NULL;
}
示例6:
//---------------------------------------------------------------------------
// @function:
// CXformGbAggDedup2StreamAggDedup::Transform
//
// @doc:
// Actual transformation
//
//---------------------------------------------------------------------------
void
CXformGbAggDedup2StreamAggDedup::Transform
(
CXformContext *pxfctxt,
CXformResult *pxfres,
CExpression *pexpr
)
const
{
GPOS_ASSERT(NULL != pxfctxt);
GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr));
GPOS_ASSERT(FCheckPattern(pexpr));
IMemoryPool *pmp = pxfctxt->Pmp();
// extract components
CExpression *pexprRel = (*pexpr)[0];
CExpression *pexprScalar = (*pexpr)[1];
GPOS_ASSERT(0 == pexprScalar->UlArity());
// addref children
pexprRel->AddRef();
pexprScalar->AddRef();
CLogicalGbAggDeduplicate *popAggDedup = CLogicalGbAggDeduplicate::PopConvert(pexpr->Pop());
DrgPcr *pdrgpcr = popAggDedup->Pdrgpcr();
pdrgpcr->AddRef();
DrgPcr *pdrgpcrKeys = popAggDedup->PdrgpcrKeys();
pdrgpcrKeys->AddRef();
// create alternative expression
CExpression *pexprAlt =
GPOS_NEW(pmp) CExpression
(
pmp,
GPOS_NEW(pmp) CPhysicalStreamAggDeduplicate
(
pmp,
pdrgpcr,
popAggDedup->PdrgpcrMinimal(),
popAggDedup->Egbaggtype(),
pdrgpcrKeys,
popAggDedup->FGeneratesDuplicates(),
CXformUtils::FMultiStageAgg(pexpr)
),
pexprRel,
pexprScalar
);
// add alternative to transformation result
pxfres->Add(pexprAlt);
}
示例7: CColRefSet
//---------------------------------------------------------------------------
// @function:
// CXformSimplifyGbAgg::FDropGbAgg
//
// @doc:
// Return true if GbAgg operator can be dropped because grouping
// columns include a key
//
//---------------------------------------------------------------------------
BOOL
CXformSimplifyGbAgg::FDropGbAgg
(
IMemoryPool *pmp,
CExpression *pexpr,
CXformResult *pxfres
)
{
CLogicalGbAgg *popAgg = CLogicalGbAgg::PopConvert(pexpr->Pop());
CExpression *pexprRelational = (*pexpr)[0];
CExpression *pexprProjectList = (*pexpr)[1];
if (0 < pexprProjectList->UlArity())
{
// GbAgg cannot be dropped if Agg functions are computed
return false;
}
CKeyCollection *pkc = CDrvdPropRelational::Pdprel(pexprRelational->PdpDerive())->Pkc();
if (NULL == pkc)
{
// relational child does not have key
return false;
}
const ULONG ulKeys = pkc->UlKeys();
BOOL fDrop = false;
for (ULONG ul = 0; !fDrop && ul < ulKeys; ul++)
{
DrgPcr *pdrgpcrKey = pkc->PdrgpcrKey(pmp, ul);
CColRefSet *pcrs = GPOS_NEW(pmp) CColRefSet(pmp, pdrgpcrKey);
pdrgpcrKey->Release();
CColRefSet *pcrsGrpCols = GPOS_NEW(pmp) CColRefSet(pmp);
pcrsGrpCols->Include(popAgg->Pdrgpcr());
BOOL fGrpColsHasKey = pcrsGrpCols->FSubset(pcrs);
pcrs->Release();
pcrsGrpCols->Release();
if (fGrpColsHasKey)
{
// Gb operator can be dropped
pexprRelational->AddRef();
CExpression *pexprResult =
CUtils::PexprLogicalSelect(pmp, pexprRelational, CPredicateUtils::PexprConjunction(pmp, NULL));
pxfres->Add(pexprResult);
fDrop = true;
}
}
return fDrop;
}
示例8: mda
//---------------------------------------------------------------------------
// @function:
// CJoinOrderTest::EresUnittest_Expand
//
// @doc:
// Simple expansion test
//
//---------------------------------------------------------------------------
GPOS_RESULT
CJoinOrderTest::EresUnittest_Expand()
{
CAutoMemoryPool amp;
IMemoryPool *pmp = amp.Pmp();
// setup a file-based provider
CMDProviderMemory *pmdp = CTestUtils::m_pmdpf;
pmdp->AddRef();
CMDAccessor mda(pmp, CMDCache::Pcache(), CTestUtils::m_sysidDefault, pmdp);
// install opt context in TLS
CAutoOptCtxt aoc
(
pmp,
&mda,
NULL, /* pceeval */
CTestUtils::Pcm(pmp)
);
// build test case
CExpression *pexpr = CTestUtils::PexprLogicalNAryJoin(pmp);
DrgPexpr *pdrgpexpr = GPOS_NEW(pmp) DrgPexpr(pmp);
ULONG ulArity = pexpr->UlArity();
for (ULONG ul = 0; ul < ulArity - 1; ul++)
{
CExpression *pexprChild = (*pexpr)[ul];
pexprChild->AddRef();
pdrgpexpr->Append(pexprChild);
}
DrgPexpr *pdrgpexprConj = CPredicateUtils::PdrgpexprConjuncts(pmp, (*pexpr)[ulArity - 1]);
// add predicates selectively to trigger special case of cross join
DrgPexpr *pdrgpexprTest = GPOS_NEW(pmp) DrgPexpr(pmp);
for (ULONG ul = 0; ul < pdrgpexprConj->UlLength() - 1; ul++)
{
CExpression *pexprConjunct = (*pdrgpexprConj)[ul];
pexprConjunct->AddRef();
pdrgpexprTest->Append(pexprConjunct);
}
pdrgpexprConj->Release();
// single-table predicate
CColRefSet *pcrsOutput = CDrvdPropRelational::Pdprel((*pdrgpexpr)[ulArity - 2]->PdpDerive())->PcrsOutput();
CExpression *pexprSingleton = CUtils::PexprScalarEqCmp(pmp, pcrsOutput->PcrAny(), pcrsOutput->PcrAny());
pdrgpexprTest->Append(pexprSingleton);
CJoinOrder jo(pmp, pdrgpexpr, pdrgpexprTest);
CExpression *pexprResult = jo.PexprExpand();
{
CAutoTrace at(pmp);
at.Os() << std::endl << "INPUT:" << std::endl << *pexpr << std::endl;
at.Os() << std::endl << "OUTPUT:" << std::endl << *pexprResult << std::endl;
}
CRefCount::SafeRelease(pexprResult);
pexpr->Release();
return GPOS_OK;
}
示例9: CStatsPredUnsupported
//---------------------------------------------------------------------------
// @function:
// CStatsPredUtils::ProcessArrayCmp
//
// @doc:
// Extract statistics filtering information from scalar array comparison
//---------------------------------------------------------------------------
void
CStatsPredUtils::ProcessArrayCmp
(
IMemoryPool *pmp,
CExpression *pexprPred,
DrgPstatspred *pdrgpstatspred
)
{
GPOS_ASSERT(NULL != pdrgpstatspred);
GPOS_ASSERT(NULL != pexprPred);
GPOS_ASSERT(2 == pexprPred->UlArity());
CScalarArrayCmp *popScArrayCmp = CScalarArrayCmp::PopConvert(pexprPred->Pop());
CExpression *pexprLeft = (*pexprPred)[0];
CExpression *pexprRight = (*pexprPred)[1];
BOOL fCompareToConst = ((COperator::EopScalarIdent == pexprLeft->Pop()->Eopid())
&& (COperator::EopScalarArray == pexprRight->Pop()->Eopid()));
if (!fCompareToConst)
{
// unsupported predicate for stats calculations
pdrgpstatspred->Append(GPOS_NEW(pmp) CStatsPredUnsupported(ULONG_MAX, CStatsPred::EstatscmptOther));
return;
}
BOOL fAny = (CScalarArrayCmp::EarrcmpAny == popScArrayCmp->Earrcmpt());
DrgPstatspred *pdrgpstatspredChild = pdrgpstatspred;
if (fAny)
{
pdrgpstatspredChild = GPOS_NEW(pmp) DrgPstatspred(pmp);
}
const ULONG ulConstants = pexprRight->UlArity();
// comparison semantics for statistics purposes is looser than regular comparison.
CStatsPred::EStatsCmpType escmpt = Estatscmptype(popScArrayCmp->PmdidOp());
CScalarIdent *popScalarIdent = CScalarIdent::PopConvert(pexprLeft->Pop());
const CColRef *pcr = popScalarIdent->Pcr();
if (!CHistogram::FSupportsFilter(escmpt))
{
// unsupported predicate for stats calculations
pdrgpstatspred->Append(GPOS_NEW(pmp) CStatsPredUnsupported(pcr->UlId(), escmpt));
return;
}
for (ULONG ul = 0; ul < ulConstants; ul++)
{
CExpression *pexprConst = (*pexprRight)[ul];
if (COperator::EopScalarConst == pexprConst->Pop()->Eopid())
{
CScalarConst *popScalarConst = CScalarConst::PopConvert(pexprConst->Pop());
IDatum *pdatumLiteral = popScalarConst->Pdatum();
CStatsPred *pstatspredChild = NULL;
if (!pdatumLiteral->FStatsComparable(pdatumLiteral))
{
// stats calculations on such datums unsupported
pstatspredChild = GPOS_NEW(pmp) CStatsPredUnsupported(pcr->UlId(), escmpt);
}
else
{
pstatspredChild = GPOS_NEW(pmp) CStatsPredPoint(pmp, pcr, escmpt, pdatumLiteral);
}
pdrgpstatspredChild->Append(pstatspredChild);
}
}
if (fAny)
{
CStatsPredDisj *pstatspredOr = GPOS_NEW(pmp) CStatsPredDisj(pdrgpstatspredChild);
pdrgpstatspred->Append(pstatspredOr);
}
}
示例10: DrgPexpr
//---------------------------------------------------------------------------
// @function:
// CNormalizer::PexprPullUpProjectElements
//
// @doc:
// Pull up project elements from the given projection expression that do not
// exist in the given used columns set. The pulled up project elements must only
// use columns that are in the output columns of the parent operator. Returns
// a new expression that does not have the pulled up project elements. These
// project elements are appended to the given array.
//
//---------------------------------------------------------------------------
CExpression *
CNormalizer::PexprPullUpProjectElements
(
IMemoryPool *pmp,
CExpression *pexpr,
CColRefSet *pcrsUsed,
CColRefSet *pcrsOutput,
DrgPexpr **ppdrgpexprPrElPullUp // output: the pulled-up project elements
)
{
GPOS_ASSERT(NULL != pexpr);
GPOS_ASSERT(COperator::EopLogicalProject == pexpr->Pop()->Eopid());
GPOS_ASSERT(NULL != pcrsUsed);
GPOS_ASSERT(NULL != ppdrgpexprPrElPullUp);
GPOS_ASSERT(NULL != *ppdrgpexprPrElPullUp);
if (2 != pexpr->UlArity())
{
// the project's children were not extracted as part of the pattern in this xform
GPOS_ASSERT(0 == pexpr->UlArity());
pexpr->AddRef();
return pexpr;
}
DrgPexpr *pdrgpexprPrElNoPullUp = GPOS_NEW(pmp) DrgPexpr(pmp);
CExpression *pexprPrL = (*pexpr)[1];
const ULONG ulProjElements = pexprPrL->UlArity();
for (ULONG ul = 0; ul < ulProjElements; ul++)
{
CExpression *pexprPrEl = (*pexprPrL)[ul];
CScalarProjectElement *popPrEl = CScalarProjectElement::PopConvert(pexprPrEl->Pop());
CColRef *pcrDefined = popPrEl->Pcr();
CColRefSet *pcrsUsedByProjElem = CDrvdPropScalar::Pdpscalar(pexprPrEl->PdpDerive())->PcrsUsed();
// a proj elem can be pulled up only if the defined column is not in
// pcrsUsed and its used columns are in pcrOutput
pexprPrEl->AddRef();
if (!pcrsUsed->FMember(pcrDefined) && pcrsOutput->FSubset(pcrsUsedByProjElem))
{
(*ppdrgpexprPrElPullUp)->Append(pexprPrEl);
}
else
{
pdrgpexprPrElNoPullUp->Append(pexprPrEl);
}
}
CExpression *pexprNew = (*pexpr)[0];
pexprNew->AddRef();
if (0 == pdrgpexprPrElNoPullUp->UlLength())
{
pdrgpexprPrElNoPullUp->Release();
}
else
{
// some project elements could not be pulled up - need a project here
CExpression *pexprPrjList = GPOS_NEW(pmp) CExpression(pmp, GPOS_NEW(pmp) CScalarProjectList(pmp), pdrgpexprPrElNoPullUp);
pexprNew = GPOS_NEW(pmp) CExpression(pmp, GPOS_NEW(pmp) CLogicalProject(pmp), pexprNew, pexprPrjList);
}
return pexprNew;
}
示例11: DrgPexpr
//---------------------------------------------------------------------------
// @function:
// CXformPushDownLeftOuterJoin::Transform
//
// @doc:
// Transform LOJ whose outer child is an NAry-join to be a child
// of NAry-join
//
// Input:
// LOJ (a=d)
// |---NAry-Join (a=b) and (b=c)
// | |--A
// | |--B
// | +--C
// +--D
//
// Output:
// NAry-Join (a=b) and (b=c)
// |--B
// |--C
// +--LOJ (a=d)
// |--A
// +--D
//
//---------------------------------------------------------------------------
void
CXformPushDownLeftOuterJoin::Transform
(
CXformContext *pxfctxt,
CXformResult *pxfres,
CExpression *pexpr
)
const
{
GPOS_ASSERT(NULL != pxfctxt);
GPOS_ASSERT(NULL != pxfres);
GPOS_ASSERT(FPromising(pxfctxt->Pmp(), this, pexpr));
GPOS_ASSERT(FCheckPattern(pexpr));
IMemoryPool *pmp = pxfctxt->Pmp();
CExpression *pexprNAryJoin = (*pexpr)[0];
CExpression *pexprLOJInnerChild = (*pexpr)[1];
CExpression *pexprLOJScalarChild = (*pexpr)[2];
CColRefSet *pcrsLOJUsed = CDrvdPropScalar::Pdpscalar(pexprLOJScalarChild->PdpDerive())->PcrsUsed();
DrgPexpr *pdrgpexprLOJChildren = GPOS_NEW(pmp) DrgPexpr(pmp);
DrgPexpr *pdrgpexprNAryJoinChildren = GPOS_NEW(pmp) DrgPexpr(pmp);
const ULONG ulArity = pexprNAryJoin->UlArity();
CExpression *pexprNAryJoinScalarChild = (*pexprNAryJoin)[ulArity - 1];
for (ULONG ul = 0 ; ul < ulArity - 1; ul++)
{
CExpression *pexprChild = (*pexprNAryJoin)[ul];
CColRefSet *pcrsOutput = CDrvdPropRelational::Pdprel(pexprChild->PdpDerive())->PcrsOutput();
pexprChild->AddRef();
if (!pcrsOutput->FDisjoint(pcrsLOJUsed))
{
pdrgpexprLOJChildren->Append(pexprChild);
}
else
{
pdrgpexprNAryJoinChildren->Append(pexprChild);
}
}
CExpression *pexprLOJOuterChild = (*pdrgpexprLOJChildren)[0];
if (1 < pdrgpexprLOJChildren->UlLength())
{
// collect all relations needed by LOJ outer side into a cross product,
// normalization at the end of this function takes care of pushing NAry
// join predicates down
pdrgpexprLOJChildren->Append(CPredicateUtils::PexprConjunction(pmp, NULL /*pdrgpexpr*/));
pexprLOJOuterChild = GPOS_NEW(pmp) CExpression(pmp, GPOS_NEW(pmp) CLogicalNAryJoin(pmp), pdrgpexprLOJChildren);
// reconstruct LOJ children and add only the created child
pdrgpexprLOJChildren = GPOS_NEW(pmp) DrgPexpr(pmp);
pdrgpexprLOJChildren->Append(pexprLOJOuterChild);
}
// continue with rest of LOJ inner and scalar children
pexprLOJInnerChild->AddRef();
pdrgpexprLOJChildren->Append(pexprLOJInnerChild);
pexprLOJScalarChild->AddRef();
pdrgpexprLOJChildren->Append(pexprLOJScalarChild);
// build new LOJ
CExpression *pexprLOJNew = GPOS_NEW(pmp) CExpression(pmp, GPOS_NEW(pmp) CLogicalLeftOuterJoin(pmp), pdrgpexprLOJChildren);
// add new NAry join children
pdrgpexprNAryJoinChildren->Append(pexprLOJNew);
pexprNAryJoinScalarChild->AddRef();
pdrgpexprNAryJoinChildren->Append(pexprNAryJoinScalarChild);
if (3 > pdrgpexprNAryJoinChildren->UlLength())
{
// xform must generate a valid NAry-join expression
// for example, in the following case we end-up with the same input
// expression, which should be avoided:
//
//.........这里部分代码省略.........