greenplumn CMDAccessorUtils 源码
greenplumn CMDAccessorUtils 代码
文件路径:/src/backend/gporca/libgpopt/src/mdcache/CMDAccessorUtils.cpp
//---------------------------------------------------------------------------
// Greenplum Database
// Copyright (C) 2012 EMC Corp.
//
// @filename:
// CMDAccessorUtils.cpp
//
// @doc:
// Implementation of the utility function associated with the metadata
// accessor
//---------------------------------------------------------------------------
#include "gpopt/mdcache/CMDAccessorUtils.h"
#include "gpos/base.h"
#include "gpos/error/CErrorHandlerStandard.h"
#include "gpos/error/CException.h"
#include "gpos/task/CAutoTraceFlag.h"
#include "gpopt/base/COptCtxt.h"
#include "gpopt/base/CUtils.h"
#include "naucrates/dxl/gpdb_types.h"
#include "naucrates/exception.h"
#include "naucrates/md/CMDIdGPDB.h"
#include "naucrates/md/IMDAggregate.h"
#include "naucrates/md/IMDFunction.h"
#include "naucrates/md/IMDScCmp.h"
#include "naucrates/md/IMDScalarOp.h"
using namespace gpmd;
using namespace gpos;
using namespace gpopt;
//---------------------------------------------------------------------------
// @function:
// CMDAccessorUtils::PstrWindowFuncName
//
// @doc:
// Return the name of the window operation
//
//---------------------------------------------------------------------------
const CWStringConst *
CMDAccessorUtils::PstrWindowFuncName(CMDAccessor *md_accessor, IMDId *mdid_func)
{
if (md_accessor->FAggWindowFunc(mdid_func))
{
const IMDAggregate *pmdagg = md_accessor->RetrieveAgg(mdid_func);
return pmdagg->Mdname().GetMDName();
}
const IMDFunction *pmdfunc = md_accessor->RetrieveFunc(mdid_func);
return pmdfunc->Mdname().GetMDName();
}
//---------------------------------------------------------------------------
// @function:
// CMDAccessorUtils::PmdidWindowReturnType
//
// @doc:
// Return the return type of the window function
//
//---------------------------------------------------------------------------
IMDId *
CMDAccessorUtils::PmdidWindowReturnType(CMDAccessor *md_accessor,
IMDId *mdid_func)
{
if (md_accessor->FAggWindowFunc(mdid_func))
{
const IMDAggregate *pmdagg = md_accessor->RetrieveAgg(mdid_func);
return pmdagg->GetResultTypeMdid();
}
const IMDFunction *pmdfunc = md_accessor->RetrieveFunc(mdid_func);
return pmdfunc->GetResultTypeMdid();
}
// Does a scalar comparison object between given types exists
BOOL
CMDAccessorUtils::FCmpExists(CMDAccessor *md_accessor, IMDId *left_mdid,
IMDId *right_mdid, IMDType::ECmpType cmp_type)
{
GPOS_ASSERT(nullptr != md_accessor);
GPOS_ASSERT(nullptr != left_mdid);
GPOS_ASSERT(nullptr != left_mdid);
GPOS_ASSERT(IMDType::EcmptOther > cmp_type);
GPOS_TRY
{
(void) GetScCmpMdid(md_accessor, left_mdid, right_mdid, cmp_type);
return true;
}
GPOS_CATCH_EX(ex)
{
if (GPOS_MATCH_EX(ex, gpdxl::ExmaMD, gpdxl::ExmiMDCacheEntryNotFound))
{
GPOS_RESET_EX;
return false;
}
GPOS_RETHROW(ex);
}
GPOS_CATCH_END;
}
// Get the mdid of the scalar comparison between the given types.
// Throws an exception if no such comparison exists! Use
// CMDAccessorUtils::FCmpExists() to check that before calling this function.
IMDId *
CMDAccessorUtils::GetScCmpMdid(CMDAccessor *md_accessor, IMDId *left_mdid,
IMDId *right_mdid, IMDType::ECmpType cmp_type)
{
GPOS_ASSERT(nullptr != md_accessor);
GPOS_ASSERT(nullptr != left_mdid);
GPOS_ASSERT(nullptr != left_mdid);
GPOS_ASSERT(IMDType::EcmptOther > cmp_type);
IMDId *sc_cmp_mdid;
// if the left & right are the same, first check the MDType
if (left_mdid->Equals(right_mdid))
{
const IMDType *pmdtypeLeft = md_accessor->RetrieveType(left_mdid);
sc_cmp_mdid = pmdtypeLeft->GetMdidForCmpType(cmp_type);
if (IMDId::IsValid(sc_cmp_mdid))
{
return sc_cmp_mdid;
}
}
// then check for an explicit operator
sc_cmp_mdid =
md_accessor->Pmdsccmp(left_mdid, right_mdid, cmp_type)->MdIdOp();
// either sc_cmp_mdid is valid or an exception was raised during lookup
GPOS_ASSERT(IMDId::IsValid(sc_cmp_mdid));
return sc_cmp_mdid;
}
// check is a comparison between given types or a comparison after casting one
// side to an another exists
BOOL
CMDAccessorUtils::FCmpOrCastedCmpExists(IMDId *left_mdid, IMDId *right_mdid,
IMDType::ECmpType cmp_type)
{
CMDAccessor *md_accessor = COptCtxt::PoctxtFromTLS()->Pmda();
GPOS_ASSERT(nullptr != md_accessor);
GPOS_ASSERT(nullptr != left_mdid);
GPOS_ASSERT(nullptr != left_mdid);
GPOS_ASSERT(IMDType::EcmptOther > cmp_type);
GPOS_TRY
{
(void) CMDAccessorUtils::GetScCmpMdIdConsiderCasts(
md_accessor, left_mdid, right_mdid, cmp_type);
return true;
}
GPOS_CATCH_EX(ex)
{
if (GPOS_MATCH_EX(ex, gpdxl::ExmaMD, gpdxl::ExmiMDCacheEntryNotFound))
{
GPOS_RESET_EX;
return false;
}
GPOS_RETHROW(ex);
}
GPOS_CATCH_END;
}
// return the scalar comparison operator id between the two types
// Throws an exception if no such comparison exists! Use
// CMDAccessorUtils::FCmpOrCastedCmpExists() to check that before calling this
// function.
IMDId *
CMDAccessorUtils::GetScCmpMdIdConsiderCasts(CMDAccessor *md_accessor,
IMDId *left_mdid, IMDId *right_mdid,
IMDType::ECmpType cmp_type)
{
GPOS_ASSERT(nullptr != left_mdid);
GPOS_ASSERT(nullptr != right_mdid);
GPOS_ASSERT(IMDType::EcmptOther > cmp_type);
// left op right
if (CMDAccessorUtils::FCmpExists(md_accessor, left_mdid, right_mdid,
cmp_type))
{
return CMDAccessorUtils::GetScCmpMdid(md_accessor, left_mdid,
right_mdid, cmp_type);
}
// left op cast(right)
if (CMDAccessorUtils::FCmpExists(md_accessor, left_mdid, left_mdid,
cmp_type) &&
CMDAccessorUtils::FCastExists(md_accessor, right_mdid, left_mdid))
{
return CMDAccessorUtils::GetScCmpMdid(md_accessor, left_mdid, left_mdid,
cmp_type);
}
// cast(left) op right
if (CMDAccessorUtils::FCmpExists(md_accessor, right_mdid, right_mdid,
cmp_type) &&
CMDAccessorUtils::FCastExists(md_accessor, left_mdid, right_mdid))
{
return CMDAccessorUtils::GetScCmpMdid(md_accessor, right_mdid,
right_mdid, cmp_type);
}
// call to raise an error on non-comparable data types
return CMDAccessorUtils::GetScCmpMdid(md_accessor, left_mdid, right_mdid,
cmp_type);
}
IMDId *
CMDAccessorUtils::GetScCmpMdIdConsiderCasts(CMDAccessor *md_accessor,
CExpression *pexprLeft,
CExpression *pexprRight,
IMDType::ECmpType cmp_type)
{
IMDId *left_mdid = CScalar::PopConvert(pexprLeft->Pop())->MdidType();
IMDId *right_mdid = CScalar::PopConvert(pexprRight->Pop())->MdidType();
return CMDAccessorUtils::GetScCmpMdIdConsiderCasts(md_accessor, left_mdid,
right_mdid, cmp_type);
}
void
CMDAccessorUtils::ApplyCastsForScCmp(CMemoryPool *mp, CMDAccessor *md_accessor,
CExpression *&pexprLeft,
CExpression *&pexprRight, IMDId *op_mdid)
{
IMDId *left_mdid = CScalar::PopConvert(pexprLeft->Pop())->MdidType();
IMDId *right_mdid = CScalar::PopConvert(pexprRight->Pop())->MdidType();
const IMDScalarOp *op = md_accessor->RetrieveScOp(op_mdid);
IMDId *op_left_mdid = op->GetLeftMdid();
IMDId *op_right_mdid = op->GetRightMdid();
// Determine if casts need to be added (following is a description of what to
// do on the left side, for the right side it's analogous):
// GetScCmpMdIdConsiderCasts() has determined that
// a) there is a comparison operator with matching input types (left_mdid equals
// op_left_mdid); or
//
// b) there is a common type t (either left_mdid or right_mdid) such that we
// can cast both left and right side to t, if needed, and that type t has a
// valid comparison operator. Note that the input types of that operator
// may or may not be equal to t. Note that we assume in this case that
// casts from t to the operators's input types "op_left_mdid" and
// "op_right_mdid" exist, otherwise this cannot be used to compare to
// values of type t (proposition A). Unfortunately, when we reach here, we
// don't know whether t is "left_mdid" or "right_mdid".
//
// Case b) may require one or two casts. If a direct cast from "left_mdid"
// to "op_left_mdid" exists, we can use that directly. Otherwise,
// GetScCmpMdIdConsiderCasts() must have picked "right_mdid" as the common
// type t and it will have established that a cast from "left_mdid" to
// "right_mdid" must exist (proposition B). We know that we can cast from
// "left_mdid" to "right_mdid" and then, using the assumption above, from
// "right_mdid" to "op_left_mdid".
if (!op_left_mdid->Equals(left_mdid))
{
// We are in case b).
if (CMDAccessorUtils::FCastExists(md_accessor, left_mdid, op_left_mdid))
{
// The simple case, a direct cast exists
pexprLeft =
CUtils::PexprCast(mp, md_accessor, pexprLeft, op_left_mdid);
}
else
{
// validate proposition B
GPOS_ASSERT(CMDAccessorUtils::FCastExists(md_accessor, left_mdid,
right_mdid));
// Create the two casts described above, first from left to right type
pexprLeft =
CUtils::PexprCast(mp, md_accessor, pexprLeft, right_mdid);
if (!right_mdid->Equals(op_left_mdid))
{
// validate proposition A
GPOS_ASSERT(CMDAccessorUtils::FCastExists(
md_accessor, right_mdid, op_left_mdid));
// and then from right type to the type the comparison operator expects
pexprLeft =
CUtils::PexprCast(mp, md_accessor, pexprLeft, op_left_mdid);
}
}
}
if (!op_right_mdid->Equals(right_mdid))
{
// We are in case b).
if (CMDAccessorUtils::FCastExists(md_accessor, right_mdid,
op_right_mdid))
{
// The simple case, a direct cast exists
pexprRight =
CUtils::PexprCast(mp, md_accessor, pexprRight, op_right_mdid);
}
else
{
// validate proposition B
GPOS_ASSERT(CMDAccessorUtils::FCastExists(md_accessor, right_mdid,
left_mdid));
// Create the two casts described above, first from right to left type
pexprRight =
CUtils::PexprCast(mp, md_accessor, pexprRight, left_mdid);
if (!left_mdid->Equals(op_right_mdid))
{
// validate proposition A
GPOS_ASSERT(CMDAccessorUtils::FCastExists(
md_accessor, left_mdid, op_right_mdid));
// and then from left type to the type the comparison operator expects
pexprRight = CUtils::PexprCast(mp, md_accessor, pexprRight,
op_right_mdid);
}
}
}
}
//---------------------------------------------------------------------------
// @function:
// CMDAccessorUtils::FCastExists
//
// @doc:
// Does if a cast object between given source and destination types exists
//
//---------------------------------------------------------------------------
BOOL
CMDAccessorUtils::FCastExists(CMDAccessor *md_accessor, IMDId *mdid_src,
IMDId *mdid_dest)
{
GPOS_ASSERT(nullptr != md_accessor);
GPOS_ASSERT(nullptr != mdid_src);
GPOS_ASSERT(nullptr != mdid_dest);
GPOS_TRY
{
(void) md_accessor->Pmdcast(mdid_src, mdid_dest);
return true;
}
GPOS_CATCH_EX(ex)
{
if (GPOS_MATCH_EX(ex, gpdxl::ExmaMD, gpdxl::ExmiMDCacheEntryNotFound))
{
GPOS_RESET_EX;
return false;
}
GPOS_RETHROW(ex);
}
GPOS_CATCH_END;
}
//---------------------------------------------------------------------------
// @function:
// CUtils::FScalarOpReturnsNullOnNullInput
//
// @doc:
// Does scalar operator return NULL on NULL input?
//
//---------------------------------------------------------------------------
BOOL
CMDAccessorUtils::FScalarOpReturnsNullOnNullInput(CMDAccessor *md_accessor,
IMDId *mdid_op)
{
GPOS_ASSERT(nullptr != md_accessor);
if (nullptr == mdid_op || !mdid_op->IsValid())
{
// invalid mdid
return false;
}
GPOS_TRY
{
const IMDScalarOp *md_scalar_op = md_accessor->RetrieveScOp(mdid_op);
return md_scalar_op->ReturnsNullOnNullInput();
}
GPOS_CATCH_EX(ex)
{
if (GPOS_MATCH_EX(ex, gpdxl::ExmaMD, gpdxl::ExmiMDCacheEntryNotFound))
{
GPOS_RESET_EX;
return false;
}
GPOS_RETHROW(ex);
}
GPOS_CATCH_END;
return false;
}
//---------------------------------------------------------------------------
// @function:
// CUtils::FBoolType
//
// @doc:
// Return True if passed mdid is for BOOL type
//
//---------------------------------------------------------------------------
BOOL
CMDAccessorUtils::FBoolType(CMDAccessor *md_accessor, IMDId *mdid_type)
{
GPOS_ASSERT(nullptr != md_accessor);
if (nullptr != mdid_type && mdid_type->IsValid())
{
return (IMDType::EtiBool ==
md_accessor->RetrieveType(mdid_type)->GetDatumType());
}
return false;
}
//---------------------------------------------------------------------------
// @function:
// CMDAccessorUtils::FCommutativeScalarOp
//
// @doc:
// Is scalar operator commutative? This can be used with ScalarOp and ScalarCmp
//
//---------------------------------------------------------------------------
BOOL
CMDAccessorUtils::FCommutativeScalarOp(CMDAccessor *md_accessor, IMDId *mdid_op)
{
GPOS_ASSERT(nullptr != md_accessor);
GPOS_ASSERT(nullptr != mdid_op);
const IMDScalarOp *md_scalar_op = md_accessor->RetrieveScOp(mdid_op);
return mdid_op->Equals(md_scalar_op->GetCommuteOpMdid());
}
// EOF
相关信息
相关文章
0
赞