greenplumn CExpressionUtils 源码
greenplumn CExpressionUtils 代码
文件路径:/src/backend/gporca/libgpopt/src/operators/CExpressionUtils.cpp
//---------------------------------------------------------------------------
// Greenplum Database
// Copyright (C) 2014 VMware, Inc. or its affiliates.
//
// @filename:
// CExpressionUtils.cpp
//
// @doc:
// Utility routines for transforming expressions
//
// @owner:
// ,
//
// @test:
//
//---------------------------------------------------------------------------
#include "gpopt/operators/CExpressionUtils.h"
#include "gpopt/base/CColRefSetIter.h"
#include "gpopt/base/CColRefTable.h"
#include "gpopt/base/CConstraintInterval.h"
#include "gpopt/base/CUtils.h"
#include "gpopt/exception.h"
#include "gpopt/mdcache/CMDAccessor.h"
#include "gpopt/operators/CLogicalJoin.h"
#include "gpopt/operators/CPredicateUtils.h"
#include "gpopt/operators/CScalarSubqueryExists.h"
#include "gpopt/operators/CScalarSubqueryNotExists.h"
#include "naucrates/md/IMDScalarOp.h"
#include "naucrates/md/IMDType.h"
#include "naucrates/statistics/CStatistics.h"
using namespace gpopt;
//---------------------------------------------------------------------------
// @function:
// CExpressionUtils::UnnestChild
//
// @doc:
// Unnest a given expression's child and append unnested nodes to
// the given expression array
//
//---------------------------------------------------------------------------
void
CExpressionUtils::UnnestChild(
CMemoryPool *mp,
CExpression *pexpr, // parent node
ULONG child_index, // child index
BOOL fAnd, // is expression an AND node?
BOOL fOr, // is expression an OR node?
BOOL fHasNegatedChild, // does expression have NOT child nodes?
CExpressionArray *pdrgpexpr // array to append results to
)
{
GPOS_ASSERT(nullptr != mp);
GPOS_ASSERT(nullptr != pexpr);
GPOS_ASSERT(child_index < pexpr->Arity());
GPOS_ASSERT(nullptr != pdrgpexpr);
CExpression *pexprChild = (*pexpr)[child_index];
if ((fAnd && CPredicateUtils::FAnd(pexprChild)) ||
(fOr && CPredicateUtils::FOr(pexprChild)))
{
// two cascaded AND nodes or two cascaded OR nodes, recursively
// pull-up children
AppendChildren(mp, pexprChild, pdrgpexpr);
return;
}
if (fHasNegatedChild && CPredicateUtils::FNot(pexprChild) &&
CPredicateUtils::FNot((*pexprChild)[0]))
{
// two cascaded Not nodes cancel each other
CExpression *pexprNot = (*pexprChild)[0];
pexprChild = (*pexprNot)[0];
}
CExpression *pexprUnnestedChild = PexprUnnest(mp, pexprChild);
pdrgpexpr->Append(pexprUnnestedChild);
}
//---------------------------------------------------------------------------
// @function:
// CExpressionUtils::AppendChildren
//
// @doc:
// Append the unnested children of given expression to given array
//
//---------------------------------------------------------------------------
void
CExpressionUtils::AppendChildren(CMemoryPool *mp, CExpression *pexpr,
CExpressionArray *pdrgpexpr)
{
GPOS_ASSERT(nullptr != mp);
GPOS_ASSERT(nullptr != pexpr);
GPOS_ASSERT(nullptr != pdrgpexpr);
CExpressionArray *pdrgpexprChildren = PdrgpexprUnnestChildren(mp, pexpr);
CUtils::AddRefAppend(pdrgpexpr, pdrgpexprChildren);
pdrgpexprChildren->Release();
}
//---------------------------------------------------------------------------
// @function:
// CExpressionUtils::PdrgpexprUnnestChildren
//
// @doc:
// Return an array of expression's children after unnesting nested
// AND/OR/NOT subtrees
//
//---------------------------------------------------------------------------
CExpressionArray *
CExpressionUtils::PdrgpexprUnnestChildren(CMemoryPool *mp, CExpression *pexpr)
{
// protect against stack overflow during recursion
GPOS_CHECK_STACK_SIZE;
GPOS_ASSERT(nullptr != mp);
GPOS_ASSERT(nullptr != pexpr);
// compute flags for cases where we may have nested predicates
BOOL fAnd = CPredicateUtils::FAnd(pexpr);
BOOL fOr = CPredicateUtils::FOr(pexpr);
BOOL fHasNegatedChild = CPredicateUtils::FHasNegatedChild(pexpr);
CExpressionArray *pdrgpexpr = GPOS_NEW(mp) CExpressionArray(mp);
const ULONG arity = pexpr->Arity();
for (ULONG ul = 0; ul < arity; ul++)
{
UnnestChild(mp, pexpr, ul, fAnd, fOr, fHasNegatedChild, pdrgpexpr);
}
return pdrgpexpr;
}
//---------------------------------------------------------------------------
// @function:
// CExpressionUtils::PexprUnnest
//
// @doc:
// Unnest AND/OR/NOT predicates
//
//---------------------------------------------------------------------------
CExpression *
CExpressionUtils::PexprUnnest(CMemoryPool *mp, CExpression *pexpr)
{
// protect against stack overflow during recursion
GPOS_CHECK_STACK_SIZE;
GPOS_ASSERT(nullptr != mp);
GPOS_ASSERT(nullptr != pexpr);
if (CPredicateUtils::FNot(pexpr))
{
CExpression *pexprChild = (*pexpr)[0];
CExpression *pexprPushedNot = PexprPushNotOneLevel(mp, pexprChild);
COperator *pop = pexprPushedNot->Pop();
CExpressionArray *pdrgpexpr =
PdrgpexprUnnestChildren(mp, pexprPushedNot);
pop->AddRef();
// clean up
pexprPushedNot->Release();
return GPOS_NEW(mp) CExpression(mp, pop, pdrgpexpr);
}
COperator *pop = pexpr->Pop();
CExpressionArray *pdrgpexpr = PdrgpexprUnnestChildren(mp, pexpr);
pop->AddRef();
return GPOS_NEW(mp) CExpression(mp, pop, pdrgpexpr);
}
//---------------------------------------------------------------------------
// @function:
// CExpressionUtils::PexprPushNotOneLevel
//
// @doc:
// Push not expression one level down the given expression. For example:
// 1. AND of expressions into an OR a negation of these expression
// 2. OR of expressions into an AND a negation of these expression
// 3. EXISTS into NOT EXISTS and vice versa
// 4. Else, return NOT of given expression
//---------------------------------------------------------------------------
CExpression *
CExpressionUtils::PexprPushNotOneLevel(CMemoryPool *mp, CExpression *pexpr)
{
GPOS_ASSERT(nullptr != pexpr);
BOOL fAnd = CPredicateUtils::FAnd(pexpr);
BOOL fOr = CPredicateUtils::FOr(pexpr);
if (fAnd || fOr)
{
COperator *popNew = nullptr;
if (fOr)
{
popNew = GPOS_NEW(mp) CScalarBoolOp(mp, CScalarBoolOp::EboolopAnd);
}
else
{
popNew = GPOS_NEW(mp) CScalarBoolOp(mp, CScalarBoolOp::EboolopOr);
}
CExpressionArray *pdrgpexpr = GPOS_NEW(mp) CExpressionArray(mp);
const ULONG arity = pexpr->Arity();
for (ULONG ul = 0; ul < arity; ul++)
{
CExpression *pexprChild = (*pexpr)[ul];
pexprChild->AddRef();
pdrgpexpr->Append(CUtils::PexprNegate(mp, pexprChild));
}
return GPOS_NEW(mp) CExpression(mp, popNew, pdrgpexpr);
}
const COperator *pop = pexpr->Pop();
if (COperator::EopScalarSubqueryExists == pop->Eopid())
{
pexpr->PdrgPexpr()->AddRef();
return GPOS_NEW(mp) CExpression(
mp, GPOS_NEW(mp) CScalarSubqueryNotExists(mp), pexpr->PdrgPexpr());
}
if (COperator::EopScalarSubqueryNotExists == pop->Eopid())
{
pexpr->PdrgPexpr()->AddRef();
return GPOS_NEW(mp) CExpression(
mp, GPOS_NEW(mp) CScalarSubqueryExists(mp), pexpr->PdrgPexpr());
}
// TODO: , Feb 4 2015, we currently only handling EXISTS/NOT EXISTS/AND/OR
pexpr->AddRef();
return GPOS_NEW(mp) CExpression(
mp, GPOS_NEW(mp) CScalarBoolOp(mp, CScalarBoolOp::EboolopNot), pexpr);
}
//---------------------------------------------------------------------------
// @function:
// CExpressionUtils::PexprDedupChildren
//
// @doc:
// Remove duplicate AND/OR children
//
//---------------------------------------------------------------------------
CExpression *
CExpressionUtils::PexprDedupChildren(CMemoryPool *mp, CExpression *pexpr)
{
// protect against stack overflow during recursion
GPOS_CHECK_STACK_SIZE;
GPOS_ASSERT(nullptr != mp);
GPOS_ASSERT(nullptr != pexpr);
// recursively process children
const ULONG arity = pexpr->Arity();
CExpressionArray *pdrgpexprChildren = GPOS_NEW(mp) CExpressionArray(mp);
for (ULONG ul = 0; ul < arity; ul++)
{
CExpression *pexprChild = PexprDedupChildren(mp, (*pexpr)[ul]);
pdrgpexprChildren->Append(pexprChild);
}
if (CPredicateUtils::FAnd(pexpr) || CPredicateUtils::FOr(pexpr))
{
CExpressionArray *pdrgpexprNewChildren =
CUtils::PdrgpexprDedup(mp, pdrgpexprChildren);
pdrgpexprChildren->Release();
pdrgpexprChildren = pdrgpexprNewChildren;
// Check if we end with one child, return that child
if (1 == pdrgpexprChildren->Size())
{
CExpression *pexprChild = (*pdrgpexprChildren)[0];
pexprChild->AddRef();
pdrgpexprChildren->Release();
return pexprChild;
}
}
COperator *pop = pexpr->Pop();
pop->AddRef();
return GPOS_NEW(mp) CExpression(mp, pop, pdrgpexprChildren);
}
// EOF
相关信息
相关文章
greenplumn CExpressionFactorizer 源码
greenplumn CExpressionHandle 源码
greenplumn CExpressionPreprocessor 源码
greenplumn CHashedDistributions 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦