greenplumn CScalar 源码
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 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
7、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦