greenplumn CScalar 代码
文件路径:/src/backend/gporca/libgpopt/src/operators/CScalar.cpp
/---------------------------------------------------------------------------
/ Greenplum Database
/ Copyright (C) 2009 Greenplum, Inc.
/
/ @filename:
/ CScalar.cpp
/
/ @doc:
/ Implementation of base class of scalar operators
/---------------------------------------------------------------------------
#include "gpopt/operators/CScalar.h"
#include "gpos/base.h"
#include "gpopt/base/CDrvdPropScalar.h"
#include "gpopt/operators/CExpression.h"
#include "gpopt/operators/CExpressionHandle.h"
using namespace gpopt;
/---------------------------------------------------------------------------
/ @function:
/ CScalar::PdpCreate
/
/ @doc:
/ Create base container of derived properties
/
/---------------------------------------------------------------------------
CDrvdProp *
CScalar::PdpCreate(CMemoryPool *mp) const
{
return GPOS_NEW(mp) CDrvdPropScalar(mp);
}
/---------------------------------------------------------------------------
/ @function:
/ CScalar::PrpCreate
/
/ @doc:
/ Create base container of required properties
/
/---------------------------------------------------------------------------
CReqdProp *
CScalar::PrpCreate(CMemoryPool * / mp
) const
{
GPOS_ASSERT(!"Cannot compute required properties on scalar");
return nullptr;
}
/---------------------------------------------------------------------------
/ @function:
/ CScalar::FHasSubquery
/
/ @doc:
/ Derive existence of subqueries from expression handle
/
/---------------------------------------------------------------------------
BOOL
CScalar::FHasSubquery(CExpressionHandle &exprhdl)
{
/ if operator is a subquery, return immediately
if (CUtils::FSubquery(exprhdl.Pop()))
{
return true;
}
/ otherwise, iterate over scalar children
const ULONG arity = exprhdl.Arity();
for (ULONG i = 0; i < arity; i++)
{
if (exprhdl.FScalarChild(i))
{
if (exprhdl.DeriveHasSubquery(i))
{
return true;
}
}
}
return false;
}
/---------------------------------------------------------------------------
/ @function:
/ CScalar::EberConjunction
/
/ @doc:
/ Perform conjunction of boolean evaluation results
/
/---------------------------------------------------------------------------
CScalar::EBoolEvalResult
CScalar::EberConjunction(ULongPtrArray *pdrgpulChildren)
{
GPOS_ASSERT(nullptr != pdrgpulChildren);
GPOS_ASSERT(1 < pdrgpulChildren->Size());
/ Here are the rules:
/ - if any child is FALSE, the result is FALSE
/ - else if all children are TRUE, the result is TRUE
/ - else if all children are ANY or TRUE, the result is ANY
/ - else if all children are NULL or TRUE, the result is NULL
/ - else (a mix of TRUE, ANY and NULL), the result is NotTrue
BOOL fAllChildrenTrue = true;
BOOL fAllChildrenAnyOrTrue = true;
BOOL fAllChildrenNullOrTrue = true;
const ULONG ulChildren = pdrgpulChildren->Size();
for (ULONG ul = 0; ul < ulChildren; ul++)
{
EBoolEvalResult eber = (EBoolEvalResult) * ((*pdrgpulChildren)[ul]);
if (EberFalse == eber)
{
return EberFalse;
}
fAllChildrenTrue = fAllChildrenTrue && (EberTrue == eber);
fAllChildrenAnyOrTrue =
fAllChildrenAnyOrTrue && (EberAny == eber || EberTrue == eber);
fAllChildrenNullOrTrue =
fAllChildrenNullOrTrue && (EberNull == eber || EberTrue == eber);
}
if (fAllChildrenTrue)
{
/ conjunction of all True children gives True
return EberTrue;
}
if (fAllChildrenAnyOrTrue)
{
return EberAny;
}
if (fAllChildrenNullOrTrue)
{
return EberNull;
}
return EberNotTrue;
}
/---------------------------------------------------------------------------
/ @function:
/ CScalar::EberDisjunction
/
/ @doc:
/ Perform disjunction of child boolean evaluation results
/
/---------------------------------------------------------------------------
CScalar::EBoolEvalResult
CScalar::EberDisjunction(ULongPtrArray *pdrgpulChildren)
{
GPOS_ASSERT(nullptr != pdrgpulChildren);
GPOS_ASSERT(1 < pdrgpulChildren->Size());
BOOL fAllChildrenFalse = true;
BOOL fNullChild = false;
BOOL fNotTrueChild = false;
BOOL fAnyChild = false;
const ULONG ulChildren = pdrgpulChildren->Size();
for (ULONG ul = 0; ul < ulChildren; ul++)
{
EBoolEvalResult eber = (EBoolEvalResult) * ((*pdrgpulChildren)[ul]);
switch (eber)
{
case EberTrue:
/ if any child is True, disjunction returns True
return EberTrue;
case EberNull:
/ if a child is NULL, we cannot return here yet since another child
/ might be True, which yields the disjunction to True
fNullChild = true;
break;
case EberNotTrue:
fNotTrueChild = true;
break;
case EberAny:
fAnyChild = true;
break;
default:
break;
}
fAllChildrenFalse = fAllChildrenFalse && (EberFalse == eber);
}
if (fAllChildrenFalse)
{
/ disjunction of all False children gives False
return EberFalse;
}
if (fAnyChild)
{
/ at least one "any" child yields disjunction Unknown
/ for example,
/ (Any OR False) = Any
/ (Any OR Null) = Any (really NULL or TRUE, FALSE is excluded)
return EberAny;
}
if (fNotTrueChild)
{
/ a NotTrue child, with zero or more NULLs or FALSEs yields NotTrue
/ (NotTrue OR False) = NotTrue
/ (NotTrue OR Null) = NotTrue
return EberNotTrue;
}
if (fNullChild)
{
/ children are either False or Null, disjunction returns Null
return EberNull;
}
return EberAny;
}
/---------------------------------------------------------------------------
/ @function:
/ CScalar::EberNullOnAnyNullChild
/
/ @doc:
/ Return Null if any child is Null, return Any otherwise
/
/---------------------------------------------------------------------------
CScalar::EBoolEvalResult
CScalar::EberNullOnAnyNullChild(ULongPtrArray *pdrgpulChildren)
{
GPOS_ASSERT(nullptr != pdrgpulChildren);
const ULONG ulChildren = pdrgpulChildren->Size();
for (ULONG ul = 0; ul < ulChildren; ul++)
{
EBoolEvalResult eber = (EBoolEvalResult) * ((*pdrgpulChildren)[ul]);
if (EberNull == eber)
{
return EberNull;
}
}
return EberAny;
}
/---------------------------------------------------------------------------
/ @function:
/ CScalar::EberNullOnAllNullChildren
/
/ @doc:
/ Return Null evaluation result if all children results are Null
/
/---------------------------------------------------------------------------
CScalar::EBoolEvalResult
CScalar::EberNullOnAllNullChildren(ULongPtrArray *pdrgpulChildren)
{
GPOS_ASSERT(nullptr != pdrgpulChildren);
const ULONG ulChildren = pdrgpulChildren->Size();
for (ULONG ul = 0; ul < ulChildren; ul++)
{
EBoolEvalResult eber = (EBoolEvalResult) * ((*pdrgpulChildren)[ul]);
if (EberNull != eber)
{
return EberAny;
}
}
return EberNull;
}
/---------------------------------------------------------------------------
/ @function:
/ CScalar::EberEvaluate
/
/ @doc:
/ Perform boolean evaluation of the given expression
/
/---------------------------------------------------------------------------
CScalar::EBoolEvalResult
CScalar::EberEvaluate(CMemoryPool *mp, CExpression *pexprScalar)
{
GPOS_CHECK_STACK_SIZE;
GPOS_ASSERT(nullptr != pexprScalar);
COperator *pop = pexprScalar->Pop();
GPOS_ASSERT(pop->FScalar());
const ULONG arity = pexprScalar->Arity();
ULongPtrArray *pdrgpulChildren = GPOS_NEW(mp) ULongPtrArray(mp);
if (!CUtils::FSubquery(pop))
{
/ do not recurse into subqueries
for (ULONG ul = 0; ul < arity; ul++)
{
CExpression *pexprChild = (*pexprScalar)[ul];
EBoolEvalResult eberChild = EberEvaluate(mp, pexprChild);
pdrgpulChildren->Append(GPOS_NEW(mp) ULONG(eberChild));
}
}
EBoolEvalResult eber = PopConvert(pop)->Eber(pdrgpulChildren);
CRefCount::SafeRelease(pdrgpulChildren);
return eber;
}
/---------------------------------------------------------------------------
/ @function:
/ CScalar::FHasNonScalarFunction
/
/ @doc:
/ Derive existence of non-scalar functions from expression handle
/
/---------------------------------------------------------------------------
BOOL
CScalar::FHasNonScalarFunction(CExpressionHandle &exprhdl)
{
/ if operator is a subquery, return immediately
if (CUtils::FSubquery(exprhdl.Pop()))
{
return false;
}
/ otherwise, iterate over scalar children
const ULONG arity = exprhdl.Arity();
for (ULONG i = 0; i < arity; i++)
{
if (exprhdl.FScalarChild(i))
{
if (exprhdl.DeriveHasNonScalarFunction(i))
{
return true;
}
}
}
return false;
}
/---------------------------------------------------------------------------
/ @function:
/ CScalar::PdrgppartconDeriveCombineScalar
/
/ @doc:
/ Combine partition consumer arrays of all scalar children
/
/---------------------------------------------------------------------------
CPartInfo *
CScalar::PpartinfoDeriveCombineScalar(CMemoryPool *mp,
CExpressionHandle &exprhdl)
{
const ULONG arity = exprhdl.Arity();
GPOS_ASSERT(0 < arity);
CPartInfo *ppartinfo = GPOS_NEW(mp) CPartInfo(mp);
for (ULONG ul = 0; ul < arity; ul++)
{
if (exprhdl.FScalarChild(ul))
{
CPartInfo *ppartinfoChild = exprhdl.DeriveScalarPartitionInfo(ul);
GPOS_ASSERT(nullptr != ppartinfoChild);
CPartInfo *ppartinfoCombined =
CPartInfo::PpartinfoCombine(mp, ppartinfo, ppartinfoChild);
ppartinfo->Release();
ppartinfo = ppartinfoCombined;
}
}
return ppartinfo;
}
BOOL
CScalar::FHasScalarArrayCmp(CExpressionHandle &exprhdl)
{
/ if operator is a ScalarArrayCmp, return immediately
if (COperator::EopScalarArrayCmp == exprhdl.Pop()->Eopid())
{
return true;
}
/ otherwise, iterate over scalar children
const ULONG arity = exprhdl.Arity();
for (ULONG i = 0; i < arity; i++)
{
if (exprhdl.FScalarChild(i))
{
if (exprhdl.DeriveHasScalarArrayCmp(i))
{
return true;
}
}
}
return false;
}
/ EOF
相关信息
相关文章
greenplumn CExpressionFactorizer 源码
greenplumn CExpressionHandle 源码
greenplumn CExpressionPreprocessor 源码
greenplumn CExpressionUtils 源码