blob: 33dc68662f2e95466a948158e135fe617e7203dd [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
//---------------------------------------------------------------------------
// @filename:
// CTranslatorDXLToScalar.cpp
//
// @doc:
// Implementation of the methods used to translate DXL Scalar Node into
// GPDB's Expr.
//
// @test:
//---------------------------------------------------------------------------
#include "postgres.h"
#include "nodes/plannodes.h"
#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
#include "nodes/makefuncs.h"
#include "utils/datum.h"
#include "gpos/base.h"
#include "gpopt/mdcache/CMDAccessor.h"
#include "gpopt/mdcache/CMDAccessorUtils.h"
#include "gpopt/base/COptCtxt.h"
#include "gpopt/translate/CTranslatorDXLToScalar.h"
#include "gpopt/translate/CTranslatorDXLToPlStmt.h"
#include "gpopt/translate/CTranslatorUtils.h"
#include "gpopt/translate/CMappingColIdVarPlStmt.h"
#include "naucrates/dxl/CDXLUtils.h"
#include "naucrates/dxl/operators/CDXLDatumBool.h"
#include "naucrates/dxl/operators/CDXLDatumInt2.h"
#include "naucrates/dxl/operators/CDXLDatumInt4.h"
#include "naucrates/dxl/operators/CDXLDatumInt8.h"
#include "naucrates/dxl/operators/CDXLDatumGeneric.h"
#include "naucrates/dxl/operators/CDXLDatumOid.h"
#include "naucrates/dxl/xml/dxltokens.h"
#include "naucrates/md/IMDAggregate.h"
#include "naucrates/md/IMDFunction.h"
#include "naucrates/md/IMDScalarOp.h"
#include "naucrates/md/IMDTypeBool.h"
#include "gpopt/gpdbwrappers.h"
using namespace gpdxl;
using namespace gpos;
using namespace gpopt;
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::CTranslatorDXLToScalar
//
// @doc:
// Constructor
//---------------------------------------------------------------------------
CTranslatorDXLToScalar::CTranslatorDXLToScalar
(
IMemoryPool *pmp,
CMDAccessor *pmda,
ULONG ulSegments
)
:
m_pmp(pmp),
m_pmda(pmda),
m_fHasSubqueries(false),
m_ulSegments(ulSegments)
{
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PexprFromDXLNodeScalar
//
// @doc:
// Translates a DXL scalar expression into a GPDB Expression node
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PexprFromDXLNodeScalar
(
const CDXLNode *pdxln,
CMappingColIdVar *pmapcidvar
)
{
STranslatorElem rgTranslators[] =
{
{EdxlopScalarIdent, &CTranslatorDXLToScalar::PexprFromDXLNodeScId},
{EdxlopScalarCmp, &CTranslatorDXLToScalar::PopexprFromDXLNodeScCmp},
{EdxlopScalarDistinct, &CTranslatorDXLToScalar::PdistexprFromDXLNodeScDistinctComp},
{EdxlopScalarOpExpr, &CTranslatorDXLToScalar::PopexprFromDXLNodeScOpExpr},
{EdxlopScalarArrayComp, &CTranslatorDXLToScalar::PstrarrayopexprFromDXLNodeScArrayComp},
{EdxlopScalarCoalesce, &CTranslatorDXLToScalar::PcoalesceFromDXLNodeScCoalesce},
{EdxlopScalarMinMax, &CTranslatorDXLToScalar::PminmaxFromDXLNodeScMinMax},
{EdxlopScalarConstValue, &CTranslatorDXLToScalar::PconstFromDXLNodeScConst},
{EdxlopScalarBoolExpr, &CTranslatorDXLToScalar::PboolexprFromDXLNodeScBoolExpr},
{EdxlopScalarBooleanTest, &CTranslatorDXLToScalar::PbooleantestFromDXLNodeScBooleanTest},
{EdxlopScalarNullTest, &CTranslatorDXLToScalar::PnulltestFromDXLNodeScNullTest},
{EdxlopScalarNullIf, &CTranslatorDXLToScalar::PnullifFromDXLNodeScNullIf},
{EdxlopScalarIfStmt, &CTranslatorDXLToScalar::PcaseexprFromDXLNodeScIfStmt},
{EdxlopScalarSwitch, &CTranslatorDXLToScalar::PcaseexprFromDXLNodeScSwitch},
{EdxlopScalarCaseTest, &CTranslatorDXLToScalar::PcasetestexprFromDXLNodeScCaseTest},
{EdxlopScalarFuncExpr, &CTranslatorDXLToScalar::PfuncexprFromDXLNodeScFuncExpr},
{EdxlopScalarAggref, &CTranslatorDXLToScalar::PaggrefFromDXLNodeScAggref},
{EdxlopScalarWindowRef, &CTranslatorDXLToScalar::PwindowrefFromDXLNodeScWindowRef},
{EdxlopScalarCast, &CTranslatorDXLToScalar::PrelabeltypeFromDXLNodeScCast},
{EdxlopScalarCoerceToDomain, &CTranslatorDXLToScalar::PcoerceFromDXLNodeScCoerce},
{EdxlopScalarInitPlan, &CTranslatorDXLToScalar::PparamFromDXLNodeScInitPlan},
{EdxlopScalarSubPlan, &CTranslatorDXLToScalar::PsubplanFromDXLNodeScSubPlan},
{EdxlopScalarArray, &CTranslatorDXLToScalar::PexprArray},
{EdxlopScalarArrayRef, &CTranslatorDXLToScalar::PexprArrayRef},
{EdxlopScalarDMLAction, &CTranslatorDXLToScalar::PexprDMLAction},
{EdxlopScalarPartOid, &CTranslatorDXLToScalar::PexprPartOid},
{EdxlopScalarPartDefault, &CTranslatorDXLToScalar::PexprPartDefault},
{EdxlopScalarPartBound, &CTranslatorDXLToScalar::PexprPartBound},
{EdxlopScalarPartBoundInclusion, &CTranslatorDXLToScalar::PexprPartBoundInclusion},
{EdxlopScalarPartBoundOpen, &CTranslatorDXLToScalar::PexprPartBoundOpen},
};
const ULONG ulTranslators = GPOS_ARRAY_SIZE(rgTranslators);
GPOS_ASSERT(NULL != pdxln);
Edxlopid eopid = pdxln->Pdxlop()->Edxlop();
// find translator for the node type
PfPexpr pf = NULL;
for (ULONG ul = 0; ul < ulTranslators; ul++)
{
STranslatorElem elem = rgTranslators[ul];
if (eopid == elem.eopid)
{
pf = elem.pf;
break;
}
}
if (NULL == pf)
{
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtConversion, pdxln->Pdxlop()->PstrOpName()->Wsz());
}
return (this->*pf)(pdxln, pmapcidvar);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PcaseexprFromDXLNodeScIfStmt
//
// @doc:
// Translates a DXL scalar if stmt into a GPDB CaseExpr node
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PcaseexprFromDXLNodeScIfStmt
(
const CDXLNode *pdxlnIfStmt,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnIfStmt);
CDXLScalarIfStmt *pdxlopIfStmt = CDXLScalarIfStmt::PdxlopConvert(pdxlnIfStmt->Pdxlop());
CaseExpr *pcaseexpr = MakeNode(CaseExpr);
pcaseexpr->casetype = CMDIdGPDB::PmdidConvert(pdxlopIfStmt->PmdidResultType())->OidObjectId();
CDXLNode *pdxlnCurr = const_cast<CDXLNode*>(pdxlnIfStmt);
Expr *pexprElse = NULL;
// An If statment is of the format: IF <condition> <then> <else>
// The leaf else statment is the def result of the case statement
BOOL fLeafElseStatement = false;
while (!fLeafElseStatement)
{
if (3 != pdxlnCurr->UlArity())
{
GPOS_RAISE
(
gpdxl::ExmaDXL,
gpdxl::ExmiDXLIncorrectNumberOfChildren
);
return NULL;
}
Expr *pexprWhen = PexprFromDXLNodeScalar((*pdxlnCurr)[0], pmapcidvar);
Expr *pexprThen = PexprFromDXLNodeScalar((*pdxlnCurr)[1], pmapcidvar);
CaseWhen *pwhen = MakeNode(CaseWhen);
pwhen->expr = pexprWhen;
pwhen->result = pexprThen;
pcaseexpr->args = gpdb::PlAppendElement(pcaseexpr->args,pwhen);
if (EdxlopScalarIfStmt == (*pdxlnCurr)[2]->Pdxlop()->Edxlop())
{
pdxlnCurr = (*pdxlnCurr)[2];
}
else
{
fLeafElseStatement = true;
pexprElse = PexprFromDXLNodeScalar((*pdxlnCurr)[2], pmapcidvar);
}
}
pcaseexpr->defresult = pexprElse;
return (Expr *)pcaseexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PcaseexprFromDXLNodeScSwitch
//
// @doc:
// Translates a DXL scalar switch into a GPDB CaseExpr node
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PcaseexprFromDXLNodeScSwitch
(
const CDXLNode *pdxlnSwitch,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnSwitch);
CDXLScalarSwitch *pdxlop = CDXLScalarSwitch::PdxlopConvert(pdxlnSwitch->Pdxlop());
CaseExpr *pcaseexpr = MakeNode(CaseExpr);
pcaseexpr->casetype = CMDIdGPDB::PmdidConvert(pdxlop->PmdidType())->OidObjectId();
// translate arg child
pcaseexpr->arg = PexprFromDXLNodeScalar((*pdxlnSwitch)[0], pmapcidvar);
GPOS_ASSERT(NULL != pcaseexpr->arg);
const ULONG ulArity = pdxlnSwitch->UlArity();
GPOS_ASSERT(1 < ulArity);
for (ULONG ul = 1; ul < ulArity; ul++)
{
const CDXLNode *pdxlnChild = (*pdxlnSwitch)[ul];
if (EdxlopScalarSwitchCase == pdxlnChild->Pdxlop()->Edxlop())
{
CaseWhen *pwhen = MakeNode(CaseWhen);
pwhen->expr = PexprFromDXLNodeScalar((*pdxlnChild)[0], pmapcidvar);
pwhen->result = PexprFromDXLNodeScalar((*pdxlnChild)[1], pmapcidvar);
pcaseexpr->args = gpdb::PlAppendElement(pcaseexpr->args, pwhen);
}
else
{
// default return value
GPOS_ASSERT(ul == ulArity - 1);
pcaseexpr->defresult = PexprFromDXLNodeScalar((*pdxlnSwitch)[ul], pmapcidvar);
}
}
return (Expr *)pcaseexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PcasetestexprFromDXLNodeScCaseTest
//
// @doc:
// Translates a DXL scalar case test into a GPDB CaseTestExpr node
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PcasetestexprFromDXLNodeScCaseTest
(
const CDXLNode *pdxlnCaseTest,
CMappingColIdVar * //pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnCaseTest);
CDXLScalarCaseTest *pdxlop = CDXLScalarCaseTest::PdxlopConvert(pdxlnCaseTest->Pdxlop());
CaseTestExpr *pcasetestexpr = MakeNode(CaseTestExpr);
pcasetestexpr->typeId = CMDIdGPDB::PmdidConvert(pdxlop->PmdidType())->OidObjectId();
pcasetestexpr->typeMod = -1;
return (Expr *)pcasetestexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PopexprFromDXLNodeScOpExpr
//
// @doc:
// Translates a DXL scalar opexpr into a GPDB OpExpr node
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PopexprFromDXLNodeScOpExpr
(
const CDXLNode *pdxlnOpExpr,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnOpExpr);
CDXLScalarOpExpr *pdxlopOpExpr = CDXLScalarOpExpr::PdxlopConvert(pdxlnOpExpr->Pdxlop());
OpExpr *popexpr = MakeNode(OpExpr);
popexpr->opno = CMDIdGPDB::PmdidConvert(pdxlopOpExpr->Pmdid())->OidObjectId();
const IMDScalarOp *pmdscop = m_pmda->Pmdscop(pdxlopOpExpr->Pmdid());
popexpr->opfuncid = CMDIdGPDB::PmdidConvert(pmdscop->PmdidFunc())->OidObjectId();
IMDId *pmdidReturnType = pdxlopOpExpr->PmdidReturnType();
if (NULL != pmdidReturnType)
{
popexpr->opresulttype = CMDIdGPDB::PmdidConvert(pmdidReturnType)->OidObjectId();
}
else
{
popexpr->opresulttype = OidFunctionReturnType(pmdscop->PmdidFunc());
}
const IMDFunction *pmdfunc = m_pmda->Pmdfunc(pmdscop->PmdidFunc());
popexpr->opretset = pmdfunc->FReturnsSet();
GPOS_ASSERT(1 == pdxlnOpExpr->UlArity() || 2 == pdxlnOpExpr->UlArity());
// translate children
popexpr->args = PlistTranslateScalarChildren(popexpr->args, pdxlnOpExpr, pmapcidvar);
return (Expr *)popexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PstrarrayopexprFromDXLNodeScArrayComp
//
// @doc:
// Translates a CDXLScalarArrayComp into a GPDB ScalarArrayOpExpr
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PstrarrayopexprFromDXLNodeScArrayComp
(
const CDXLNode *pdxlnArrayComp,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnArrayComp);
CDXLScalarArrayComp *pdxlopArrayComp = CDXLScalarArrayComp::PdxlopConvert(pdxlnArrayComp->Pdxlop());
ScalarArrayOpExpr *parrayopexpr = MakeNode(ScalarArrayOpExpr);
parrayopexpr->opno = CMDIdGPDB::PmdidConvert(pdxlopArrayComp->Pmdid())->OidObjectId();
const IMDScalarOp *pmdscop = m_pmda->Pmdscop(pdxlopArrayComp->Pmdid());
parrayopexpr->opfuncid = CMDIdGPDB::PmdidConvert(pmdscop->PmdidFunc())->OidObjectId();
switch(pdxlopArrayComp->Edxlarraycomptype())
{
case Edxlarraycomptypeany:
parrayopexpr->useOr = true;
break;
case Edxlarraycomptypeall:
parrayopexpr->useOr = false;
break;
default:
GPOS_RAISE
(
gpdxl::ExmaDXL,
gpdxl::ExmiPlStmt2DXLConversion,
GPOS_WSZ_LIT("Scalar Array Comparison: Specified operator type is invalid")
);
}
// translate left and right child
GPOS_ASSERT(2 == pdxlnArrayComp->UlArity());
CDXLNode *pdxlnLeft = (*pdxlnArrayComp)[EdxlsccmpIndexLeft];
CDXLNode *pdxlnRight = (*pdxlnArrayComp)[EdxlsccmpIndexRight];
Expr *pexprLeft = PexprFromDXLNodeScalar(pdxlnLeft, pmapcidvar);
Expr *pexprRight = PexprFromDXLNodeScalar(pdxlnRight, pmapcidvar);
parrayopexpr->args = ListMake2(pexprLeft, pexprRight);
return (Expr *)parrayopexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PdistexprFromDXLNodeScDistinctComp
//
// @doc:
// Translates a DXL scalar distinct comparison into a GPDB DistinctExpr node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PdistexprFromDXLNodeScDistinctComp
(
const CDXLNode *pdxlnDistComp,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnDistComp);
CDXLScalarDistinctComp *pdxlop = CDXLScalarDistinctComp::PdxlopConvert(pdxlnDistComp->Pdxlop());
DistinctExpr *pdistexpr = MakeNode(DistinctExpr);
pdistexpr->opno = CMDIdGPDB::PmdidConvert(pdxlop->Pmdid())->OidObjectId();
const IMDScalarOp *pmdscop = m_pmda->Pmdscop(pdxlop->Pmdid());
pdistexpr->opfuncid = CMDIdGPDB::PmdidConvert(pmdscop->PmdidFunc())->OidObjectId();
pdistexpr->opresulttype = OidFunctionReturnType(pmdscop->PmdidFunc());
// translate left and right child
GPOS_ASSERT(2 == pdxlnDistComp->UlArity());
CDXLNode *pdxlnLeft = (*pdxlnDistComp)[EdxlscdistcmpIndexLeft];
CDXLNode *pdxlnRight = (*pdxlnDistComp)[EdxlscdistcmpIndexRight];
Expr *pexprLeft = PexprFromDXLNodeScalar(pdxlnLeft, pmapcidvar);
Expr *pexprRight = PexprFromDXLNodeScalar(pdxlnRight, pmapcidvar);
pdistexpr->args = ListMake2(pexprLeft, pexprRight);
return (Expr *)pdistexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PaggrefFromDXLNodeScAggref
//
// @doc:
// Translates a DXL scalar aggref into a GPDB Aggref node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PaggrefFromDXLNodeScAggref
(
const CDXLNode *pdxlnAggref,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnAggref);
CDXLScalarAggref *pdxlop = CDXLScalarAggref::PdxlopConvert(pdxlnAggref->Pdxlop());
Aggref *paggref = MakeNode(Aggref);
paggref->aggfnoid = CMDIdGPDB::PmdidConvert(pdxlop->PmdidAgg())->OidObjectId();
paggref->aggdistinct = pdxlop->FDistinct();
paggref->agglevelsup = 0;
paggref->location = -1;
CMDIdGPDB *pmdidAgg = CTranslatorUtils::PmdidWithVersion(m_pmp, paggref->aggfnoid);
const IMDAggregate *pmdagg = m_pmda->Pmdagg(pmdidAgg);
pmdidAgg->Release();
EdxlAggrefStage edxlaggstage = pdxlop->Edxlaggstage();
if (NULL != pdxlop->PmdidResolvedRetType())
{
// use resolved type
paggref->aggtype = CMDIdGPDB::PmdidConvert(pdxlop->PmdidResolvedRetType())->OidObjectId();
}
else if (EdxlaggstageIntermediate == edxlaggstage || EdxlaggstagePartial == edxlaggstage)
{
paggref->aggtype = CMDIdGPDB::PmdidConvert(pmdagg->PmdidTypeIntermediate())->OidObjectId();
}
else
{
paggref->aggtype = CMDIdGPDB::PmdidConvert(pmdagg->PmdidTypeResult())->OidObjectId();
}
switch(pdxlop->Edxlaggstage())
{
case EdxlaggstageNormal:
paggref->aggstage = AGGSTAGE_NORMAL;
break;
case EdxlaggstagePartial:
paggref->aggstage = AGGSTAGE_PARTIAL;
break;
case EdxlaggstageIntermediate:
paggref->aggstage = AGGSTAGE_INTERMEDIATE;
break;
case EdxlaggstageFinal:
paggref->aggstage = AGGSTAGE_FINAL;
break;
default:
GPOS_RAISE
(
gpdxl::ExmaDXL,
gpdxl::ExmiPlStmt2DXLConversion,
GPOS_WSZ_LIT("AGGREF: Specified AggStage value is invalid")
);
}
// translate each DXL argument
paggref->args = PlistTranslateScalarChildren(paggref->args, pdxlnAggref, pmapcidvar);
return (Expr *)paggref;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PwindowrefFromDXLNodeScWindowRef
//
// @doc:
// Translate a DXL scalar window ref into a GPDB WindowRef node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PwindowrefFromDXLNodeScWindowRef
(
const CDXLNode *pdxlnWinref,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnWinref);
CDXLScalarWindowRef *pdxlop = CDXLScalarWindowRef::PdxlopConvert(pdxlnWinref->Pdxlop());
WindowRef *pwindowref = MakeNode(WindowRef);
pwindowref->winfnoid = CMDIdGPDB::PmdidConvert(pdxlop->PmdidFunc())->OidObjectId();
pwindowref->windistinct = pdxlop->FDistinct();
pwindowref->winlevelsup = 0;
pwindowref->location = -1;
pwindowref->winlevel = 0;
pwindowref->winspec = pdxlop->UlWinSpecPos();
pwindowref->restype = CMDIdGPDB::PmdidConvert(pdxlop->PmdidRetType())->OidObjectId();
EdxlWinStage edxlwinstage = pdxlop->Edxlwinstage();
GPOS_ASSERT(edxlwinstage != EdxlwinstageSentinel);
ULONG rgrgulMapping[][2] =
{
{WINSTAGE_IMMEDIATE, EdxlwinstageImmediate},
{WINSTAGE_PRELIMINARY, EdxlwinstagePreliminary},
{WINSTAGE_ROWKEY, EdxlwinstageRowKey},
};
const ULONG ulArity = GPOS_ARRAY_SIZE(rgrgulMapping);
for (ULONG ul = 0; ul < ulArity; ul++)
{
ULONG *pulElem = rgrgulMapping[ul];
if ((ULONG) edxlwinstage == pulElem[1])
{
pwindowref->winstage = (WinStage) pulElem[0];
break;
}
}
// translate the arguments of the window function
pwindowref->args = PlistTranslateScalarChildren(pwindowref->args, pdxlnWinref, pmapcidvar);
return (Expr *) pwindowref;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PfuncexprFromDXLNodeScFuncExpr
//
// @doc:
// Translates a DXL scalar opexpr into a GPDB FuncExpr node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PfuncexprFromDXLNodeScFuncExpr
(
const CDXLNode *pdxlnFuncExpr,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnFuncExpr);
CDXLScalarFuncExpr *pdxlop = CDXLScalarFuncExpr::PdxlopConvert(pdxlnFuncExpr->Pdxlop());
FuncExpr *pfuncexpr = MakeNode(FuncExpr);
pfuncexpr->funcid = CMDIdGPDB::PmdidConvert(pdxlop->PmdidFunc())->OidObjectId();
pfuncexpr->funcretset = pdxlop->FReturnSet();
pfuncexpr->funcformat = COERCE_DONTCARE;
pfuncexpr->funcresulttype = CMDIdGPDB::PmdidConvert(pdxlop->PmdidRetType())->OidObjectId();
pfuncexpr->args = PlistTranslateScalarChildren(pfuncexpr->args, pdxlnFuncExpr, pmapcidvar);
return (Expr *)pfuncexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PparamFromDXLNodeScInitPlan
//
// @doc:
// Translates a DXL scalar InitPlan into a GPDB PARAM node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PparamFromDXLNodeScInitPlan
(
const CDXLNode *pdxlnInitPlan,
CMappingColIdVar *pmapcidvar
)
{
CDXLTranslateContext *pdxltrctxOut = (dynamic_cast<CMappingColIdVarPlStmt*>(pmapcidvar))->PpdxltrctxOut();
Plan *pplan = ((CMappingColIdVarPlStmt*) pmapcidvar)->Pplan();
if(NULL == pplan)
{
GPOS_RAISE
(
gpdxl::ExmaDXL,
ExmiDXL2PlStmtMissingPlanForInitPlanTranslation
);
}
GPOS_ASSERT(NULL != pdxlnInitPlan);
GPOS_ASSERT(EdxlopScalarInitPlan == pdxlnInitPlan->Pdxlop()->Edxlop());
GPOS_ASSERT(1 == pdxlnInitPlan->UlArity());
CDXLNode *pdxlnChild = (*pdxlnInitPlan)[0];
GPOS_ASSERT(EdxloptypePhysical == pdxlnChild->Pdxlop()->Edxloperatortype());
// Step 1: Generate the child plan
// Since an init plan is not a scalar node, we create a new DXLTranslator to handle its translation
CContextDXLToPlStmt *pctxdxltoplstmt = (dynamic_cast<CMappingColIdVarPlStmt*>(pmapcidvar))->Pctxdxltoplstmt();
CTranslatorDXLToPlStmt trdxltoplstmt(m_pmp, m_pmda, pctxdxltoplstmt, m_ulSegments);
DrgPdxltrctx *pdrgpdxltrctxPrevSiblings = GPOS_NEW(m_pmp) DrgPdxltrctx(m_pmp);
Plan *pplanChild = trdxltoplstmt.PplFromDXL(pdxlnChild, pdxltrctxOut, pplan, pdrgpdxltrctxPrevSiblings);
pdrgpdxltrctxPrevSiblings->Release();
// Step 2: Add the generated child to the root plan's subplan list
pctxdxltoplstmt->AddSubplan(pplanChild);
// Step 3: Generate a SubPlan node and insert into the initPlan (which is a list) of the pplan node.
SubPlan *psubplan = MakeNode(SubPlan);
psubplan->plan_id = gpdb::UlListLength(pctxdxltoplstmt->PlPplanSubplan());
psubplan->is_initplan = true;
GPOS_ASSERT(NULL != pplanChild->targetlist && 1 <= gpdb::UlListLength(pplanChild->targetlist));
psubplan->firstColType = gpdb::OidExprType( (Node*) ((TargetEntry*) gpdb::PvListNth(pplanChild->targetlist, 0))->expr);
psubplan->firstColTypmod = -1;
psubplan->subLinkType = EXPR_SUBLINK;
pplan->initPlan = gpdb::PlAppendElement(pplan->initPlan, psubplan);
// Step 4: Create the PARAM node
Param *pparam = MakeNode(Param);
pparam->paramkind = PARAM_EXEC;
pparam->paramid = pctxdxltoplstmt->UlNextParamId();
pparam->paramtype = psubplan->firstColType;
// Step 5: Link Param to the SubPlan node
psubplan->setParam = ListMake1Int(pparam->paramid);
return (Expr *)pparam;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PsubplanFromDXLNodeScSubPlan
//
// @doc:
// Translates a DXL scalar SubPlan into a GPDB SubPlan node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PsubplanFromDXLNodeScSubPlan
(
const CDXLNode *pdxlnSubPlan,
CMappingColIdVar *pmapcidvar
)
{
CDXLTranslateContext *pdxltrctxOut = (dynamic_cast<CMappingColIdVarPlStmt*>(pmapcidvar))->PpdxltrctxOut();
CContextDXLToPlStmt *pctxdxltoplstmt = (dynamic_cast<CMappingColIdVarPlStmt*>(pmapcidvar))->Pctxdxltoplstmt();
CDXLScalarSubPlan *pdxlop = CDXLScalarSubPlan::PdxlopConvert(pdxlnSubPlan->Pdxlop());
// translate subplan test expression
SubLinkType slink = CTranslatorUtils::Slink(pdxlop->Edxlsptype());
Expr *pexprTestExpr = PexprSubplanTestExpr(pdxlop->PdxlnTestExpr(), slink, pmapcidvar);
const DrgPdxlcr *pdrgdxlcrOuterRefs = pdxlop->DrgdxlcrOuterRefs();
const DrgPmdid *pdrgmdidOuterRefs = pdxlop->DrgmdidOuterRefs();
const ULONG ulLen = pdrgdxlcrOuterRefs->UlLength();
// create a copy of the translate context: the param mappings from the outer scope get copied in the constructor
CDXLTranslateContext dxltrctxSubplan(m_pmp, pdxltrctxOut->FParentAggNode(), pdxltrctxOut->PhmColParam());
// insert new outer ref mappings in the subplan translate context
for (ULONG ul = 0; ul < ulLen; ul++)
{
IMDId *pmdid = (*pdrgmdidOuterRefs)[ul];
CDXLColRef *pdxlcr = (*pdrgdxlcrOuterRefs)[ul];
ULONG ulColid = pdxlcr->UlID();
if (NULL == dxltrctxSubplan.Pmecolidparamid(ulColid))
{
// keep outer reference mapping to the original column for subsequent subplans
CMappingElementColIdParamId *pmecolidparamid = GPOS_NEW(m_pmp) CMappingElementColIdParamId(ulColid, pctxdxltoplstmt->UlNextParamId(), pmdid);
#ifdef GPOS_DEBUG
BOOL fInserted =
#endif
dxltrctxSubplan.FInsertParamMapping(ulColid, pmecolidparamid);
GPOS_ASSERT(fInserted);
}
}
CDXLNode *pdxlnChild = (*pdxlnSubPlan)[0];
GPOS_ASSERT(EdxloptypePhysical == pdxlnChild->Pdxlop()->Edxloperatortype());
Plan *pplan = ((CMappingColIdVarPlStmt*) pmapcidvar)->Pplan();
if(NULL == pplan)
{
GPOS_RAISE(gpdxl::ExmaDXL, ExmiDXL2PlStmtMissingPlanForSubPlanTranslation);
}
GPOS_ASSERT(NULL != pdxlnSubPlan);
GPOS_ASSERT(EdxlopScalarSubPlan == pdxlnSubPlan->Pdxlop()->Edxlop());
GPOS_ASSERT(1 == pdxlnSubPlan->UlArity());
// generate the child plan,
// create DXL->PlStmt translator to handle subplan's relational children
CTranslatorDXLToPlStmt trdxltoplstmt
(
m_pmp,
m_pmda,
(dynamic_cast<CMappingColIdVarPlStmt*>(pmapcidvar))->Pctxdxltoplstmt(),
m_ulSegments
);
DrgPdxltrctx *pdrgpdxltrctxPrevSiblings = GPOS_NEW(m_pmp) DrgPdxltrctx(m_pmp);
Plan *pplanChild = trdxltoplstmt.PplFromDXL(pdxlnChild, &dxltrctxSubplan, pplan, pdrgpdxltrctxPrevSiblings);
pdrgpdxltrctxPrevSiblings->Release();
GPOS_ASSERT(NULL != pplanChild->targetlist && 1 <= gpdb::UlListLength(pplanChild->targetlist));
// translate subplan and set test expression
SubPlan *psubplan = PsubplanFromChildPlan(pplanChild, slink, pctxdxltoplstmt);
psubplan->testexpr = (Node *) pexprTestExpr;
if (NULL != psubplan->testexpr && nodeTag(psubplan->testexpr) != T_Const)
{
// test expression is used for non-scalar subplan,
// second arg of test expression must be an EXEC param referring to subplan output,
// we add this param to subplan param ids before translating other params
Param *pparam = (Param *) gpdb::PvListNth(((OpExpr *)psubplan->testexpr)->args, 1);
psubplan->paramIds = NIL;
psubplan->paramIds = gpdb::PlAppendInt(psubplan->paramIds, pparam->paramid);
}
// translate other subplan params
TranslateSubplanParams(psubplan, &dxltrctxSubplan, pdrgdxlcrOuterRefs, pmapcidvar);
return (Expr *)psubplan;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PexprSubplanTestExpr
//
// @doc:
// Translate subplan test expression
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PexprSubplanTestExpr
(
CDXLNode *pdxlnTestExpr,
SubLinkType slink,
CMappingColIdVar *pmapcidvar
)
{
if (EXPR_SUBLINK == slink || EXISTS_SUBLINK == slink || NOT_EXISTS_SUBLINK == slink)
{
// expr/exists/not-exists sublinks have no test expression
return NULL;
}
GPOS_ASSERT(NULL != pdxlnTestExpr);
if (FConstTrue(pdxlnTestExpr, m_pmda))
{
// dummy test expression
return (Expr *) PconstFromDXLNodeScConst(pdxlnTestExpr, NULL);
}
if (EdxlopScalarCmp != pdxlnTestExpr->Pdxlop()->Edxlop())
{
// test expression is expected to be a comparison
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtConversion, GPOS_WSZ_LIT("Unexpected subplan test expression"));
}
GPOS_ASSERT(2 == pdxlnTestExpr->UlArity());
GPOS_ASSERT(ANY_SUBLINK == slink || ALL_SUBLINK == slink);
CDXLNode *pdxlnOuterChild = (*pdxlnTestExpr)[0];
CDXLNode *pdxlnInnerChild = (*pdxlnTestExpr)[1];
if (EdxlopScalarIdent != pdxlnInnerChild->Pdxlop()->Edxlop())
{
// test expression is expected to be a comparison between an outer expression
// and a scalar identifier from subplan child
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtConversion, GPOS_WSZ_LIT("Unexpected subplan test expression"));
}
// extract type of inner column
CDXLScalarComp *pdxlopCmp = CDXLScalarComp::PdxlopConvert(pdxlnTestExpr->Pdxlop());
CDXLScalarIdent *pdxlopInnerIdent = CDXLScalarIdent::PdxlopConvert(pdxlnInnerChild->Pdxlop());
Oid oidInnerType = CMDIdGPDB::PmdidConvert(pdxlopInnerIdent->PmdidType())->OidObjectId();
// create an OpExpr for subplan test expression
OpExpr *popexpr = MakeNode(OpExpr);
popexpr->opno = CMDIdGPDB::PmdidConvert(pdxlopCmp->Pmdid())->OidObjectId();
const IMDScalarOp *pmdscop = m_pmda->Pmdscop(pdxlopCmp->Pmdid());
popexpr->opfuncid = CMDIdGPDB::PmdidConvert(pmdscop->PmdidFunc())->OidObjectId();
popexpr->opresulttype = CMDIdGPDB::PmdidConvert(m_pmda->PtMDType<IMDTypeBool>()->Pmdid())->OidObjectId();
popexpr->opretset = false;
// translate outer expression (can be a deep scalar tree)
Expr *pexprTestExprOuterArg = PexprFromDXLNodeScalar(pdxlnOuterChild, pmapcidvar);
// add translated outer expression as first arg of OpExpr
List *plistArgs = NIL;
plistArgs = gpdb::PlAppendElement(plistArgs, pexprTestExprOuterArg);
// second arg must be an EXEC param which is replaced during query execution with subplan output
Param *pparam = MakeNode(Param);
pparam->paramkind = PARAM_EXEC;
CContextDXLToPlStmt *pctxdxltoplstmt = (dynamic_cast<CMappingColIdVarPlStmt*>(pmapcidvar))->Pctxdxltoplstmt();
pparam->paramid = pctxdxltoplstmt->UlNextParamId();
pparam->paramtype = oidInnerType;
plistArgs = gpdb::PlAppendElement(plistArgs, pparam);
popexpr->args = plistArgs;
return (Expr *) popexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::TranslateSubplanParams
//
// @doc:
// Translate subplan parameters
//
//---------------------------------------------------------------------------
void
CTranslatorDXLToScalar::TranslateSubplanParams
(
SubPlan *psubplan,
CDXLTranslateContext *pdxltrctx,
const DrgPdxlcr *pdrgdxlcrOuterRefs,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != psubplan);
GPOS_ASSERT(NULL != pdxltrctx);
GPOS_ASSERT(NULL != pdrgdxlcrOuterRefs);
GPOS_ASSERT(NULL != pmapcidvar);
// Create the PARAM and ARG nodes
const ULONG ulSize = pdrgdxlcrOuterRefs->UlLength();
for (ULONG ul = 0; ul < ulSize; ul++)
{
CDXLColRef *pdxlcr = (*pdrgdxlcrOuterRefs)[ul];
ULONG ulColId = pdxlcr->UlID();
pdxlcr->AddRef();
const CMappingElementColIdParamId *pmecolidparamid = pdxltrctx->Pmecolidparamid(pdxlcr->UlID());
Param *pparam = PparamFromMapping(pmecolidparamid);
psubplan->parParam = gpdb::PlAppendInt(psubplan->parParam, pparam->paramid);
IMDId *pmdidType = pmecolidparamid->PmdidType();
pmdidType->AddRef();
CDXLScalarIdent *pdxlopIdent = GPOS_NEW(m_pmp) CDXLScalarIdent(m_pmp, pdxlcr, pmdidType);
Expr *parg = (Expr *) pmapcidvar->PvarFromDXLNodeScId(pdxlopIdent);
// not found in mapping, it must be an external parameter
if (NULL == parg)
{
parg = (Expr*) PparamFromMapping(pmecolidparamid);
GPOS_ASSERT(NULL != parg);
}
pdxlopIdent->Release();
psubplan->args = gpdb::PlAppendElement(psubplan->args, parg);
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PsubplanFromChildPlan
//
// @doc:
// add child plan to translation context, and build a subplan from it
//
//---------------------------------------------------------------------------
SubPlan *
CTranslatorDXLToScalar::PsubplanFromChildPlan
(
Plan *pplan,
SubLinkType slink,
CContextDXLToPlStmt *pctxdxltoplstmt
)
{
pctxdxltoplstmt->AddSubplan(pplan);
SubPlan *psubplan = MakeNode(SubPlan);
psubplan->plan_id = gpdb::UlListLength(pctxdxltoplstmt->PlPplanSubplan());
psubplan->plan_name = SzSubplanAlias(psubplan->plan_id);
psubplan->is_initplan = false;
psubplan->firstColType = gpdb::OidExprType( (Node*) ((TargetEntry*) gpdb::PvListNth(pplan->targetlist, 0))->expr);
psubplan->firstColTypmod = -1;
psubplan->subLinkType = slink;
psubplan->is_multirow = false;
psubplan->unknownEqFalse = false;
return psubplan;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::SzSubplanAlias
//
// @doc:
// build plan name, for explain purposes
//
//---------------------------------------------------------------------------
CHAR *
CTranslatorDXLToScalar::SzSubplanAlias
(
ULONG ulPlanId
)
{
CWStringDynamic *pstr = GPOS_NEW(m_pmp) CWStringDynamic(m_pmp);
pstr->AppendFormat(GPOS_WSZ_LIT("SubPlan %d"), ulPlanId);
const WCHAR *wsz = pstr->Wsz();
ULONG ulMaxLength = (GPOS_WSZ_LENGTH(wsz) + 1) * GPOS_SIZEOF(WCHAR);
CHAR *sz = (CHAR *) gpdb::GPDBAlloc(ulMaxLength);
gpos::clib::LWcsToMbs(sz, const_cast<WCHAR *>(wsz), ulMaxLength);
sz[ulMaxLength - 1] = '\0';
GPOS_DELETE(pstr);
return sz;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PparamFromMapping
//
// @doc:
// Creates a GPDB param from the given mapping
//
//---------------------------------------------------------------------------
Param *
CTranslatorDXLToScalar::PparamFromMapping
(
const CMappingElementColIdParamId *pmecolidparamid
)
{
Param *pparam = MakeNode(Param);
pparam->paramid = pmecolidparamid->UlParamId();
pparam->paramkind = PARAM_EXEC;
pparam->paramtype = CMDIdGPDB::PmdidConvert(pmecolidparamid->PmdidType())->OidObjectId();
return pparam;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PboolexprFromDXLNodeScBoolExpr
//
// @doc:
// Translates a DXL scalar BoolExpr into a GPDB OpExpr node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PboolexprFromDXLNodeScBoolExpr
(
const CDXLNode *pdxlnBoolExpr,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnBoolExpr);
CDXLScalarBoolExpr *pdxlop = CDXLScalarBoolExpr::PdxlopConvert(pdxlnBoolExpr->Pdxlop());
BoolExpr *pboolexpr = MakeNode(BoolExpr);
GPOS_ASSERT(1 <= pdxlnBoolExpr->UlArity());
switch (pdxlop->EdxlBoolType())
{
case Edxlnot:
{
GPOS_ASSERT(1 == pdxlnBoolExpr->UlArity());
pboolexpr->boolop = NOT_EXPR;
break;
}
case Edxland:
{
GPOS_ASSERT(2 <= pdxlnBoolExpr->UlArity());
pboolexpr->boolop = AND_EXPR;
break;
}
case Edxlor:
{
GPOS_ASSERT(2 <= pdxlnBoolExpr->UlArity());
pboolexpr->boolop = OR_EXPR;
break;
}
default:
{
GPOS_ASSERT(!"Boolean Operation: Must be either or/ and / not");
return NULL;
}
}
pboolexpr->args = PlistTranslateScalarChildren(pboolexpr->args, pdxlnBoolExpr, pmapcidvar);
pboolexpr->location = -1;
return (Expr *)pboolexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PbooleantestFromDXLNodeScBooleanTest
//
// @doc:
// Translates a DXL scalar BooleanTest into a GPDB OpExpr node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PbooleantestFromDXLNodeScBooleanTest
(
const CDXLNode *pdxlnBooleanTest,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnBooleanTest);
CDXLScalarBooleanTest *pdxlop = CDXLScalarBooleanTest::PdxlopConvert(pdxlnBooleanTest->Pdxlop());
BooleanTest *pbooleantest = MakeNode(BooleanTest);
switch (pdxlop->EdxlBoolType())
{
case EdxlbooleantestIsTrue:
pbooleantest->booltesttype = IS_TRUE;
break;
case EdxlbooleantestIsNotTrue:
pbooleantest->booltesttype = IS_NOT_TRUE;
break;
case EdxlbooleantestIsFalse:
pbooleantest->booltesttype = IS_FALSE;
break;
case EdxlbooleantestIsNotFalse:
pbooleantest->booltesttype = IS_NOT_FALSE;
break;
case EdxlbooleantestIsUnknown:
pbooleantest->booltesttype = IS_UNKNOWN;
break;
case EdxlbooleantestIsNotUnknown:
pbooleantest->booltesttype = IS_NOT_UNKNOWN;
break;
default:
{
GPOS_ASSERT(!"Invalid Boolean Test Operation");
return NULL;
}
}
GPOS_ASSERT(1 == pdxlnBooleanTest->UlArity());
CDXLNode *pdxlnArg = (*pdxlnBooleanTest)[0];
Expr *pexprArg = PexprFromDXLNodeScalar(pdxlnArg, pmapcidvar);
pbooleantest->arg = pexprArg;
return (Expr *)pbooleantest;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PnulltestFromDXLNodeScNullTest
//
// @doc:
// Translates a DXL scalar NullTest into a GPDB NullTest node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PnulltestFromDXLNodeScNullTest
(
const CDXLNode *pdxlnNullTest,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnNullTest);
CDXLScalarNullTest *pdxlop = CDXLScalarNullTest::PdxlopConvert(pdxlnNullTest->Pdxlop());
NullTest *pnulltest = MakeNode(NullTest);
GPOS_ASSERT(1 == pdxlnNullTest->UlArity());
CDXLNode *pdxlnChild = (*pdxlnNullTest)[0];
Expr *pexprChild = PexprFromDXLNodeScalar(pdxlnChild, pmapcidvar);
if (pdxlop->FIsNullTest())
{
pnulltest->nulltesttype = IS_NULL;
}
else
{
pnulltest->nulltesttype = IS_NOT_NULL;
}
pnulltest->arg = pexprChild;
return (Expr *)pnulltest;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PnullifFromDXLNodeScNullIf
//
// @doc:
// Translates a DXL scalar nullif into a GPDB NullIfExpr node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PnullifFromDXLNodeScNullIf
(
const CDXLNode *pdxlnNullIf,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnNullIf);
CDXLScalarNullIf *pdxlop = CDXLScalarNullIf::PdxlopConvert(pdxlnNullIf->Pdxlop());
NullIfExpr *pnullifexpr = MakeNode(NullIfExpr);
pnullifexpr->opno = CMDIdGPDB::PmdidConvert(pdxlop->PmdidOp())->OidObjectId();
const IMDScalarOp *pmdscop = m_pmda->Pmdscop(pdxlop->PmdidOp());
pnullifexpr->opfuncid = CMDIdGPDB::PmdidConvert(pmdscop->PmdidFunc())->OidObjectId();
pnullifexpr->opresulttype = OidFunctionReturnType(pmdscop->PmdidFunc());
pnullifexpr->opretset = false;
// translate children
GPOS_ASSERT(2 == pdxlnNullIf->UlArity());
pnullifexpr->args = PlistTranslateScalarChildren(pnullifexpr->args, pdxlnNullIf, pmapcidvar);
return (Expr *) pnullifexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PrelabeltypeFromDXLNodeScCast
//
// @doc:
// Translates a DXL scalar cast into a GPDB RelabelType / FuncExpr node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PrelabeltypeFromDXLNodeScCast
(
const CDXLNode *pdxlnCast,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnCast);
CDXLScalarCast *pdxlop = CDXLScalarCast::PdxlopConvert(pdxlnCast->Pdxlop());
GPOS_ASSERT(1 == pdxlnCast->UlArity());
CDXLNode *pdxlnChild = (*pdxlnCast)[0];
Expr *pexprChild = PexprFromDXLNodeScalar(pdxlnChild, pmapcidvar);
if (pdxlop->PmdidFunc()->FValid())
{
FuncExpr *pfuncexpr = MakeNode(FuncExpr);
pfuncexpr->funcid = CMDIdGPDB::PmdidConvert(pdxlop->PmdidFunc())->OidObjectId();
const IMDFunction *pmdfunc = m_pmda->Pmdfunc(pdxlop->PmdidFunc());
pfuncexpr->funcretset = pmdfunc->FReturnsSet();;
pfuncexpr->funcformat = COERCE_IMPLICIT_CAST;
pfuncexpr->funcresulttype = CMDIdGPDB::PmdidConvert(pdxlop->PmdidType())->OidObjectId();
pfuncexpr->args = NIL;
pfuncexpr->args = gpdb::PlAppendElement(pfuncexpr->args, pexprChild);
return (Expr *) pfuncexpr;
}
RelabelType *prelabeltype = MakeNode(RelabelType);
prelabeltype->resulttype = CMDIdGPDB::PmdidConvert(pdxlop->PmdidType())->OidObjectId();
prelabeltype->arg = pexprChild;
prelabeltype->resulttypmod = -1;
prelabeltype->location = -1;
prelabeltype->relabelformat = COERCE_DONTCARE;
return (Expr *) prelabeltype;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PcoerceFromDXLNodeScCoerce
//
// @doc:
// Translates a DXL scalar coerce into a GPDB coerce node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PcoerceFromDXLNodeScCoerce
(
const CDXLNode *pdxlnCoerce,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnCoerce);
CDXLScalarCoerceToDomain *pdxlop = CDXLScalarCoerceToDomain::PdxlopConvert(pdxlnCoerce->Pdxlop());
GPOS_ASSERT(1 == pdxlnCoerce->UlArity());
CDXLNode *pdxlnChild = (*pdxlnCoerce)[0];
Expr *pexprChild = PexprFromDXLNodeScalar(pdxlnChild, pmapcidvar);
CoerceToDomain *pcoerce = MakeNode(CoerceToDomain);
pcoerce->resulttype = CMDIdGPDB::PmdidConvert(pdxlop->PmdidResultType())->OidObjectId();
pcoerce->arg = pexprChild;
pcoerce->resulttypmod = pdxlop->IMod();
pcoerce->location = pdxlop->ILoc();
pcoerce->coercionformat = (CoercionForm) pdxlop->Edxlcf();
return (Expr *) pcoerce;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PcoalesceFromDXLNodeScCoalesce
//
// @doc:
// Translates a DXL scalar coalesce operator into a GPDB coalesce node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PcoalesceFromDXLNodeScCoalesce
(
const CDXLNode *pdxlnCoalesce,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnCoalesce);
CDXLScalarCoalesce *pdxlop = CDXLScalarCoalesce::PdxlopConvert(pdxlnCoalesce->Pdxlop());
CoalesceExpr *pcoalesce = MakeNode(CoalesceExpr);
pcoalesce->coalescetype = CMDIdGPDB::PmdidConvert(pdxlop->PmdidType())->OidObjectId();
pcoalesce->args = PlistTranslateScalarChildren(pcoalesce->args, pdxlnCoalesce, pmapcidvar);
pcoalesce->location = -1;
return (Expr *) pcoalesce;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PminmaxFromDXLNodeScMinMax
//
// @doc:
// Translates a DXL scalar minmax operator into a GPDB minmax node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PminmaxFromDXLNodeScMinMax
(
const CDXLNode *pdxlnMinMax,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnMinMax);
CDXLScalarMinMax *pdxlop = CDXLScalarMinMax::PdxlopConvert(pdxlnMinMax->Pdxlop());
MinMaxExpr *pminmax = MakeNode(MinMaxExpr);
pminmax->minmaxtype = CMDIdGPDB::PmdidConvert(pdxlop->PmdidType())->OidObjectId();
pminmax->args = PlistTranslateScalarChildren(pminmax->args, pdxlnMinMax, pmapcidvar);
pminmax->location = -1;
CDXLScalarMinMax::EdxlMinMaxType emmt = pdxlop->Emmt();
if (CDXLScalarMinMax::EmmtMax == emmt)
{
pminmax->op = IS_GREATEST;
}
else
{
GPOS_ASSERT(CDXLScalarMinMax::EmmtMin == emmt);
pminmax->op = IS_LEAST;
}
return (Expr *) pminmax;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PlistTranslateScalarChildren
//
// @doc:
// Translate children of DXL node, and add them to list
//
//---------------------------------------------------------------------------
List *
CTranslatorDXLToScalar::PlistTranslateScalarChildren
(
List *plist,
const CDXLNode *pdxln,
CMappingColIdVar *pmapcidvar
)
{
List *plistNew = plist;
const ULONG ulArity = pdxln->UlArity();
for (ULONG ul = 0; ul < ulArity; ul++)
{
CDXLNode *pdxlnChild = (*pdxln)[ul];
Expr *pexprChild = PexprFromDXLNodeScalar(pdxlnChild, pmapcidvar);
plistNew = gpdb::PlAppendElement(plistNew, pexprChild);
}
return plistNew;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PconstFromDXLNodeScConst
//
// @doc:
// Translates a DXL scalar constant operator into a GPDB scalar const node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PconstFromDXLNodeScConst
(
const CDXLNode *pdxlnConst,
CMappingColIdVar * //pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnConst);
CDXLScalarConstValue *pdxlop = CDXLScalarConstValue::PdxlopConvert(pdxlnConst->Pdxlop());
CDXLDatum *pdxldatum = const_cast<CDXLDatum*>(pdxlop->Pdxldatum());
return PconstFromDXLDatum(pdxldatum);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PconstFromDXLDatum
//
// @doc:
// Translates a DXL datum into a GPDB scalar const node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PconstFromDXLDatum
(
CDXLDatum *pdxldatum
)
{
GPOS_ASSERT(NULL != pdxldatum);
SDatumTranslatorElem rgTranslators[] =
{
{CDXLDatum::EdxldatumInt2 , &CTranslatorDXLToScalar::PconstInt2},
{CDXLDatum::EdxldatumInt4 , &CTranslatorDXLToScalar::PconstInt4},
{CDXLDatum::EdxldatumInt8 , &CTranslatorDXLToScalar::PconstInt8},
{CDXLDatum::EdxldatumBool , &CTranslatorDXLToScalar::PconstBool},
{CDXLDatum::EdxldatumOid , &CTranslatorDXLToScalar::PconstOid},
{CDXLDatum::EdxldatumGeneric, &CTranslatorDXLToScalar::PconstGeneric},
{CDXLDatum::EdxldatumStatsDoubleMappable, &CTranslatorDXLToScalar::PconstGeneric},
{CDXLDatum::EdxldatumStatsLintMappable, &CTranslatorDXLToScalar::PconstGeneric}
};
const ULONG ulTranslators = GPOS_ARRAY_SIZE(rgTranslators);
CDXLDatum::EdxldatumType edxldatumtype = pdxldatum->Edxldt();
// find translator for the node type
PfPconst pf = NULL;
for (ULONG ul = 0; ul < ulTranslators; ul++)
{
SDatumTranslatorElem elem = rgTranslators[ul];
if (edxldatumtype == elem.edxldt)
{
pf = elem.pf;
break;
}
}
if (NULL == pf)
{
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtConversion, CDXLTokens::PstrToken(EdxltokenScalarConstValue)->Wsz());
}
return (Expr*) (this->*pf)(pdxldatum);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PconstOid
//
// @doc:
// Translates an oid datum into a constant
//
//---------------------------------------------------------------------------
Const *
CTranslatorDXLToScalar::PconstOid
(
CDXLDatum *pdxldatum
)
{
CDXLDatumOid *pdxldatumOid = CDXLDatumOid::PdxldatumConvert(pdxldatum);
Const *pconst = MakeNode(Const);
pconst->consttype = CMDIdGPDB::PmdidConvert(pdxldatumOid->Pmdid())->OidObjectId();
pconst->constbyval = pdxldatumOid->FByValue();
pconst->constisnull = pdxldatumOid->FNull();
pconst->constlen = pdxldatumOid->UlLength();
if (pconst->constisnull)
{
pconst->constvalue = (Datum) 0;
}
else
{
pconst->constvalue = gpdb::DDatumFromInt32(pdxldatumOid->OidValue());
}
return pconst;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PconstInt2
//
// @doc:
// Translates an int2 datum into a constant
//
//---------------------------------------------------------------------------
Const *
CTranslatorDXLToScalar::PconstInt2
(
CDXLDatum *pdxldatum
)
{
CDXLDatumInt2 *pdxldatumint2 = CDXLDatumInt2::PdxldatumConvert(pdxldatum);
Const *pconst = MakeNode(Const);
pconst->consttype = CMDIdGPDB::PmdidConvert(pdxldatumint2->Pmdid())->OidObjectId();
pconst->constbyval = pdxldatumint2->FByValue();
pconst->constisnull = pdxldatumint2->FNull();
pconst->constlen = pdxldatumint2->UlLength();
if (pconst->constisnull)
{
pconst->constvalue = (Datum) 0;
}
else
{
pconst->constvalue = gpdb::DDatumFromInt16(pdxldatumint2->SValue());
}
return pconst;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PconstInt4
//
// @doc:
// Translates an int4 datum into a constant
//
//---------------------------------------------------------------------------
Const *
CTranslatorDXLToScalar::PconstInt4
(
CDXLDatum *pdxldatum
)
{
CDXLDatumInt4 *pdxldatumint4 = CDXLDatumInt4::PdxldatumConvert(pdxldatum);
Const *pconst = MakeNode(Const);
pconst->consttype = CMDIdGPDB::PmdidConvert(pdxldatumint4->Pmdid())->OidObjectId();
pconst->constbyval = pdxldatumint4->FByValue();
pconst->constisnull = pdxldatumint4->FNull();
pconst->constlen = pdxldatumint4->UlLength();
if (pconst->constisnull)
{
pconst->constvalue = (Datum) 0;
}
else
{
pconst->constvalue = gpdb::DDatumFromInt32(pdxldatumint4->IValue());
}
return pconst;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PconstInt8
//
// @doc:
// Translates an int8 datum into a constant
//
//---------------------------------------------------------------------------
Const *
CTranslatorDXLToScalar::PconstInt8
(
CDXLDatum *pdxldatum
)
{
CDXLDatumInt8 *pdxldatumint8 = CDXLDatumInt8::PdxldatumConvert(pdxldatum);
Const *pconst = MakeNode(Const);
pconst->consttype = CMDIdGPDB::PmdidConvert(pdxldatumint8->Pmdid())->OidObjectId();
pconst->constbyval = pdxldatumint8->FByValue();
pconst->constisnull = pdxldatumint8->FNull();
pconst->constlen = pdxldatumint8->UlLength();
if (pconst->constisnull)
{
pconst->constvalue = (Datum) 0;
}
else
{
pconst->constvalue = gpdb::DDatumFromInt64(pdxldatumint8->LValue());
}
return pconst;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PconstBool
//
// @doc:
// Translates a boolean datum into a constant
//
//---------------------------------------------------------------------------
Const *
CTranslatorDXLToScalar::PconstBool
(
CDXLDatum *pdxldatum
)
{
CDXLDatumBool *pdxldatumbool = CDXLDatumBool::PdxldatumConvert(pdxldatum);
Const *pconst = MakeNode(Const);
pconst->consttype = CMDIdGPDB::PmdidConvert(pdxldatumbool->Pmdid())->OidObjectId();
pconst->constbyval = pdxldatumbool->FByValue();
pconst->constisnull = pdxldatumbool->FNull();
pconst->constlen = pdxldatumbool->UlLength();
if (pconst->constisnull)
{
pconst->constvalue = (Datum) 0;
}
else
{
pconst->constvalue = gpdb::DDatumFromBool(pdxldatumbool->FValue());
}
return pconst;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PconstGeneric
//
// @doc:
// Translates a datum of generic type into a constant
//
//---------------------------------------------------------------------------
Const *
CTranslatorDXLToScalar::PconstGeneric
(
CDXLDatum *pdxldatum
)
{
CDXLDatumGeneric *pdxldatumgeneric = CDXLDatumGeneric::PdxldatumConvert(pdxldatum);
Const *pconst = MakeNode(Const);
pconst->consttype = CMDIdGPDB::PmdidConvert(pdxldatumgeneric->Pmdid())->OidObjectId();
pconst->constbyval = pdxldatumgeneric->FByValue();
pconst->constisnull = pdxldatumgeneric->FNull();
pconst->constlen = pdxldatumgeneric->UlLength();
if (pconst->constisnull)
{
pconst->constvalue = (Datum) 0;
}
else if (pconst->constbyval)
{
// if it is a by-value constant, the value is stored in the datum.
GPOS_ASSERT(pconst->constlen >= 0);
GPOS_ASSERT((ULONG) pconst->constlen <= sizeof(Datum));
memcpy(&pconst->constvalue, pdxldatumgeneric->Pba(), sizeof(Datum));
}
else
{
Datum dVal = gpdb::DDatumFromPointer(pdxldatumgeneric->Pba());
ULONG ulLength = (ULONG) gpdb::SDatumSize(dVal, false, pconst->constlen);
CHAR *pcsz = (CHAR *) gpdb::GPDBAlloc(ulLength + 1);
memcpy(pcsz, pdxldatumgeneric->Pba(), ulLength);
pcsz[ulLength] = '\0';
pconst->constvalue = gpdb::DDatumFromPointer(pcsz);
}
return pconst;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PexprPartOid
//
// @doc:
// Translates a DXL part oid into a GPDB part oid
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PexprPartOid
(
const CDXLNode *pdxlnPartOid,
CMappingColIdVar * //pmapcidvar
)
{
CDXLScalarPartOid *pdxlop = CDXLScalarPartOid::PdxlopConvert(pdxlnPartOid->Pdxlop());
PartOidExpr *pexpr = MakeNode(PartOidExpr);
pexpr->level = pdxlop->UlLevel();
return (Expr *) pexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PexprPartDefault
//
// @doc:
// Translates a DXL part default into a GPDB part default
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PexprPartDefault
(
const CDXLNode *pdxlnPartDefault,
CMappingColIdVar * //pmapcidvar
)
{
CDXLScalarPartDefault *pdxlop = CDXLScalarPartDefault::PdxlopConvert(pdxlnPartDefault->Pdxlop());
PartDefaultExpr *pexpr = MakeNode(PartDefaultExpr);
pexpr->level = pdxlop->UlLevel();
return (Expr *) pexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PexprPartBound
//
// @doc:
// Translates a DXL part bound into a GPDB part bound
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PexprPartBound
(
const CDXLNode *pdxlnPartBound,
CMappingColIdVar * //pmapcidvar
)
{
CDXLScalarPartBound *pdxlop = CDXLScalarPartBound::PdxlopConvert(pdxlnPartBound->Pdxlop());
PartBoundExpr *pexpr = MakeNode(PartBoundExpr);
pexpr->level = pdxlop->UlLevel();
pexpr->boundType = CMDIdGPDB::PmdidConvert(pdxlop->PmdidType())->OidObjectId();
pexpr->isLowerBound = pdxlop->FLower();
return (Expr *) pexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PexprPartBoundInclusion
//
// @doc:
// Translates a DXL part bound inclusion into a GPDB part bound inclusion
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PexprPartBoundInclusion
(
const CDXLNode *pdxlnPartBoundIncl,
CMappingColIdVar * //pmapcidvar
)
{
CDXLScalarPartBoundInclusion *pdxlop = CDXLScalarPartBoundInclusion::PdxlopConvert(pdxlnPartBoundIncl->Pdxlop());
PartBoundInclusionExpr *pexpr = MakeNode(PartBoundInclusionExpr);
pexpr->level = pdxlop->UlLevel();
pexpr->isLowerBound = pdxlop->FLower();
return (Expr *) pexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PexprPartBoundOpen
//
// @doc:
// Translates a DXL part bound openness into a GPDB part bound openness
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PexprPartBoundOpen
(
const CDXLNode *pdxlnPartBoundOpen,
CMappingColIdVar * //pmapcidvar
)
{
CDXLScalarPartBoundOpen *pdxlop = CDXLScalarPartBoundOpen::PdxlopConvert(pdxlnPartBoundOpen->Pdxlop());
PartBoundOpenExpr *pexpr = MakeNode(PartBoundOpenExpr);
pexpr->level = pdxlop->UlLevel();
pexpr->isLowerBound = pdxlop->FLower();
return (Expr *) pexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PexprFromDXLNodeScId
//
// @doc:
// Translates a DXL scalar ident into a GPDB Expr node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PexprFromDXLNodeScId
(
const CDXLNode *pdxlnIdent,
CMappingColIdVar *pmapcidvar
)
{
CMappingColIdVarPlStmt *pmapcidvarplstmt = dynamic_cast<CMappingColIdVarPlStmt*>(pmapcidvar);
// scalar identifier
CDXLScalarIdent *pdxlop = CDXLScalarIdent::PdxlopConvert(pdxlnIdent->Pdxlop());
Expr *pexprResult = NULL;
if (NULL == pmapcidvarplstmt || NULL == pmapcidvarplstmt->PpdxltrctxOut()->Pmecolidparamid(pdxlop->Pdxlcr()->UlID()))
{
// not an outer ref -> create var node
pexprResult = (Expr *) pmapcidvar->PvarFromDXLNodeScId(pdxlop);
}
else
{
// outer ref -> create param node
pexprResult = (Expr *) pmapcidvarplstmt->PparamFromDXLNodeScId(pdxlop);
}
if (NULL == pexprResult)
{
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtAttributeNotFound, pdxlop->Pdxlcr()->UlID());
}
return pexprResult;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PopexprFromDXLNodeScCmp
//
// @doc:
// Translates a DXL scalar comparison operator or a scalar distinct comparison into a GPDB OpExpr node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PopexprFromDXLNodeScCmp
(
const CDXLNode *pdxlnCmp,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnCmp);
CDXLScalarComp *pdxlop = CDXLScalarComp::PdxlopConvert(pdxlnCmp->Pdxlop());
OpExpr *popexpr = MakeNode(OpExpr);
popexpr->opno = CMDIdGPDB::PmdidConvert(pdxlop->Pmdid())->OidObjectId();
const IMDScalarOp *pmdscop = m_pmda->Pmdscop(pdxlop->Pmdid());
popexpr->opfuncid = CMDIdGPDB::PmdidConvert(pmdscop->PmdidFunc())->OidObjectId();
popexpr->opresulttype = CMDIdGPDB::PmdidConvert(m_pmda->PtMDType<IMDTypeBool>()->Pmdid())->OidObjectId();
popexpr->opretset = false;
// translate left and right child
GPOS_ASSERT(2 == pdxlnCmp->UlArity());
CDXLNode *pdxlnLeft = (*pdxlnCmp)[EdxlsccmpIndexLeft];
CDXLNode *pdxlnRight = (*pdxlnCmp)[EdxlsccmpIndexRight];
Expr *pexprLeft = PexprFromDXLNodeScalar(pdxlnLeft, pmapcidvar);
Expr *pexprRight = PexprFromDXLNodeScalar(pdxlnRight, pmapcidvar);
popexpr->args = ListMake2(pexprLeft, pexprRight);
return (Expr *) popexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PexprArray
//
// @doc:
// Translates a DXL scalar array into a GPDB ArrayExpr node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PexprArray
(
const CDXLNode *pdxlnArray,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnArray);
CDXLScalarArray *pdxlop = CDXLScalarArray::PdxlopConvert(pdxlnArray->Pdxlop());
ArrayExpr *pexpr = MakeNode(ArrayExpr);
pexpr->element_typeid = CMDIdGPDB::PmdidConvert(pdxlop->PmdidElem())->OidObjectId();
pexpr->array_typeid = CMDIdGPDB::PmdidConvert(pdxlop->PmdidArray())->OidObjectId();
pexpr->multidims = pdxlop->FMultiDimensional();
pexpr->elements = PlistTranslateScalarChildren(pexpr->elements, pdxlnArray, pmapcidvar);
return (Expr *) gpdb::PnodeFoldArrayexprConstants(pexpr);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PexprArrayRef
//
// @doc:
// Translates a DXL scalar arrayref into a GPDB ArrayRef node
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PexprArrayRef
(
const CDXLNode *pdxlnArrayref,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnArrayref);
CDXLScalarArrayRef *pdxlop = CDXLScalarArrayRef::PdxlopConvert(pdxlnArrayref->Pdxlop());
ArrayRef *parrayref = MakeNode(ArrayRef);
parrayref->refarraytype = CMDIdGPDB::PmdidConvert(pdxlop->PmdidArray())->OidObjectId();
parrayref->refelemtype = CMDIdGPDB::PmdidConvert(pdxlop->PmdidElem())->OidObjectId();
parrayref->refrestype = CMDIdGPDB::PmdidConvert(pdxlop->PmdidReturn())->OidObjectId();
const ULONG ulArity = pdxlnArrayref->UlArity();
GPOS_ASSERT(3 == ulArity || 4 == ulArity);
parrayref->reflowerindexpr = PlTranslateArrayRefIndexList((*pdxlnArrayref)[0], CDXLScalarArrayRefIndexList::EilbLower, pmapcidvar);
parrayref->refupperindexpr = PlTranslateArrayRefIndexList((*pdxlnArrayref)[1], CDXLScalarArrayRefIndexList::EilbUpper, pmapcidvar);
parrayref->refexpr = PexprFromDXLNodeScalar((*pdxlnArrayref)[2], pmapcidvar);
parrayref->refassgnexpr = NULL;
if (4 == ulArity)
{
parrayref->refassgnexpr = PexprFromDXLNodeScalar((*pdxlnArrayref)[3], pmapcidvar);
}
return (Expr *) parrayref;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PlTranslateArrayRefIndexList
//
// @doc:
// Translates a DXL arrayref index list
//
//---------------------------------------------------------------------------
List *
CTranslatorDXLToScalar::PlTranslateArrayRefIndexList
(
const CDXLNode *pdxlnIndexlist,
CDXLScalarArrayRefIndexList::EIndexListBound
#ifdef GPOS_DEBUG
eilb
#endif //GPOS_DEBUG
,
CMappingColIdVar *pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnIndexlist);
GPOS_ASSERT(eilb == CDXLScalarArrayRefIndexList::PdxlopConvert(pdxlnIndexlist->Pdxlop())->Eilb());
List *plChildren = NIL;
plChildren = PlistTranslateScalarChildren(plChildren, pdxlnIndexlist, pmapcidvar);
return plChildren;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::PexprDMLAction
//
// @doc:
// Translates a DML action expression
//
//---------------------------------------------------------------------------
Expr *
CTranslatorDXLToScalar::PexprDMLAction
(
const CDXLNode *
#ifdef GPOS_DEBUG
pdxlnDMLAction
#endif
,
CMappingColIdVar * // pmapcidvar
)
{
GPOS_ASSERT(NULL != pdxlnDMLAction);
GPOS_ASSERT(EdxlopScalarDMLAction == pdxlnDMLAction->Pdxlop()->Edxlop());
DMLActionExpr *pexpr = MakeNode(DMLActionExpr);
return (Expr *) pexpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::OidFunctionReturnType
//
// @doc:
// Returns the operator return type oid for the operator funcid from the translation context
//
//---------------------------------------------------------------------------
Oid
CTranslatorDXLToScalar::OidFunctionReturnType
(
IMDId *pmdid
)
const
{
return CMDIdGPDB::PmdidConvert(m_pmda->Pmdfunc(pmdid)->PmdidTypeResult())->OidObjectId();
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::FBoolean
//
// @doc:
// Check to see if the operator returns a boolean result
//
//---------------------------------------------------------------------------
BOOL
CTranslatorDXLToScalar::FBoolean
(
CDXLNode *pdxln,
CMDAccessor *pmda
)
{
GPOS_ASSERT(NULL != pdxln);
if(EdxloptypeScalar != pdxln->Pdxlop()->Edxloperatortype())
{
return false;
}
CDXLScalar *pdxlop = dynamic_cast<CDXLScalar*>(pdxln->Pdxlop());
return pdxlop->FBoolean(pmda);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::FConstTrue
//
// @doc:
// Check if the operator is a "true" bool constant
//
//---------------------------------------------------------------------------
BOOL
CTranslatorDXLToScalar::FConstTrue
(
CDXLNode *pdxln,
CMDAccessor *pmda
)
{
GPOS_ASSERT(NULL != pdxln);
if (!FBoolean(pdxln, pmda) || EdxlopScalarConstValue != pdxln->Pdxlop()->Edxlop())
{
return false;
}
CDXLScalarConstValue *pdxlop = CDXLScalarConstValue::PdxlopConvert(pdxln->Pdxlop());
CDXLDatumBool *pdxldatumbool = CDXLDatumBool::PdxldatumConvert(const_cast<CDXLDatum *>(pdxlop->Pdxldatum()));
return pdxldatumbool->FValue();
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToScalar::FConstNull
//
// @doc:
// Check if the operator is a NULL constant
//
//---------------------------------------------------------------------------
BOOL
CTranslatorDXLToScalar::FConstNull
(
CDXLNode *pdxln
)
{
GPOS_ASSERT(NULL != pdxln);
if (EdxlopScalarConstValue != pdxln->Pdxlop()->Edxlop())
{
return false;
}
CDXLScalarConstValue *pdxlop = CDXLScalarConstValue::PdxlopConvert(pdxln->Pdxlop());
return pdxlop->Pdxldatum()->FNull();
}
// EOF