greenplumn CTranslatorExprToDXL 源码
greenplumn CTranslatorExprToDXL 代码
文件路径:/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp
//---------------------------------------------------------------------------
// Greenplum Database
// Copyright (C) 2011 EMC Corp.
//
// @filename:
// CTranslatorExprToDXL.cpp
//
// @doc:
// Implementation of the methods for translating Optimizer physical expression
// trees into DXL.
//
// @owner:
//
//
// @test:
//
//---------------------------------------------------------------------------
#include "gpopt/translate/CTranslatorExprToDXL.h"
#include "gpos/common/CAutoTimer.h"
#include "gpos/common/CHashMap.h"
#include "gpopt/base/CCastUtils.h"
#include "gpopt/base/CColRefSetIter.h"
#include "gpopt/base/CConstraintInterval.h"
#include "gpopt/base/COptCtxt.h"
#include "gpopt/base/CUtils.h"
#include "gpopt/cost/ICostModel.h"
#include "gpopt/exception.h"
#include "gpopt/mdcache/CMDAccessorUtils.h"
#include "gpopt/operators/CPhysicalAgg.h"
#include "gpopt/operators/CPhysicalAssert.h"
#include "gpopt/operators/CPhysicalBitmapTableScan.h"
#include "gpopt/operators/CPhysicalCTEConsumer.h"
#include "gpopt/operators/CPhysicalCTEProducer.h"
#include "gpopt/operators/CPhysicalConstTableGet.h"
#include "gpopt/operators/CPhysicalCorrelatedLeftOuterNLJoin.h"
#include "gpopt/operators/CPhysicalDML.h"
#include "gpopt/operators/CPhysicalDynamicBitmapTableScan.h"
#include "gpopt/operators/CPhysicalDynamicIndexScan.h"
#include "gpopt/operators/CPhysicalDynamicTableScan.h"
#include "gpopt/operators/CPhysicalHashAgg.h"
#include "gpopt/operators/CPhysicalHashAggDeduplicate.h"
#include "gpopt/operators/CPhysicalHashJoin.h"
#include "gpopt/operators/CPhysicalIndexOnlyScan.h"
#include "gpopt/operators/CPhysicalIndexScan.h"
#include "gpopt/operators/CPhysicalInnerIndexNLJoin.h"
#include "gpopt/operators/CPhysicalLeftOuterIndexNLJoin.h"
#include "gpopt/operators/CPhysicalLimit.h"
#include "gpopt/operators/CPhysicalMotionGather.h"
#include "gpopt/operators/CPhysicalMotionHashDistribute.h"
#include "gpopt/operators/CPhysicalMotionRandom.h"
#include "gpopt/operators/CPhysicalMotionRoutedDistribute.h"
#include "gpopt/operators/CPhysicalNLJoin.h"
#include "gpopt/operators/CPhysicalPartitionSelector.h"
#include "gpopt/operators/CPhysicalRowTrigger.h"
#include "gpopt/operators/CPhysicalScalarAgg.h"
#include "gpopt/operators/CPhysicalSequenceProject.h"
#include "gpopt/operators/CPhysicalSort.h"
#include "gpopt/operators/CPhysicalSplit.h"
#include "gpopt/operators/CPhysicalSpool.h"
#include "gpopt/operators/CPhysicalStreamAgg.h"
#include "gpopt/operators/CPhysicalStreamAggDeduplicate.h"
#include "gpopt/operators/CPhysicalTVF.h"
#include "gpopt/operators/CPhysicalTableScan.h"
#include "gpopt/operators/CPhysicalUnionAll.h"
#include "gpopt/operators/CPredicateUtils.h"
#include "gpopt/operators/CScalarArray.h"
#include "gpopt/operators/CScalarArrayCoerceExpr.h"
#include "gpopt/operators/CScalarArrayRef.h"
#include "gpopt/operators/CScalarAssertConstraint.h"
#include "gpopt/operators/CScalarBitmapBoolOp.h"
#include "gpopt/operators/CScalarBitmapIndexProbe.h"
#include "gpopt/operators/CScalarBooleanTest.h"
#include "gpopt/operators/CScalarCaseTest.h"
#include "gpopt/operators/CScalarCast.h"
#include "gpopt/operators/CScalarCmp.h"
#include "gpopt/operators/CScalarCoalesce.h"
#include "gpopt/operators/CScalarCoerceToDomain.h"
#include "gpopt/operators/CScalarCoerceViaIO.h"
#include "gpopt/operators/CScalarIdent.h"
#include "gpopt/operators/CScalarIf.h"
#include "gpopt/operators/CScalarIsDistinctFrom.h"
#include "gpopt/operators/CScalarMinMax.h"
#include "gpopt/operators/CScalarNullIf.h"
#include "gpopt/operators/CScalarOp.h"
#include "gpopt/operators/CScalarProjectElement.h"
#include "gpopt/operators/CScalarSortGroupClause.h"
#include "gpopt/operators/CScalarSwitch.h"
#include "gpopt/translate/CTranslatorExprToDXLUtils.h"
#include "naucrates/base/CDatumBoolGPDB.h"
#include "naucrates/base/IDatumInt8.h"
#include "naucrates/dxl/operators/CDXLCtasStorageOptions.h"
#include "naucrates/dxl/operators/CDXLDatumBool.h"
#include "naucrates/dxl/operators/CDXLDirectDispatchInfo.h"
#include "naucrates/dxl/operators/CDXLPhysicalAppend.h"
#include "naucrates/dxl/operators/CDXLPhysicalAssert.h"
#include "naucrates/dxl/operators/CDXLPhysicalBitmapTableScan.h"
#include "naucrates/dxl/operators/CDXLPhysicalBroadcastMotion.h"
#include "naucrates/dxl/operators/CDXLPhysicalCTAS.h"
#include "naucrates/dxl/operators/CDXLPhysicalCTEConsumer.h"
#include "naucrates/dxl/operators/CDXLPhysicalCTEProducer.h"
#include "naucrates/dxl/operators/CDXLPhysicalDynamicBitmapTableScan.h"
#include "naucrates/dxl/operators/CDXLPhysicalDynamicIndexScan.h"
#include "naucrates/dxl/operators/CDXLPhysicalDynamicTableScan.h"
#include "naucrates/dxl/operators/CDXLPhysicalExternalScan.h"
#include "naucrates/dxl/operators/CDXLPhysicalGatherMotion.h"
#include "naucrates/dxl/operators/CDXLPhysicalHashJoin.h"
#include "naucrates/dxl/operators/CDXLPhysicalIndexOnlyScan.h"
#include "naucrates/dxl/operators/CDXLPhysicalIndexScan.h"
#include "naucrates/dxl/operators/CDXLPhysicalLimit.h"
#include "naucrates/dxl/operators/CDXLPhysicalMaterialize.h"
#include "naucrates/dxl/operators/CDXLPhysicalMergeJoin.h"
#include "naucrates/dxl/operators/CDXLPhysicalNLJoin.h"
#include "naucrates/dxl/operators/CDXLPhysicalPartitionSelector.h"
#include "naucrates/dxl/operators/CDXLPhysicalRandomMotion.h"
#include "naucrates/dxl/operators/CDXLPhysicalRedistributeMotion.h"
#include "naucrates/dxl/operators/CDXLPhysicalResult.h"
#include "naucrates/dxl/operators/CDXLPhysicalRoutedDistributeMotion.h"
#include "naucrates/dxl/operators/CDXLPhysicalRowTrigger.h"
#include "naucrates/dxl/operators/CDXLPhysicalSequence.h"
#include "naucrates/dxl/operators/CDXLPhysicalSort.h"
#include "naucrates/dxl/operators/CDXLPhysicalSplit.h"
#include "naucrates/dxl/operators/CDXLPhysicalTVF.h"
#include "naucrates/dxl/operators/CDXLPhysicalTableScan.h"
#include "naucrates/dxl/operators/CDXLPhysicalWindow.h"
#include "naucrates/dxl/operators/CDXLScalarAggref.h"
#include "naucrates/dxl/operators/CDXLScalarArray.h"
#include "naucrates/dxl/operators/CDXLScalarArrayCoerceExpr.h"
#include "naucrates/dxl/operators/CDXLScalarArrayComp.h"
#include "naucrates/dxl/operators/CDXLScalarArrayRef.h"
#include "naucrates/dxl/operators/CDXLScalarAssertConstraint.h"
#include "naucrates/dxl/operators/CDXLScalarAssertConstraintList.h"
#include "naucrates/dxl/operators/CDXLScalarBitmapBoolOp.h"
#include "naucrates/dxl/operators/CDXLScalarBitmapIndexProbe.h"
#include "naucrates/dxl/operators/CDXLScalarBooleanTest.h"
#include "naucrates/dxl/operators/CDXLScalarCaseTest.h"
#include "naucrates/dxl/operators/CDXLScalarCast.h"
#include "naucrates/dxl/operators/CDXLScalarCoalesce.h"
#include "naucrates/dxl/operators/CDXLScalarCoerceToDomain.h"
#include "naucrates/dxl/operators/CDXLScalarCoerceViaIO.h"
#include "naucrates/dxl/operators/CDXLScalarComp.h"
#include "naucrates/dxl/operators/CDXLScalarDMLAction.h"
#include "naucrates/dxl/operators/CDXLScalarDistinctComp.h"
#include "naucrates/dxl/operators/CDXLScalarFuncExpr.h"
#include "naucrates/dxl/operators/CDXLScalarHashCondList.h"
#include "naucrates/dxl/operators/CDXLScalarHashExpr.h"
#include "naucrates/dxl/operators/CDXLScalarHashExprList.h"
#include "naucrates/dxl/operators/CDXLScalarIfStmt.h"
#include "naucrates/dxl/operators/CDXLScalarIndexCondList.h"
#include "naucrates/dxl/operators/CDXLScalarJoinFilter.h"
#include "naucrates/dxl/operators/CDXLScalarLimitCount.h"
#include "naucrates/dxl/operators/CDXLScalarLimitOffset.h"
#include "naucrates/dxl/operators/CDXLScalarMergeCondList.h"
#include "naucrates/dxl/operators/CDXLScalarMinMax.h"
#include "naucrates/dxl/operators/CDXLScalarNullIf.h"
#include "naucrates/dxl/operators/CDXLScalarNullTest.h"
#include "naucrates/dxl/operators/CDXLScalarOneTimeFilter.h"
#include "naucrates/dxl/operators/CDXLScalarOpExpr.h"
#include "naucrates/dxl/operators/CDXLScalarOpList.h"
#include "naucrates/dxl/operators/CDXLScalarPartBound.h"
#include "naucrates/dxl/operators/CDXLScalarPartDefault.h"
#include "naucrates/dxl/operators/CDXLScalarPartListNullTest.h"
#include "naucrates/dxl/operators/CDXLScalarProjElem.h"
#include "naucrates/dxl/operators/CDXLScalarProjList.h"
#include "naucrates/dxl/operators/CDXLScalarRecheckCondFilter.h"
#include "naucrates/dxl/operators/CDXLScalarSortCol.h"
#include "naucrates/dxl/operators/CDXLScalarSortColList.h"
#include "naucrates/dxl/operators/CDXLScalarSortGroupClause.h"
#include "naucrates/dxl/operators/CDXLScalarSwitch.h"
#include "naucrates/dxl/operators/CDXLScalarSwitchCase.h"
#include "naucrates/dxl/operators/CDXLScalarValuesList.h"
#include "naucrates/dxl/operators/CDXLScalarWindowFrameEdge.h"
#include "naucrates/dxl/operators/CDXLWindowFrame.h"
#include "naucrates/dxl/operators/CDXLWindowKey.h"
#include "naucrates/exception.h"
#include "naucrates/md/CMDRelationCtasGPDB.h"
#include "naucrates/md/IMDCast.h"
#include "naucrates/md/IMDFunction.h"
#include "naucrates/md/IMDScalarOp.h"
#include "naucrates/md/IMDTypeInt4.h"
#include "naucrates/statistics/CStatistics.h"
#include "naucrates/traceflags/traceflags.h"
using namespace gpos;
using namespace gpmd;
using namespace gpdxl;
using namespace gpopt;
using namespace gpnaucrates;
#define GPOPT_MASTER_SEGMENT_ID (-1)
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::CTranslatorExprToDXL
//
// @doc:
// Ctor
//
//---------------------------------------------------------------------------
CTranslatorExprToDXL::CTranslatorExprToDXL(CMemoryPool *mp,
CMDAccessor *md_accessor,
IntPtrArray *pdrgpiSegments,
BOOL fInitColumnFactory)
: m_mp(mp),
m_pmda(md_accessor),
m_pdpplan(nullptr),
m_pcf(nullptr),
m_pdrgpiSegments(pdrgpiSegments),
m_iMasterId(GPOPT_MASTER_SEGMENT_ID)
{
GPOS_ASSERT(nullptr != mp);
GPOS_ASSERT(nullptr != md_accessor);
GPOS_ASSERT_IMP(nullptr != pdrgpiSegments, (0 < pdrgpiSegments->Size()));
// initialize hash map
m_phmcrdxln = GPOS_NEW(m_mp) ColRefToDXLNodeMap(m_mp);
m_phmcrdxlnIndexLookup = GPOS_NEW(m_mp) ColRefToDXLNodeMap(m_mp);
if (fInitColumnFactory)
{
// get column factory from optimizer context object
m_pcf = COptCtxt::PoctxtFromTLS()->Pcf();
GPOS_ASSERT(nullptr != m_pcf);
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::~CTranslatorExprToDXL
//
// @doc:
// Destructor
//
//---------------------------------------------------------------------------
CTranslatorExprToDXL::~CTranslatorExprToDXL()
{
CRefCount::SafeRelease(m_pdrgpiSegments);
m_phmcrdxln->Release();
m_phmcrdxlnIndexLookup->Release();
CRefCount::SafeRelease(m_pdpplan);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnTranslate
//
// @doc:
// Main driver
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnTranslate(CExpression *pexpr,
CColRefArray *colref_array,
CMDNameArray *pdrgpmdname)
{
CAutoTimer at("\n[OPT]: Expr To DXL Translation Time",
GPOS_FTRACE(EopttracePrintOptimizationStatistics));
GPOS_ASSERT(nullptr == m_pdpplan);
m_pdpplan = CDrvdPropPlan::Pdpplan(pexpr->PdpDerive());
m_pdpplan->AddRef();
CDistributionSpecArray *pdrgpdsBaseTables =
GPOS_NEW(m_mp) CDistributionSpecArray(m_mp);
ULONG ulNonGatherMotions = 0;
BOOL fDML = false;
CDXLNode *dxlnode = CreateDXLNode(pexpr, colref_array, pdrgpdsBaseTables,
&ulNonGatherMotions, &fDML,
true /*fRemap*/, true /*fRoot*/);
if (fDML)
{
pdrgpdsBaseTables->Release();
return dxlnode;
}
CDXLNode *pdxlnPrL = (*dxlnode)[0];
GPOS_ASSERT(EdxlopScalarProjectList ==
pdxlnPrL->GetOperator()->GetDXLOperator());
const ULONG length = pdrgpmdname->Size();
GPOS_ASSERT(length == colref_array->Size());
GPOS_ASSERT(length == pdxlnPrL->Arity());
for (ULONG ul = 0; ul < length; ul++)
{
// desired output column name
CMDName *mdname =
GPOS_NEW(m_mp) CMDName(m_mp, (*pdrgpmdname)[ul]->GetMDName());
// get the old project element for the ColId
CDXLNode *pdxlnPrElOld = (*pdxlnPrL)[ul];
CDXLScalarProjElem *pdxlopPrElOld =
CDXLScalarProjElem::Cast(pdxlnPrElOld->GetOperator());
GPOS_ASSERT(1 == pdxlnPrElOld->Arity());
CDXLNode *child_dxlnode = (*pdxlnPrElOld)[0];
const ULONG colid = pdxlopPrElOld->Id();
// create a new project element node with the col id and new column name
// and add the scalar child
CDXLNode *pdxlnPrElNew = GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarProjElem(m_mp, colid, mdname));
child_dxlnode->AddRef();
pdxlnPrElNew->AddChild(child_dxlnode);
// replace the project element
pdxlnPrL->ReplaceChild(ul, pdxlnPrElNew);
}
if (0 == ulNonGatherMotions)
{
CTranslatorExprToDXLUtils::SetDirectDispatchInfo(
m_mp, m_pmda, dxlnode, pexpr, pdrgpdsBaseTables);
}
pdrgpdsBaseTables->Release();
return dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::CreateDXLNode
//
// @doc:
// Translates an optimizer physical expression tree into DXL.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::CreateDXLNode(CExpression *pexpr,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML,
BOOL fRemap, BOOL fRoot)
{
GPOS_ASSERT(nullptr != pexpr);
ULONG ulOpId = (ULONG) pexpr->Pop()->Eopid();
if (COperator::EopPhysicalTableScan == ulOpId ||
COperator::EopPhysicalExternalScan == ulOpId)
{
CDXLNode *dxlnode = PdxlnTblScan(
pexpr, nullptr /*pcrsOutput*/, colref_array, pdrgpdsBaseTables,
nullptr /* pexprScalarCond */, nullptr /* cost info */);
CTranslatorExprToDXLUtils::SetStats(m_mp, m_pmda, dxlnode,
pexpr->Pstats(), fRoot);
return dxlnode;
}
// add a result node on top to project out columns not needed any further,
// for instance, if the grouping /order by /partition/ distribution columns
// are no longer needed
CDXLNode *pdxlnNew = nullptr;
CDXLNode *dxlnode = nullptr;
switch (pexpr->Pop()->Eopid())
{
case COperator::EopPhysicalFilter:
dxlnode = CTranslatorExprToDXL::PdxlnResult(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalIndexScan:
dxlnode = CTranslatorExprToDXL::PdxlnIndexScan(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalIndexOnlyScan:
dxlnode = CTranslatorExprToDXL::PdxlnIndexOnlyScan(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalBitmapTableScan:
dxlnode = CTranslatorExprToDXL::PdxlnBitmapTableScan(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalComputeScalar:
dxlnode = CTranslatorExprToDXL::PdxlnComputeScalar(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalScalarAgg:
case COperator::EopPhysicalHashAgg:
case COperator::EopPhysicalStreamAgg:
dxlnode = CTranslatorExprToDXL::PdxlnAggregate(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalHashAggDeduplicate:
case COperator::EopPhysicalStreamAggDeduplicate:
dxlnode = CTranslatorExprToDXL::PdxlnAggregateDedup(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalSort:
dxlnode = CTranslatorExprToDXL::PdxlnSort(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalLimit:
dxlnode = CTranslatorExprToDXL::PdxlnLimit(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalSequenceProject:
dxlnode = CTranslatorExprToDXL::PdxlnWindow(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalInnerNLJoin:
case COperator::EopPhysicalInnerIndexNLJoin:
case COperator::EopPhysicalLeftOuterIndexNLJoin:
case COperator::EopPhysicalLeftOuterNLJoin:
case COperator::EopPhysicalLeftSemiNLJoin:
case COperator::EopPhysicalLeftAntiSemiNLJoin:
case COperator::EopPhysicalLeftAntiSemiNLJoinNotIn:
dxlnode = CTranslatorExprToDXL::PdxlnNLJoin(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalCorrelatedInnerNLJoin:
case COperator::EopPhysicalCorrelatedLeftOuterNLJoin:
case COperator::EopPhysicalCorrelatedLeftSemiNLJoin:
case COperator::EopPhysicalCorrelatedInLeftSemiNLJoin:
case COperator::EopPhysicalCorrelatedLeftAntiSemiNLJoin:
case COperator::EopPhysicalCorrelatedNotInLeftAntiSemiNLJoin:
dxlnode = CTranslatorExprToDXL::PdxlnCorrelatedNLJoin(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalInnerHashJoin:
case COperator::EopPhysicalLeftOuterHashJoin:
case COperator::EopPhysicalLeftSemiHashJoin:
case COperator::EopPhysicalLeftAntiSemiHashJoin:
case COperator::EopPhysicalLeftAntiSemiHashJoinNotIn:
case COperator::EopPhysicalRightOuterHashJoin:
dxlnode = CTranslatorExprToDXL::PdxlnHashJoin(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalMotionGather:
case COperator::EopPhysicalMotionBroadcast:
case COperator::EopPhysicalMotionHashDistribute:
case COperator::EopPhysicalMotionRoutedDistribute:
case COperator::EopPhysicalMotionRandom:
dxlnode = CTranslatorExprToDXL::PdxlnMotion(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalSpool:
dxlnode = CTranslatorExprToDXL::PdxlnMaterialize(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalSequence:
dxlnode = CTranslatorExprToDXL::PdxlnSequence(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalDynamicTableScan:
dxlnode = CTranslatorExprToDXL::PdxlnDynamicTableScan(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalDynamicBitmapTableScan:
dxlnode = CTranslatorExprToDXL::PdxlnDynamicBitmapTableScan(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalDynamicIndexScan:
dxlnode = CTranslatorExprToDXL::PdxlnDynamicIndexScan(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalPartitionSelector:
dxlnode = CTranslatorExprToDXL::PdxlnPartitionSelector(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalConstTableGet:
dxlnode = CTranslatorExprToDXL::PdxlnResultFromConstTableGet(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalTVF:
dxlnode = CTranslatorExprToDXL::PdxlnTVF(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalSerialUnionAll:
case COperator::EopPhysicalParallelUnionAll:
dxlnode = CTranslatorExprToDXL::PdxlnAppend(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalDML:
dxlnode = CTranslatorExprToDXL::PdxlnDML(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalSplit:
dxlnode = CTranslatorExprToDXL::PdxlnSplit(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalRowTrigger:
dxlnode = CTranslatorExprToDXL::PdxlnRowTrigger(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalAssert:
dxlnode = CTranslatorExprToDXL::PdxlnAssert(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalCTEProducer:
dxlnode = CTranslatorExprToDXL::PdxlnCTEProducer(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalCTEConsumer:
dxlnode = CTranslatorExprToDXL::PdxlnCTEConsumer(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
case COperator::EopPhysicalFullMergeJoin:
dxlnode = CTranslatorExprToDXL::PdxlnMergeJoin(
pexpr, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
break;
default:
GPOS_RAISE(gpopt::ExmaGPOPT, gpopt::ExmiUnsupportedOp,
pexpr->Pop()->SzId());
return nullptr;
}
if (!fRemap ||
EdxlopPhysicalDML == dxlnode->GetOperator()->GetDXLOperator())
{
pdxlnNew = dxlnode;
}
else
{
CColRefArray *pdrgpcrRequired = nullptr;
if (EdxlopPhysicalCTAS == dxlnode->GetOperator()->GetDXLOperator())
{
colref_array->AddRef();
pdrgpcrRequired = colref_array;
}
else
{
pdrgpcrRequired = pexpr->Prpp()->PcrsRequired()->Pdrgpcr(m_mp);
}
pdxlnNew = PdxlnRemapOutputColumns(pexpr, dxlnode, pdrgpcrRequired,
colref_array);
pdrgpcrRequired->Release();
}
if (nullptr == pdxlnNew->GetProperties()->GetDxlStatsDrvdRelation())
{
CTranslatorExprToDXLUtils::SetStats(m_mp, m_pmda, pdxlnNew,
pexpr->Pstats(), fRoot);
}
return pdxlnNew;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScalar
//
// @doc:
// Translates an optimizer scalar expression tree into DXL. Any column
// refs that are members of the input colrefset are replaced by the input
// subplan node
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScalar(CExpression *pexpr)
{
GPOS_ASSERT(nullptr != pexpr);
switch (pexpr->Pop()->Eopid())
{
case COperator::EopScalarIdent:
return CTranslatorExprToDXL::PdxlnScId(pexpr);
case COperator::EopScalarCmp:
return CTranslatorExprToDXL::PdxlnScCmp(pexpr);
case COperator::EopScalarIsDistinctFrom:
return CTranslatorExprToDXL::PdxlnScDistinctCmp(pexpr);
case COperator::EopScalarOp:
return CTranslatorExprToDXL::PdxlnScOp(pexpr);
case COperator::EopScalarBoolOp:
return CTranslatorExprToDXL::PdxlnScBoolExpr(pexpr);
case COperator::EopScalarConst:
return CTranslatorExprToDXL::PdxlnScConst(pexpr);
case COperator::EopScalarSortGroupClause:
return CTranslatorExprToDXL::PdxlnScSortGroupClause(pexpr);
case COperator::EopScalarFunc:
return CTranslatorExprToDXL::PdxlnScFuncExpr(pexpr);
case COperator::EopScalarWindowFunc:
return CTranslatorExprToDXL::PdxlnScWindowFuncExpr(pexpr);
case COperator::EopScalarAggFunc:
return CTranslatorExprToDXL::PdxlnScAggref(pexpr);
case COperator::EopScalarNullIf:
return CTranslatorExprToDXL::PdxlnScNullIf(pexpr);
case COperator::EopScalarNullTest:
return CTranslatorExprToDXL::PdxlnScNullTest(pexpr);
case COperator::EopScalarBooleanTest:
return CTranslatorExprToDXL::PdxlnScBooleanTest(pexpr);
case COperator::EopScalarIf:
return CTranslatorExprToDXL::PdxlnScIfStmt(pexpr);
case COperator::EopScalarSwitch:
return CTranslatorExprToDXL::PdxlnScSwitch(pexpr);
case COperator::EopScalarSwitchCase:
return CTranslatorExprToDXL::PdxlnScSwitchCase(pexpr);
case COperator::EopScalarCaseTest:
return CTranslatorExprToDXL::PdxlnScCaseTest(pexpr);
case COperator::EopScalarCoalesce:
return CTranslatorExprToDXL::PdxlnScCoalesce(pexpr);
case COperator::EopScalarMinMax:
return CTranslatorExprToDXL::PdxlnScMinMax(pexpr);
case COperator::EopScalarCast:
return CTranslatorExprToDXL::PdxlnScCast(pexpr);
case COperator::EopScalarCoerceToDomain:
return CTranslatorExprToDXL::PdxlnScCoerceToDomain(pexpr);
case COperator::EopScalarCoerceViaIO:
return CTranslatorExprToDXL::PdxlnScCoerceViaIO(pexpr);
case COperator::EopScalarArrayCoerceExpr:
return CTranslatorExprToDXL::PdxlnScArrayCoerceExpr(pexpr);
case COperator::EopScalarArray:
return CTranslatorExprToDXL::PdxlnArray(pexpr);
case COperator::EopScalarValuesList:
return CTranslatorExprToDXL::PdxlnValuesList(pexpr);
case COperator::EopScalarArrayCmp:
return CTranslatorExprToDXL::PdxlnArrayCmp(pexpr);
case COperator::EopScalarArrayRef:
return CTranslatorExprToDXL::PdxlnArrayRef(pexpr);
case COperator::EopScalarArrayRefIndexList:
return CTranslatorExprToDXL::PdxlnArrayRefIndexList(pexpr);
case COperator::EopScalarAssertConstraintList:
return CTranslatorExprToDXL::PdxlnAssertPredicate(pexpr);
case COperator::EopScalarAssertConstraint:
return CTranslatorExprToDXL::PdxlnAssertConstraint(pexpr);
case COperator::EopScalarDMLAction:
return CTranslatorExprToDXL::PdxlnDMLAction(pexpr);
case COperator::EopScalarBitmapIndexProbe:
return CTranslatorExprToDXL::PdxlnBitmapIndexProbe(pexpr);
case COperator::EopScalarBitmapBoolOp:
return CTranslatorExprToDXL::PdxlnBitmapBoolOp(pexpr);
default:
GPOS_RAISE(gpopt::ExmaGPOPT, gpopt::ExmiUnsupportedOp,
pexpr->Pop()->SzId());
return nullptr;
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnTblScan
//
// @doc:
// Create a DXL table scan node from an optimizer table scan node
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnTblScan(CExpression *pexprTblScan,
CColRefSet *pcrsOutput,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
CExpression *pexprScalar,
CDXLPhysicalProperties *dxl_properties)
{
GPOS_ASSERT(nullptr != pexprTblScan);
CPhysicalTableScan *popTblScan =
CPhysicalTableScan::PopConvert(pexprTblScan->Pop());
CColRefArray *pdrgpcrOutput = popTblScan->PdrgpcrOutput();
// translate table descriptor
CDXLTableDescr *table_descr = MakeDXLTableDescr(
popTblScan->Ptabdesc(), pdrgpcrOutput, pexprTblScan->Prpp());
// construct plan costs, if there are not passed as a parameter
if (nullptr == dxl_properties)
{
dxl_properties = GetProperties(pexprTblScan);
}
// construct scan operator
CDXLPhysicalTableScan *pdxlopTS = nullptr;
COperator::EOperatorId op_id = pexprTblScan->Pop()->Eopid();
if (COperator::EopPhysicalTableScan == op_id)
{
pdxlopTS = GPOS_NEW(m_mp) CDXLPhysicalTableScan(m_mp, table_descr);
}
else
{
GPOS_ASSERT(COperator::EopPhysicalExternalScan == op_id);
pdxlopTS = GPOS_NEW(m_mp) CDXLPhysicalExternalScan(m_mp, table_descr);
}
CDXLNode *pdxlnTblScan = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopTS);
pdxlnTblScan->SetProperties(dxl_properties);
// construct projection list
GPOS_ASSERT(nullptr != pexprTblScan->Prpp());
// if the output columns are passed from above then use them
if (nullptr == pcrsOutput)
{
pcrsOutput = pexprTblScan->Prpp()->PcrsRequired();
}
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, colref_array);
CDXLNode *pdxlnCond = nullptr;
if (nullptr != pexprScalar)
{
pdxlnCond = PdxlnScalar(pexprScalar);
}
CDXLNode *filter_dxlnode = PdxlnFilter(pdxlnCond);
// add children in the right order
pdxlnTblScan->AddChild(pdxlnPrL); // project list
pdxlnTblScan->AddChild(filter_dxlnode); // filter
#ifdef GPOS_DEBUG
pdxlnTblScan->GetOperator()->AssertValid(pdxlnTblScan,
false /* validate_children */);
#endif
CDistributionSpec *pds = pexprTblScan->GetDrvdPropPlan()->Pds();
pds->AddRef();
pdrgpdsBaseTables->Append(pds);
return pdxlnTblScan;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnIndexScan
//
// @doc:
// Create a DXL index scan node from an optimizer index scan node based
// on passed properties
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnIndexScan(CExpression *pexprIndexScan,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *, // pulNonGatherMotions,
BOOL * // pfDML
)
{
GPOS_ASSERT(nullptr != pexprIndexScan);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprIndexScan);
COptCtxt::PoctxtFromTLS()->AddDirectDispatchableFilterCandidate(
pexprIndexScan);
CDistributionSpec *pds = pexprIndexScan->GetDrvdPropPlan()->Pds();
pds->AddRef();
pdrgpdsBaseTables->Append(pds);
return PdxlnIndexScan(pexprIndexScan, colref_array, dxl_properties,
pexprIndexScan->Prpp());
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnIndexScan
//
// @doc:
// Create a DXL index scan node from an optimizer index scan node
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnIndexScan(CExpression *pexprIndexScan,
CColRefArray *colref_array,
CDXLPhysicalProperties *dxl_properties,
CReqdPropPlan *prpp)
{
GPOS_ASSERT(nullptr != pexprIndexScan);
GPOS_ASSERT(nullptr != dxl_properties);
GPOS_ASSERT(nullptr != prpp);
CPhysicalIndexScan *popIs =
CPhysicalIndexScan::PopConvert(pexprIndexScan->Pop());
CColRefArray *pdrgpcrOutput = popIs->PdrgpcrOutput();
// translate table descriptor
CDXLTableDescr *table_descr = MakeDXLTableDescr(
popIs->Ptabdesc(), pdrgpcrOutput, pexprIndexScan->Prpp());
// create index descriptor
CIndexDescriptor *pindexdesc = popIs->Pindexdesc();
CMDName *pmdnameIndex =
GPOS_NEW(m_mp) CMDName(m_mp, pindexdesc->Name().Pstr());
IMDId *pmdidIndex = pindexdesc->MDId();
pmdidIndex->AddRef();
CDXLIndexDescr *dxl_index_descr =
GPOS_NEW(m_mp) CDXLIndexDescr(pmdidIndex, pmdnameIndex);
// TODO: vrgahavan; we assume that the index are always forward access.
// create the physical index scan operator
CDXLPhysicalIndexScan *dxl_op = GPOS_NEW(m_mp) CDXLPhysicalIndexScan(
m_mp, table_descr, dxl_index_descr, EdxlisdForward);
CDXLNode *pdxlnIndexScan = GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op);
// set properties
pdxlnIndexScan->SetProperties(dxl_properties);
// translate project list
CColRefSet *pcrsOutput = prpp->PcrsRequired();
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, colref_array);
// translate index predicates
CExpression *pexprCond = (*pexprIndexScan)[0];
CDXLNode *pdxlnIndexCondList = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarIndexCondList(m_mp));
CExpressionArray *pdrgpexprConds =
CPredicateUtils::PdrgpexprConjuncts(m_mp, pexprCond);
const ULONG length = pdrgpexprConds->Size();
for (ULONG ul = 0; ul < length; ul++)
{
CExpression *pexprIndexCond = (*pdrgpexprConds)[ul];
CDXLNode *pdxlnIndexCond = PdxlnScalar(pexprIndexCond);
pdxlnIndexCondList->AddChild(pdxlnIndexCond);
}
pdrgpexprConds->Release();
CDXLNode *pdxlnResidualCond = nullptr;
if (2 == pexprIndexScan->Arity())
{
// translate residual predicates into the filter node
CExpression *pexprResidualCond = (*pexprIndexScan)[1];
if (COperator::EopScalarConst != pexprResidualCond->Pop()->Eopid())
{
pdxlnResidualCond = PdxlnScalar(pexprResidualCond);
}
}
CDXLNode *filter_dxlnode = PdxlnFilter(pdxlnResidualCond);
pdxlnIndexScan->AddChild(pdxlnPrL);
pdxlnIndexScan->AddChild(filter_dxlnode);
pdxlnIndexScan->AddChild(pdxlnIndexCondList);
#ifdef GPOS_DEBUG
pdxlnIndexScan->GetOperator()->AssertValid(pdxlnIndexScan,
false /* validate_children */);
#endif
return pdxlnIndexScan;
}
CDXLNode *
CTranslatorExprToDXL::PdxlnIndexOnlyScan(
CExpression *pexprIndexOnlyScan, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *, // pulNonGatherMotions,
BOOL * // pfDML
)
{
GPOS_ASSERT(nullptr != pexprIndexOnlyScan);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprIndexOnlyScan);
COptCtxt::PoctxtFromTLS()->AddDirectDispatchableFilterCandidate(
pexprIndexOnlyScan);
CDistributionSpec *pds = pexprIndexOnlyScan->GetDrvdPropPlan()->Pds();
pds->AddRef();
pdrgpdsBaseTables->Append(pds);
return PdxlnIndexOnlyScan(pexprIndexOnlyScan, colref_array, dxl_properties,
pexprIndexOnlyScan->Prpp());
}
CDXLNode *
CTranslatorExprToDXL::PdxlnIndexOnlyScan(CExpression *pexprIndexOnlyScan,
CColRefArray *colref_array,
CDXLPhysicalProperties *dxl_properties,
CReqdPropPlan *prpp)
{
GPOS_ASSERT(nullptr != pexprIndexOnlyScan);
GPOS_ASSERT(nullptr != dxl_properties);
GPOS_ASSERT(nullptr != prpp);
CPhysicalIndexOnlyScan *popIs =
CPhysicalIndexOnlyScan::PopConvert(pexprIndexOnlyScan->Pop());
CColRefArray *pdrgpcrOutput = popIs->PdrgpcrOutput();
// translate table descriptor
CDXLTableDescr *table_descr = MakeDXLTableDescr(
popIs->Ptabdesc(), pdrgpcrOutput, pexprIndexOnlyScan->Prpp());
// create index descriptor
CIndexDescriptor *pindexdesc = popIs->Pindexdesc();
CMDName *pmdnameIndex =
GPOS_NEW(m_mp) CMDName(m_mp, pindexdesc->Name().Pstr());
IMDId *pmdidIndex = pindexdesc->MDId();
pmdidIndex->AddRef();
CDXLIndexDescr *dxl_index_descr =
GPOS_NEW(m_mp) CDXLIndexDescr(pmdidIndex, pmdnameIndex);
// TODO: vrgahavan; we assume that the index are always forward access.
// create the physical index scan operator
CDXLPhysicalIndexOnlyScan *dxl_op =
GPOS_NEW(m_mp) CDXLPhysicalIndexOnlyScan(
m_mp, table_descr, dxl_index_descr, EdxlisdForward);
CDXLNode *pdxlnIndexOnlyScan = GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op);
// set properties
pdxlnIndexOnlyScan->SetProperties(dxl_properties);
// translate project list
CColRefSet *pcrsOutput = prpp->PcrsRequired();
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, colref_array);
// translate index predicates
CExpression *pexprCond = (*pexprIndexOnlyScan)[0];
CDXLNode *pdxlnIndexCondList = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarIndexCondList(m_mp));
CExpressionArray *pdrgpexprConds =
CPredicateUtils::PdrgpexprConjuncts(m_mp, pexprCond);
const ULONG length = pdrgpexprConds->Size();
for (ULONG ul = 0; ul < length; ul++)
{
CExpression *pexprIndexCond = (*pdrgpexprConds)[ul];
CDXLNode *pdxlnIndexCond = PdxlnScalar(pexprIndexCond);
pdxlnIndexCondList->AddChild(pdxlnIndexCond);
}
pdrgpexprConds->Release();
CDXLNode *pdxlnResidualCond = nullptr;
if (2 == pexprIndexOnlyScan->Arity())
{
// translate residual predicates into the filter node
CExpression *pexprResidualCond = (*pexprIndexOnlyScan)[1];
if (COperator::EopScalarConst != pexprResidualCond->Pop()->Eopid())
{
pdxlnResidualCond = PdxlnScalar(pexprResidualCond);
}
}
CDXLNode *filter_dxlnode = PdxlnFilter(pdxlnResidualCond);
pdxlnIndexOnlyScan->AddChild(pdxlnPrL);
pdxlnIndexOnlyScan->AddChild(filter_dxlnode);
pdxlnIndexOnlyScan->AddChild(pdxlnIndexCondList);
#ifdef GPOS_DEBUG
pdxlnIndexOnlyScan->GetOperator()->AssertValid(
pdxlnIndexOnlyScan, false /* validate_children */);
#endif
return pdxlnIndexOnlyScan;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnBitmapIndexProbe
//
// @doc:
// Create a DXL scalar bitmap index probe from an optimizer
// scalar bitmap index probe operator.
//
// GPDB_12_MERGE_FIXME: whenever we modify this function, we may
// as well consider updating PdxlnBitmapIndexProbeForChildPart().
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnBitmapIndexProbe(CExpression *pexprBitmapIndexProbe)
{
GPOS_ASSERT(nullptr != pexprBitmapIndexProbe);
CScalarBitmapIndexProbe *pop =
CScalarBitmapIndexProbe::PopConvert(pexprBitmapIndexProbe->Pop());
// create index descriptor
CIndexDescriptor *pindexdesc = pop->Pindexdesc();
CMDName *pmdnameIndex =
GPOS_NEW(m_mp) CMDName(m_mp, pindexdesc->Name().Pstr());
IMDId *pmdidIndex = pindexdesc->MDId();
pmdidIndex->AddRef();
CDXLIndexDescr *dxl_index_descr =
GPOS_NEW(m_mp) CDXLIndexDescr(pmdidIndex, pmdnameIndex);
CDXLScalarBitmapIndexProbe *dxl_op =
GPOS_NEW(m_mp) CDXLScalarBitmapIndexProbe(m_mp, dxl_index_descr);
CDXLNode *pdxlnBitmapIndexProbe = GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op);
// translate index predicates
CExpression *pexprCond = (*pexprBitmapIndexProbe)[0];
CDXLNode *pdxlnIndexCondList = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarIndexCondList(m_mp));
CExpressionArray *pdrgpexprConds =
CPredicateUtils::PdrgpexprConjuncts(m_mp, pexprCond);
const ULONG length = pdrgpexprConds->Size();
for (ULONG ul = 0; ul < length; ul++)
{
CExpression *pexprIndexCond = (*pdrgpexprConds)[ul];
CDXLNode *pdxlnIndexCond = PdxlnScalar(pexprIndexCond);
pdxlnIndexCondList->AddChild(pdxlnIndexCond);
}
pdrgpexprConds->Release();
pdxlnBitmapIndexProbe->AddChild(pdxlnIndexCondList);
#ifdef GPOS_DEBUG
pdxlnBitmapIndexProbe->GetOperator()->AssertValid(
pdxlnBitmapIndexProbe, false /*validate_children*/);
#endif
return pdxlnBitmapIndexProbe;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnBitmapBoolOp
//
// @doc:
// Create a DXL scalar bitmap boolean operator from an optimizer
// scalar bitmap boolean operator operator.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnBitmapBoolOp(CExpression *pexprBitmapBoolOp)
{
GPOS_ASSERT(nullptr != pexprBitmapBoolOp);
GPOS_ASSERT(2 == pexprBitmapBoolOp->Arity());
CScalarBitmapBoolOp *popBitmapBoolOp =
CScalarBitmapBoolOp::PopConvert(pexprBitmapBoolOp->Pop());
CExpression *pexprLeft = (*pexprBitmapBoolOp)[0];
CExpression *pexprRight = (*pexprBitmapBoolOp)[1];
CDXLNode *dxlnode_left = PdxlnScalar(pexprLeft);
CDXLNode *dxlnode_right = PdxlnScalar(pexprRight);
IMDId *mdid_type = popBitmapBoolOp->MdidType();
mdid_type->AddRef();
CDXLScalarBitmapBoolOp::EdxlBitmapBoolOp edxlbitmapop =
CDXLScalarBitmapBoolOp::EdxlbitmapAnd;
if (CScalarBitmapBoolOp::EbitmapboolOr == popBitmapBoolOp->Ebitmapboolop())
{
edxlbitmapop = CDXLScalarBitmapBoolOp::EdxlbitmapOr;
}
return GPOS_NEW(m_mp) CDXLNode(
m_mp,
GPOS_NEW(m_mp) CDXLScalarBitmapBoolOp(m_mp, mdid_type, edxlbitmapop),
dxlnode_left, dxlnode_right);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnBitmapTableScan
//
// @doc:
// Create a DXL physical bitmap table scan from an optimizer
// physical bitmap table scan operator.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnBitmapTableScan(
CExpression *pexprBitmapTableScan, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *, // pulNonGatherMotions,
BOOL * // pfDML
)
{
return PdxlnBitmapTableScan(pexprBitmapTableScan,
nullptr, // pcrsOutput
colref_array, pdrgpdsBaseTables,
nullptr, // pexprScalar
nullptr // dxl_properties
);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::AddBitmapFilterColumns
//
// @doc:
// Add used columns in the bitmap recheck and the remaining scalar filter
// condition to the required output column
//---------------------------------------------------------------------------
void
CTranslatorExprToDXL::AddBitmapFilterColumns(
CMemoryPool *mp, CPhysicalScan *pop, CExpression *pexprRecheckCond,
CExpression *pexprScalar,
CColRefSet *pcrsReqdOutput // append the required column reference
)
{
GPOS_ASSERT(nullptr != pop);
GPOS_ASSERT(COperator::EopPhysicalDynamicBitmapTableScan == pop->Eopid() ||
COperator::EopPhysicalBitmapTableScan == pop->Eopid());
GPOS_ASSERT(nullptr != pcrsReqdOutput);
// compute what additional columns are required in the output of the (Dynamic) Bitmap Table Scan
CColRefSet *pcrsAdditional = GPOS_NEW(mp) CColRefSet(mp);
if (nullptr != pexprRecheckCond)
{
// add the columns used in the recheck condition
pcrsAdditional->Include(pexprRecheckCond->DeriveUsedColumns());
}
if (nullptr != pexprScalar)
{
// add the columns used in the filter condition
pcrsAdditional->Include(pexprScalar->DeriveUsedColumns());
}
CColRefSet *pcrsBitmap = GPOS_NEW(mp) CColRefSet(mp);
pcrsBitmap->Include(pop->PdrgpcrOutput());
// only keep the columns that are in the table associated with the bitmap
pcrsAdditional->Intersection(pcrsBitmap);
if (0 < pcrsAdditional->Size())
{
pcrsReqdOutput->Include(pcrsAdditional);
}
// clean up
pcrsAdditional->Release();
pcrsBitmap->Release();
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnBitmapTableScan
//
// @doc:
// Create a DXL physical bitmap table scan from an optimizer
// physical bitmap table scan operator.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnBitmapTableScan(
CExpression *pexprBitmapTableScan, CColRefSet *pcrsOutput,
CColRefArray *colref_array, CDistributionSpecArray *pdrgpdsBaseTables,
CExpression *pexprScalar, CDXLPhysicalProperties *dxl_properties)
{
GPOS_ASSERT(nullptr != pexprBitmapTableScan);
CPhysicalBitmapTableScan *pop =
CPhysicalBitmapTableScan::PopConvert(pexprBitmapTableScan->Pop());
COptCtxt::PoctxtFromTLS()->AddDirectDispatchableFilterCandidate(
pexprBitmapTableScan);
// translate table descriptor
CDXLTableDescr *table_descr = MakeDXLTableDescr(
pop->Ptabdesc(), pop->PdrgpcrOutput(), pexprBitmapTableScan->Prpp());
CDXLPhysicalBitmapTableScan *dxl_op =
GPOS_NEW(m_mp) CDXLPhysicalBitmapTableScan(m_mp, table_descr);
CDXLNode *pdxlnBitmapTableScan = GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op);
// set properties
// construct plan costs, if there are not passed as a parameter
if (nullptr == dxl_properties)
{
dxl_properties = GetProperties(pexprBitmapTableScan);
}
pdxlnBitmapTableScan->SetProperties(dxl_properties);
// build projection list
if (nullptr == pcrsOutput)
{
pcrsOutput = pexprBitmapTableScan->Prpp()->PcrsRequired();
}
// translate scalar predicate into DXL filter only if it is not redundant
CExpression *pexprRecheckCond = (*pexprBitmapTableScan)[0];
CDXLNode *pdxlnCond = nullptr;
if (nullptr != pexprScalar && !CUtils::FScalarConstTrue(pexprScalar) &&
!pexprScalar->Matches(pexprRecheckCond))
{
pdxlnCond = PdxlnScalar(pexprScalar);
}
CDXLNode *filter_dxlnode = PdxlnFilter(pdxlnCond);
CDXLNode *pdxlnRecheckCond = PdxlnScalar(pexprRecheckCond);
CDXLNode *pdxlnRecheckCondFilter = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarRecheckCondFilter(m_mp),
pdxlnRecheckCond);
AddBitmapFilterColumns(m_mp, pop, pexprRecheckCond, pexprScalar,
pcrsOutput);
CDXLNode *proj_list_dxlnode = PdxlnProjList(pcrsOutput, colref_array);
// translate bitmap access path
CDXLNode *pdxlnBitmapIndexPath = PdxlnScalar((*pexprBitmapTableScan)[1]);
pdxlnBitmapTableScan->AddChild(proj_list_dxlnode);
pdxlnBitmapTableScan->AddChild(filter_dxlnode);
pdxlnBitmapTableScan->AddChild(pdxlnRecheckCondFilter);
pdxlnBitmapTableScan->AddChild(pdxlnBitmapIndexPath);
#ifdef GPOS_DEBUG
pdxlnBitmapTableScan->GetOperator()->AssertValid(
pdxlnBitmapTableScan, false /*validate_children*/);
#endif
CDistributionSpec *pds = pexprBitmapTableScan->GetDrvdPropPlan()->Pds();
pds->AddRef();
pdrgpdsBaseTables->Append(pds);
return pdxlnBitmapTableScan;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnDynamicTableScan
//
// @doc:
// Create a DXL dynamic table scan node from an optimizer
// dynamic table scan node.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnDynamicTableScan(
CExpression *pexprDTS, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *, // pulNonGatherMotions,
BOOL * // pfDML
)
{
CExpression *pexprScalarCond = nullptr;
CDXLPhysicalProperties *dxl_properties = nullptr;
return PdxlnDynamicTableScan(pexprDTS, colref_array, pdrgpdsBaseTables,
pexprScalarCond, dxl_properties);
}
// Construct a dxl table descr for a child partition
CTableDescriptor *
CTranslatorExprToDXL::MakeTableDescForPart(const IMDRelation *part,
CTableDescriptor *root_table_desc)
{
IMDId *part_mdid = part->MDId();
part_mdid->AddRef();
CTableDescriptor *table_descr = GPOS_NEW(m_mp) CTableDescriptor(
m_mp, part_mdid, part->Mdname().GetMDName(),
part->ConvertHashToRandom(), part->GetRelDistribution(),
part->RetrieveRelStorageType(), root_table_desc->GetExecuteAsUserId(),
root_table_desc->LockMode());
for (ULONG ul = 0; ul < part->ColumnCount(); ++ul)
{
const IMDColumn *mdCol = part->GetMdCol(ul);
if (mdCol->IsDropped())
{
continue;
}
CWStringConst strColName{m_mp,
mdCol->Mdname().GetMDName()->GetBuffer()};
CName colname(m_mp, &strColName);
CColumnDescriptor *coldesc = GPOS_NEW(m_mp)
CColumnDescriptor(m_mp, m_pmda->RetrieveType(mdCol->MdidType()),
mdCol->TypeModifier(), colname, mdCol->AttrNum(),
mdCol->IsNullable(), mdCol->Length());
table_descr->AddColumn(coldesc);
}
return table_descr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnIndexDescForPart
//
// @doc:
// Construct a dxl index descriptor for a child partition
//
//---------------------------------------------------------------------------
CDXLIndexDescr *
CTranslatorExprToDXL::PdxlnIndexDescForPart(CMemoryPool *m_mp,
MdidHashSet *child_index_mdids_set,
const IMDRelation *part,
const CWStringConst *index_name)
{
// iterate over each index in the child to find the matching index
IMDId *found_index = nullptr;
for (ULONG j = 0; j < part->IndexCount(); ++j)
{
IMDId *pmdidPartIndex = part->IndexMDidAt(j);
if (child_index_mdids_set->Contains(pmdidPartIndex))
{
found_index = pmdidPartIndex;
break;
}
}
GPOS_ASSERT(nullptr != found_index);
found_index->AddRef();
// create index descriptor (this name is the parent name, but isn't displayed in the plan)
CMDName *pmdnameIndex = GPOS_NEW(m_mp) CMDName(m_mp, index_name);
CDXLIndexDescr *dxl_index_descr =
GPOS_NEW(m_mp) CDXLIndexDescr(found_index, pmdnameIndex);
return dxl_index_descr;
}
// Translate CPhysicalDynamicTableScan node. It creates a CDXLPhysicalAppend
// node over a number of CDXLPhysicalTableScan nodes - one for each unpruned
// child partition of the root partition in CPhysicalDynamicTableScan.
//
// To handle dropped and re-ordered columns, the project list and any filter
// expression from the root table are modified using the per partition mappings
// for each child CDXLPhysicalTableScan
CDXLNode *
CTranslatorExprToDXL::PdxlnDynamicTableScan(
CExpression *pexprDTS, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables, CExpression *pexprScalarCond,
CDXLPhysicalProperties *dxl_properties)
{
GPOS_ASSERT(nullptr != pexprDTS);
GPOS_ASSERT_IFF(nullptr != pexprScalarCond, nullptr != dxl_properties);
CPhysicalDynamicTableScan *popDTS =
CPhysicalDynamicTableScan::PopConvert(pexprDTS->Pop());
CColRefArray *pdrgpcrOutput = popDTS->PdrgpcrOutput();
// translate table descriptor
CDXLTableDescr *table_descr =
MakeDXLTableDescr(popDTS->Ptabdesc(), pdrgpcrOutput, pexprDTS->Prpp());
// construct plan costs
CDXLPhysicalProperties *pdxlpropDTS = GetProperties(pexprDTS);
if (nullptr != dxl_properties)
{
CWStringDynamic *rows_out_str = GPOS_NEW(m_mp) CWStringDynamic(
m_mp,
dxl_properties->GetDXLOperatorCost()->GetRowsOutStr()->GetBuffer());
CWStringDynamic *pstrCost = GPOS_NEW(m_mp)
CWStringDynamic(m_mp, dxl_properties->GetDXLOperatorCost()
->GetTotalCostStr()
->GetBuffer());
pdxlpropDTS->GetDXLOperatorCost()->SetRows(rows_out_str);
pdxlpropDTS->GetDXLOperatorCost()->SetCost(pstrCost);
dxl_properties->Release();
}
// construct dynamic table scan operator
IMdIdArray *part_mdids = popDTS->GetPartitionMdids();
part_mdids->AddRef();
ULongPtrArray *selector_ids = GPOS_NEW(m_mp) ULongPtrArray(m_mp);
CPartitionPropagationSpec *pps_reqd =
pexprDTS->Prpp()->Pepp()->PppsRequired();
if (pps_reqd->Contains(popDTS->ScanId()))
{
const CBitSet *bs = pps_reqd->SelectorIds(popDTS->ScanId());
CBitSetIter bsi(*bs);
for (ULONG ul = 0; bsi.Advance(); ul++)
{
selector_ids->Append(GPOS_NEW(m_mp) ULONG(bsi.Bit()));
}
}
CDXLPhysicalDynamicTableScan *pdxlopDTS =
GPOS_NEW(m_mp) CDXLPhysicalDynamicTableScan(m_mp, table_descr,
part_mdids, selector_ids);
CDXLNode *pdxlnDTS = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopDTS);
pdxlnDTS->SetProperties(pdxlpropDTS);
CDXLNode *pdxlnCond = nullptr;
if (nullptr != pexprScalarCond)
{
pdxlnCond = PdxlnScalar(pexprScalarCond);
}
CDXLNode *filter_dxlnode = PdxlnFilter(pdxlnCond);
// construct projection list
GPOS_ASSERT(nullptr != pexprDTS->Prpp());
CColRefSet *pcrsOutput = pexprDTS->Prpp()->PcrsRequired();
pdxlnDTS->AddChild(PdxlnProjList(pcrsOutput, colref_array));
pdxlnDTS->AddChild(filter_dxlnode);
#ifdef GPOS_DEBUG
pdxlnDTS->GetOperator()->AssertValid(pdxlnDTS, false);
#endif
CDistributionSpec *pds = pexprDTS->GetDrvdPropPlan()->Pds();
pds->AddRef();
pdrgpdsBaseTables->Append(pds);
return pdxlnDTS;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnDynamicBitmapTableScan
//
// @doc:
// Create a DXL dynamic bitmap table scan node from an optimizer
// dynamic bitmap table scan node.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnDynamicBitmapTableScan(
CExpression *pexprScan, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *, // pulNonGatherMotions,
BOOL * // pfDML
)
{
CExpression *pexprScalar = nullptr;
CDXLPhysicalProperties *dxl_properties = nullptr;
return PdxlnDynamicBitmapTableScan(pexprScan, colref_array,
pdrgpdsBaseTables, pexprScalar,
dxl_properties);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnDynamicBitmapTableScan
//
// @doc:
// Create a DXL dynamic bitmap table scan node from an optimizer
// dynamic bitmap table scan node.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnDynamicBitmapTableScan(
CExpression *pexprScan, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables, CExpression *pexprScalar,
CDXLPhysicalProperties *dxl_properties)
{
GPOS_ASSERT(nullptr != pexprScan);
CPhysicalDynamicBitmapTableScan *pop =
CPhysicalDynamicBitmapTableScan::PopConvert(pexprScan->Pop());
CColRefArray *pdrgpcrOutput = pop->PdrgpcrOutput();
CDXLTableDescr *table_descr =
MakeDXLTableDescr(pop->Ptabdesc(), pdrgpcrOutput, pexprScan->Prpp());
// construct dynamic table scan operator
IMdIdArray *part_mdids = pop->GetPartitionMdids();
part_mdids->AddRef();
ULongPtrArray *selector_ids = GPOS_NEW(m_mp) ULongPtrArray(m_mp);
CPartitionPropagationSpec *pps_reqd =
pexprScan->Prpp()->Pepp()->PppsRequired();
if (pps_reqd->Contains(pop->ScanId()))
{
const CBitSet *bs = pps_reqd->SelectorIds(pop->ScanId());
CBitSetIter bsi(*bs);
for (ULONG ul = 0; bsi.Advance(); ul++)
{
selector_ids->Append(GPOS_NEW(m_mp) ULONG(bsi.Bit()));
}
}
CDXLPhysicalDynamicBitmapTableScan *pdxlopScan =
GPOS_NEW(m_mp) CDXLPhysicalDynamicBitmapTableScan(
m_mp, table_descr, part_mdids, selector_ids);
CDXLNode *pdxlnScan = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopScan);
// construct plan costs
if (nullptr == dxl_properties)
{
dxl_properties = GetProperties(pexprScan);
}
pdxlnScan->SetProperties(dxl_properties);
// translate predicates into DXL filter
CDXLNode *pdxlnCond = nullptr;
if (nullptr != pexprScalar)
{
pdxlnCond = PdxlnScalar(pexprScalar);
}
CDXLNode *filter_dxlnode = PdxlnFilter(pdxlnCond);
CExpression *pexprRecheckCond = (*pexprScan)[0];
CDXLNode *pdxlnRecheckCond = PdxlnScalar(pexprRecheckCond);
CDXLNode *pdxlnRecheckCondFilter = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarRecheckCondFilter(m_mp));
pdxlnRecheckCondFilter->AddChild(pdxlnRecheckCond);
// translate bitmap access path
CDXLNode *pdxlnBitmapAccessPath = PdxlnScalar((*pexprScan)[1]);
// build projection list
CColRefSet *pcrsOutput = pexprScan->Prpp()->PcrsRequired();
CDXLNode *proj_list_dxlnode = PdxlnProjList(pcrsOutput, colref_array);
pdxlnScan->AddChild(proj_list_dxlnode);
pdxlnScan->AddChild(filter_dxlnode);
pdxlnScan->AddChild(pdxlnRecheckCondFilter);
pdxlnScan->AddChild(pdxlnBitmapAccessPath);
#ifdef GPOS_DEBUG
pdxlnScan->GetOperator()->AssertValid(pdxlnScan,
false /* validate_children */);
#endif
CDistributionSpec *pds = pexprScan->GetDrvdPropPlan()->Pds();
pds->AddRef();
pdrgpdsBaseTables->Append(pds);
return pdxlnScan;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnDynamicIndexScan
//
// @doc:
// Create a DXL dynamic index scan node from an optimizer
// dynamic index scan node based on passed properties
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnDynamicIndexScan(
CExpression *pexprDIS, CColRefArray *colref_array,
CDXLPhysicalProperties *dxl_properties, CReqdPropPlan *prpp)
{
GPOS_ASSERT(nullptr != pexprDIS);
GPOS_ASSERT(nullptr != dxl_properties);
GPOS_ASSERT(nullptr != prpp);
CPhysicalDynamicIndexScan *popDIS =
CPhysicalDynamicIndexScan::PopConvert(pexprDIS->Pop());
CColRefArray *pdrgpcrOutput = popDIS->PdrgpcrOutput();
// translate table descriptor
CDXLTableDescr *table_descr =
MakeDXLTableDescr(popDIS->Ptabdesc(), pdrgpcrOutput, pexprDIS->Prpp());
// create index descriptor
CIndexDescriptor *pindexdesc = popDIS->Pindexdesc();
CMDName *pmdnameIndex =
GPOS_NEW(m_mp) CMDName(m_mp, pindexdesc->Name().Pstr());
IMDId *pmdidIndex = pindexdesc->MDId();
pmdidIndex->AddRef();
CDXLIndexDescr *dxl_index_descr =
GPOS_NEW(m_mp) CDXLIndexDescr(pmdidIndex, pmdnameIndex);
// construct dynamic table scan operator
IMdIdArray *part_mdids = popDIS->GetPartitionMdids();
part_mdids->AddRef();
ULongPtrArray *selector_ids = GPOS_NEW(m_mp) ULongPtrArray(m_mp);
CPartitionPropagationSpec *pps_reqd = prpp->Pepp()->PppsRequired();
if (pps_reqd->Contains(popDIS->ScanId()))
{
const CBitSet *bs = pps_reqd->SelectorIds(popDIS->ScanId());
CBitSetIter bsi(*bs);
for (ULONG ul = 0; bsi.Advance(); ul++)
{
selector_ids->Append(GPOS_NEW(m_mp) ULONG(bsi.Bit()));
}
}
// TODO: we assume that the index are always forward access.
CDXLNode *pdxlnDIS = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLPhysicalDynamicIndexScan(
m_mp, table_descr, dxl_index_descr, EdxlisdForward,
part_mdids, selector_ids));
// set plan costs
pdxlnDIS->SetProperties(dxl_properties);
// construct projection list
CColRefSet *pcrsOutput = prpp->PcrsRequired();
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, colref_array);
// translate index predicates
CExpression *pexprCond = (*pexprDIS)[0];
CDXLNode *pdxlnIndexCondList = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarIndexCondList(m_mp));
CExpressionArray *pdrgpexprConds =
CPredicateUtils::PdrgpexprConjuncts(m_mp, pexprCond);
const ULONG length = pdrgpexprConds->Size();
for (ULONG ul = 0; ul < length; ul++)
{
CExpression *pexprIndexCond = (*pdrgpexprConds)[ul];
CDXLNode *pdxlnIndexCond = PdxlnScalar(pexprIndexCond);
pdxlnIndexCondList->AddChild(pdxlnIndexCond);
}
pdrgpexprConds->Release();
CDXLNode *pdxlnResidualCond = nullptr;
if (2 == pexprDIS->Arity())
{
// translate residual predicates into the filter node
CExpression *pexprResidualCond = (*pexprDIS)[1];
if (COperator::EopScalarConst != pexprResidualCond->Pop()->Eopid())
{
pdxlnResidualCond = PdxlnScalar(pexprResidualCond);
}
}
CDXLNode *filter_dxlnode = PdxlnFilter(pdxlnResidualCond);
pdxlnDIS->AddChild(pdxlnPrL);
pdxlnDIS->AddChild(filter_dxlnode);
pdxlnDIS->AddChild(pdxlnIndexCondList);
#ifdef GPOS_DEBUG
pdxlnDIS->GetOperator()->AssertValid(pdxlnDIS,
false /* validate_children */);
#endif
return pdxlnDIS;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnDynamicIndexScan
//
// @doc:
// Create a DXL dynamic index scan node from an optimizer
// dynamic index scan node.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnDynamicIndexScan(
CExpression *pexprDIS, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions GPOS_UNUSED, BOOL *pfDML GPOS_UNUSED)
{
GPOS_ASSERT(nullptr != pexprDIS);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprDIS);
CDistributionSpec *pds = pexprDIS->GetDrvdPropPlan()->Pds();
pds->AddRef();
pdrgpdsBaseTables->Append(pds);
return PdxlnDynamicIndexScan(pexprDIS, colref_array, dxl_properties,
pexprDIS->Prpp());
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnResult
//
// @doc:
// Create a DXL result node over a relational expression with a DXL
// scalar condition.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnResult(CExpression *pexprRelational,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML,
CDXLNode *pdxlnScalar)
{
// extract physical properties from filter
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprRelational);
return PdxlnResult(pexprRelational, colref_array, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, pdxlnScalar, dxl_properties);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnResult
//
// @doc:
// Create a DXL result node over a relational expression with a DXL
// scalar condition using the passed DXL properties
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnResult(CExpression *pexprRelational,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML,
CDXLNode *pdxlnScalar,
CDXLPhysicalProperties *dxl_properties)
{
GPOS_ASSERT(nullptr != pexprRelational);
// translate relational child expression
CDXLNode *pdxlnRelationalChild = CreateDXLNode(
pexprRelational, colref_array, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML, false /*fRemap*/, false /*fRoot */);
GPOS_ASSERT(nullptr != pexprRelational->Prpp());
CColRefSet *pcrsOutput = pexprRelational->Prpp()->PcrsRequired();
return PdxlnAddScalarFilterOnRelationalChild(pdxlnRelationalChild,
pdxlnScalar, dxl_properties,
pcrsOutput, colref_array);
}
CDXLNode *
CTranslatorExprToDXL::PdxlnAddScalarFilterOnRelationalChild(
CDXLNode *pdxlnRelationalChild, CDXLNode *pdxlnScalarChild,
CDXLPhysicalProperties *dxl_properties, CColRefSet *pcrsOutput,
CColRefArray *pdrgpcrOrder)
{
GPOS_ASSERT(nullptr != dxl_properties);
// for a true condition, just translate the child
if (CTranslatorExprToDXLUtils::FScalarConstTrue(m_pmda, pdxlnScalarChild))
{
pdxlnScalarChild->Release();
dxl_properties->Release();
return pdxlnRelationalChild;
}
// create a result node over outer child
else
{
// wrap condition in a DXL filter node
CDXLNode *filter_dxlnode = PdxlnFilter(pdxlnScalarChild);
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, pdrgpcrOrder);
// create an empty one-time filter
CDXLNode *one_time_filter = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarOneTimeFilter(m_mp));
return CTranslatorExprToDXLUtils::PdxlnResult(
m_mp, dxl_properties, pdxlnPrL, filter_dxlnode, one_time_filter,
pdxlnRelationalChild);
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnResult
//
// @doc:
// Create a DXL result node from an optimizer filter node.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnResult(CExpression *pexprFilter,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprFilter);
CDXLNode *pdxlnode =
PdxlnFromFilter(pexprFilter, colref_array, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, dxl_properties);
dxl_properties->Release();
return pdxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnIndexScanWithInlinedCondition
//
// @doc:
// Create a (dynamic) index scan node after inlining the given
// scalar condition, if needed
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnIndexScanWithInlinedCondition(
CExpression *pexprIndexScan, CExpression *pexprScalarCond,
CDXLPhysicalProperties *dxl_properties, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables)
{
GPOS_ASSERT(nullptr != pexprIndexScan);
GPOS_ASSERT(nullptr != pexprScalarCond);
GPOS_ASSERT(pexprScalarCond->Pop()->FScalar());
COperator::EOperatorId op_id = pexprIndexScan->Pop()->Eopid();
GPOS_ASSERT(COperator::EopPhysicalIndexScan == op_id ||
COperator::EopPhysicalIndexOnlyScan == op_id ||
COperator::EopPhysicalDynamicIndexScan == op_id);
// TODO: Index only scans work on GiST and SP-GiST only for specific operators
// check if index is of type GiST
BOOL isGist = false;
if (COperator::EopPhysicalIndexScan == op_id)
{
CPhysicalIndexScan *indexScan =
CPhysicalIndexScan::PopConvert(pexprIndexScan->Pop());
isGist = (indexScan->Pindexdesc()->IndexType() == IMDIndex::EmdindGist);
}
else if (COperator::EopPhysicalIndexOnlyScan != op_id)
{
CPhysicalDynamicIndexScan *indexScan =
CPhysicalDynamicIndexScan::PopConvert(pexprIndexScan->Pop());
isGist = (indexScan->Pindexdesc()->IndexType() == IMDIndex::EmdindGist);
}
// inline scalar condition in index scan, if it is not the same as index lookup condition
// Exception: most GiST indexes require a recheck condition since they are lossy: re-add the lookup
// condition as a scalar condition. For now, all GiST indexes are treated as lossy
CExpression *pexprIndexLookupCond = (*pexprIndexScan)[0];
CDXLNode *pdxlnIndexScan = nullptr;
if ((!CUtils::FScalarConstTrue(pexprScalarCond) &&
!pexprScalarCond->Matches(pexprIndexLookupCond)) ||
isGist)
{
// combine scalar condition with existing index conditions, if any
pexprScalarCond->AddRef();
CExpression *pexprNewScalarCond = pexprScalarCond;
if (2 == pexprIndexScan->Arity())
{
pexprNewScalarCond->Release();
pexprNewScalarCond = CPredicateUtils::PexprConjunction(
m_mp, (*pexprIndexScan)[1], pexprScalarCond);
}
pexprIndexLookupCond->AddRef();
pexprIndexScan->Pop()->AddRef();
CExpression *pexprNewIndexScan = GPOS_NEW(m_mp)
CExpression(m_mp, pexprIndexScan->Pop(), pexprIndexLookupCond,
pexprNewScalarCond);
if (COperator::EopPhysicalIndexScan == op_id)
{
pdxlnIndexScan =
PdxlnIndexScan(pexprNewIndexScan, colref_array, dxl_properties,
pexprIndexScan->Prpp());
}
else if (COperator::EopPhysicalIndexOnlyScan == op_id)
{
pdxlnIndexScan =
PdxlnIndexOnlyScan(pexprNewIndexScan, colref_array,
dxl_properties, pexprIndexScan->Prpp());
}
else
{
pdxlnIndexScan =
PdxlnDynamicIndexScan(pexprNewIndexScan, colref_array,
dxl_properties, pexprIndexScan->Prpp());
}
pexprNewIndexScan->Release();
CDistributionSpec *pds = pexprIndexScan->GetDrvdPropPlan()->Pds();
pds->AddRef();
pdrgpdsBaseTables->Append(pds);
return pdxlnIndexScan;
}
// index scan does not need the properties of the filter, as it does not
// need to further inline the scalar condition
dxl_properties->Release();
ULONG ulNonGatherMotions = 0;
BOOL fDML = false;
if (COperator::EopPhysicalIndexScan == op_id)
{
return PdxlnIndexScan(pexprIndexScan, colref_array, pdrgpdsBaseTables,
&ulNonGatherMotions, &fDML);
}
if (COperator::EopPhysicalIndexOnlyScan == op_id)
{
return PdxlnIndexOnlyScan(pexprIndexScan, colref_array,
pdrgpdsBaseTables, &ulNonGatherMotions,
&fDML);
}
return PdxlnDynamicIndexScan(pexprIndexScan, colref_array,
pdrgpdsBaseTables, &ulNonGatherMotions, &fDML);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnResult
//
// @doc:
// Create a DXL result node from an optimizer filter node.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnFromFilter(CExpression *pexprFilter,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML,
CDXLPhysicalProperties *dxl_properties)
{
GPOS_ASSERT(nullptr != pexprFilter);
GPOS_ASSERT(nullptr != dxl_properties);
// extract components
CExpression *pexprRelational = (*pexprFilter)[0];
CExpression *pexprScalar = (*pexprFilter)[1];
if (CTranslatorExprToDXLUtils::FDirectDispatchableFilter(pexprFilter))
{
COptCtxt::PoctxtFromTLS()->AddDirectDispatchableFilterCandidate(
pexprFilter);
}
// if the filter predicate is a constant TRUE, skip to translating relational child
if (CUtils::FScalarConstTrue(pexprScalar))
{
return CreateDXLNode(pexprRelational, colref_array, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, true /*fRemap*/,
false /* fRoot */);
}
COperator::EOperatorId eopidRelational = pexprRelational->Pop()->Eopid();
CColRefSet *pcrsOutput = pexprFilter->Prpp()->PcrsRequired();
switch (eopidRelational)
{
case COperator::EopPhysicalTableScan:
case COperator::EopPhysicalExternalScan:
{
// if there is a structure of the form
// filter->tablescan, or filter->CTG then
// push the scalar filter expression to the tablescan/CTG respectively
dxl_properties->AddRef();
// translate the table scan with the filter condition
return PdxlnTblScan(pexprRelational, pcrsOutput,
nullptr /* colref_array */, pdrgpdsBaseTables,
pexprScalar, dxl_properties /* cost info */
);
}
case COperator::EopPhysicalBitmapTableScan:
{
dxl_properties->AddRef();
return PdxlnBitmapTableScan(
pexprRelational, pcrsOutput, nullptr /*colref_array*/,
pdrgpdsBaseTables, pexprScalar, dxl_properties);
}
case COperator::EopPhysicalDynamicTableScan:
{
dxl_properties->AddRef();
// inline condition in the Dynamic Table Scan
return PdxlnDynamicTableScan(pexprRelational, colref_array,
pdrgpdsBaseTables, pexprScalar,
dxl_properties);
}
case COperator::EopPhysicalIndexOnlyScan:
case COperator::EopPhysicalIndexScan:
case COperator::EopPhysicalDynamicIndexScan:
{
dxl_properties->AddRef();
return PdxlnIndexScanWithInlinedCondition(
pexprRelational, pexprScalar, dxl_properties, colref_array,
pdrgpdsBaseTables);
}
case COperator::EopPhysicalDynamicBitmapTableScan:
{
dxl_properties->AddRef();
return PdxlnDynamicBitmapTableScan(pexprRelational, colref_array,
pdrgpdsBaseTables, pexprScalar,
dxl_properties);
}
default:
{
return PdxlnResultFromFilter(pexprFilter, colref_array,
pdrgpdsBaseTables, pulNonGatherMotions,
pfDML);
}
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnResultFromFilter
//
// @doc:
// Create a DXL result node from an optimizer filter node.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnResultFromFilter(
CExpression *pexprFilter, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables, ULONG *pulNonGatherMotions,
BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprFilter);
// extract components
CExpression *pexprRelational = (*pexprFilter)[0];
CExpression *pexprScalar = (*pexprFilter)[1];
CColRefSet *pcrsOutput = pexprFilter->Prpp()->PcrsRequired();
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprFilter);
// translate relational child expression
CDXLNode *child_dxlnode = CreateDXLNode(
pexprRelational, nullptr /* colref_array */, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
// translate scalar expression in to filter and one time filter dxl nodes
CColRefSet *relational_child_colrefset =
pexprRelational->DeriveOutputColumns();
// get all the scalar conditions in an array
CExpressionArray *scalar_exprs =
CPredicateUtils::PdrgpexprConjuncts(m_mp, pexprScalar);
// array to hold scalar conditions which will qualify for filter condition
CExpressionArray *filter_quals_exprs =
GPOS_NEW(m_mp) CExpressionArray(m_mp);
// array to hold scalar conditions which qualify for one time filter condition
CExpressionArray *one_time_filter_quals_exprs =
GPOS_NEW(m_mp) CExpressionArray(m_mp);
for (ULONG ul = 0; ul < scalar_exprs->Size(); ul++)
{
CExpression *scalar_child_expr = (*scalar_exprs)[ul];
CColRefSet *scalar_child_colrefset =
scalar_child_expr->DeriveUsedColumns();
// What qualifies for a one time filter qual?
// 1. if there is no column in the scalar child of filter expression coming from its relational
// child
// and
// 2. if there is no volatile function in the scalar child
//
// Why quals are separated into one time filter vs filter quals?
// one time filter quals are evaluated once for each scan, and if the filter evaluates to false,
// the data from the nodes below is not requested, however in case of filter quals, they are
// evaluated for each tuple coming from the nodes below. So, if the filter does not depends on the tuple
// values coming from the nodes below, it could be a one time filter and we can save processing time on
// each tuple and evaluating it against the filter.
if (scalar_child_colrefset->FIntersects(relational_child_colrefset) ||
CPredicateUtils::FContainsVolatileFunction(scalar_child_expr))
{
scalar_child_expr->AddRef();
filter_quals_exprs->Append(scalar_child_expr);
}
else
{
scalar_child_expr->AddRef();
one_time_filter_quals_exprs->Append(scalar_child_expr);
}
}
scalar_exprs->Release();
// create an emtpy filter
CDXLNode *filter_dxlnode =
GPOS_NEW(m_mp) CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarFilter(m_mp));
// create an empty one-time filter
CDXLNode *one_time_filter_dxlnode = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarOneTimeFilter(m_mp));
if (filter_quals_exprs->Size() > 0)
{
// create scalar cmp expression for filter expression
CExpression *scalar_cmp_expr =
CPredicateUtils::PexprConjunction(m_mp, filter_quals_exprs);
// create dxl node for the filter
CDXLNode *scalar_cmp_dxlnode = PdxlnScalar(scalar_cmp_expr);
filter_dxlnode->AddChild(scalar_cmp_dxlnode);
scalar_cmp_expr->Release();
}
else
{
filter_quals_exprs->Release();
}
if (one_time_filter_quals_exprs->Size() > 0)
{
// create scalar cmp expression for one time filter expression
CExpression *scalar_cmp_expr = CPredicateUtils::PexprConjunction(
m_mp, one_time_filter_quals_exprs);
// create dxl node for one time filter
CDXLNode *scalar_cmp_dxlnode = PdxlnScalar(scalar_cmp_expr);
one_time_filter_dxlnode->AddChild(scalar_cmp_dxlnode);
scalar_cmp_expr->Release();
}
else
{
one_time_filter_quals_exprs->Release();
}
GPOS_ASSERT(nullptr != pexprFilter->Prpp());
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, colref_array);
return CTranslatorExprToDXLUtils::PdxlnResult(
m_mp, dxl_properties, pdxlnPrL, filter_dxlnode, one_time_filter_dxlnode,
child_dxlnode);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnAssert
//
// @doc:
// Translate a physical assert expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnAssert(CExpression *pexprAssert,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprAssert);
// extract components
CExpression *pexprRelational = (*pexprAssert)[0];
CExpression *pexprScalar = (*pexprAssert)[1];
CPhysicalAssert *popAssert =
CPhysicalAssert::PopConvert(pexprAssert->Pop());
// extract physical properties from assert
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprAssert);
CColRefSet *pcrsOutput = pexprAssert->Prpp()->PcrsRequired();
// translate relational child expression
CDXLNode *child_dxlnode = CreateDXLNode(
pexprRelational, nullptr /* colref_array */, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
// translate scalar expression
CDXLNode *pdxlnAssertPredicate = PdxlnScalar(pexprScalar);
GPOS_ASSERT(nullptr != pexprAssert->Prpp());
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, colref_array);
const CHAR *sql_state = popAssert->Pexc()->GetSQLState();
CDXLPhysicalAssert *pdxlopAssert =
GPOS_NEW(m_mp) CDXLPhysicalAssert(m_mp, sql_state);
CDXLNode *pdxlnAssert = GPOS_NEW(m_mp) CDXLNode(
m_mp, pdxlopAssert, pdxlnPrL, pdxlnAssertPredicate, child_dxlnode);
pdxlnAssert->SetProperties(dxl_properties);
return pdxlnAssert;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnCTEProducer
//
// @doc:
// Translate a physical cte producer expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnCTEProducer(
CExpression *pexprCTEProducer,
CColRefArray *, //colref_array,
CDistributionSpecArray *pdrgpdsBaseTables, ULONG *pulNonGatherMotions,
BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprCTEProducer);
// extract components
CExpression *pexprRelational = (*pexprCTEProducer)[0];
CPhysicalCTEProducer *popCTEProducer =
CPhysicalCTEProducer::PopConvert(pexprCTEProducer->Pop());
// extract physical properties from cte producer
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprCTEProducer);
// extract the CTE id and the array of colids
const ULONG ulCTEId = popCTEProducer->UlCTEId();
ULongPtrArray *colids = CUtils::Pdrgpul(m_mp, popCTEProducer->Pdrgpcr());
GPOS_ASSERT(nullptr != pexprCTEProducer->Prpp());
CColRefArray *pdrgpcrRequired = popCTEProducer->Pdrgpcr();
CColRefSet *pcrsOutput = GPOS_NEW(m_mp) CColRefSet(m_mp);
pcrsOutput->Include(pdrgpcrRequired);
// translate relational child expression
CDXLNode *child_dxlnode = CreateDXLNode(
pexprRelational, pdrgpcrRequired, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, true /*fRemap*/, false /*fRoot */);
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, pdrgpcrRequired);
pcrsOutput->Release();
CDXLNode *pdxlnCTEProducer = GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLPhysicalCTEProducer(m_mp, ulCTEId, colids),
pdxlnPrL, child_dxlnode);
pdxlnCTEProducer->SetProperties(dxl_properties);
return pdxlnCTEProducer;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnCTEConsumer
//
// @doc:
// Translate a physical cte consumer expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnCTEConsumer(
CExpression *pexprCTEConsumer,
CColRefArray *, //colref_array,
CDistributionSpecArray *, // pdrgpdsBaseTables,
ULONG *, // pulNonGatherMotions,
BOOL * // pfDML
)
{
GPOS_ASSERT(nullptr != pexprCTEConsumer);
// extract components
CPhysicalCTEConsumer *popCTEConsumer =
CPhysicalCTEConsumer::PopConvert(pexprCTEConsumer->Pop());
// extract physical properties from cte consumer
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprCTEConsumer);
// extract the CTE id and the array of colids
const ULONG ulCTEId = popCTEConsumer->UlCTEId();
CColRefArray *colref_array = popCTEConsumer->Pdrgpcr();
ULongPtrArray *colids = CUtils::Pdrgpul(m_mp, colref_array);
CColRefSet *pcrsOutput = GPOS_NEW(m_mp) CColRefSet(m_mp);
pcrsOutput->Include(colref_array);
// translate relational child expression
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, colref_array);
CDXLNode *pdxlnCTEConsumer = GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLPhysicalCTEConsumer(m_mp, ulCTEId, colids),
pdxlnPrL);
pcrsOutput->Release();
pdxlnCTEConsumer->SetProperties(dxl_properties);
return pdxlnCTEConsumer;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnAppend
//
// @doc:
// Create a DXL Append node from an optimizer an union all node
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnAppend(CExpression *pexprUnionAll,
CColRefArray *, //colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprUnionAll);
CPhysicalUnionAll *popUnionAll =
CPhysicalUnionAll::PopConvert(pexprUnionAll->Pop());
CColRefArray *pdrgpcrOutputAll = popUnionAll->PdrgpcrOutput();
CColRefSet *reqdCols = pexprUnionAll->Prpp()->PcrsRequired();
CDXLPhysicalAppend *dxl_op =
GPOS_NEW(m_mp) CDXLPhysicalAppend(m_mp, false, false);
CDXLNode *pdxlnAppend = GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op);
// compute a list of indexes of output columns that are actually required
CColRefArray *reqd_col_array = GPOS_NEW(m_mp) CColRefArray(m_mp);
ULONG num_total_cols = pdrgpcrOutputAll->Size();
for (ULONG c = 0; c < num_total_cols; c++)
{
if (reqdCols->FMember((*pdrgpcrOutputAll)[c]))
{
reqd_col_array->Append((*pdrgpcrOutputAll)[c]);
}
}
ULongPtrArray *reqd_col_positions =
pdrgpcrOutputAll->IndexesOfSubsequence(reqd_col_array);
CColRefArray *requiredOutput =
pdrgpcrOutputAll->CreateReducedArray(reqd_col_positions);
reqd_col_array->Release();
GPOS_ASSERT(nullptr != reqd_col_positions);
// set properties
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprUnionAll);
pdxlnAppend->SetProperties(dxl_properties);
// translate project list
CColRefSet *pcrsOutput = GPOS_NEW(m_mp) CColRefSet(m_mp);
pcrsOutput->Include(reqdCols);
// the append node does not re-order its input or output columns. The
// re-ordering of its output columns has to be done above it (if needed)
// via a separate result node
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, requiredOutput);
pcrsOutput->Release();
requiredOutput->Release();
pcrsOutput = nullptr;
requiredOutput = nullptr;
pdxlnAppend->AddChild(pdxlnPrL);
// scalar condition
CDXLNode *pdxlnCond = nullptr;
CDXLNode *filter_dxlnode = PdxlnFilter(pdxlnCond);
pdxlnAppend->AddChild(filter_dxlnode);
// translate children
CColRef2dArray *pdrgpdrgpcrInput = popUnionAll->PdrgpdrgpcrInput();
GPOS_ASSERT(nullptr != pdrgpdrgpcrInput);
const ULONG length = pexprUnionAll->Arity();
GPOS_ASSERT(length == pdrgpdrgpcrInput->Size());
for (ULONG ul = 0; ul < length; ul++)
{
// translate child
CColRefArray *pdrgpcrInput = (*pdrgpdrgpcrInput)[ul];
CColRefArray *requiredInput =
pdrgpcrInput->CreateReducedArray(reqd_col_positions);
CExpression *pexprChild = (*pexprUnionAll)[ul];
CDXLNode *child_dxlnode = CreateDXLNode(
pexprChild, requiredInput, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML, false /*fRemap*/, false /*fRoot*/);
// add a result node on top if necessary so the order of the input project list
// matches the order in which the append node requires it
CDXLNode *pdxlnChildProjected = PdxlnRemapOutputColumns(
pexprChild, child_dxlnode,
requiredInput /* required input columns */,
requiredInput /* order of the input columns */
);
pdxlnAppend->AddChild(pdxlnChildProjected);
requiredInput->Release();
}
reqd_col_positions->Release();
return pdxlnAppend;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdrgpcrMerge
//
// @doc:
// Combines the ordered columns and required columns into a single list
// with members in the ordered list inserted before the remaining columns in
// required list. For instance, if the order list is (c, d) and
// the required list is (a, b, c, d) then the combined list is (c, d, a, b)
//---------------------------------------------------------------------------
CColRefArray *
CTranslatorExprToDXL::PdrgpcrMerge(CMemoryPool *mp, CColRefArray *pdrgpcrOrder,
CColRefArray *pdrgpcrRequired)
{
CColRefSet *pcrsOutput = GPOS_NEW(mp) CColRefSet(mp);
CColRefArray *pdrgpcrMerge = GPOS_NEW(mp) CColRefArray(mp);
if (nullptr != pdrgpcrOrder)
{
const ULONG ulLenOrder = pdrgpcrOrder->Size();
for (ULONG ul = 0; ul < ulLenOrder; ul++)
{
CColRef *colref = (*pdrgpcrOrder)[ul];
pdrgpcrMerge->Append(colref);
}
pcrsOutput->Include(pdrgpcrMerge);
}
const ULONG ulLenReqd = pdrgpcrRequired->Size();
for (ULONG ul = 0; ul < ulLenReqd; ul++)
{
CColRef *colref = (*pdrgpcrRequired)[ul];
if (!pcrsOutput->FMember(colref))
{
pcrsOutput->Include(colref);
pdrgpcrMerge->Append(colref);
}
}
pcrsOutput->Release();
return pdrgpcrMerge;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnRemapOutputColumns
//
// @doc:
// Checks if the project list of the given node matches the required
// columns and their order. If not then a result node is created on
// top of it
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnRemapOutputColumns(CExpression *pexpr,
CDXLNode *dxlnode,
CColRefArray *pdrgpcrRequired,
CColRefArray *pdrgpcrOrder)
{
GPOS_ASSERT(nullptr != pexpr);
GPOS_ASSERT(nullptr != dxlnode);
GPOS_ASSERT(nullptr != pdrgpcrRequired);
// get project list
CDXLNode *pdxlnPrL = (*dxlnode)[0];
CColRefArray *pdrgpcrOrderedReqdCols =
PdrgpcrMerge(m_mp, pdrgpcrOrder, pdrgpcrRequired);
// if the combined list is the same as proj list then no
// further action needed. Otherwise we need result node on top
if (CTranslatorExprToDXLUtils::FProjectListMatch(pdxlnPrL,
pdrgpcrOrderedReqdCols))
{
pdrgpcrOrderedReqdCols->Release();
return dxlnode;
}
pdrgpcrOrderedReqdCols->Release();
// output columns of new result node
CColRefSet *pcrsOutput = GPOS_NEW(m_mp) CColRefSet(m_mp);
pcrsOutput->Include(pdrgpcrRequired);
CDXLNode *pdxlnPrLNew = PdxlnProjList(pcrsOutput, pdrgpcrOrder);
pcrsOutput->Release();
// create a result node on top of the current dxl node with a new project list
return PdxlnResult(GetProperties(pexpr), pdxlnPrLNew, dxlnode);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnTVF
//
// @doc:
// Create a DXL TVF node from an optimizer TVF node
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnTVF(CExpression *pexprTVF,
CColRefArray *, //colref_array,
CDistributionSpecArray *, // pdrgpdsBaseTables,
ULONG *, // pulNonGatherMotions,
BOOL * // pfDML
)
{
GPOS_ASSERT(nullptr != pexprTVF);
CPhysicalTVF *popTVF = CPhysicalTVF::PopConvert(pexprTVF->Pop());
CColRefSet *pcrsOutput = popTVF->DeriveOutputColumns();
IMDId *mdid_func = popTVF->FuncMdId();
mdid_func->AddRef();
IMDId *mdid_return_type = popTVF->ReturnTypeMdId();
mdid_return_type->AddRef();
CWStringConst *pstrFunc =
GPOS_NEW(m_mp) CWStringConst(m_mp, popTVF->Pstr()->GetBuffer());
CDXLPhysicalTVF *dxl_op = GPOS_NEW(m_mp)
CDXLPhysicalTVF(m_mp, mdid_func, mdid_return_type, pstrFunc);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprTVF);
CDXLNode *pdxlnTVF = GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op);
pdxlnTVF->SetProperties(dxl_properties);
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, nullptr /*colref_array*/);
pdxlnTVF->AddChild(pdxlnPrL); // project list
TranslateScalarChildren(pexprTVF, pdxlnTVF);
return pdxlnTVF;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnResultFromConstTableGet
//
// @doc:
// Create a DXL result node from an optimizer const table get node
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnResultFromConstTableGet(CExpression *pexprCTG,
CColRefArray *colref_array,
CExpression *pexprScalar)
{
GPOS_ASSERT(nullptr != pexprCTG);
CPhysicalConstTableGet *popCTG =
CPhysicalConstTableGet::PopConvert(pexprCTG->Pop());
// construct project list from the const table get values
CColRefArray *pdrgpcrCTGOutput = popCTG->PdrgpcrOutput();
IDatum2dArray *pdrgpdrgdatum = popCTG->Pdrgpdrgpdatum();
const ULONG ulRows = pdrgpdrgdatum->Size();
CDXLNode *pdxlnPrL = nullptr;
CDXLNode *one_time_filter = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarOneTimeFilter(m_mp));
IDatumArray *pdrgpdatum = nullptr;
if (0 == ulRows)
{
// no-tuples... only generate one row of NULLS and one-time "false" filter
pdrgpdatum =
CTranslatorExprToDXLUtils::PdrgpdatumNulls(m_mp, pdrgpcrCTGOutput);
CExpression *pexprFalse = CUtils::PexprScalarConstBool(
m_mp, false /*value*/, false /*is_null*/);
CDXLNode *pdxlnFalse = PdxlnScConst(pexprFalse);
pexprFalse->Release();
one_time_filter->AddChild(pdxlnFalse);
}
else
{
GPOS_ASSERT(1 <= ulRows);
pdrgpdatum = (*pdrgpdrgdatum)[0];
pdrgpdatum->AddRef();
CDXLNode *pdxlnCond = nullptr;
if (nullptr != pexprScalar)
{
pdxlnCond = PdxlnScalar(pexprScalar);
one_time_filter->AddChild(pdxlnCond);
}
}
// if CTG has multiple rows then it has to be a valuescan of constants,
// else, a Result node is created
if (ulRows > 1)
{
GPOS_ASSERT(nullptr != pdrgpcrCTGOutput);
CColRefSet *pcrsOutput = pexprCTG->DeriveOutputColumns();
pdxlnPrL = PdxlnProjList(pcrsOutput, pdrgpcrCTGOutput);
CDXLNode *pdxlnValuesScan = CTranslatorExprToDXLUtils::PdxlnValuesScan(
m_mp, GetProperties(pexprCTG), pdxlnPrL, pdrgpdrgdatum);
one_time_filter->Release();
pdrgpdatum->Release();
return pdxlnValuesScan;
}
else
{
pdxlnPrL = PdxlnProjListFromConstTableGet(colref_array,
pdrgpcrCTGOutput, pdrgpdatum);
pdrgpdatum->Release();
return CTranslatorExprToDXLUtils::PdxlnResult(
m_mp, GetProperties(pexprCTG), pdxlnPrL, PdxlnFilter(nullptr),
one_time_filter,
nullptr //child_dxlnode
);
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnResultFromConstTableGet
//
// @doc:
// Create a DXL result node from an optimizer const table get node
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnResultFromConstTableGet(
CExpression *pexprCTG, CColRefArray *colref_array,
CDistributionSpecArray *, // pdrgpdsBaseTables,
ULONG *, // pulNonGatherMotions,
BOOL * // pfDML
)
{
return PdxlnResultFromConstTableGet(pexprCTG, colref_array,
nullptr /*pexprScalarCond*/);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnComputeScalar
//
// @doc:
// Create a DXL result node from an optimizer compute scalar expression
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnComputeScalar(
CExpression *pexprComputeScalar, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables, ULONG *pulNonGatherMotions,
BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprComputeScalar);
// extract components
CExpression *pexprRelational = (*pexprComputeScalar)[0];
CExpression *pexprProjList = (*pexprComputeScalar)[1];
// translate relational child expression
CDXLNode *child_dxlnode = CreateDXLNode(
pexprRelational, nullptr /* colref_array */, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
// compute required columns
GPOS_ASSERT(nullptr != pexprComputeScalar->Prpp());
CColRefSet *pcrsOutput = pexprComputeScalar->Prpp()->PcrsRequired();
// iterate the columns in the projection list, add the columns containing
// set-returning functions to the output columns
const ULONG ulPrLs = pexprProjList->Arity();
for (ULONG ul = 0; ul < ulPrLs; ul++)
{
CExpression *pexprPrE = (*pexprProjList)[ul];
// for column that doesn't contain set-returning function, if it is not the
// required column in the relational plan properties, then no need to add them
// to the output columns
if (pexprPrE->DeriveHasNonScalarFunction())
{
CScalarProjectElement *popScPrE =
CScalarProjectElement::PopConvert(pexprPrE->Pop());
pcrsOutput->Include(popScPrE->Pcr());
}
}
// translate project list expression
CDXLNode *pdxlnPrL = nullptr;
if (nullptr == colref_array || CUtils::FHasDuplicates(colref_array))
{
pdxlnPrL = PdxlnProjList(pexprProjList, pcrsOutput);
}
else
{
pdxlnPrL = PdxlnProjList(pexprProjList, pcrsOutput, colref_array);
}
// construct a result node
CDXLNode *pdxlnResult =
PdxlnResult(GetProperties(pexprComputeScalar), pdxlnPrL, child_dxlnode);
#ifdef GPOS_DEBUG
(void) CDXLPhysicalResult::Cast(pdxlnResult->GetOperator())
->AssertValid(pdxlnResult, false /* validate_children */);
#endif
return pdxlnResult;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnAggregate
//
// @doc:
// Create a DXL aggregate node from an optimizer hash agg expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnAggregate(CExpression *pexprAgg,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprAgg);
COperator::EOperatorId op_id = pexprAgg->Pop()->Eopid();
// extract components and construct an aggregate node
CPhysicalAgg *popAgg = nullptr;
GPOS_ASSERT(COperator::EopPhysicalStreamAgg == op_id ||
COperator::EopPhysicalHashAgg == op_id ||
COperator::EopPhysicalScalarAgg == op_id);
EdxlAggStrategy dxl_agg_strategy = EdxlaggstrategySentinel;
switch (op_id)
{
case COperator::EopPhysicalStreamAgg:
{
popAgg = CPhysicalStreamAgg::PopConvert(pexprAgg->Pop());
dxl_agg_strategy = EdxlaggstrategySorted;
break;
}
case COperator::EopPhysicalHashAgg:
{
popAgg = CPhysicalHashAgg::PopConvert(pexprAgg->Pop());
dxl_agg_strategy = EdxlaggstrategyHashed;
break;
}
case COperator::EopPhysicalScalarAgg:
{
popAgg = CPhysicalScalarAgg::PopConvert(pexprAgg->Pop());
dxl_agg_strategy = EdxlaggstrategyPlain;
break;
}
default:
{
return nullptr; // to silence the compiler
}
}
const CColRefArray *pdrgpcrGroupingCols = popAgg->PdrgpcrGroupingCols();
return PdxlnAggregate(pexprAgg, colref_array, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, dxl_agg_strategy,
pdrgpcrGroupingCols, nullptr /*pcrsKeys*/
);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnAggregateDedup
//
// @doc:
// Create a DXL aggregate node from an optimizer dedup agg expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnAggregateDedup(
CExpression *pexprAgg, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables, ULONG *pulNonGatherMotions,
BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprAgg);
COperator::EOperatorId op_id = pexprAgg->Pop()->Eopid();
GPOS_ASSERT(COperator::EopPhysicalStreamAggDeduplicate == op_id ||
COperator::EopPhysicalHashAggDeduplicate == op_id);
EdxlAggStrategy dxl_agg_strategy = EdxlaggstrategySentinel;
const CColRefArray *pdrgpcrGroupingCols = nullptr;
CColRefSet *pcrsKeys = GPOS_NEW(m_mp) CColRefSet(m_mp);
if (COperator::EopPhysicalStreamAggDeduplicate == op_id)
{
CPhysicalStreamAggDeduplicate *popAggDedup =
CPhysicalStreamAggDeduplicate::PopConvert(pexprAgg->Pop());
pcrsKeys->Include(popAggDedup->PdrgpcrKeys());
pdrgpcrGroupingCols = popAggDedup->PdrgpcrGroupingCols();
dxl_agg_strategy = EdxlaggstrategySorted;
}
else
{
CPhysicalHashAggDeduplicate *popAggDedup =
CPhysicalHashAggDeduplicate::PopConvert(pexprAgg->Pop());
pcrsKeys->Include(popAggDedup->PdrgpcrKeys());
pdrgpcrGroupingCols = popAggDedup->PdrgpcrGroupingCols();
dxl_agg_strategy = EdxlaggstrategyHashed;
}
CDXLNode *pdxlnAgg = PdxlnAggregate(
pexprAgg, colref_array, pdrgpdsBaseTables, pulNonGatherMotions, pfDML,
dxl_agg_strategy, pdrgpcrGroupingCols, pcrsKeys);
pcrsKeys->Release();
return pdxlnAgg;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnAggregate
//
// @doc:
// Create a DXL aggregate node from an optimizer agg expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnAggregate(CExpression *pexprAgg,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML,
EdxlAggStrategy dxl_agg_strategy,
const CColRefArray *pdrgpcrGroupingCols,
CColRefSet *pcrsKeys)
{
GPOS_ASSERT(nullptr != pexprAgg);
GPOS_ASSERT(nullptr != pdrgpcrGroupingCols);
#ifdef GPOS_DEBUG
COperator::EOperatorId op_id = pexprAgg->Pop()->Eopid();
GPOS_ASSERT_IMP(nullptr == pcrsKeys,
COperator::EopPhysicalStreamAgg == op_id ||
COperator::EopPhysicalHashAgg == op_id ||
COperator::EopPhysicalScalarAgg == op_id);
#endif //GPOS_DEBUG
// is it safe to stream the local hash aggregate
BOOL stream_safe =
CTranslatorExprToDXLUtils::FLocalHashAggStreamSafe(pexprAgg);
CExpression *pexprChild = (*pexprAgg)[0];
CExpression *pexprProjList = (*pexprAgg)[1];
// translate relational child expression
CDXLNode *child_dxlnode =
CreateDXLNode(pexprChild,
nullptr, // colref_array,
pdrgpdsBaseTables, pulNonGatherMotions, pfDML,
false, // fRemap,
false // fRoot
);
// compute required columns
GPOS_ASSERT(nullptr != pexprAgg->Prpp());
CColRefSet *pcrsRequired = pexprAgg->Prpp()->PcrsRequired();
// translate project list expression
CDXLNode *proj_list_dxlnode =
PdxlnProjList(pexprProjList, pcrsRequired, colref_array);
// create an empty filter
CDXLNode *filter_dxlnode =
GPOS_NEW(m_mp) CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarFilter(m_mp));
// construct grouping columns list and check if all the grouping column are
// already in the project list of the aggregate operator
const ULONG num_cols = proj_list_dxlnode->Arity();
UlongToUlongMap *phmululPL = GPOS_NEW(m_mp) UlongToUlongMap(m_mp);
for (ULONG ul = 0; ul < num_cols; ul++)
{
CDXLNode *pdxlnProjElem = (*proj_list_dxlnode)[ul];
ULONG colid =
CDXLScalarProjElem::Cast(pdxlnProjElem->GetOperator())->Id();
if (nullptr == phmululPL->Find(&colid))
{
BOOL fRes GPOS_ASSERTS_ONLY = phmululPL->Insert(
GPOS_NEW(m_mp) ULONG(colid), GPOS_NEW(m_mp) ULONG(colid));
GPOS_ASSERT(fRes);
}
}
ULongPtrArray *pdrgpulGroupingCols = GPOS_NEW(m_mp) ULongPtrArray(m_mp);
const ULONG length = pdrgpcrGroupingCols->Size();
for (ULONG ul = 0; ul < length; ul++)
{
CColRef *pcrGroupingCol = (*pdrgpcrGroupingCols)[ul];
// only add columns that are either required or in the join keys.
// if the keys colrefset is null, then skip this check
if (nullptr != pcrsKeys && !pcrsKeys->FMember(pcrGroupingCol) &&
!pcrsRequired->FMember(pcrGroupingCol))
{
continue;
}
pdrgpulGroupingCols->Append(GPOS_NEW(m_mp) ULONG(pcrGroupingCol->Id()));
ULONG colid = pcrGroupingCol->Id();
if (nullptr == phmululPL->Find(&colid))
{
CDXLNode *pdxlnProjElem = CTranslatorExprToDXLUtils::PdxlnProjElem(
m_mp, m_phmcrdxln, pcrGroupingCol);
proj_list_dxlnode->AddChild(pdxlnProjElem);
BOOL fRes GPOS_ASSERTS_ONLY = phmululPL->Insert(
GPOS_NEW(m_mp) ULONG(colid), GPOS_NEW(m_mp) ULONG(colid));
GPOS_ASSERT(fRes);
}
}
phmululPL->Release();
CDXLPhysicalAgg *pdxlopAgg =
GPOS_NEW(m_mp) CDXLPhysicalAgg(m_mp, dxl_agg_strategy, stream_safe);
pdxlopAgg->SetGroupingCols(pdrgpulGroupingCols);
CDXLNode *pdxlnAgg = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopAgg);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprAgg);
pdxlnAgg->SetProperties(dxl_properties);
// add children
pdxlnAgg->AddChild(proj_list_dxlnode);
pdxlnAgg->AddChild(filter_dxlnode);
pdxlnAgg->AddChild(child_dxlnode);
#ifdef GPOS_DEBUG
pdxlopAgg->AssertValid(pdxlnAgg, false /* validate_children */);
#endif
return pdxlnAgg;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnSort
//
// @doc:
// Create a DXL sort node from an optimizer physical sort expression
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnSort(CExpression *pexprSort,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprSort);
GPOS_ASSERT(1 == pexprSort->Arity());
// extract components
CPhysicalSort *popSort = CPhysicalSort::PopConvert(pexprSort->Pop());
CExpression *pexprChild = (*pexprSort)[0];
// translate relational child expression
CDXLNode *child_dxlnode = CreateDXLNode(
pexprChild, colref_array, pdrgpdsBaseTables, pulNonGatherMotions, pfDML,
false /*fRemap*/, false /*fRoot*/);
// translate order spec
CDXLNode *sort_col_list_dxlnode = GetSortColListDXL(popSort->Pos());
// construct project list from child project list
GPOS_ASSERT(nullptr != child_dxlnode && 1 <= child_dxlnode->Arity());
CDXLNode *pdxlnProjListChild = (*child_dxlnode)[0];
CDXLNode *proj_list_dxlnode =
CTranslatorExprToDXLUtils::PdxlnProjListFromChildProjList(
m_mp, m_pcf, m_phmcrdxln, pdxlnProjListChild);
// create an empty filter
CDXLNode *filter_dxlnode = PdxlnFilter(nullptr);
// construct a sort node
CDXLPhysicalSort *pdxlopSort =
GPOS_NEW(m_mp) CDXLPhysicalSort(m_mp, false /*discard_duplicates*/);
// construct sort node from its components
CDXLNode *pdxlnSort = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopSort);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprSort);
pdxlnSort->SetProperties(dxl_properties);
// construct empty limit count and offset nodes
CDXLNode *limit_count_dxlnode = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarLimitCount(m_mp));
CDXLNode *limit_offset_dxlnode = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarLimitOffset(m_mp));
// add children
pdxlnSort->AddChild(proj_list_dxlnode);
pdxlnSort->AddChild(filter_dxlnode);
pdxlnSort->AddChild(sort_col_list_dxlnode);
pdxlnSort->AddChild(limit_count_dxlnode);
pdxlnSort->AddChild(limit_offset_dxlnode);
pdxlnSort->AddChild(child_dxlnode);
#ifdef GPOS_DEBUG
pdxlopSort->AssertValid(pdxlnSort, false /* validate_children */);
#endif
return pdxlnSort;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnLimit
//
// @doc:
// Create a DXL limit node from an optimizer physical limit expression.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnLimit(CExpression *pexprLimit,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprLimit);
GPOS_ASSERT(3 == pexprLimit->Arity());
// extract components
CExpression *pexprChild = (*pexprLimit)[0];
CExpression *pexprOffset = (*pexprLimit)[1];
CExpression *pexprCount = (*pexprLimit)[2];
// bypass translation of limit if it does not have row count and offset
CPhysicalLimit *popLimit = CPhysicalLimit::PopConvert(pexprLimit->Pop());
if (!popLimit->FHasCount() && CUtils::FHasZeroOffset(pexprLimit))
{
return CreateDXLNode(pexprChild, colref_array, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, true /*fRemap*/,
false /*fRoot*/);
}
// translate relational child expression
CDXLNode *child_dxlnode = CreateDXLNode(
pexprChild, colref_array, pdrgpdsBaseTables, pulNonGatherMotions, pfDML,
true /*fRemap*/, false /*fRoot*/);
// translate limit offset and count
CDXLNode *limit_offset = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarLimitOffset(m_mp));
limit_offset->AddChild(PdxlnScalar(pexprOffset));
CDXLNode *limit_count = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarLimitCount(m_mp));
limit_count->AddChild(PdxlnScalar(pexprCount));
// construct project list from child project list
GPOS_ASSERT(nullptr != child_dxlnode && 1 <= child_dxlnode->Arity());
CDXLNode *pdxlnProjListChild = (*child_dxlnode)[0];
CDXLNode *proj_list_dxlnode =
CTranslatorExprToDXLUtils::PdxlnProjListFromChildProjList(
m_mp, m_pcf, m_phmcrdxln, pdxlnProjListChild);
// construct a limit node
CDXLPhysicalLimit *pdxlopLimit = GPOS_NEW(m_mp) CDXLPhysicalLimit(m_mp);
// construct limit node from its components
CDXLNode *pdxlnLimit = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopLimit);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprLimit);
pdxlnLimit->SetProperties(dxl_properties);
pdxlnLimit->AddChild(proj_list_dxlnode);
pdxlnLimit->AddChild(child_dxlnode);
pdxlnLimit->AddChild(limit_count);
pdxlnLimit->AddChild(limit_offset);
#ifdef GPOS_DEBUG
pdxlopLimit->AssertValid(pdxlnLimit, false /* validate_children */);
#endif
return pdxlnLimit;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::BuildSubplansForCorrelatedLOJ
//
// @doc:
// Helper to build subplans from correlated LOJ
//
//---------------------------------------------------------------------------
void
CTranslatorExprToDXL::BuildSubplansForCorrelatedLOJ(
CExpression *pexprCorrelatedLOJ, CDXLColRefArray *dxl_colref_array,
CDXLNode **
ppdxlnScalar, // output: scalar condition after replacing inner child reference with subplan
CDistributionSpecArray *pdrgpdsBaseTables, ULONG *pulNonGatherMotions,
BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprCorrelatedLOJ);
GPOS_ASSERT(COperator::EopPhysicalCorrelatedLeftOuterNLJoin ==
pexprCorrelatedLOJ->Pop()->Eopid());
CExpression *pexprInner = (*pexprCorrelatedLOJ)[1];
CExpression *pexprScalar = (*pexprCorrelatedLOJ)[2];
CColRefArray *pdrgpcrInner =
CPhysicalNLJoin::PopConvert(pexprCorrelatedLOJ->Pop())->PdrgPcrInner();
GPOS_ASSERT(nullptr != pdrgpcrInner);
EdxlSubPlanType dxl_subplan_type = Edxlsubplantype(pexprCorrelatedLOJ);
if (EdxlSubPlanTypeScalar == dxl_subplan_type)
{
// for correlated left outer join for scalar subplan type, we generate a scalar subplan
BuildScalarSubplans(pdrgpcrInner, pexprInner, dxl_colref_array,
pdrgpdsBaseTables, pulNonGatherMotions, pfDML);
// now translate the scalar - references to the inner child will be
// replaced by the subplan
*ppdxlnScalar = PdxlnScalar(pexprScalar);
return;
}
GPOS_ASSERT(EdxlSubPlanTypeAny == dxl_subplan_type ||
EdxlSubPlanTypeAll == dxl_subplan_type ||
EdxlSubPlanTypeExists == dxl_subplan_type ||
EdxlSubPlanTypeNotExists == dxl_subplan_type);
// for correlated left outer join with non-scalar subplan type,
// we need to generate quantified/exitential subplan
if (EdxlSubPlanTypeAny == dxl_subplan_type ||
EdxlSubPlanTypeAll == dxl_subplan_type)
{
(void) PdxlnQuantifiedSubplan(pdrgpcrInner, pexprCorrelatedLOJ,
dxl_colref_array, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML);
}
else
{
GPOS_ASSERT(EdxlSubPlanTypeExists == dxl_subplan_type ||
EdxlSubPlanTypeNotExists == dxl_subplan_type);
(void) PdxlnExistentialSubplan(pdrgpcrInner, pexprCorrelatedLOJ,
dxl_colref_array, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML);
}
CExpression *pexprTrue =
CUtils::PexprScalarConstBool(m_mp, true /*value*/, false /*is_null*/);
*ppdxlnScalar = PdxlnScalar(pexprTrue);
pexprTrue->Release();
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::BuildSubplans
//
// @doc:
// Helper to build subplans of different types
//
//---------------------------------------------------------------------------
void
CTranslatorExprToDXL::BuildSubplans(
CExpression *pexprCorrelatedNLJoin, CDXLColRefArray *dxl_colref_array,
CDXLNode **
ppdxlnScalar, // output: scalar condition after replacing inner child reference with subplan
CDistributionSpecArray *pdrgpdsBaseTables, ULONG *pulNonGatherMotions,
BOOL *pfDML)
{
GPOS_ASSERT(CUtils::FCorrelatedNLJoin(pexprCorrelatedNLJoin->Pop()));
GPOS_ASSERT(nullptr != ppdxlnScalar);
CExpression *pexprInner = (*pexprCorrelatedNLJoin)[1];
CExpression *pexprScalar = (*pexprCorrelatedNLJoin)[2];
CColRefArray *pdrgpcrInner =
CPhysicalNLJoin::PopConvert(pexprCorrelatedNLJoin->Pop())
->PdrgPcrInner();
GPOS_ASSERT(nullptr != pdrgpcrInner);
COperator::EOperatorId op_id = pexprCorrelatedNLJoin->Pop()->Eopid();
CDXLNode *pdxlnSubPlan = nullptr;
switch (op_id)
{
case COperator::EopPhysicalCorrelatedLeftOuterNLJoin:
BuildSubplansForCorrelatedLOJ(
pexprCorrelatedNLJoin, dxl_colref_array, ppdxlnScalar,
pdrgpdsBaseTables, pulNonGatherMotions, pfDML);
return;
case COperator::EopPhysicalCorrelatedInnerNLJoin:
BuildScalarSubplans(pdrgpcrInner, pexprInner, dxl_colref_array,
pdrgpdsBaseTables, pulNonGatherMotions, pfDML);
// now translate the scalar - references to the inner child will be
// replaced by the subplan
*ppdxlnScalar = PdxlnScalar(pexprScalar);
return;
case COperator::EopPhysicalCorrelatedInLeftSemiNLJoin:
case COperator::EopPhysicalCorrelatedNotInLeftAntiSemiNLJoin:
pdxlnSubPlan = PdxlnQuantifiedSubplan(
pdrgpcrInner, pexprCorrelatedNLJoin, dxl_colref_array,
pdrgpdsBaseTables, pulNonGatherMotions, pfDML);
pdxlnSubPlan->AddRef();
*ppdxlnScalar = pdxlnSubPlan;
return;
case COperator::EopPhysicalCorrelatedLeftSemiNLJoin:
case COperator::EopPhysicalCorrelatedLeftAntiSemiNLJoin:
pdxlnSubPlan = PdxlnExistentialSubplan(
pdrgpcrInner, pexprCorrelatedNLJoin, dxl_colref_array,
pdrgpdsBaseTables, pulNonGatherMotions, pfDML);
pdxlnSubPlan->AddRef();
*ppdxlnScalar = pdxlnSubPlan;
return;
default:
GPOS_ASSERT(!"Unsupported correlated join");
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnRestrictResult
//
// @doc:
// Helper to build a Result expression with project list
// restricted to required column
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnRestrictResult(CDXLNode *dxlnode,
const CColRef *colref)
{
CDXLNode *dxlresult = nullptr;
CColRefSet *pcrInner = GPOS_NEW(m_mp) CColRefSet(m_mp);
pcrInner->Include(colref);
dxlresult = PdxlnRestrictResult(dxlnode, pcrInner);
pcrInner->Release();
return dxlresult;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnRestrictResult
//
// @doc:
// Helper to build a Result expression with project list
// restricted to required columns
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnRestrictResult(CDXLNode *dxlnode,
const CColRefSet *colrefs)
{
GPOS_ASSERT(nullptr != dxlnode);
GPOS_ASSERT(nullptr != colrefs);
CDXLNode *pdxlnProjListOld = (*dxlnode)[0];
const ULONG ulPrjElems = pdxlnProjListOld->Arity();
if (0 == ulPrjElems)
{
// failed to find project elements
dxlnode->Release();
return nullptr;
}
CDXLNode *pdxlnResult = dxlnode;
if (1 < ulPrjElems)
{
// restrict project list to required column
CDXLScalarProjList *pdxlopPrL = GPOS_NEW(m_mp) CDXLScalarProjList(m_mp);
CDXLNode *pdxlnProjListNew = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopPrL);
IntToColRefMap *phmicr = colrefs->Phmicr(m_mp);
for (ULONG ul = 0; ul < ulPrjElems; ul++)
{
CDXLNode *child_dxlnode = (*pdxlnProjListOld)[ul];
CDXLScalarProjElem *pdxlPrjElem =
CDXLScalarProjElem::Cast(child_dxlnode->GetOperator());
const INT colid = pdxlPrjElem->Id();
CColRef *colref = phmicr->Find(&colid);
if (colref)
{
// create a new project element that simply points to required column,
// we cannot re-use child_dxlnode here since it may have a deep expression with columns inaccessible
// above the child (inner) DXL expression
CDXLNode *pdxlnPrEl = CTranslatorExprToDXLUtils::PdxlnProjElem(
m_mp, m_phmcrdxln, colref);
pdxlnProjListNew->AddChild(pdxlnPrEl);
}
}
phmicr->Release();
GPOS_ASSERT(colrefs->Size() == pdxlnProjListNew->Arity());
pdxlnResult = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLPhysicalResult(m_mp));
CDXLPhysicalProperties *dxl_properties =
CTranslatorExprToDXLUtils::PdxlpropCopy(m_mp, dxlnode);
pdxlnResult->SetProperties(dxl_properties);
pdxlnResult->AddChild(pdxlnProjListNew);
pdxlnResult->AddChild(PdxlnFilter(nullptr));
pdxlnResult->AddChild(GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarOneTimeFilter(m_mp)));
pdxlnResult->AddChild(dxlnode);
}
return pdxlnResult;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnQuantifiedSubplan
//
// @doc:
// Helper to build subplans for quantified (ANY/ALL) subqueries
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnQuantifiedSubplan(
CColRefArray *pdrgpcrInner, CExpression *pexprCorrelatedNLJoin,
CDXLColRefArray *dxl_colref_array,
CDistributionSpecArray *pdrgpdsBaseTables, ULONG *pulNonGatherMotions,
BOOL *pfDML)
{
COperator *popCorrelatedJoin = pexprCorrelatedNLJoin->Pop();
COperator::EOperatorId op_id = popCorrelatedJoin->Eopid();
BOOL fCorrelatedLOJ =
(COperator::EopPhysicalCorrelatedLeftOuterNLJoin == op_id);
GPOS_ASSERT(COperator::EopPhysicalCorrelatedInLeftSemiNLJoin == op_id ||
COperator::EopPhysicalCorrelatedNotInLeftAntiSemiNLJoin ==
op_id ||
fCorrelatedLOJ);
EdxlSubPlanType dxl_subplan_type = Edxlsubplantype(pexprCorrelatedNLJoin);
GPOS_ASSERT_IMP(fCorrelatedLOJ, EdxlSubPlanTypeAny == dxl_subplan_type ||
EdxlSubPlanTypeAll == dxl_subplan_type);
CExpression *pexprInner = (*pexprCorrelatedNLJoin)[1];
CExpression *pexprScalar = (*pexprCorrelatedNLJoin)[2];
// translate inner child
CDXLNode *pdxlnInnerChild = CreateDXLNode(
pexprInner, nullptr /*colref_array*/, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
// find required column from inner child
CColRefSet *pcrInner = GPOS_NEW(m_mp) CColRefSet(m_mp);
pcrInner->Include((*pdrgpcrInner)[0]);
BOOL outerParam = false;
if (fCorrelatedLOJ)
{
// overwrite required inner column based on scalar expression
CColRefSet *pcrsInner = pexprInner->DeriveOutputColumns();
CColRefSet *pcrsUsed =
GPOS_NEW(m_mp) CColRefSet(m_mp, *pexprScalar->DeriveUsedColumns());
pcrsUsed->Intersection(pcrsInner);
if (0 < pcrsUsed->Size())
{
GPOS_ASSERT(1 == pcrsUsed->Size() || 2 == pcrsUsed->Size());
// Both sides of the SubPlan test expression can come from the
// inner side. So we need to pass pcrsUsed instead of pcrInner into
// PdxlnRestrictResult()
outerParam = pcrsUsed->Size() > 1;
pcrInner->Release();
pcrInner = pcrsUsed;
}
else
{
pcrsUsed->Release();
}
}
CDXLNode *inner_dxlnode = PdxlnRestrictResult(pdxlnInnerChild, pcrInner);
pcrInner->Release();
if (nullptr == inner_dxlnode)
{
GPOS_RAISE(
gpopt::ExmaDXL, gpopt::ExmiExpr2DXLUnsupportedFeature,
GPOS_WSZ_LIT(
"Outer references in the project list of a correlated subquery"));
}
// translate test expression
CDXLNode *dxlnode_test_expr = PdxlnScalar(pexprScalar);
const IMDTypeBool *pmdtypebool = m_pmda->PtMDType<IMDTypeBool>();
IMDId *mdid = pmdtypebool->MDId();
mdid->AddRef();
// construct a subplan node, with the inner child under it
CDXLNode *pdxlnSubPlan = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarSubPlan(
m_mp, mdid, dxl_colref_array, dxl_subplan_type,
dxlnode_test_expr, outerParam));
pdxlnSubPlan->AddChild(inner_dxlnode);
// add to hashmap
BOOL fRes GPOS_ASSERTS_ONLY =
m_phmcrdxln->Insert((*pdrgpcrInner)[0], pdxlnSubPlan);
GPOS_ASSERT(fRes);
return pdxlnSubPlan;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnProjectBoolConst
//
// @doc:
// Helper to add a project of bool constant on top of given DXL node
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnProjectBoolConst(CDXLNode *dxlnode, BOOL value)
{
GPOS_ASSERT(nullptr != dxlnode);
// create a new project element with bool value
const IMDTypeBool *pmdtypebool = m_pmda->PtMDType<IMDTypeBool>();
IMDId *mdid = pmdtypebool->MDId();
mdid->AddRef();
CDXLDatumBool *dxl_datum =
GPOS_NEW(m_mp) CDXLDatumBool(m_mp, mdid, false /* is_null */, value);
CDXLScalarConstValue *pdxlopConstValue =
GPOS_NEW(m_mp) CDXLScalarConstValue(m_mp, dxl_datum);
CColRef *colref = m_pcf->PcrCreate(pmdtypebool, default_type_modifier);
CDXLNode *pdxlnPrEl =
PdxlnProjElem(colref, GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopConstValue));
CDXLScalarProjList *pdxlopPrL = GPOS_NEW(m_mp) CDXLScalarProjList(m_mp);
CDXLNode *proj_list_dxlnode = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopPrL);
proj_list_dxlnode->AddChild(pdxlnPrEl);
CDXLNode *pdxlnResult =
GPOS_NEW(m_mp) CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLPhysicalResult(m_mp));
CDXLPhysicalProperties *dxl_properties =
CTranslatorExprToDXLUtils::PdxlpropCopy(m_mp, dxlnode);
pdxlnResult->SetProperties(dxl_properties);
pdxlnResult->AddChild(proj_list_dxlnode);
pdxlnResult->AddChild(PdxlnFilter(nullptr));
pdxlnResult->AddChild(GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarOneTimeFilter(m_mp)));
pdxlnResult->AddChild(dxlnode);
return pdxlnResult;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::EdxlsubplantypeCorrelatedLOJ
//
// @doc:
// Helper to find subplan type from a correlated left outer
// join expression
//
//---------------------------------------------------------------------------
EdxlSubPlanType
CTranslatorExprToDXL::EdxlsubplantypeCorrelatedLOJ(
CExpression *pexprCorrelatedLOJ)
{
GPOS_ASSERT(nullptr != pexprCorrelatedLOJ);
GPOS_ASSERT(COperator::EopPhysicalCorrelatedLeftOuterNLJoin ==
pexprCorrelatedLOJ->Pop()->Eopid());
COperator::EOperatorId eopidSubq =
CPhysicalCorrelatedLeftOuterNLJoin::PopConvert(
pexprCorrelatedLOJ->Pop())
->EopidOriginSubq();
switch (eopidSubq)
{
case COperator::EopScalarSubquery:
return EdxlSubPlanTypeScalar;
case COperator::EopScalarSubqueryAll:
return EdxlSubPlanTypeAll;
case COperator::EopScalarSubqueryAny:
return EdxlSubPlanTypeAny;
case COperator::EopScalarSubqueryExists:
return EdxlSubPlanTypeExists;
case COperator::EopScalarSubqueryNotExists:
return EdxlSubPlanTypeNotExists;
default:
GPOS_ASSERT(
!"Unexpected origin subquery in correlated left outer join");
}
return EdxlSubPlanTypeSentinel;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::Edxlsubplantype
//
// @doc:
// Helper to find subplan type from a correlated join expression
//
//---------------------------------------------------------------------------
EdxlSubPlanType
CTranslatorExprToDXL::Edxlsubplantype(CExpression *pexprCorrelatedNLJoin)
{
GPOS_ASSERT(nullptr != pexprCorrelatedNLJoin);
GPOS_ASSERT(CUtils::FCorrelatedNLJoin(pexprCorrelatedNLJoin->Pop()));
COperator::EOperatorId op_id = pexprCorrelatedNLJoin->Pop()->Eopid();
switch (op_id)
{
case COperator::EopPhysicalCorrelatedLeftOuterNLJoin:
return EdxlsubplantypeCorrelatedLOJ(pexprCorrelatedNLJoin);
case COperator::EopPhysicalCorrelatedInnerNLJoin:
return EdxlSubPlanTypeScalar;
case COperator::EopPhysicalCorrelatedNotInLeftAntiSemiNLJoin:
return EdxlSubPlanTypeAll;
case COperator::EopPhysicalCorrelatedInLeftSemiNLJoin:
return EdxlSubPlanTypeAny;
case COperator::EopPhysicalCorrelatedLeftSemiNLJoin:
return EdxlSubPlanTypeExists;
case COperator::EopPhysicalCorrelatedLeftAntiSemiNLJoin:
return EdxlSubPlanTypeNotExists;
default:
GPOS_ASSERT(!"Unexpected correlated join");
}
return EdxlSubPlanTypeSentinel;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnExistentialSubplan
//
// @doc:
// Helper to build subplans for existential subqueries
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnExistentialSubplan(
CColRefArray *pdrgpcrInner, CExpression *pexprCorrelatedNLJoin,
CDXLColRefArray *dxl_colref_array,
CDistributionSpecArray *pdrgpdsBaseTables, ULONG *pulNonGatherMotions,
BOOL *pfDML)
{
#ifdef GPOS_DEBUG
COperator::EOperatorId op_id = pexprCorrelatedNLJoin->Pop()->Eopid();
BOOL fCorrelatedLOJ =
(COperator::EopPhysicalCorrelatedLeftOuterNLJoin == op_id);
#endif // GPOS_DEBUG
GPOS_ASSERT(COperator::EopPhysicalCorrelatedLeftSemiNLJoin == op_id ||
COperator::EopPhysicalCorrelatedLeftAntiSemiNLJoin == op_id ||
fCorrelatedLOJ);
EdxlSubPlanType dxl_subplan_type = Edxlsubplantype(pexprCorrelatedNLJoin);
GPOS_ASSERT_IMP(fCorrelatedLOJ,
EdxlSubPlanTypeExists == dxl_subplan_type ||
EdxlSubPlanTypeNotExists == dxl_subplan_type);
// translate inner child
CExpression *pexprInner = (*pexprCorrelatedNLJoin)[1];
CDXLNode *pdxlnInnerChild = CreateDXLNode(
pexprInner, nullptr /*colref_array*/, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
CDXLNode *pdxlnInnerProjList = (*pdxlnInnerChild)[0];
CDXLNode *inner_dxlnode = nullptr;
if (0 == pdxlnInnerProjList->Arity())
{
// no requested columns from subplan, add a dummy boolean constant to project list
inner_dxlnode = PdxlnProjectBoolConst(pdxlnInnerChild, true /*value*/);
}
else
{
// restrict requested columns to required inner column
inner_dxlnode =
PdxlnRestrictResult(pdxlnInnerChild, (*pdrgpcrInner)[0]);
}
if (nullptr == inner_dxlnode)
{
GPOS_RAISE(
gpopt::ExmaDXL, gpopt::ExmiExpr2DXLUnsupportedFeature,
GPOS_WSZ_LIT(
"Outer references in the project list of a correlated subquery"));
}
const IMDTypeBool *pmdtypebool = m_pmda->PtMDType<IMDTypeBool>();
IMDId *mdid = pmdtypebool->MDId();
mdid->AddRef();
// construct a subplan node, with the inner child under it
CDXLNode *pdxlnSubPlan = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarSubPlan(
m_mp, mdid, dxl_colref_array, dxl_subplan_type,
nullptr /*dxlnode_test_expr*/));
pdxlnSubPlan->AddChild(inner_dxlnode);
// add to hashmap
BOOL fRes GPOS_ASSERTS_ONLY = m_phmcrdxln->Insert(
const_cast<CColRef *>((*pdrgpcrInner)[0]), pdxlnSubPlan);
GPOS_ASSERT(fRes);
return pdxlnSubPlan;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::BuildScalarSubplans
//
// @doc:
// Helper to build subplans from inner column references and store
// generated subplans in subplan map
//
//---------------------------------------------------------------------------
void
CTranslatorExprToDXL::BuildScalarSubplans(
CColRefArray *pdrgpcrInner, CExpression *pexprInner,
CDXLColRefArray *dxl_colref_array,
CDistributionSpecArray *pdrgpdsBaseTables, ULONG *pulNonGatherMotions,
BOOL *pfDML)
{
const ULONG size = pdrgpcrInner->Size();
CDXLNodeArray *pdrgpdxlnInner = GPOS_NEW(m_mp) CDXLNodeArray(m_mp);
for (ULONG ul = 0; ul < size; ul++)
{
// for each subplan, we need to re-translate inner expression
CDXLNode *pdxlnInnerChild = CreateDXLNode(
pexprInner, nullptr /*colref_array*/, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
CDXLNode *inner_dxlnode =
PdxlnRestrictResult(pdxlnInnerChild, (*pdrgpcrInner)[ul]);
if (nullptr == inner_dxlnode)
{
GPOS_RAISE(
gpopt::ExmaDXL, gpopt::ExmiExpr2DXLUnsupportedFeature,
GPOS_WSZ_LIT(
"Outer references in the project list of a correlated subquery"));
}
pdrgpdxlnInner->Append(inner_dxlnode);
}
for (ULONG ul = 0; ul < size; ul++)
{
CDXLNode *inner_dxlnode = (*pdrgpdxlnInner)[ul];
inner_dxlnode->AddRef();
if (0 < ul)
{
// if there is more than one subplan, we need to add-ref passed arrays
dxl_colref_array->AddRef();
}
const CColRef *pcrInner = (*pdrgpcrInner)[ul];
BuildDxlnSubPlan(inner_dxlnode, pcrInner, dxl_colref_array);
}
pdrgpdxlnInner->Release();
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PcrsOuterRefsForCorrelatedNLJoin
//
// @doc:
// Return outer refs in correlated join inner child
//
//---------------------------------------------------------------------------
CColRefSet *
CTranslatorExprToDXL::PcrsOuterRefsForCorrelatedNLJoin(CExpression *pexpr)
{
GPOS_ASSERT(CUtils::FCorrelatedNLJoin(pexpr->Pop()));
CExpression *pexprInnerChild = (*pexpr)[1];
return pexprInnerChild->DeriveOuterReferences();
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnCorrelatedNLJoin
//
// @doc:
// Translate correlated NLJ expression.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnCorrelatedNLJoin(
CExpression *pexpr, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables, ULONG *pulNonGatherMotions,
BOOL *pfDML)
{
GPOS_ASSERT(CUtils::FCorrelatedNLJoin(pexpr->Pop()));
// extract components
CExpression *pexprOuterChild = (*pexpr)[0];
CExpression *pexprInnerChild = (*pexpr)[1];
CExpression *pexprScalar = (*pexpr)[2];
// outer references in the inner child
CDXLColRefArray *dxl_colref_array = GPOS_NEW(m_mp) CDXLColRefArray(m_mp);
CColRefSet *outer_refs = PcrsOuterRefsForCorrelatedNLJoin(pexpr);
CColRefSetIter crsi(*outer_refs);
while (crsi.Advance())
{
CColRef *colref = crsi.Pcr();
CMDName *mdname = GPOS_NEW(m_mp) CMDName(m_mp, colref->Name().Pstr());
IMDId *mdid = colref->RetrieveType()->MDId();
mdid->AddRef();
CDXLColRef *dxl_colref = GPOS_NEW(m_mp)
CDXLColRef(mdname, colref->Id(), mdid, colref->TypeModifier());
dxl_colref_array->Append(dxl_colref);
}
COperator::EOperatorId op_id = pexpr->Pop()->Eopid();
CDXLNode *pdxlnCond = nullptr;
// Create a subplan with a Boolean from the inner child if we have a Const True as a join condition.
// One scenario for this is when IN sublinks contain a projection from the outer table only such as:
// select * from foo where foo.a in (select foo.b from bar);
// If bar is a very small table, ORCA generates a CorrelatedInLeftSemiNLJoin with a Const true join filter
// and condition foo.a = foo.b is added as a filter on the table scan of foo. If bar is a large table,
// ORCA generates a plan with CorrelatedInnerNLJoin with a Const true join filter and a LIMIT over the
// scan of bar. The same foo.a = foo.b condition is also added as a filter on the table scan of foo.
if (CUtils::FScalarConstTrue(pexprScalar) &&
(COperator::EopPhysicalCorrelatedInnerNLJoin == op_id ||
COperator::EopPhysicalCorrelatedInLeftSemiNLJoin == op_id))
{
// translate relational inner child expression
CDXLNode *pdxlnInnerChild =
CreateDXLNode(pexprInnerChild,
nullptr, // colref_array,
pdrgpdsBaseTables, pulNonGatherMotions, pfDML,
false, // fRemap
false // fRoot
);
// if the filter predicate is a constant TRUE, create a subplan that returns
// Boolean from the inner child, and use that as the scalar condition
pdxlnCond =
PdxlnBooleanScalarWithSubPlan(pdxlnInnerChild, dxl_colref_array);
}
else
{
BuildSubplans(pexpr, dxl_colref_array, &pdxlnCond, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML);
}
// extract dxl properties from correlated join
CDXLPhysicalProperties *dxl_properties = GetProperties(pexpr);
CDXLNode *dxlnode = nullptr;
switch (pexprOuterChild->Pop()->Eopid())
{
case COperator::EopPhysicalTableScan:
{
dxl_properties->AddRef();
// create and return a table scan node
dxlnode = PdxlnTblScanFromNLJoinOuter(
pexprOuterChild, pdxlnCond, colref_array, pdrgpdsBaseTables,
pulNonGatherMotions, dxl_properties);
break;
}
case COperator::EopPhysicalFilter:
{
dxl_properties->AddRef();
dxlnode = PdxlnResultFromNLJoinOuter(
pexprOuterChild, pdxlnCond, colref_array, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, dxl_properties);
break;
}
default:
{
// create a result node over outer child
dxl_properties->AddRef();
dxlnode = PdxlnResult(pexprOuterChild, colref_array,
pdrgpdsBaseTables, pulNonGatherMotions, pfDML,
pdxlnCond, dxl_properties);
}
}
dxl_properties->Release();
return dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::BuildDxlnSubPlan
//
// @doc:
// Construct a scalar dxl node with a subplan as its child. Also put this
// subplan in the hashmap with its output column, so that anyone who
// references that column can use the subplan
//
//---------------------------------------------------------------------------
void
CTranslatorExprToDXL::BuildDxlnSubPlan(CDXLNode *pdxlnRelChild,
const CColRef *colref,
CDXLColRefArray *dxl_colref_array)
{
GPOS_ASSERT(nullptr != colref);
IMDId *mdid = colref->RetrieveType()->MDId();
mdid->AddRef();
// construct a subplan node, with the inner child under it
CDXLNode *pdxlnSubPlan = GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarSubPlan(m_mp, mdid, dxl_colref_array,
EdxlSubPlanTypeScalar, nullptr));
pdxlnSubPlan->AddChild(pdxlnRelChild);
// add to hashmap
BOOL fRes GPOS_ASSERTS_ONLY =
m_phmcrdxln->Insert(const_cast<CColRef *>(colref), pdxlnSubPlan);
GPOS_ASSERT(fRes);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnBooleanScalarWithSubPlan
//
// @doc:
// Construct a boolean scalar dxl node with a subplan as its child. The
// sublan has a boolean output column, and has the given relational child
// under it
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnBooleanScalarWithSubPlan(
CDXLNode *pdxlnRelChild, CDXLColRefArray *dxl_colref_array)
{
// create a new project element (const:true), and replace the first child with it
const IMDTypeBool *pmdtypebool = m_pmda->PtMDType<IMDTypeBool>();
IMDId *mdid = pmdtypebool->MDId();
mdid->AddRef();
CDXLDatumBool *dxl_datum = GPOS_NEW(m_mp)
CDXLDatumBool(m_mp, mdid, false /* is_null */, true /* value */);
CDXLScalarConstValue *pdxlopConstValue =
GPOS_NEW(m_mp) CDXLScalarConstValue(m_mp, dxl_datum);
CColRef *colref = m_pcf->PcrCreate(pmdtypebool, default_type_modifier);
CDXLNode *pdxlnPrEl =
PdxlnProjElem(colref, GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopConstValue));
// create a new Result node for the created project element
CDXLNode *pdxlnProjListNew =
GPOS_NEW(m_mp) CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarProjList(m_mp));
pdxlnProjListNew->AddChild(pdxlnPrEl);
CDXLNode *pdxlnResult =
GPOS_NEW(m_mp) CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLPhysicalResult(m_mp));
CDXLPhysicalProperties *dxl_properties =
CTranslatorExprToDXLUtils::PdxlpropCopy(m_mp, pdxlnRelChild);
pdxlnResult->SetProperties(dxl_properties);
pdxlnResult->AddChild(pdxlnProjListNew);
pdxlnResult->AddChild(PdxlnFilter(nullptr));
pdxlnResult->AddChild(GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarOneTimeFilter(m_mp)));
pdxlnResult->AddChild(pdxlnRelChild);
// construct a subplan node, with the Result node under it
mdid->AddRef();
CDXLNode *pdxlnSubPlan = GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarSubPlan(m_mp, mdid, dxl_colref_array,
EdxlSubPlanTypeScalar, nullptr));
pdxlnSubPlan->AddChild(pdxlnResult);
return pdxlnSubPlan;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScBoolExpr
//
// @doc:
// Create a DXL scalar boolean node given two DXL boolean nodes
// and a boolean op
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScBoolExpr(EdxlBoolExprType boolexptype,
CDXLNode *dxlnode_left,
CDXLNode *dxlnode_right)
{
CDXLNode *pdxlnBoolExpr = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarBoolExpr(m_mp, boolexptype));
pdxlnBoolExpr->AddChild(dxlnode_left);
pdxlnBoolExpr->AddChild(dxlnode_right);
return pdxlnBoolExpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnTblScanFromNLJoinOuter
//
// @doc:
// Create a DXL table scan node from the outer child of a NLJ
// and a DXL scalar condition. Used for translated correlated
// subqueries.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnTblScanFromNLJoinOuter(
CExpression *pexprRelational, CDXLNode *pdxlnCond,
CColRefArray *colref_array, CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *, // pulNonGatherMotions,
CDXLPhysicalProperties *dxl_properties)
{
// create a table scan over the input expression, without a filter
CDXLNode *pdxlnTblScan = PdxlnTblScan(pexprRelational,
nullptr, //pcrsOutput
colref_array, pdrgpdsBaseTables,
nullptr, //pexprScalar
dxl_properties);
if (!CTranslatorExprToDXLUtils::FScalarConstTrue(m_pmda, pdxlnCond))
{
// add the new filter to the table scan replacing its original
// empty filter
CDXLNode *filter_dxlnode = PdxlnFilter(pdxlnCond);
pdxlnTblScan->ReplaceChild(EdxltsIndexFilter /*ulPos*/, filter_dxlnode);
}
else
{
// not used
pdxlnCond->Release();
}
return pdxlnTblScan;
}
static ULONG
UlIndexFilter(Edxlopid edxlopid)
{
switch (edxlopid)
{
case EdxlopPhysicalTableScan:
case EdxlopPhysicalExternalScan:
return EdxltsIndexFilter;
case EdxlopPhysicalBitmapTableScan:
case EdxlopPhysicalDynamicBitmapTableScan:
return EdxlbsIndexFilter;
case EdxlopPhysicalDynamicTableScan:
return EdxldtsIndexFilter;
case EdxlopPhysicalIndexScan:
case EdxlopPhysicalDynamicIndexScan:
return EdxlisIndexFilter;
case EdxlopPhysicalResult:
return EdxlresultIndexFilter;
default:
GPOS_RTL_ASSERT(
"Unexpected operator. Expected operators that contain a filter child");
return gpos::ulong_max;
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnResultFromNLJoinOuter
//
// @doc:
// Create a DXL result node from the outer child of a NLJ
// and a DXL scalar join condition. Used for translated correlated
// subqueries.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnResultFromNLJoinOuter(
CExpression *pexprOuterChildRelational, CDXLNode *pdxlnJoinCond,
CColRefArray *colref_array, CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML,
CDXLPhysicalProperties *dxl_properties)
{
// create a result node using the filter from the outer child of the input expression
CDXLNode *pdxlnRelationalNew = PdxlnFromFilter(
pexprOuterChildRelational, colref_array, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, dxl_properties);
dxl_properties->Release();
Edxlopid edxlopid = pdxlnRelationalNew->GetOperator()->GetDXLOperator();
switch (edxlopid)
{
case EdxlopPhysicalTableScan:
case EdxlopPhysicalExternalScan:
case EdxlopPhysicalBitmapTableScan:
case EdxlopPhysicalDynamicTableScan:
case EdxlopPhysicalIndexScan:
case EdxlopPhysicalDynamicIndexScan:
case EdxlopPhysicalDynamicBitmapTableScan:
case EdxlopPhysicalResult:
{
// if the scalar join condition is a constant TRUE, just translate the child, no need to create an AND expression
if (CTranslatorExprToDXLUtils::FScalarConstTrue(m_pmda,
pdxlnJoinCond))
{
pdxlnJoinCond->Release();
break;
}
// create new AND expression with the outer child's filter node and the join condition
ULONG ulIndexFilter = UlIndexFilter(edxlopid);
GPOS_ASSERT(ulIndexFilter != gpos::ulong_max);
CDXLNode *pdxlnChildFilter = (*pdxlnRelationalNew)[ulIndexFilter];
GPOS_ASSERT(EdxlopScalarFilter ==
pdxlnChildFilter->GetOperator()->GetDXLOperator());
CDXLNode *newFilterPred = pdxlnJoinCond;
if (0 < pdxlnChildFilter->Arity())
{
// we have both a filter condition (from the outer child) in our result node
// and a non-trivial condition pdxlnJoinCond passed in as parameter, need to AND the two
CDXLNode *pdxlnCondFromChildFilter = (*pdxlnChildFilter)[0];
GPOS_ASSERT(2 > pdxlnChildFilter->Arity());
pdxlnCondFromChildFilter->AddRef();
newFilterPred = PdxlnScBoolExpr(
Edxland, pdxlnCondFromChildFilter, pdxlnJoinCond);
}
// add the new filter to the result replacing its original
// empty filter
CDXLNode *new_filter_dxlnode = PdxlnFilter(newFilterPred);
pdxlnRelationalNew->ReplaceChild(ulIndexFilter /*ulPos*/,
new_filter_dxlnode);
}
break;
// In case the OuterChild is a physical sequence, it will already have the filter in the partition selector and
// dynamic scan, thus we should not replace the filter.
case EdxlopPhysicalSequence:
case EdxlopPhysicalAppend:
{
dxl_properties->AddRef();
GPOS_ASSERT(nullptr != pexprOuterChildRelational->Prpp());
CColRefSet *pcrsOutput =
pexprOuterChildRelational->Prpp()->PcrsRequired();
pdxlnRelationalNew = PdxlnAddScalarFilterOnRelationalChild(
pdxlnRelationalNew, pdxlnJoinCond, dxl_properties, pcrsOutput,
colref_array);
}
break;
default:
pdxlnJoinCond->Release();
GPOS_RTL_ASSERT(false && "Unexpected node here");
}
return pdxlnRelationalNew;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::StoreIndexNLJOuterRefs
//
// @doc:
// Store outer references in index NLJ inner child into global map
//
//---------------------------------------------------------------------------
void
CTranslatorExprToDXL::StoreIndexNLJOuterRefs(CPhysical *pop)
{
CColRefArray *colref_array = nullptr;
if (COperator::EopPhysicalInnerIndexNLJoin == pop->Eopid())
{
colref_array =
CPhysicalInnerIndexNLJoin::PopConvert(pop)->PdrgPcrOuterRefs();
}
else
{
colref_array =
CPhysicalLeftOuterIndexNLJoin::PopConvert(pop)->PdrgPcrOuterRefs();
}
GPOS_ASSERT(colref_array != nullptr);
const ULONG size = colref_array->Size();
for (ULONG ul = 0; ul < size; ul++)
{
CColRef *colref = (*colref_array)[ul];
if (nullptr == m_phmcrdxlnIndexLookup->Find(colref))
{
CDXLNode *dxlnode = CTranslatorExprToDXLUtils::PdxlnIdent(
m_mp, m_phmcrdxln, m_phmcrdxlnIndexLookup, m_phmcrulPartColId,
colref);
#ifdef GPOS_DEBUG
BOOL fInserted =
#endif // GPOS_DEBUG
m_phmcrdxlnIndexLookup->Insert(colref, dxlnode);
GPOS_ASSERT(fInserted);
}
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnNLJoin
//
// @doc:
// Create a DXL nested loop join node from an optimizer nested loop
// join expression
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnNLJoin(CExpression *pexprInnerNLJ,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprInnerNLJ);
GPOS_ASSERT(3 == pexprInnerNLJ->Arity());
// extract components
CPhysical *pop = CPhysical::PopConvert(pexprInnerNLJ->Pop());
CExpression *pexprOuterChild = (*pexprInnerNLJ)[0];
CExpression *pexprInnerChild = (*pexprInnerNLJ)[1];
CExpression *pexprScalar = (*pexprInnerNLJ)[2];
#ifdef GPOS_DEBUG
GPOS_ASSERT_IMP(
COperator::EopPhysicalInnerIndexNLJoin != pop->Eopid() &&
COperator::EopPhysicalLeftOuterIndexNLJoin != pop->Eopid(),
pexprInnerChild->DeriveOuterReferences()->IsDisjoint(
pexprOuterChild->DeriveOutputColumns()) &&
"detected outer references in NL inner child");
#endif // GPOS_DEBUG
EdxlJoinType join_type = EdxljtSentinel;
BOOL is_index_nlj = false;
CColRefArray *outer_refs = nullptr;
switch (pop->Eopid())
{
case COperator::EopPhysicalInnerNLJoin:
join_type = EdxljtInner;
break;
case COperator::EopPhysicalInnerIndexNLJoin:
join_type = EdxljtInner;
is_index_nlj = true;
StoreIndexNLJOuterRefs(pop);
outer_refs =
CPhysicalInnerIndexNLJoin::PopConvert(pop)->PdrgPcrOuterRefs();
break;
case COperator::EopPhysicalLeftOuterIndexNLJoin:
join_type = EdxljtLeft;
is_index_nlj = true;
StoreIndexNLJOuterRefs(pop);
outer_refs = CPhysicalLeftOuterIndexNLJoin::PopConvert(pop)
->PdrgPcrOuterRefs();
break;
case COperator::EopPhysicalLeftOuterNLJoin:
join_type = EdxljtLeft;
break;
case COperator::EopPhysicalLeftSemiNLJoin:
join_type = EdxljtIn;
break;
case COperator::EopPhysicalLeftAntiSemiNLJoin:
join_type = EdxljtLeftAntiSemijoin;
break;
case COperator::EopPhysicalLeftAntiSemiNLJoinNotIn:
join_type = EdxljtLeftAntiSemijoinNotIn;
break;
default:
GPOS_ASSERT(!"Invalid join type");
}
// translate relational child expressions
CDXLNode *pdxlnOuterChild = CreateDXLNode(
pexprOuterChild, nullptr /*colref_array*/, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
CDXLNode *pdxlnInnerChild = CreateDXLNode(
pexprInnerChild, nullptr /*colref_array*/, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
CDXLNode *pdxlnCond = PdxlnScalar(pexprScalar);
CDXLNode *dxlnode_join_filter = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarJoinFilter(m_mp));
if (nullptr != pdxlnCond)
{
dxlnode_join_filter->AddChild(pdxlnCond);
}
BOOL nest_params_exists = false;
CDXLColRefArray *col_refs = nullptr;
if (is_index_nlj && GPOS_FTRACE(EopttraceIndexedNLJOuterRefAsParams))
{
nest_params_exists = true;
col_refs = GPOS_NEW(m_mp) CDXLColRefArray(m_mp);
for (ULONG ul = 0; ul < outer_refs->Size(); ul++)
{
CColRef *col_ref = (*outer_refs)[ul];
CMDName *md_name =
GPOS_NEW(m_mp) CMDName(m_mp, col_ref->Name().Pstr());
IMDId *mdid = col_ref->RetrieveType()->MDId();
mdid->AddRef();
CDXLColRef *colref_dxl = GPOS_NEW(m_mp) CDXLColRef(
md_name, col_ref->Id(), mdid, col_ref->TypeModifier());
col_refs->Append(colref_dxl);
}
}
// construct a join node
CDXLPhysicalNLJoin *pdxlopNLJ = GPOS_NEW(m_mp)
CDXLPhysicalNLJoin(m_mp, join_type, is_index_nlj, nest_params_exists);
pdxlopNLJ->SetNestLoopParamsColRefs(col_refs);
// construct projection list
// compute required columns
GPOS_ASSERT(nullptr != pexprInnerNLJ->Prpp());
CColRefSet *pcrsOutput = pexprInnerNLJ->Prpp()->PcrsRequired();
CDXLNode *proj_list_dxlnode = PdxlnProjList(pcrsOutput, colref_array);
CDXLNode *pdxlnNLJ = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopNLJ);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprInnerNLJ);
pdxlnNLJ->SetProperties(dxl_properties);
// construct an empty plan filter
CDXLNode *filter_dxlnode = PdxlnFilter(nullptr);
// add children
pdxlnNLJ->AddChild(proj_list_dxlnode);
pdxlnNLJ->AddChild(filter_dxlnode);
pdxlnNLJ->AddChild(dxlnode_join_filter);
pdxlnNLJ->AddChild(pdxlnOuterChild);
pdxlnNLJ->AddChild(pdxlnInnerChild);
#ifdef GPOS_DEBUG
pdxlopNLJ->AssertValid(pdxlnNLJ, false /* validate_children */);
#endif
return pdxlnNLJ;
}
CDXLNode *
CTranslatorExprToDXL::PdxlnMergeJoin(CExpression *pexprMJ,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprMJ);
GPOS_ASSERT(3 == pexprMJ->Arity());
// extract components
CPhysical *pop = CPhysical::PopConvert(pexprMJ->Pop());
CExpression *pexprOuterChild = (*pexprMJ)[0];
CExpression *pexprInnerChild = (*pexprMJ)[1];
CExpression *pexprScalar = (*pexprMJ)[2];
EdxlJoinType join_type = EdxljtSentinel;
switch (pop->Eopid())
{
case COperator::EopPhysicalFullMergeJoin:
join_type = EdxljtFull;
break;
default:
GPOS_ASSERT(!"Invalid join type");
}
// translate relational child expressions
CDXLNode *pdxlnOuterChild = CreateDXLNode(
pexprOuterChild, nullptr /*colref_array*/, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
CDXLNode *pdxlnInnerChild = CreateDXLNode(
pexprInnerChild, nullptr /*colref_array*/, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
CDXLNode *dxlnode_merge_conds = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarMergeCondList(m_mp));
CExpressionArray *pdrgpexprPredicates =
CPredicateUtils::PdrgpexprConjuncts(m_mp, pexprScalar);
const ULONG length = pdrgpexprPredicates->Size();
for (ULONG ul = 0; ul < length; ul++)
{
CExpression *pexprPred = (*pdrgpexprPredicates)[ul];
// At this point, they all better be merge joinable
GPOS_ASSERT(CPhysicalJoin::FMergeJoinCompatible(
pexprPred, pexprOuterChild, pexprInnerChild));
CExpression *pexprPredOuter = (*pexprPred)[0];
CExpression *pexprPredInner = (*pexprPred)[1];
// align extracted columns with outer and inner children of the join
CColRefSet *pcrsOuterChild = pexprOuterChild->DeriveOutputColumns();
CColRefSet *pcrsPredInner = pexprPredInner->DeriveUsedColumns();
#ifdef GPOS_DEBUG
CColRefSet *pcrsInnerChild = pexprInnerChild->DeriveOutputColumns();
CColRefSet *pcrsPredOuter = pexprPredOuter->DeriveUsedColumns();
#endif
if (pcrsOuterChild->ContainsAll(pcrsPredInner))
{
GPOS_ASSERT(pcrsInnerChild->ContainsAll(pcrsPredOuter));
std::swap(pexprPredOuter, pexprPredInner);
#ifdef GPOS_DEBUG
std::swap(pcrsPredOuter, pcrsPredInner);
#endif
pexprPredOuter->AddRef();
pexprPredInner->AddRef();
pexprPred =
CUtils::PexprScalarEqCmp(m_mp, pexprPredOuter, pexprPredInner);
}
else
{
pexprPred->AddRef();
}
GPOS_ASSERT(pcrsOuterChild->ContainsAll(pcrsPredOuter) &&
pcrsInnerChild->ContainsAll(pcrsPredInner) &&
"merge join keys are not aligned with children");
dxlnode_merge_conds->AddChild(PdxlnScalar(pexprPred));
pexprPred->Release();
}
pdrgpexprPredicates->Release();
// construct a join node
CDXLPhysicalMergeJoin *pdxlopMJ = GPOS_NEW(m_mp)
CDXLPhysicalMergeJoin(m_mp, join_type, false /* is_unique_outer */);
// construct projection list
// compute required columns
GPOS_ASSERT(nullptr != pexprMJ->Prpp());
CColRefSet *pcrsOutput = pexprMJ->Prpp()->PcrsRequired();
CDXLNode *proj_list_dxlnode = PdxlnProjList(pcrsOutput, colref_array);
CDXLNode *pdxlnMJ = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopMJ);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprMJ);
pdxlnMJ->SetProperties(dxl_properties);
// construct an empty plan filter and join filter
CDXLNode *filter_dxlnode = PdxlnFilter(nullptr);
CDXLNode *dxlnode_join_filter = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarJoinFilter(m_mp));
// add children
pdxlnMJ->AddChild(proj_list_dxlnode);
pdxlnMJ->AddChild(filter_dxlnode);
pdxlnMJ->AddChild(dxlnode_join_filter);
pdxlnMJ->AddChild(dxlnode_merge_conds);
pdxlnMJ->AddChild(pdxlnOuterChild);
pdxlnMJ->AddChild(pdxlnInnerChild);
#ifdef GPOS_DEBUG
pdxlnMJ->AssertValid(false /* validate_children */);
#endif
return pdxlnMJ;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::EdxljtHashJoin
//
// @doc:
// Return hash join type
//---------------------------------------------------------------------------
EdxlJoinType
CTranslatorExprToDXL::EdxljtHashJoin(CPhysicalHashJoin *popHJ)
{
GPOS_ASSERT(CUtils::FHashJoin(popHJ));
switch (popHJ->Eopid())
{
case COperator::EopPhysicalInnerHashJoin:
return EdxljtInner;
case COperator::EopPhysicalLeftOuterHashJoin:
return EdxljtLeft;
case COperator::EopPhysicalRightOuterHashJoin:
return EdxljtRight;
case COperator::EopPhysicalLeftSemiHashJoin:
return EdxljtIn;
case COperator::EopPhysicalLeftAntiSemiHashJoin:
return EdxljtLeftAntiSemijoin;
case COperator::EopPhysicalLeftAntiSemiHashJoinNotIn:
return EdxljtLeftAntiSemijoinNotIn;
default:
GPOS_ASSERT(!"Invalid join type");
return EdxljtSentinel;
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnHashJoin
//
// @doc:
// Create a DXL hash join node from an optimizer hash join expression.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnHashJoin(CExpression *pexprHJ,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprHJ);
GPOS_ASSERT(3 == pexprHJ->Arity());
// extract components
CPhysicalHashJoin *popHJ = CPhysicalHashJoin::PopConvert(pexprHJ->Pop());
CExpression *pexprOuterChild = (*pexprHJ)[0];
CExpression *pexprInnerChild = (*pexprHJ)[1];
CExpression *pexprScalar = (*pexprHJ)[2];
EdxlJoinType join_type = EdxljtHashJoin(popHJ);
GPOS_ASSERT(popHJ->PdrgpexprOuterKeys()->Size() ==
popHJ->PdrgpexprInnerKeys()->Size());
// translate relational child expression
CDXLNode *pdxlnOuterChild = CreateDXLNode(
pexprOuterChild, nullptr /*colref_array*/, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
CDXLNode *pdxlnInnerChild = CreateDXLNode(
pexprInnerChild, nullptr /*colref_array*/, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
// construct hash condition
CDXLNode *pdxlnHashCondList = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarHashCondList(m_mp));
#ifdef GPOS_DEBUG
ULONG ulHashJoinPreds = 0;
#endif
CExpressionArray *pdrgpexprPredicates =
CPredicateUtils::PdrgpexprConjuncts(m_mp, pexprScalar);
CExpressionArray *pdrgpexprRemainingPredicates =
GPOS_NEW(m_mp) CExpressionArray(m_mp);
const ULONG size = pdrgpexprPredicates->Size();
for (ULONG ul = 0; ul < size; ul++)
{
CExpression *pexprPred = (*pdrgpexprPredicates)[ul];
if (CPhysicalJoin::FHashJoinCompatible(pexprPred, pexprOuterChild,
pexprInnerChild))
{
CExpression *pexprPredOuter;
CExpression *pexprPredInner;
IMDId *mdid_scop;
CPhysicalJoin::AlignJoinKeyOuterInner(
pexprPred, pexprOuterChild, pexprInnerChild, &pexprPredOuter,
&pexprPredInner, &mdid_scop);
pexprPredOuter->AddRef();
pexprPredInner->AddRef();
// create hash join predicate based on conjunct type
if (CPredicateUtils::IsEqualityOp(pexprPred))
{
pexprPred = CUtils::PexprScalarCmp(m_mp, pexprPredOuter,
pexprPredInner, mdid_scop);
}
else
{
GPOS_ASSERT(CPredicateUtils::FINDF(pexprPred));
pexprPred = CUtils::PexprINDF(m_mp, pexprPredOuter,
pexprPredInner, mdid_scop);
}
CDXLNode *pdxlnPred = PdxlnScalar(pexprPred);
pdxlnHashCondList->AddChild(pdxlnPred);
pexprPred->Release();
#ifdef GPOS_DEBUG
ulHashJoinPreds++;
#endif // GPOS_DEBUG
}
else
{
pexprPred->AddRef();
pdrgpexprRemainingPredicates->Append(pexprPred);
}
}
GPOS_ASSERT(popHJ->PdrgpexprOuterKeys()->Size() == ulHashJoinPreds);
CDXLNode *dxlnode_join_filter = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarJoinFilter(m_mp));
if (0 < pdrgpexprRemainingPredicates->Size())
{
CExpression *pexprJoinCond = CPredicateUtils::PexprConjunction(
m_mp, pdrgpexprRemainingPredicates);
CDXLNode *pdxlnJoinCond = PdxlnScalar(pexprJoinCond);
dxlnode_join_filter->AddChild(pdxlnJoinCond);
pexprJoinCond->Release();
}
else
{
pdrgpexprRemainingPredicates->Release();
}
// construct a hash join node
CDXLPhysicalHashJoin *pdxlopHJ =
GPOS_NEW(m_mp) CDXLPhysicalHashJoin(m_mp, join_type);
// construct projection list from required columns
GPOS_ASSERT(nullptr != pexprHJ->Prpp());
CColRefSet *pcrsOutput = pexprHJ->Prpp()->PcrsRequired();
CDXLNode *proj_list_dxlnode = PdxlnProjList(pcrsOutput, colref_array);
CDXLNode *pdxlnHJ = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopHJ);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprHJ);
pdxlnHJ->SetProperties(dxl_properties);
// construct an empty plan filter
CDXLNode *filter_dxlnode = PdxlnFilter(nullptr);
// add children
pdxlnHJ->AddChild(proj_list_dxlnode);
pdxlnHJ->AddChild(filter_dxlnode);
pdxlnHJ->AddChild(dxlnode_join_filter);
pdxlnHJ->AddChild(pdxlnHashCondList);
pdxlnHJ->AddChild(pdxlnOuterChild);
pdxlnHJ->AddChild(pdxlnInnerChild);
// cleanup
pdrgpexprPredicates->Release();
#ifdef GPOS_DEBUG
pdxlopHJ->AssertValid(pdxlnHJ, false /* validate_children */);
#endif
return pdxlnHJ;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnMotion
//
// @doc:
// Create a DXL motion node from an optimizer motion expression
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnMotion(CExpression *pexprMotion,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprMotion);
GPOS_ASSERT(1 == pexprMotion->Arity());
// extract components
CExpression *pexprChild = (*pexprMotion)[0];
// translate relational child expression
CDXLNode *child_dxlnode = CreateDXLNode(
pexprChild, colref_array, pdrgpdsBaseTables, pulNonGatherMotions, pfDML,
true /*fRemap*/, false /*fRoot*/);
// construct a motion node
CDXLPhysicalMotion *motion = nullptr;
BOOL fDuplicateHazardMotion = CUtils::FDuplicateHazardMotion(pexprMotion);
switch (pexprMotion->Pop()->Eopid())
{
case COperator::EopPhysicalMotionGather:
motion = GPOS_NEW(m_mp) CDXLPhysicalGatherMotion(m_mp);
break;
case COperator::EopPhysicalMotionBroadcast:
motion = GPOS_NEW(m_mp) CDXLPhysicalBroadcastMotion(m_mp);
break;
case COperator::EopPhysicalMotionHashDistribute:
// If child is tainted-replicated, then we cannot use a result hash
// filter node because the values on each segment are not guaranteed
// to be identical.
//
// Example of tainted-replication: a scan of a replicated table that
// contains the values (10), (20) along with a project of nextval()
// can produce the following tuples:
//
// rep-val nextval
// Seg1: 10 1
// 20 2
//
// Seg2: 10 3
// 20 4
//
// Seg3: 10 5
// 20 6
//
// If nextval is used in a hash filter we could get missing or
// duplicate results because we're not guaranteed that 1, 3, and 5
// (coresponding to value 10) will produce same hashed segment
// value. Same for 2, 4, and 6 (corresponding to value 20).
//
// CDXLPhysicalRedistributeMotion::is_duplicate_sensitive is set to
// decide whether the motion should be translated into result hash
// filter node or redistribute motion.
motion = GPOS_NEW(m_mp)
CDXLPhysicalRedistributeMotion(m_mp, fDuplicateHazardMotion);
break;
case COperator::EopPhysicalMotionRandom:
motion = GPOS_NEW(m_mp)
CDXLPhysicalRandomMotion(m_mp, fDuplicateHazardMotion);
break;
case COperator::EopPhysicalMotionRoutedDistribute:
{
CPhysicalMotionRoutedDistribute *popMotion =
CPhysicalMotionRoutedDistribute::PopConvert(pexprMotion->Pop());
CColRef *pcrSegmentId =
dynamic_cast<const CDistributionSpecRouted *>(popMotion->Pds())
->Pcr();
motion = GPOS_NEW(m_mp)
CDXLPhysicalRoutedDistributeMotion(m_mp, pcrSegmentId->Id());
break;
}
default:
GPOS_ASSERT(!"Unrecognized motion type");
}
if (COperator::EopPhysicalMotionGather != pexprMotion->Pop()->Eopid())
{
(*pulNonGatherMotions)++;
}
GPOS_ASSERT(nullptr != motion);
// construct project list from child project list
GPOS_ASSERT(nullptr != child_dxlnode && 1 <= child_dxlnode->Arity());
CDXLNode *pdxlnProjListChild = (*child_dxlnode)[0];
CDXLNode *proj_list_dxlnode =
CTranslatorExprToDXLUtils::PdxlnProjListFromChildProjList(
m_mp, m_pcf, m_phmcrdxln, pdxlnProjListChild);
// set input and output segment information
motion->SetSegmentInfo(GetInputSegIdsArray(pexprMotion),
GetOutputSegIdsArray(pexprMotion));
CDXLNode *pdxlnMotion = GPOS_NEW(m_mp) CDXLNode(m_mp, motion);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprMotion);
pdxlnMotion->SetProperties(dxl_properties);
// construct an empty filter node
CDXLNode *filter_dxlnode = PdxlnFilter(nullptr /*pdxlnCond*/);
// construct sort column list
CDXLNode *sort_col_list_dxlnode = GetSortColListDXL(pexprMotion);
// add children
pdxlnMotion->AddChild(proj_list_dxlnode);
pdxlnMotion->AddChild(filter_dxlnode);
pdxlnMotion->AddChild(sort_col_list_dxlnode);
if (COperator::EopPhysicalMotionHashDistribute ==
pexprMotion->Pop()->Eopid())
{
// construct a hash expr list node
CPhysicalMotionHashDistribute *popHashDistribute =
CPhysicalMotionHashDistribute::PopConvert(pexprMotion->Pop());
CDistributionSpecHashed *pdsHashed =
CDistributionSpecHashed::PdsConvert(popHashDistribute->Pds());
CDXLNode *hash_expr_list =
PdxlnHashExprList(pdsHashed->Pdrgpexpr(), pdsHashed->Opfamilies());
pdxlnMotion->AddChild(hash_expr_list);
}
pdxlnMotion->AddChild(child_dxlnode);
#ifdef GPOS_DEBUG
motion->AssertValid(pdxlnMotion, false /* validate_children */);
#endif
return pdxlnMotion;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnMaterialize
//
// @doc:
// Create a DXL materialize node from an optimizer spool expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnMaterialize(
CExpression *pexprSpool, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables, ULONG *pulNonGatherMotions,
BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprSpool);
GPOS_ASSERT(1 == pexprSpool->Arity());
// extract components
CExpression *pexprChild = (*pexprSpool)[0];
// translate relational child expression
CDXLNode *child_dxlnode = CreateDXLNode(
pexprChild, colref_array, pdrgpdsBaseTables, pulNonGatherMotions, pfDML,
false /*fRemap*/, false /*fRoot*/);
CPhysicalSpool *spool = CPhysicalSpool::PopConvert(pexprSpool->Pop());
// construct a materialize node
CDXLPhysicalMaterialize *pdxlopMat =
GPOS_NEW(m_mp) CDXLPhysicalMaterialize(m_mp, spool->FEager());
// construct project list from child project list
GPOS_ASSERT(nullptr != child_dxlnode && 1 <= child_dxlnode->Arity());
CDXLNode *pdxlnProjListChild = (*child_dxlnode)[0];
CDXLNode *proj_list_dxlnode =
CTranslatorExprToDXLUtils::PdxlnProjListFromChildProjList(
m_mp, m_pcf, m_phmcrdxln, pdxlnProjListChild);
CDXLNode *pdxlnMaterialize = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopMat);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprSpool);
pdxlnMaterialize->SetProperties(dxl_properties);
// construct an empty filter node
CDXLNode *filter_dxlnode = PdxlnFilter(nullptr /* pdxlnCond */);
// add children
pdxlnMaterialize->AddChild(proj_list_dxlnode);
pdxlnMaterialize->AddChild(filter_dxlnode);
pdxlnMaterialize->AddChild(child_dxlnode);
#ifdef GPOS_DEBUG
pdxlopMat->AssertValid(pdxlnMaterialize, false /* validate_children */);
#endif
return pdxlnMaterialize;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnSequence
//
// @doc:
// Create a DXL sequence node from an optimizer sequence expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnSequence(CExpression *pexprSequence,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprSequence);
const ULONG arity = pexprSequence->Arity();
GPOS_ASSERT(0 < arity);
// construct sequence node
CDXLPhysicalSequence *pdxlopSequence =
GPOS_NEW(m_mp) CDXLPhysicalSequence(m_mp);
CDXLNode *pdxlnSequence = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopSequence);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprSequence);
pdxlnSequence->SetProperties(dxl_properties);
// translate children
CDXLNodeArray *pdrgpdxlnChildren = GPOS_NEW(m_mp) CDXLNodeArray(m_mp);
for (ULONG ul = 0; ul < arity; ul++)
{
CExpression *pexprChild = (*pexprSequence)[ul];
CColRefArray *pdrgpcrChildOutput = nullptr;
if (ul == arity - 1)
{
// impose output columns on last child
pdrgpcrChildOutput = colref_array;
}
CDXLNode *child_dxlnode = CreateDXLNode(
pexprChild, pdrgpcrChildOutput, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
pdrgpdxlnChildren->Append(child_dxlnode);
}
// construct project list from the project list of the last child
CDXLNode *pdxlnLastChild = (*pdrgpdxlnChildren)[arity - 1];
CDXLNode *pdxlnProjListChild = (*pdxlnLastChild)[0];
CDXLNode *proj_list_dxlnode =
CTranslatorExprToDXLUtils::PdxlnProjListFromChildProjList(
m_mp, m_pcf, m_phmcrdxln, pdxlnProjListChild);
pdxlnSequence->AddChild(proj_list_dxlnode);
// add children
for (ULONG ul = 0; ul < arity; ul++)
{
CDXLNode *pdxlnChid = (*pdrgpdxlnChildren)[ul];
pdxlnChid->AddRef();
pdxlnSequence->AddChild(pdxlnChid);
}
pdrgpdxlnChildren->Release();
#ifdef GPOS_DEBUG
pdxlopSequence->AssertValid(pdxlnSequence, false /* validate_children */);
#endif
return pdxlnSequence;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnPartitionSelector
//
// @doc:
// Translate a partition selector into DXL
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnPartitionSelector(
CExpression *pexpr, CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables, ULONG *pulNonGatherMotions,
BOOL *pfDML)
{
CPhysicalPartitionSelector *popSelector =
CPhysicalPartitionSelector::PopConvert(pexpr->Pop());
CExpression *pexprChild = (*pexpr)[0];
// translate child
CDXLNode *child_dxlnode = CreateDXLNode(
pexprChild, colref_array, pdrgpdsBaseTables, pulNonGatherMotions, pfDML,
false /*fRemap*/, false /*fRoot*/);
CDXLNode *pdxlnPrLChild = (*child_dxlnode)[0];
CDXLNode *pdxlnPrL =
CTranslatorExprToDXLUtils::PdxlnProjListFromChildProjList(
m_mp, m_pcf, m_phmcrdxln, pdxlnPrLChild);
const ULONG scanid = popSelector->ScanId();
CBitSet *bs = COptCtxt::PoctxtFromTLS()->GetPartitionsForScanId(scanid);
GPOS_ASSERT(nullptr != bs);
ULongPtrArray *parts = GPOS_NEW(m_mp) ULongPtrArray(m_mp);
CBitSetIter bsi(*bs);
for (ULONG ul = 0; bsi.Advance(); ul++)
{
parts->Append(GPOS_NEW(m_mp) ULONG(bsi.Bit()));
}
popSelector->MDId()->AddRef();
CDXLNode *pdxlnSelector = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLPhysicalPartitionSelector(
m_mp, popSelector->MDId(), popSelector->SelectorId(),
popSelector->ScanId(), parts));
CDXLNode *pdxlnFilter = PdxlnScalar(popSelector->FilterExpr());
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprChild);
pdxlnSelector->SetProperties(dxl_properties);
pdxlnSelector->AddChild(pdxlnPrL);
pdxlnSelector->AddChild(pdxlnFilter);
pdxlnSelector->AddChild(child_dxlnode);
return pdxlnSelector;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnDML
//
// @doc:
// Translate a DML operator
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnDML(CExpression *pexpr,
CColRefArray *, // colref_array
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexpr);
GPOS_ASSERT(1 == pexpr->Arity());
ULONG action_colid = 0;
ULONG oid_colid = 0;
ULONG ctid_colid = 0;
ULONG segid_colid = 0;
// extract components
CPhysicalDML *popDML = CPhysicalDML::PopConvert(pexpr->Pop());
*pfDML = false;
if (IMDId::EmdidGPDBCtas == popDML->Ptabdesc()->MDId()->MdidType())
{
return PdxlnCTAS(pexpr, pdrgpdsBaseTables, pulNonGatherMotions, pfDML);
}
EdxlDmlType dxl_dml_type = Edxldmloptype(popDML->Edmlop());
CExpression *pexprChild = (*pexpr)[0];
CTableDescriptor *ptabdesc = popDML->Ptabdesc();
CColRefArray *pdrgpcrSource = popDML->PdrgpcrSource();
CColRef *pcrAction = popDML->PcrAction();
GPOS_ASSERT(nullptr != pcrAction);
action_colid = pcrAction->Id();
CColRef *pcrOid = popDML->PcrTableOid();
if (pcrOid != nullptr)
{
oid_colid = pcrOid->Id();
}
CColRef *pcrCtid = popDML->PcrCtid();
CColRef *pcrSegmentId = popDML->PcrSegmentId();
if (nullptr != pcrCtid)
{
GPOS_ASSERT(nullptr != pcrSegmentId);
ctid_colid = pcrCtid->Id();
segid_colid = pcrSegmentId->Id();
}
CDXLNode *child_dxlnode = CreateDXLNode(
pexprChild, pdrgpcrSource, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML, false /*fRemap*/, false /*fRoot*/);
CDXLTableDescr *table_descr = MakeDXLTableDescr(
ptabdesc, nullptr /*pdrgpcrOutput*/, nullptr /*requiredProperties*/);
ULongPtrArray *pdrgpul = CUtils::Pdrgpul(m_mp, pdrgpcrSource);
CDXLDirectDispatchInfo *dxl_direct_dispatch_info =
GetDXLDirectDispatchInfo(pexpr);
CDXLPhysicalDML *pdxlopDML = GPOS_NEW(m_mp) CDXLPhysicalDML(
m_mp, dxl_dml_type, table_descr, pdrgpul, action_colid, oid_colid,
ctid_colid, segid_colid, dxl_direct_dispatch_info,
popDML->IsInputSortReq(), popDML->FSplit());
// project list
CColRefSet *pcrsOutput = pexpr->Prpp()->PcrsRequired();
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, pdrgpcrSource);
CDXLNode *pdxlnDML = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopDML);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexpr);
pdxlnDML->SetProperties(dxl_properties);
pdxlnDML->AddChild(pdxlnPrL);
pdxlnDML->AddChild(child_dxlnode);
#ifdef GPOS_DEBUG
pdxlnDML->GetOperator()->AssertValid(pdxlnDML,
false /* validate_children */);
#endif
*pfDML = true;
return pdxlnDML;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnCTAS
//
// @doc:
// Translate a CTAS expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnCTAS(CExpression *pexpr,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexpr);
GPOS_ASSERT(1 == pexpr->Arity());
CPhysicalDML *popDML = CPhysicalDML::PopConvert(pexpr->Pop());
GPOS_ASSERT(CLogicalDML::EdmlInsert == popDML->Edmlop());
CExpression *pexprChild = (*pexpr)[0];
CTableDescriptor *ptabdesc = popDML->Ptabdesc();
CColRefArray *pdrgpcrSource = popDML->PdrgpcrSource();
CMDRelationCtasGPDB *pmdrel =
(CMDRelationCtasGPDB *) m_pmda->RetrieveRel(ptabdesc->MDId());
CDXLNode *child_dxlnode = CreateDXLNode(
pexprChild, pdrgpcrSource, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML, true /*fRemap*/, true /*fRoot*/);
ULongPtrArray *pdrgpul = CUtils::Pdrgpul(m_mp, pdrgpcrSource);
pmdrel->GetDxlCtasStorageOption()->AddRef();
const ULONG ulColumns = ptabdesc->ColumnCount();
IntPtrArray *vartypemod_array = pmdrel->GetVarTypeModArray();
GPOS_ASSERT(ulColumns == vartypemod_array->Size());
// translate col descriptors
CDXLColDescrArray *dxl_col_descr_array =
GPOS_NEW(m_mp) CDXLColDescrArray(m_mp);
for (ULONG ul = 0; ul < ulColumns; ul++)
{
const CColumnDescriptor *pcd = ptabdesc->Pcoldesc(ul);
CMDName *pmdnameCol = GPOS_NEW(m_mp) CMDName(m_mp, pcd->Name().Pstr());
CColRef *colref = m_pcf->PcrCreate(pcd->RetrieveType(),
pcd->TypeModifier(), pcd->Name());
// use the col ref id for the corresponding output output column as
// colid for the dxl column
CMDIdGPDB *pmdidColType =
CMDIdGPDB::CastMdid(colref->RetrieveType()->MDId());
pmdidColType->AddRef();
CDXLColDescr *pdxlcd = GPOS_NEW(m_mp) CDXLColDescr(
pmdnameCol, colref->Id(), pcd->AttrNum(), pmdidColType,
colref->TypeModifier(), false /* fdropped */, pcd->Width());
dxl_col_descr_array->Append(pdxlcd);
}
ULongPtrArray *pdrgpulDistr = nullptr;
if (IMDRelation::EreldistrHash == pmdrel->GetRelDistribution())
{
pdrgpulDistr = GPOS_NEW(m_mp) ULongPtrArray(m_mp);
const ULONG ulDistrCols = pmdrel->DistrColumnCount();
for (ULONG ul = 0; ul < ulDistrCols; ul++)
{
const IMDColumn *pmdcol = pmdrel->GetDistrColAt(ul);
INT attno = pmdcol->AttrNum();
GPOS_ASSERT(0 < attno);
pdrgpulDistr->Append(GPOS_NEW(m_mp) ULONG(attno - 1));
}
}
CMDName *mdname_schema = nullptr;
if (nullptr != pmdrel->GetMdNameSchema())
{
mdname_schema = GPOS_NEW(m_mp)
CMDName(m_mp, pmdrel->GetMdNameSchema()->GetMDName());
}
IMdIdArray *distr_opclasses = pmdrel->GetDistrOpClasses();
distr_opclasses->AddRef();
vartypemod_array->AddRef();
CDXLPhysicalCTAS *pdxlopCTAS = GPOS_NEW(m_mp) CDXLPhysicalCTAS(
m_mp, mdname_schema,
GPOS_NEW(m_mp) CMDName(m_mp, pmdrel->Mdname().GetMDName()),
dxl_col_descr_array, pmdrel->GetDxlCtasStorageOption(),
pmdrel->GetRelDistribution(), pdrgpulDistr, pmdrel->GetDistrOpClasses(),
pmdrel->IsTemporary(), pmdrel->RetrieveRelStorageType(), pdrgpul,
vartypemod_array);
CDXLNode *pdxlnCTAS = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopCTAS);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexpr);
pdxlnCTAS->SetProperties(dxl_properties);
CColRefSet *pcrsOutput = pexpr->Prpp()->PcrsRequired();
CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, pdrgpcrSource);
pdxlnCTAS->AddChild(pdxlnPrL);
pdxlnCTAS->AddChild(child_dxlnode);
#ifdef GPOS_DEBUG
pdxlnCTAS->GetOperator()->AssertValid(pdxlnCTAS,
false /* validate_children */);
#endif
return pdxlnCTAS;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::GetDXLDirectDispatchInfo
//
// @doc:
// Return the direct dispatch info spec for the possible values of the distribution
// key in a DML insert statement. Returns NULL if values are not constant.
//
//---------------------------------------------------------------------------
CDXLDirectDispatchInfo *
CTranslatorExprToDXL::GetDXLDirectDispatchInfo(CExpression *pexprDML)
{
GPOS_ASSERT(nullptr != pexprDML);
CPhysicalDML *popDML = CPhysicalDML::PopConvert(pexprDML->Pop());
CTableDescriptor *ptabdesc = popDML->Ptabdesc();
const CColumnDescriptorArray *pdrgpcoldescDist =
ptabdesc->PdrgpcoldescDist();
if (CLogicalDML::EdmlInsert != popDML->Edmlop() ||
IMDRelation::EreldistrHash != ptabdesc->GetRelDistribution() ||
1 < pdrgpcoldescDist->Size())
{
// directed dispatch only supported for insert statements on hash-distributed tables
// with a single distribution column
return nullptr;
}
GPOS_ASSERT(1 == pdrgpcoldescDist->Size());
CColumnDescriptor *pcoldesc = (*pdrgpcoldescDist)[0];
ULONG ulPos =
gpopt::CTableDescriptor::UlPos(pcoldesc, ptabdesc->Pdrgpcoldesc());
GPOS_ASSERT(ulPos < ptabdesc->Pdrgpcoldesc()->Size() && "Column not found");
CColRef *pcrDistrCol = (*popDML->PdrgpcrSource())[ulPos];
CPropConstraint *ppc = (*pexprDML)[0]->DerivePropertyConstraint();
if (nullptr == ppc->Pcnstr())
{
return nullptr;
}
CConstraint *pcnstrDistrCol = ppc->Pcnstr()->Pcnstr(m_mp, pcrDistrCol);
if (!CPredicateUtils::FConstColumn(pcnstrDistrCol, pcrDistrCol))
{
CRefCount::SafeRelease(pcnstrDistrCol);
return nullptr;
}
GPOS_ASSERT(CConstraint::EctInterval == pcnstrDistrCol->Ect());
CConstraintInterval *pci =
dynamic_cast<CConstraintInterval *>(pcnstrDistrCol);
GPOS_ASSERT(1 >= pci->Pdrgprng()->Size());
CDXLDatumArray *pdrgpdxldatum = GPOS_NEW(m_mp) CDXLDatumArray(m_mp);
CDXLDatum *dxl_datum = nullptr;
if (1 == pci->Pdrgprng()->Size())
{
const CRange *prng = (*pci->Pdrgprng())[0];
dxl_datum = CTranslatorExprToDXLUtils::GetDatumVal(m_mp, m_pmda,
prng->PdatumLeft());
}
else
{
GPOS_ASSERT(pci->FIncludesNull());
dxl_datum = pcrDistrCol->RetrieveType()->GetDXLDatumNull(m_mp);
}
pdrgpdxldatum->Append(dxl_datum);
pcnstrDistrCol->Release();
CDXLDatum2dArray *pdrgpdrgpdxldatum = GPOS_NEW(m_mp) CDXLDatum2dArray(m_mp);
pdrgpdrgpdxldatum->Append(pdrgpdxldatum);
return GPOS_NEW(m_mp) CDXLDirectDispatchInfo(pdrgpdrgpdxldatum, false);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnSplit
//
// @doc:
// Translate a split operator
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnSplit(CExpression *pexpr,
CColRefArray *, // colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexpr);
GPOS_ASSERT(2 == pexpr->Arity());
ULONG action_colid = 0;
ULONG ctid_colid = 0;
ULONG segid_colid = 0;
// extract components
CPhysicalSplit *popSplit = CPhysicalSplit::PopConvert(pexpr->Pop());
CExpression *pexprChild = (*pexpr)[0];
CExpression *pexprProjList = (*pexpr)[1];
CColRef *pcrAction = popSplit->PcrAction();
GPOS_ASSERT(nullptr != pcrAction);
action_colid = pcrAction->Id();
CColRef *pcrCtid = popSplit->PcrCtid();
GPOS_ASSERT(nullptr != pcrCtid);
ctid_colid = pcrCtid->Id();
CColRef *pcrSegmentId = popSplit->PcrSegmentId();
GPOS_ASSERT(nullptr != pcrSegmentId);
segid_colid = pcrSegmentId->Id();
CColRefArray *pdrgpcrDelete = popSplit->PdrgpcrDelete();
ULongPtrArray *delete_colid_array = CUtils::Pdrgpul(m_mp, pdrgpcrDelete);
CColRefArray *pdrgpcrInsert = popSplit->PdrgpcrInsert();
ULongPtrArray *insert_colid_array = CUtils::Pdrgpul(m_mp, pdrgpcrInsert);
CColRefSet *pcrsRequired = GPOS_NEW(m_mp) CColRefSet(m_mp);
pcrsRequired->Include(pdrgpcrInsert);
pcrsRequired->Include(pdrgpcrDelete);
CColRefArray *pdrgpcrRequired = pcrsRequired->Pdrgpcr(m_mp);
CDXLNode *child_dxlnode = CreateDXLNode(
pexprChild, pdrgpcrRequired, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML, true /*fRemap*/, false /*fRoot*/);
pdrgpcrRequired->Release();
pcrsRequired->Release();
CDXLPhysicalSplit *pdxlopSplit = GPOS_NEW(m_mp)
CDXLPhysicalSplit(m_mp, delete_colid_array, insert_colid_array,
action_colid, ctid_colid, segid_colid);
// project list
CColRefSet *pcrsOutput = pexpr->Prpp()->PcrsRequired();
CDXLNode *pdxlnPrL =
PdxlnProjList(pexprProjList, pcrsOutput, pdrgpcrDelete);
CDXLNode *pdxlnSplit = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopSplit);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexpr);
pdxlnSplit->SetProperties(dxl_properties);
pdxlnSplit->AddChild(pdxlnPrL);
pdxlnSplit->AddChild(child_dxlnode);
#ifdef GPOS_DEBUG
pdxlnSplit->GetOperator()->AssertValid(pdxlnSplit,
false /* validate_children */);
#endif
return pdxlnSplit;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnRowTrigger
//
// @doc:
// Translate a row trigger operator
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnRowTrigger(CExpression *pexpr,
CColRefArray *, // colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexpr);
GPOS_ASSERT(1 == pexpr->Arity());
// extract components
CPhysicalRowTrigger *popRowTrigger =
CPhysicalRowTrigger::PopConvert(pexpr->Pop());
CExpression *pexprChild = (*pexpr)[0];
IMDId *rel_mdid = popRowTrigger->GetRelMdId();
rel_mdid->AddRef();
INT type = popRowTrigger->GetType();
CColRefSet *pcrsRequired = GPOS_NEW(m_mp) CColRefSet(m_mp);
ULongPtrArray *colids_old = nullptr;
ULongPtrArray *colids_new = nullptr;
CColRefArray *pdrgpcrOld = popRowTrigger->PdrgpcrOld();
if (nullptr != pdrgpcrOld)
{
colids_old = CUtils::Pdrgpul(m_mp, pdrgpcrOld);
pcrsRequired->Include(pdrgpcrOld);
}
CColRefArray *pdrgpcrNew = popRowTrigger->PdrgpcrNew();
if (nullptr != pdrgpcrNew)
{
colids_new = CUtils::Pdrgpul(m_mp, pdrgpcrNew);
pcrsRequired->Include(pdrgpcrNew);
}
CColRefArray *pdrgpcrRequired = pcrsRequired->Pdrgpcr(m_mp);
CDXLNode *child_dxlnode = CreateDXLNode(
pexprChild, pdrgpcrRequired, pdrgpdsBaseTables, pulNonGatherMotions,
pfDML, false /*fRemap*/, false /*fRoot*/);
pdrgpcrRequired->Release();
pcrsRequired->Release();
CDXLPhysicalRowTrigger *pdxlopRowTrigger = GPOS_NEW(m_mp)
CDXLPhysicalRowTrigger(m_mp, rel_mdid, type, colids_old, colids_new);
// project list
CColRefSet *pcrsOutput = pexpr->Prpp()->PcrsRequired();
CDXLNode *pdxlnPrL = nullptr;
if (nullptr != pdrgpcrNew)
{
pdxlnPrL = PdxlnProjList(pcrsOutput, pdrgpcrNew);
}
else
{
pdxlnPrL = PdxlnProjList(pcrsOutput, pdrgpcrOld);
}
CDXLNode *pdxlnRowTrigger = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopRowTrigger);
CDXLPhysicalProperties *dxl_properties = GetProperties(pexpr);
pdxlnRowTrigger->SetProperties(dxl_properties);
pdxlnRowTrigger->AddChild(pdxlnPrL);
pdxlnRowTrigger->AddChild(child_dxlnode);
#ifdef GPOS_DEBUG
pdxlnRowTrigger->GetOperator()->AssertValid(pdxlnRowTrigger,
false /* validate_children */);
#endif
return pdxlnRowTrigger;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::Edxldmloptype
//
// @doc:
// Return the EdxlDmlType for a given DML op type
//
//---------------------------------------------------------------------------
EdxlDmlType
CTranslatorExprToDXL::Edxldmloptype(const CLogicalDML::EDMLOperator edmlop)
{
switch (edmlop)
{
case CLogicalDML::EdmlInsert:
return Edxldmlinsert;
case CLogicalDML::EdmlDelete:
return Edxldmldelete;
case CLogicalDML::EdmlUpdate:
return Edxldmlupdate;
default:
GPOS_ASSERT(!"Unrecognized DML operation");
return EdxldmlSentinel;
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScCmp
//
// @doc:
// Create a DXL scalar comparison node from an optimizer scalar comparison
// expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScCmp(CExpression *pexprScCmp)
{
GPOS_ASSERT(nullptr != pexprScCmp);
// extract components
CExpression *pexprLeft = (*pexprScCmp)[0];
CExpression *pexprRight = (*pexprScCmp)[1];
// translate children expression
CDXLNode *dxlnode_left = PdxlnScalar(pexprLeft);
CDXLNode *dxlnode_right = PdxlnScalar(pexprRight);
CScalarCmp *popScCmp = CScalarCmp::PopConvert(pexprScCmp->Pop());
GPOS_ASSERT(nullptr != popScCmp);
GPOS_ASSERT(nullptr != popScCmp->Pstr());
GPOS_ASSERT(nullptr != popScCmp->Pstr()->GetBuffer());
// construct a scalar comparison node
IMDId *mdid = popScCmp->MdIdOp();
mdid->AddRef();
CWStringConst *str_name =
GPOS_NEW(m_mp) CWStringConst(m_mp, popScCmp->Pstr()->GetBuffer());
CDXLNode *pdxlnCmp = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarComp(m_mp, mdid, str_name));
// add children
pdxlnCmp->AddChild(dxlnode_left);
pdxlnCmp->AddChild(dxlnode_right);
#ifdef GPOS_DEBUG
pdxlnCmp->GetOperator()->AssertValid(pdxlnCmp,
false /* validate_children */);
#endif
return pdxlnCmp;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScDistinctCmp
//
// @doc:
// Create a DXL scalar distinct comparison node from an optimizer scalar
// is distinct from expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScDistinctCmp(CExpression *pexprScDist)
{
GPOS_ASSERT(nullptr != pexprScDist);
// extract components
CExpression *pexprLeft = (*pexprScDist)[0];
CExpression *pexprRight = (*pexprScDist)[1];
// translate children expression
CDXLNode *dxlnode_left = PdxlnScalar(pexprLeft);
CDXLNode *dxlnode_right = PdxlnScalar(pexprRight);
CScalarIsDistinctFrom *popScIDF =
CScalarIsDistinctFrom::PopConvert(pexprScDist->Pop());
// construct a scalar distinct comparison node
IMDId *mdid = popScIDF->MdIdOp();
mdid->AddRef();
CDXLNode *pdxlnDistCmp = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarDistinctComp(m_mp, mdid));
// add children
pdxlnDistCmp->AddChild(dxlnode_left);
pdxlnDistCmp->AddChild(dxlnode_right);
#ifdef GPOS_DEBUG
pdxlnDistCmp->GetOperator()->AssertValid(pdxlnDistCmp,
false /* validate_children */);
#endif
return pdxlnDistCmp;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScOp
//
// @doc:
// Create a DXL scalar op expr node from an optimizer scalar op expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScOp(CExpression *pexprOp)
{
GPOS_ASSERT(nullptr != pexprOp &&
((1 == pexprOp->Arity()) || (2 == pexprOp->Arity())));
CScalarOp *pscop = CScalarOp::PopConvert(pexprOp->Pop());
// construct a scalar opexpr node
CWStringConst *str_name =
GPOS_NEW(m_mp) CWStringConst(m_mp, pscop->Pstr()->GetBuffer());
IMDId *mdid_op = pscop->MdIdOp();
mdid_op->AddRef();
IMDId *return_type_mdid = pscop->GetReturnTypeMdId();
if (nullptr != return_type_mdid)
{
return_type_mdid->AddRef();
}
CDXLNode *pdxlnOpExpr = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarOpExpr(
m_mp, mdid_op, return_type_mdid, str_name));
TranslateScalarChildren(pexprOp, pdxlnOpExpr);
#ifdef GPOS_DEBUG
pdxlnOpExpr->GetOperator()->AssertValid(pdxlnOpExpr,
false /* validate_children */);
#endif
return pdxlnOpExpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScBoolExpr
//
// @doc:
// Create a DXL scalar bool expression node from an optimizer scalar log op
// expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScBoolExpr(CExpression *pexprScBoolOp)
{
GPOS_ASSERT(nullptr != pexprScBoolOp);
CScalarBoolOp *popScBoolOp =
CScalarBoolOp::PopConvert(pexprScBoolOp->Pop());
EdxlBoolExprType edxlbooltype = Edxlbooltype(popScBoolOp->Eboolop());
#ifdef GPOS_DEBUG
if (CScalarBoolOp::EboolopNot == popScBoolOp->Eboolop())
{
GPOS_ASSERT(1 == pexprScBoolOp->Arity());
}
else
{
GPOS_ASSERT(2 <= pexprScBoolOp->Arity());
}
#endif // GPOS_DEBUG
CDXLNode *pdxlnBoolExpr = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarBoolExpr(m_mp, edxlbooltype));
TranslateScalarChildren(pexprScBoolOp, pdxlnBoolExpr);
#ifdef GPOS_DEBUG
pdxlnBoolExpr->GetOperator()->AssertValid(pdxlnBoolExpr,
false /* validate_children */);
#endif
return pdxlnBoolExpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::Edxlbooltype
//
// @doc:
// Return the EdxlBoolExprType for a given scalar logical op type
//
//---------------------------------------------------------------------------
EdxlBoolExprType
CTranslatorExprToDXL::Edxlbooltype(const CScalarBoolOp::EBoolOperator eboolop)
{
switch (eboolop)
{
case CScalarBoolOp::EboolopNot:
return Edxlnot;
case CScalarBoolOp::EboolopAnd:
return Edxland;
case CScalarBoolOp::EboolopOr:
return Edxlor;
default:
GPOS_ASSERT(!"Unrecognized boolean expression type");
return EdxlBoolExprTypeSentinel;
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScId
//
// @doc:
// Create a DXL scalar identifier node from an optimizer scalar id expr.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScId(CExpression *pexprIdent)
{
GPOS_ASSERT(nullptr != pexprIdent);
CScalarIdent *popScId = CScalarIdent::PopConvert(pexprIdent->Pop());
CColRef *colref = const_cast<CColRef *>(popScId->Pcr());
return CTranslatorExprToDXLUtils::PdxlnIdent(
m_mp, m_phmcrdxln, m_phmcrdxlnIndexLookup, m_phmcrulPartColId, colref);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScFuncExpr
//
// @doc:
// Create a DXL scalar func expr node from an optimizer scalar func expr.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScFuncExpr(CExpression *pexprFunc)
{
GPOS_ASSERT(nullptr != pexprFunc);
CScalarFunc *popScFunc = CScalarFunc::PopConvert(pexprFunc->Pop());
IMDId *mdid_func = popScFunc->FuncMdId();
mdid_func->AddRef();
IMDId *mdid_return_type = popScFunc->MdidType();
mdid_return_type->AddRef();
const IMDFunction *pmdfunc = m_pmda->RetrieveFunc(mdid_func);
CDXLNode *pdxlnFuncExpr = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarFuncExpr(
m_mp, mdid_func, mdid_return_type,
popScFunc->TypeModifier(), pmdfunc->ReturnsSet()));
// translate children
TranslateScalarChildren(pexprFunc, pdxlnFuncExpr);
return pdxlnFuncExpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScWindowFuncExpr
//
// @doc:
// Create a DXL scalar window ref node from an optimizer scalar window
// function expr
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScWindowFuncExpr(CExpression *pexprWindowFunc)
{
GPOS_ASSERT(nullptr != pexprWindowFunc);
CScalarWindowFunc *popScWindowFunc =
CScalarWindowFunc::PopConvert(pexprWindowFunc->Pop());
IMDId *mdid_func = popScWindowFunc->FuncMdId();
mdid_func->AddRef();
IMDId *mdid_return_type = popScWindowFunc->MdidType();
mdid_return_type->AddRef();
EdxlWinStage dxl_win_stage = Ews(popScWindowFunc->Ews());
CDXLScalarWindowRef *pdxlopWindowref = GPOS_NEW(m_mp) CDXLScalarWindowRef(
m_mp, mdid_func, mdid_return_type, popScWindowFunc->IsDistinct(),
popScWindowFunc->IsStarArg(), popScWindowFunc->IsSimpleAgg(),
dxl_win_stage, 0 /* ulWinspecPosition */
);
CDXLNode *pdxlnWindowRef = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopWindowref);
// translate children
TranslateScalarChildren(pexprWindowFunc, pdxlnWindowRef);
return pdxlnWindowRef;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::Ews
//
// @doc:
// Get the DXL representation of the window stage
//
//---------------------------------------------------------------------------
EdxlWinStage
CTranslatorExprToDXL::Ews(CScalarWindowFunc::EWinStage ews)
{
ULONG window_frame_boundary_to_frame_boundary_mapping[][2] = {
{EdxlwinstageImmediate, CScalarWindowFunc::EwsImmediate},
{EdxlwinstagePreliminary, CScalarWindowFunc::EwsPreliminary},
{EdxlwinstageRowKey, CScalarWindowFunc::EwsRowKey}};
#ifdef GPOS_DEBUG
const ULONG arity =
GPOS_ARRAY_SIZE(window_frame_boundary_to_frame_boundary_mapping);
GPOS_ASSERT(arity > (ULONG) ews);
#endif
ULONG *pulElem =
window_frame_boundary_to_frame_boundary_mapping[(ULONG) ews];
EdxlWinStage edxlws = (EdxlWinStage) pulElem[0];
return edxlws;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScAggref
//
// @doc:
// Create a DXL scalar aggref node from an optimizer scalar agg func expr.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScAggref(CExpression *pexprAggFunc)
{
GPOS_ASSERT(nullptr != pexprAggFunc);
CScalarAggFunc *popScAggFunc =
CScalarAggFunc::PopConvert(pexprAggFunc->Pop());
IMDId *pmdidAggFunc = popScAggFunc->MDId();
pmdidAggFunc->AddRef();
IMDId *resolved_rettype = nullptr;
if (popScAggFunc->FHasAmbiguousReturnType())
{
// Agg has an ambiguous return type, use the resolved type instead
resolved_rettype = popScAggFunc->MdidType();
resolved_rettype->AddRef();
}
EdxlAggrefStage edxlaggrefstage = EdxlaggstageNormal;
if (popScAggFunc->FGlobal() && popScAggFunc->FSplit())
{
edxlaggrefstage = EdxlaggstageFinal;
}
else if (EaggfuncstageIntermediate == popScAggFunc->Eaggfuncstage())
{
edxlaggrefstage = EdxlaggstageIntermediate;
}
else if (!popScAggFunc->FGlobal())
{
edxlaggrefstage = EdxlaggstagePartial;
}
EdxlAggrefKind edxlaggrefkind = EdxlaggkindNormal;
switch (popScAggFunc->AggKind())
{
case EaggfunckindNormal:
{
edxlaggrefkind = EdxlaggkindNormal;
break;
}
case EaggfunckindOrderedSet:
{
edxlaggrefkind = EdxlaggkindOrderedSet;
break;
}
case EaggfunckindHypothetical:
{
edxlaggrefkind = EdxlaggkindHypothetical;
break;
}
}
ULongPtrArray *argtypes = popScAggFunc->GetArgTypes();
argtypes->AddRef();
CDXLScalarAggref *pdxlopAggRef = GPOS_NEW(m_mp) CDXLScalarAggref(
m_mp, pmdidAggFunc, resolved_rettype, popScAggFunc->IsDistinct(),
edxlaggrefstage, edxlaggrefkind, argtypes);
CDXLNode *pdxlnAggref = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopAggRef);
pdxlnAggref->AddChild(
PdxlnValuesList((*pexprAggFunc)[EdxlscalaraggrefIndexArgs]));
pdxlnAggref->AddChild(
PdxlnValuesList((*pexprAggFunc)[EdxlscalaraggrefIndexDirectArgs]));
pdxlnAggref->AddChild(
PdxlnValuesList((*pexprAggFunc)[EdxlscalaraggrefIndexAggOrder]));
pdxlnAggref->AddChild(
PdxlnValuesList((*pexprAggFunc)[EdxlscalaraggrefIndexAggDistinct]));
return pdxlnAggref;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScIfStmt
//
// @doc:
// Create a DXL scalar if node from an optimizer scalar if expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScIfStmt(CExpression *pexprIfStmt)
{
GPOS_ASSERT(nullptr != pexprIfStmt);
GPOS_ASSERT(3 == pexprIfStmt->Arity());
CScalarIf *popScIf = CScalarIf::PopConvert(pexprIfStmt->Pop());
IMDId *mdid_type = popScIf->MdidType();
mdid_type->AddRef();
CDXLNode *pdxlnIfStmt = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarIfStmt(m_mp, mdid_type));
TranslateScalarChildren(pexprIfStmt, pdxlnIfStmt);
return pdxlnIfStmt;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScSwitch
//
// @doc:
// Create a DXL scalar switch node from an optimizer scalar switch expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScSwitch(CExpression *pexprSwitch)
{
GPOS_ASSERT(nullptr != pexprSwitch);
GPOS_ASSERT(1 < pexprSwitch->Arity());
CScalarSwitch *pop = CScalarSwitch::PopConvert(pexprSwitch->Pop());
IMDId *mdid_type = pop->MdidType();
mdid_type->AddRef();
CDXLNode *dxlnode = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarSwitch(m_mp, mdid_type));
TranslateScalarChildren(pexprSwitch, dxlnode);
return dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScSwitchCase
//
// @doc:
// Create a DXL scalar switch case node from an optimizer scalar switch
// case expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScSwitchCase(CExpression *pexprSwitchCase)
{
GPOS_ASSERT(nullptr != pexprSwitchCase);
GPOS_ASSERT(2 == pexprSwitchCase->Arity());
CDXLNode *dxlnode = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarSwitchCase(m_mp));
TranslateScalarChildren(pexprSwitchCase, dxlnode);
return dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScNullIf
//
// @doc:
// Create a DXL scalar nullif node from an optimizer scalar
// nullif expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScNullIf(CExpression *pexprScNullIf)
{
GPOS_ASSERT(nullptr != pexprScNullIf);
CScalarNullIf *pop = CScalarNullIf::PopConvert(pexprScNullIf->Pop());
IMDId *mdid = pop->MdIdOp();
mdid->AddRef();
IMDId *mdid_type = pop->MdidType();
mdid_type->AddRef();
CDXLScalarNullIf *dxl_op =
GPOS_NEW(m_mp) CDXLScalarNullIf(m_mp, mdid, mdid_type);
CDXLNode *dxlnode = GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op);
TranslateScalarChildren(pexprScNullIf, dxlnode);
return dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScCaseTest
//
// @doc:
// Create a DXL scalar case test node from an optimizer scalar case test
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScCaseTest(CExpression *pexprScCaseTest)
{
GPOS_ASSERT(nullptr != pexprScCaseTest);
CScalarCaseTest *pop = CScalarCaseTest::PopConvert(pexprScCaseTest->Pop());
IMDId *mdid_type = pop->MdidType();
mdid_type->AddRef();
CDXLScalarCaseTest *dxl_op =
GPOS_NEW(m_mp) CDXLScalarCaseTest(m_mp, mdid_type);
return GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScNullTest
//
// @doc:
// Create a DXL scalar null test node from an optimizer scalar null test expr.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScNullTest(CExpression *pexprNullTest)
{
GPOS_ASSERT(nullptr != pexprNullTest);
CDXLNode *pdxlnNullTest = GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarNullTest(m_mp, true /* is_null */));
// translate child
GPOS_ASSERT(1 == pexprNullTest->Arity());
CExpression *pexprChild = (*pexprNullTest)[0];
CDXLNode *child_dxlnode = PdxlnScalar(pexprChild);
pdxlnNullTest->AddChild(child_dxlnode);
return pdxlnNullTest;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScBooleanTest
//
// @doc:
// Create a DXL scalar null test node from an optimizer scalar null test expr.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScBooleanTest(CExpression *pexprScBooleanTest)
{
GPOS_ASSERT(nullptr != pexprScBooleanTest);
GPOS_ASSERT(1 == pexprScBooleanTest->Arity());
const ULONG rgulBoolTestMapping[][2] = {
{CScalarBooleanTest::EbtIsTrue, EdxlbooleantestIsTrue},
{CScalarBooleanTest::EbtIsNotTrue, EdxlbooleantestIsNotTrue},
{CScalarBooleanTest::EbtIsFalse, EdxlbooleantestIsFalse},
{CScalarBooleanTest::EbtIsNotFalse, EdxlbooleantestIsNotFalse},
{CScalarBooleanTest::EbtIsUnknown, EdxlbooleantestIsUnknown},
{CScalarBooleanTest::EbtIsNotUnknown, EdxlbooleantestIsNotUnknown},
};
CScalarBooleanTest *popBoolTest =
CScalarBooleanTest::PopConvert(pexprScBooleanTest->Pop());
EdxlBooleanTestType edxlbooltest =
(EdxlBooleanTestType)(rgulBoolTestMapping[popBoolTest->Ebt()][1]);
CDXLNode *pdxlnScBooleanTest = GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarBooleanTest(m_mp, edxlbooltest));
// translate child
CExpression *pexprChild = (*pexprScBooleanTest)[0];
CDXLNode *child_dxlnode = PdxlnScalar(pexprChild);
pdxlnScBooleanTest->AddChild(child_dxlnode);
return pdxlnScBooleanTest;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScCoalesce
//
// @doc:
// Create a DXL scalar coalesce node from an optimizer scalar coalesce expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScCoalesce(CExpression *pexprCoalesce)
{
GPOS_ASSERT(nullptr != pexprCoalesce);
GPOS_ASSERT(0 < pexprCoalesce->Arity());
CScalarCoalesce *popScCoalesce =
CScalarCoalesce::PopConvert(pexprCoalesce->Pop());
IMDId *mdid_type = popScCoalesce->MdidType();
mdid_type->AddRef();
CDXLNode *dxlnode = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarCoalesce(m_mp, mdid_type));
TranslateScalarChildren(pexprCoalesce, dxlnode);
return dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScMinMax
//
// @doc:
// Create a DXL scalar MinMax node from an optimizer scalar MinMax expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScMinMax(CExpression *pexprMinMax)
{
GPOS_ASSERT(nullptr != pexprMinMax);
GPOS_ASSERT(0 < pexprMinMax->Arity());
CScalarMinMax *popScMinMax = CScalarMinMax::PopConvert(pexprMinMax->Pop());
CScalarMinMax::EScalarMinMaxType esmmt = popScMinMax->Esmmt();
GPOS_ASSERT(CScalarMinMax::EsmmtMin == esmmt ||
CScalarMinMax::EsmmtMax == esmmt);
CDXLScalarMinMax::EdxlMinMaxType min_max_type = CDXLScalarMinMax::EmmtMin;
if (CScalarMinMax::EsmmtMax == esmmt)
{
min_max_type = CDXLScalarMinMax::EmmtMax;
}
IMDId *mdid_type = popScMinMax->MdidType();
mdid_type->AddRef();
CDXLNode *dxlnode = GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarMinMax(m_mp, mdid_type, min_max_type));
TranslateScalarChildren(pexprMinMax, dxlnode);
return dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::TranslateScalarChildren
//
// @doc:
// Translate expression children and add them as children of the DXL node
//
//---------------------------------------------------------------------------
void
CTranslatorExprToDXL::TranslateScalarChildren(CExpression *pexpr,
CDXLNode *dxlnode)
{
const ULONG arity = pexpr->Arity();
for (ULONG ul = 0; ul < arity; ul++)
{
CExpression *pexprChild = (*pexpr)[ul];
CDXLNode *child_dxlnode = PdxlnScalar(pexprChild);
dxlnode->AddChild(child_dxlnode);
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScCast
//
// @doc:
// Create a DXL scalar relabel type node from an
// optimizer scalar relabel type expr.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScCast(CExpression *pexprCast)
{
GPOS_ASSERT(nullptr != pexprCast);
CScalarCast *popScCast = CScalarCast::PopConvert(pexprCast->Pop());
IMDId *mdid = popScCast->MdidType();
mdid->AddRef();
IMDId *mdid_func = popScCast->FuncMdId();
mdid_func->AddRef();
CDXLNode *pdxlnCast = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarCast(m_mp, mdid, mdid_func));
// translate child
GPOS_ASSERT(1 == pexprCast->Arity());
CExpression *pexprChild = (*pexprCast)[0];
CDXLNode *child_dxlnode = PdxlnScalar(pexprChild);
pdxlnCast->AddChild(child_dxlnode);
return pdxlnCast;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScCoerceToDomain
//
// @doc:
// Create a DXL scalar coerce node from an optimizer scalar coerce expr.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScCoerceToDomain(CExpression *pexprCoerce)
{
GPOS_ASSERT(nullptr != pexprCoerce);
CScalarCoerceToDomain *popScCoerce =
CScalarCoerceToDomain::PopConvert(pexprCoerce->Pop());
IMDId *mdid = popScCoerce->MdidType();
mdid->AddRef();
CDXLNode *pdxlnCoerce = GPOS_NEW(m_mp) CDXLNode(
m_mp,
GPOS_NEW(m_mp) CDXLScalarCoerceToDomain(
m_mp, mdid, popScCoerce->TypeModifier(),
(EdxlCoercionForm) popScCoerce
->Ecf(), // map Coercion Form directly based on position in enum
popScCoerce->Location()));
// translate child
GPOS_ASSERT(1 == pexprCoerce->Arity());
CExpression *pexprChild = (*pexprCoerce)[0];
CDXLNode *child_dxlnode = PdxlnScalar(pexprChild);
pdxlnCoerce->AddChild(child_dxlnode);
return pdxlnCoerce;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScCoerceViaIO
//
// @doc:
// Create a DXL scalar coerce node from an optimizer scalar coerce expr.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScCoerceViaIO(CExpression *pexprCoerce)
{
GPOS_ASSERT(nullptr != pexprCoerce);
CScalarCoerceViaIO *popScCerce =
CScalarCoerceViaIO::PopConvert(pexprCoerce->Pop());
IMDId *mdid = popScCerce->MdidType();
mdid->AddRef();
CDXLNode *pdxlnCoerce = GPOS_NEW(m_mp) CDXLNode(
m_mp,
GPOS_NEW(m_mp) CDXLScalarCoerceViaIO(
m_mp, mdid, popScCerce->TypeModifier(),
(EdxlCoercionForm) popScCerce
->Ecf(), // map Coercion Form directly based on position in enum
popScCerce->Location()));
// translate child
GPOS_ASSERT(1 == pexprCoerce->Arity());
CExpression *pexprChild = (*pexprCoerce)[0];
CDXLNode *child_dxlnode = PdxlnScalar(pexprChild);
pdxlnCoerce->AddChild(child_dxlnode);
return pdxlnCoerce;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScArrayCoerceExpr
//
// @doc:
// Create a DXL node from an optimizer scalar array coerce expr.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScArrayCoerceExpr(CExpression *pexprArrayCoerceExpr)
{
GPOS_ASSERT(nullptr != pexprArrayCoerceExpr);
CScalarArrayCoerceExpr *popScArrayCoerceExpr =
CScalarArrayCoerceExpr::PopConvert(pexprArrayCoerceExpr->Pop());
IMDId *pmdidElemFunc = popScArrayCoerceExpr->PmdidElementFunc();
pmdidElemFunc->AddRef();
IMDId *mdid = popScArrayCoerceExpr->MdidType();
mdid->AddRef();
CDXLNode *pdxlnArrayCoerceExpr = GPOS_NEW(m_mp) CDXLNode(
m_mp,
GPOS_NEW(m_mp) CDXLScalarArrayCoerceExpr(
m_mp, pmdidElemFunc, mdid, popScArrayCoerceExpr->TypeModifier(),
popScArrayCoerceExpr->IsExplicit(),
(EdxlCoercionForm) popScArrayCoerceExpr
->Ecf(), // map Coercion Form directly based on position in enum
popScArrayCoerceExpr->Location()));
// translate child
GPOS_ASSERT(1 == pexprArrayCoerceExpr->Arity());
CExpression *pexprChild = (*pexprArrayCoerceExpr)[0];
CDXLNode *child_dxlnode = PdxlnScalar(pexprChild);
pdxlnArrayCoerceExpr->AddChild(child_dxlnode);
return pdxlnArrayCoerceExpr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::GetWindowFrame
//
// @doc:
// Translate a window frame
//
//---------------------------------------------------------------------------
CDXLWindowFrame *
CTranslatorExprToDXL::GetWindowFrame(CWindowFrame *pwf)
{
GPOS_ASSERT(nullptr != pwf);
if (CWindowFrame::IsEmpty(pwf))
{
// an empty frame is translated as 'no frame'
return nullptr;
}
// mappings for frame info in expression and dxl worlds
const ULONG rgulSpecMapping[][2] = {{CWindowFrame::EfsRows, EdxlfsRow},
{CWindowFrame::EfsRange, EdxlfsRange}};
const ULONG rgulBoundaryMapping[][2] = {
{CWindowFrame::EfbUnboundedPreceding, EdxlfbUnboundedPreceding},
{CWindowFrame::EfbBoundedPreceding, EdxlfbBoundedPreceding},
{CWindowFrame::EfbCurrentRow, EdxlfbCurrentRow},
{CWindowFrame::EfbUnboundedFollowing, EdxlfbUnboundedFollowing},
{CWindowFrame::EfbBoundedFollowing, EdxlfbBoundedFollowing},
{CWindowFrame::EfbDelayedBoundedPreceding,
EdxlfbDelayedBoundedPreceding},
{CWindowFrame::EfbDelayedBoundedFollowing,
EdxlfbDelayedBoundedFollowing}};
const ULONG rgulExclusionStrategyMapping[][2] = {
{CWindowFrame::EfesNone, EdxlfesNone},
{CWindowFrame::EfesNulls, EdxlfesNulls},
{CWindowFrame::EfesCurrentRow, EdxlfesCurrentRow},
{CWindowFrame::EfseMatchingOthers, EdxlfesGroup},
{CWindowFrame::EfesTies, EdxlfesTies}};
EdxlFrameSpec edxlfs = (EdxlFrameSpec)(rgulSpecMapping[pwf->Efs()][1]);
EdxlFrameBoundary edxlfbLeading =
(EdxlFrameBoundary)(rgulBoundaryMapping[pwf->EfbLeading()][1]);
EdxlFrameBoundary edxlfbTrailing =
(EdxlFrameBoundary)(rgulBoundaryMapping[pwf->EfbTrailing()][1]);
EdxlFrameExclusionStrategy frame_exc_strategy =
(EdxlFrameExclusionStrategy)(
rgulExclusionStrategyMapping[pwf->Efes()][1]);
// translate scalar expressions representing leading and trailing frame edges
CDXLNode *pdxlnLeading = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarWindowFrameEdge(
m_mp, true /* fLeading */, edxlfbLeading));
if (nullptr != pwf->PexprLeading())
{
pdxlnLeading->AddChild(PdxlnScalar(pwf->PexprLeading()));
}
CDXLNode *pdxlnTrailing = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarWindowFrameEdge(
m_mp, false /* fLeading */, edxlfbTrailing));
if (nullptr != pwf->PexprTrailing())
{
pdxlnTrailing->AddChild(PdxlnScalar(pwf->PexprTrailing()));
}
return GPOS_NEW(m_mp) CDXLWindowFrame(edxlfs, frame_exc_strategy,
pdxlnLeading, pdxlnTrailing);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnWindow
//
// @doc:
// Create a DXL window node from physical sequence project expression.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnWindow(CExpression *pexprSeqPrj,
CColRefArray *colref_array,
CDistributionSpecArray *pdrgpdsBaseTables,
ULONG *pulNonGatherMotions, BOOL *pfDML)
{
GPOS_ASSERT(nullptr != pexprSeqPrj);
CPhysicalSequenceProject *popSeqPrj =
CPhysicalSequenceProject::PopConvert(pexprSeqPrj->Pop());
CDistributionSpec *pds = popSeqPrj->Pds();
ULongPtrArray *colids = GPOS_NEW(m_mp) ULongPtrArray(m_mp);
CExpressionArray *pdrgpexprPartCol = nullptr;
if (CDistributionSpec::EdtHashed == pds->Edt())
{
CDistributionSpecHashed *pdshashed =
CDistributionSpecHashed::PdsConvert(pds);
pdrgpexprPartCol = pdshashed->Pdrgpexpr();
const ULONG size = pdrgpexprPartCol->Size();
for (ULONG ul = 0; ul < size; ul++)
{
CExpression *pexpr = (*pdrgpexprPartCol)[ul];
CScalarIdent *popScId = CScalarIdent::PopConvert(pexpr->Pop());
colids->Append(GPOS_NEW(m_mp) ULONG(popScId->Pcr()->Id()));
}
}
// translate order specification and window frames into window keys
CDXLWindowKeyArray *pdrgpdxlwk = GPOS_NEW(m_mp) CDXLWindowKeyArray(m_mp);
COrderSpecArray *pdrgpos = popSeqPrj->Pdrgpos();
GPOS_ASSERT(nullptr != pdrgpos);
const ULONG ulOsSize = pdrgpos->Size();
for (ULONG ul = 0; ul < ulOsSize; ul++)
{
CDXLWindowKey *pdxlwk = GPOS_NEW(m_mp) CDXLWindowKey();
CDXLNode *sort_col_list_dxlnode =
GetSortColListDXL((*popSeqPrj->Pdrgpos())[ul]);
pdxlwk->SetSortColList(sort_col_list_dxlnode);
pdrgpdxlwk->Append(pdxlwk);
}
const ULONG ulFrames = popSeqPrj->Pdrgpwf()->Size();
for (ULONG ul = 0; ul < ulFrames; ul++)
{
CDXLWindowFrame *window_frame =
GetWindowFrame((*popSeqPrj->Pdrgpwf())[ul]);
if (nullptr != window_frame)
{
GPOS_ASSERT(ul <= ulOsSize);
CDXLWindowKey *pdxlwk = (*pdrgpdxlwk)[ul];
pdxlwk->SetWindowFrame(window_frame);
}
}
// extract physical properties
CDXLPhysicalProperties *dxl_properties = GetProperties(pexprSeqPrj);
// translate relational child
CDXLNode *child_dxlnode = CreateDXLNode(
(*pexprSeqPrj)[0], nullptr /* colref_array */, pdrgpdsBaseTables,
pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/);
GPOS_ASSERT(nullptr != pexprSeqPrj->Prpp());
CColRefSet *pcrsOutput = GPOS_NEW(m_mp) CColRefSet(m_mp);
pcrsOutput->Include(pexprSeqPrj->Prpp()->PcrsRequired());
if (nullptr != pdrgpexprPartCol)
{
CColRefSet *pcrs = CUtils::PcrsExtractColumns(m_mp, pdrgpexprPartCol);
pcrsOutput->Include(pcrs);
pcrs->Release();
}
for (ULONG ul = 0; ul < ulOsSize; ul++)
{
COrderSpec *pos = (*popSeqPrj->Pdrgpos())[ul];
if (!pos->IsEmpty())
{
const CColRef *colref = pos->Pcr(ul);
pcrsOutput->Include(colref);
}
}
// translate project list expression
CDXLNode *pdxlnPrL =
PdxlnProjList((*pexprSeqPrj)[1], pcrsOutput, colref_array);
// create an empty one-time filter
CDXLNode *filter_dxlnode = PdxlnFilter(nullptr /* pdxlnCond */);
// construct a Window node
CDXLPhysicalWindow *pdxlopWindow =
GPOS_NEW(m_mp) CDXLPhysicalWindow(m_mp, colids, pdrgpdxlwk);
CDXLNode *pdxlnWindow = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopWindow);
pdxlnWindow->SetProperties(dxl_properties);
// add children
pdxlnWindow->AddChild(pdxlnPrL);
pdxlnWindow->AddChild(filter_dxlnode);
pdxlnWindow->AddChild(child_dxlnode);
#ifdef GPOS_DEBUG
pdxlopWindow->AssertValid(pdxlnWindow, false /* validate_children */);
#endif
pcrsOutput->Release();
return pdxlnWindow;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnArray
//
// @doc:
// Create a DXL array node from an optimizer array expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnArray(CExpression *pexpr)
{
GPOS_ASSERT(nullptr != pexpr);
CScalarArray *pop = CScalarArray::PopConvert(pexpr->Pop());
IMDId *elem_type_mdid = pop->PmdidElem();
elem_type_mdid->AddRef();
IMDId *array_type_mdid = pop->PmdidArray();
array_type_mdid->AddRef();
CDXLNode *pdxlnArray = GPOS_NEW(m_mp) CDXLNode(
m_mp,
GPOS_NEW(m_mp) CDXLScalarArray(m_mp, elem_type_mdid, array_type_mdid,
pop->FMultiDimensional()));
const ULONG arity = CUtils::UlScalarArrayArity(pexpr);
for (ULONG ul = 0; ul < arity; ul++)
{
CExpression *pexprChild =
CUtils::PScalarArrayExprChildAt(m_mp, pexpr, ul);
CDXLNode *child_dxlnode = PdxlnScalar(pexprChild);
pdxlnArray->AddChild(child_dxlnode);
pexprChild->Release();
}
return pdxlnArray;
}
CDXLNode *
CTranslatorExprToDXL::PdxlnValuesList(CExpression *pexpr)
{
GPOS_ASSERT(nullptr != pexpr);
CDXLNode *pdxlnValuesList = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarValuesList(m_mp));
for (ULONG ul = 0; ul < pexpr->Arity(); ul++)
{
CExpression *pexprChild = (*pexpr)[ul];
CDXLNode *child_dxlnode = PdxlnScalar(pexprChild);
pdxlnValuesList->AddChild(child_dxlnode);
}
return pdxlnValuesList;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnArrayRef
//
// @doc:
// Create a DXL arrayref node from an optimizer arrayref expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnArrayRef(CExpression *pexpr)
{
GPOS_ASSERT(nullptr != pexpr);
CScalarArrayRef *pop = CScalarArrayRef::PopConvert(pexpr->Pop());
IMDId *elem_type_mdid = pop->PmdidElem();
elem_type_mdid->AddRef();
IMDId *array_type_mdid = pop->PmdidArray();
array_type_mdid->AddRef();
IMDId *return_type_mdid = pop->MdidType();
return_type_mdid->AddRef();
CDXLNode *pdxlnArrayref = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarArrayRef(
m_mp, elem_type_mdid, pop->TypeModifier(),
array_type_mdid, return_type_mdid));
TranslateScalarChildren(pexpr, pdxlnArrayref);
return pdxlnArrayref;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnArrayRefIndexList
//
// @doc:
// Create a DXL arrayref index list from an optimizer arrayref index list
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnArrayRefIndexList(CExpression *pexpr)
{
GPOS_ASSERT(nullptr != pexpr);
CScalarArrayRefIndexList *pop =
CScalarArrayRefIndexList::PopConvert(pexpr->Pop());
CDXLNode *pdxlnIndexlist = GPOS_NEW(m_mp) CDXLNode(
m_mp,
GPOS_NEW(m_mp) CDXLScalarArrayRefIndexList(m_mp, Eilb(pop->Eilt())));
TranslateScalarChildren(pexpr, pdxlnIndexlist);
return pdxlnIndexlist;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnAssertPredicate
//
// @doc:
// Create a DXL assert predicate from an optimizer assert predicate expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnAssertPredicate(CExpression *pexpr)
{
GPOS_ASSERT(nullptr != pexpr);
CDXLNode *pdxlnAssertConstraintList = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarAssertConstraintList(m_mp));
TranslateScalarChildren(pexpr, pdxlnAssertConstraintList);
return pdxlnAssertConstraintList;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnAssertConstraint
//
// @doc:
// Create a DXL assert constraint from an optimizer assert constraint expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnAssertConstraint(CExpression *pexpr)
{
GPOS_ASSERT(nullptr != pexpr);
CScalarAssertConstraint *popAssertConstraint =
CScalarAssertConstraint::PopConvert(pexpr->Pop());
CWStringDynamic *pstrErrorMsg = GPOS_NEW(m_mp)
CWStringDynamic(m_mp, popAssertConstraint->PstrErrorMsg()->GetBuffer());
CDXLNode *pdxlnAssertConstraint = GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarAssertConstraint(m_mp, pstrErrorMsg));
TranslateScalarChildren(pexpr, pdxlnAssertConstraint);
return pdxlnAssertConstraint;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::Eilb
//
// @doc:
// Translate the arrayref index list bound
//
//---------------------------------------------------------------------------
CDXLScalarArrayRefIndexList::EIndexListBound
CTranslatorExprToDXL::Eilb(const CScalarArrayRefIndexList::EIndexListType eilt)
{
switch (eilt)
{
case CScalarArrayRefIndexList::EiltLower:
return CDXLScalarArrayRefIndexList::EilbLower;
case CScalarArrayRefIndexList::EiltUpper:
return CDXLScalarArrayRefIndexList::EilbUpper;
default:
GPOS_RAISE(gpopt::ExmaGPOPT, gpopt::ExmiUnsupportedOp,
GPOS_WSZ_LIT("Invalid arrayref index bound"));
return CDXLScalarArrayRefIndexList::EilbSentinel;
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnArrayCmp
//
// @doc:
// Create a DXL array compare node from an optimizer array expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnArrayCmp(CExpression *pexpr)
{
GPOS_ASSERT(nullptr != pexpr);
CScalarArrayCmp *pop = CScalarArrayCmp::PopConvert(pexpr->Pop());
IMDId *mdid_op = pop->MdIdOp();
mdid_op->AddRef();
const CWStringConst *str_opname = pop->Pstr();
CScalarArrayCmp::EArrCmpType earrcmpt = pop->Earrcmpt();
GPOS_ASSERT(CScalarArrayCmp::EarrcmpSentinel > earrcmpt);
EdxlArrayCompType edxlarrcmpt = Edxlarraycomptypeall;
if (CScalarArrayCmp::EarrcmpAny == earrcmpt)
{
edxlarrcmpt = Edxlarraycomptypeany;
}
CDXLNode *pdxlnArrayCmp = GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarArrayComp(
m_mp, mdid_op,
GPOS_NEW(m_mp) CWStringConst(m_mp, str_opname->GetBuffer()),
edxlarrcmpt));
TranslateScalarChildren(pexpr, pdxlnArrayCmp);
return pdxlnArrayCmp;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnDMLAction
//
// @doc:
// Create a DXL DML action node from an optimizer action expression
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnDMLAction(CExpression *
#ifdef GPOS_DEBUG
pexpr
#endif // GPOS_DEBUG
)
{
GPOS_ASSERT(nullptr != pexpr);
GPOS_ASSERT(COperator::EopScalarDMLAction == pexpr->Pop()->Eopid());
return GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarDMLAction(m_mp));
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnScConst
//
// @doc:
// Create a DXL scalar constant node from an optimizer scalar const expr.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnScConst(CExpression *pexprScConst)
{
GPOS_ASSERT(nullptr != pexprScConst);
CScalarConst *popScConst = CScalarConst::PopConvert(pexprScConst->Pop());
IDatum *datum = popScConst->GetDatum();
CMDAccessor *md_accessor = COptCtxt::PoctxtFromTLS()->Pmda();
const IMDType *pmdtype = md_accessor->RetrieveType(datum->MDId());
CDXLNode *dxlnode =
GPOS_NEW(m_mp) CDXLNode(m_mp, pmdtype->GetDXLOpScConst(m_mp, datum));
return dxlnode;
}
CDXLNode *
CTranslatorExprToDXL::PdxlnScSortGroupClause(
CExpression *pexprScSortGroupClause)
{
GPOS_ASSERT(nullptr != pexprScSortGroupClause);
CScalarSortGroupClause *pop =
CScalarSortGroupClause::PopConvert(pexprScSortGroupClause->Pop());
CDXLNode *dxlnode = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarSortGroupClause(
m_mp, pop->Index(), pop->EqOp(), pop->SortOp(),
pop->NullsFirst(), pop->IsHashable()));
return dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnFilter
//
// @doc:
// Create a DXL filter node containing the given scalar node as a child.
// If the scalar node is NULL, a filter node with no children is returned
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnFilter(CDXLNode *pdxlnCond)
{
CDXLNode *filter_dxlnode =
GPOS_NEW(m_mp) CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarFilter(m_mp));
if (nullptr != pdxlnCond)
{
filter_dxlnode->AddChild(pdxlnCond);
}
return filter_dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::MakeDXLTableDescr
//
// @doc:
// Create a DXL table descriptor from the corresponding optimizer structure
//
//---------------------------------------------------------------------------
CDXLTableDescr *
CTranslatorExprToDXL::MakeDXLTableDescr(
const CTableDescriptor *ptabdesc, const CColRefArray *pdrgpcrOutput,
const CReqdPropPlan *reqd_prop_plan GPOS_ASSERTS_ONLY)
{
GPOS_ASSERT(nullptr != ptabdesc);
GPOS_ASSERT_IMP(nullptr != pdrgpcrOutput,
ptabdesc->ColumnCount() == pdrgpcrOutput->Size());
// get tbl name
CMDName *pmdnameTbl = GPOS_NEW(m_mp) CMDName(m_mp, ptabdesc->Name().Pstr());
CMDIdGPDB *mdid = CMDIdGPDB::CastMdid(ptabdesc->MDId());
mdid->AddRef();
CDXLTableDescr *table_descr = GPOS_NEW(m_mp)
CDXLTableDescr(m_mp, mdid, pmdnameTbl, ptabdesc->GetExecuteAsUserId(),
ptabdesc->LockMode());
const ULONG ulColumns = ptabdesc->ColumnCount();
// translate col descriptors
for (ULONG ul = 0; ul < ulColumns; ul++)
{
const CColumnDescriptor *pcd = ptabdesc->Pcoldesc(ul);
GPOS_ASSERT(nullptr != pcd);
// output col ref for the current col descrs
CColRef *colref = nullptr;
if (nullptr != pdrgpcrOutput)
{
colref = (*pdrgpcrOutput)[ul];
if (colref->GetUsage() != CColRef::EUsed)
{
#ifdef GPOS_DEBUG
if (nullptr != reqd_prop_plan &&
nullptr != reqd_prop_plan->PcrsRequired())
{
// ensure that any col removed is not a part of the plan's required cols
GPOS_ASSERT(
!reqd_prop_plan->PcrsRequired()->FMember(colref));
}
#endif
continue;
}
}
else
{
colref = m_pcf->PcrCreate(pcd->RetrieveType(), pcd->TypeModifier(),
pcd->Name());
}
CMDName *pmdnameCol = GPOS_NEW(m_mp) CMDName(m_mp, pcd->Name().Pstr());
// use the col ref id for the corresponding output column as
// colid for the dxl column
CMDIdGPDB *pmdidColType =
CMDIdGPDB::CastMdid(colref->RetrieveType()->MDId());
pmdidColType->AddRef();
CDXLColDescr *pdxlcd = GPOS_NEW(m_mp) CDXLColDescr(
pmdnameCol, colref->Id(), pcd->AttrNum(), pmdidColType,
colref->TypeModifier(), false /* fdropped */, pcd->Width());
table_descr->AddColumnDescr(pdxlcd);
}
return table_descr;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::GetProperties
//
// @doc:
// Construct a DXL physical properties container with operator costs for
// the given expression
//
//---------------------------------------------------------------------------
CDXLPhysicalProperties *
CTranslatorExprToDXL::GetProperties(const CExpression *pexpr)
{
// extract out rows from statistics object
CWStringDynamic *rows_out_str = GPOS_NEW(m_mp) CWStringDynamic(m_mp);
const IStatistics *stats = pexpr->Pstats();
CDouble rows = CStatistics::DefaultRelationRows;
// stats may not be present in artificially generated physical expression trees.
// fill in default statistics
if (nullptr != stats)
{
rows = stats->Rows();
}
if (CDistributionSpec::EdtStrictReplicated ==
pexpr->GetDrvdPropPlan()->Pds()->Edt() ||
CDistributionSpec::EdtTaintedReplicated ==
pexpr->GetDrvdPropPlan()->Pds()->Edt())
{
// if distribution is replicated, multiply number of rows by number of segments
ULONG ulSegments = COptCtxt::PoctxtFromTLS()->GetCostModel()->UlHosts();
rows = rows * ulSegments;
}
rows_out_str->AppendFormat(GPOS_WSZ_LIT("%f"), rows.Get());
// extract our width from statistics object
CDouble width = CStatistics::DefaultColumnWidth;
CReqdPropPlan *prpp = pexpr->Prpp();
CColRefSet *pcrs = prpp->PcrsRequired();
ULongPtrArray *colids = GPOS_NEW(m_mp) ULongPtrArray(m_mp);
pcrs->ExtractColIds(m_mp, colids);
CWStringDynamic *width_str = GPOS_NEW(m_mp) CWStringDynamic(m_mp);
if (nullptr != stats)
{
width = stats->Width(colids);
}
colids->Release();
width_str->AppendFormat(GPOS_WSZ_LIT("%lld"), (LINT) width.Get());
// get the cost from expression node
CWStringDynamic str(m_mp);
COstreamString oss(&str);
oss << pexpr->Cost();
CWStringDynamic *pstrStartupcost =
GPOS_NEW(m_mp) CWStringDynamic(m_mp, GPOS_WSZ_LIT("0"));
CWStringDynamic *pstrTotalcost =
GPOS_NEW(m_mp) CWStringDynamic(m_mp, str.GetBuffer());
CDXLOperatorCost *cost = GPOS_NEW(m_mp) CDXLOperatorCost(
pstrStartupcost, pstrTotalcost, rows_out_str, width_str);
CDXLPhysicalProperties *dxl_properties =
GPOS_NEW(m_mp) CDXLPhysicalProperties(cost);
return dxl_properties;
}
CDXLNode *
CTranslatorExprToDXL::PdxlnProjListForChildPart(
const ColRefToUlongMap *root_col_mapping, const CColRefArray *part_colrefs,
const CColRefSet *reqd_colrefs, const CColRefArray *colref_array)
{
CColRefArray *mapped_colrefs = GPOS_NEW(m_mp) CColRefArray(m_mp);
CColRefSet *pcrs = GPOS_NEW(m_mp) CColRefSet(m_mp);
// project columns in order if explicitly asked
if (nullptr != colref_array)
{
for (ULONG i = 0; i < colref_array->Size(); ++i)
{
CColRef *cr = (*colref_array)[i];
ULONG *idx = root_col_mapping->Find(cr);
GPOS_ASSERT(nullptr != idx);
CColRef *mapped_cr = (*part_colrefs)[*idx];
mapped_colrefs->Append(mapped_cr);
pcrs->Include(mapped_cr);
}
}
CColRefSetIter crsi(*reqd_colrefs);
while (crsi.Advance())
{
CColRef *cr = crsi.Pcr();
ULONG *idx = root_col_mapping->Find(cr);
GPOS_ASSERT(nullptr != idx);
CColRef *mapped_cr = (*part_colrefs)[*idx];
if (!pcrs->FMember(mapped_cr))
{
mapped_colrefs->Append(mapped_cr);
}
}
CColRefSet *empty_set = GPOS_NEW(m_mp) CColRefSet(m_mp);
CDXLNode *pdxlnPrL = PdxlnProjList(empty_set, mapped_colrefs);
empty_set->Release();
mapped_colrefs->Release();
pcrs->Release();
return pdxlnPrL;
}
// Translate a filter expr on the root for a child partition using:
// root_col_mapping - root col to part col mapping
// part_colrefs - (new) colrefs of the child partition
// root_colrefs - (original) root DTS colrefs
// pred - filter predicate to translate
//
// The method first creates a temporary mapping from root colrefs to (new) child
// partition colref ids, which is used when translating via PdxlnScalar().
CDXLNode *
CTranslatorExprToDXL::PdxlnCondForChildPart(
const ColRefToUlongMap *root_col_mapping, const CColRefArray *part_colrefs,
const CColRefArray *root_colrefs, CExpression *pred)
{
GPOS_ASSERT(part_colrefs->Size() == root_colrefs->Size());
// Set up a temporary mapping from root colrefs to partition colref ids
m_phmcrulPartColId = GPOS_NEW(m_mp) ColRefToUlongMap(m_mp);
for (ULONG i = 0; i < root_colrefs->Size(); ++i)
{
CColRef *cr = (*root_colrefs)[i];
ULONG *idx = root_col_mapping->Find(cr);
GPOS_ASSERT(nullptr != idx);
CColRef *mapped_cr = (*part_colrefs)[*idx];
m_phmcrulPartColId->Insert(cr, GPOS_NEW(m_mp) ULONG(mapped_cr->Id()));
}
CDXLNode *pdxlnCond = nullptr;
if (nullptr != pred)
{
pdxlnCond = PdxlnScalar(pred);
}
// clean up the temporary mapping
m_phmcrulPartColId->Release();
m_phmcrulPartColId = nullptr;
return pdxlnCond;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnBitmapIndexPathForChildPart
//
// @doc:
// Construct a DXL BitmapTableScan's bitmap index path child
// DLX node for a child partition.
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnBitmapIndexPathForChildPart(
const ColRefToUlongMap *root_col_mapping, const CColRefArray *part_colrefs,
const CColRefArray *root_colrefs, const IMDRelation *part,
CExpression *pexprBitmapIndexPath)
{
GPOS_CHECK_STACK_SIZE;
switch (pexprBitmapIndexPath->Pop()->Eopid())
{
case COperator::EopScalarBitmapIndexProbe:
return PdxlnBitmapIndexProbeForChildPart(
root_col_mapping, part_colrefs, root_colrefs, part,
pexprBitmapIndexPath);
case COperator::EopScalarBitmapBoolOp:
{
GPOS_ASSERT(nullptr != pexprBitmapIndexPath);
GPOS_ASSERT(2 == pexprBitmapIndexPath->Arity());
CScalarBitmapBoolOp *popBitmapBoolOp =
CScalarBitmapBoolOp::PopConvert(pexprBitmapIndexPath->Pop());
CExpression *pexprLeft = (*pexprBitmapIndexPath)[0];
CExpression *pexprRight = (*pexprBitmapIndexPath)[1];
CDXLNode *dxlnode_left = PdxlnBitmapIndexPathForChildPart(
root_col_mapping, part_colrefs, root_colrefs, part, pexprLeft);
CDXLNode *dxlnode_right = PdxlnBitmapIndexPathForChildPart(
root_col_mapping, part_colrefs, root_colrefs, part, pexprRight);
IMDId *mdid_type = popBitmapBoolOp->MdidType();
mdid_type->AddRef();
CDXLScalarBitmapBoolOp::EdxlBitmapBoolOp edxlbitmapop =
CDXLScalarBitmapBoolOp::EdxlbitmapAnd;
if (CScalarBitmapBoolOp::EbitmapboolOr ==
popBitmapBoolOp->Ebitmapboolop())
{
edxlbitmapop = CDXLScalarBitmapBoolOp::EdxlbitmapOr;
}
return GPOS_NEW(m_mp) CDXLNode(
m_mp,
GPOS_NEW(m_mp)
CDXLScalarBitmapBoolOp(m_mp, mdid_type, edxlbitmapop),
dxlnode_left, dxlnode_right);
}
default:
GPOS_RAISE(gpopt::ExmaGPOPT, gpopt::ExmiUnsupportedOp,
pexprBitmapIndexPath->Pop()->SzId());
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnBitmapIndexProbeForChildPart
//
// @doc:
// Create a DXL scalar bitmap index probe from an optimizer
// scalar bitmap index probe operator for a child partition.
//
// GPDB_12_MERGE_FIXME: this function should always keep parity
// with PdxlnBitmapIndexProbe(). We did not extract the duplicate
// code into a common function because the handlings for child
// partition are also all over this function.
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnBitmapIndexProbeForChildPart(
const ColRefToUlongMap *root_col_mapping, const CColRefArray *part_colrefs,
const CColRefArray *root_colrefs, const IMDRelation *part,
CExpression *pexprBitmapIndexProbe)
{
GPOS_ASSERT(nullptr != pexprBitmapIndexProbe);
CScalarBitmapIndexProbe *pop =
CScalarBitmapIndexProbe::PopConvert(pexprBitmapIndexProbe->Pop());
// create index descriptor
CIndexDescriptor *pindexdesc = pop->Pindexdesc();
IMDId *pmdidIndex = pindexdesc->MDId();
// construct set of child indexes from parent list of child indexes
const IMDIndex *md_index = m_pmda->RetrieveIndex(pmdidIndex);
IMdIdArray *child_indexes = md_index->ChildIndexMdids();
MdidHashSet *child_index_mdids_set = GPOS_NEW(m_mp) MdidHashSet(m_mp);
for (ULONG ul = 0; ul < child_indexes->Size(); ul++)
{
(*child_indexes)[ul]->AddRef();
child_index_mdids_set->Insert((*child_indexes)[ul]);
}
CDXLIndexDescr *dxl_index_descr = PdxlnIndexDescForPart(
m_mp, child_index_mdids_set, part, pindexdesc->Name().Pstr());
child_index_mdids_set->Release();
CDXLScalarBitmapIndexProbe *dxl_op =
GPOS_NEW(m_mp) CDXLScalarBitmapIndexProbe(m_mp, dxl_index_descr);
CDXLNode *pdxlnBitmapIndexProbe = GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op);
// translate index predicates
CExpression *pexprCond = (*pexprBitmapIndexProbe)[0];
CDXLNode *pdxlnIndexCondList = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarIndexCondList(m_mp));
CExpressionArray *pdrgpexprConds =
CPredicateUtils::PdrgpexprConjuncts(m_mp, pexprCond);
const ULONG length = pdrgpexprConds->Size();
for (ULONG ul = 0; ul < length; ul++)
{
CExpression *pexprIndexCond = (*pdrgpexprConds)[ul];
CDXLNode *pdxlnIndexCond = PdxlnCondForChildPart(
root_col_mapping, part_colrefs, root_colrefs, pexprIndexCond);
pdxlnIndexCondList->AddChild(pdxlnIndexCond);
}
pdrgpexprConds->Release();
pdxlnBitmapIndexProbe->AddChild(pdxlnIndexCondList);
#ifdef GPOS_DEBUG
pdxlnBitmapIndexProbe->GetOperator()->AssertValid(
pdxlnBitmapIndexProbe, false /*validate_children*/);
#endif
return pdxlnBitmapIndexProbe;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnProjList
//
// @doc:
// Translate the set of output col refs into a dxl project list.
// If the given array of columns is not NULL, it specifies the order of the
// columns in the project list, otherwise any order is good
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnProjList(const CColRefSet *pcrsOutput,
CColRefArray *colref_array)
{
GPOS_ASSERT(nullptr != pcrsOutput);
CDXLScalarProjList *pdxlopPrL = GPOS_NEW(m_mp) CDXLScalarProjList(m_mp);
CDXLNode *pdxlnPrL = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopPrL);
if (nullptr != colref_array)
{
CColRefSet *pcrs = GPOS_NEW(m_mp) CColRefSet(m_mp);
for (ULONG ul = 0; ul < colref_array->Size(); ul++)
{
CColRef *colref = (*colref_array)[ul];
CDXLNode *pdxlnPrEl = CTranslatorExprToDXLUtils::PdxlnProjElem(
m_mp, m_phmcrdxln, colref);
pdxlnPrL->AddChild(pdxlnPrEl);
pcrs->Include(colref);
}
// add the remaining required columns
CColRefSetIter crsi(*pcrsOutput);
while (crsi.Advance())
{
CColRef *colref = crsi.Pcr();
if (!pcrs->FMember(colref))
{
CDXLNode *pdxlnPrEl = CTranslatorExprToDXLUtils::PdxlnProjElem(
m_mp, m_phmcrdxln, colref);
pdxlnPrL->AddChild(pdxlnPrEl);
pcrs->Include(colref);
}
}
pcrs->Release();
}
else
{
// no order specified
CColRefSetIter crsi(*pcrsOutput);
while (crsi.Advance())
{
CColRef *colref = crsi.Pcr();
CDXLNode *pdxlnPrEl = CTranslatorExprToDXLUtils::PdxlnProjElem(
m_mp, m_phmcrdxln, colref);
pdxlnPrL->AddChild(pdxlnPrEl);
}
}
return pdxlnPrL;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnProjList
//
// @doc:
// Translate a project list expression into DXL project list node
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnProjList(const CExpression *pexprProjList,
const CColRefSet *pcrsRequired,
CColRefArray *colref_array)
{
if (nullptr == colref_array)
{
// no order specified
return PdxlnProjList(pexprProjList, pcrsRequired);
}
// translate computed column expressions into DXL and index them on their col ids
CHashMap<ULONG, CDXLNode, gpos::HashValue<ULONG>, gpos::Equals<ULONG>,
CleanupDelete<ULONG>,
CleanupRelease<CDXLNode> > *phmComputedColumns = GPOS_NEW(m_mp)
CHashMap<ULONG, CDXLNode, gpos::HashValue<ULONG>, gpos::Equals<ULONG>,
CleanupDelete<ULONG>, CleanupRelease<CDXLNode> >(m_mp);
for (ULONG ul = 0; nullptr != pexprProjList && ul < pexprProjList->Arity();
ul++)
{
CExpression *pexprProjElem = (*pexprProjList)[ul];
// translate proj elem
CDXLNode *pdxlnProjElem = PdxlnProjElem(pexprProjElem);
const CScalarProjectElement *popScPrEl =
CScalarProjectElement::PopConvert(pexprProjElem->Pop());
ULONG *pulKey = GPOS_NEW(m_mp) ULONG(popScPrEl->Pcr()->Id());
BOOL fInserted GPOS_ASSERTS_ONLY =
phmComputedColumns->Insert(pulKey, pdxlnProjElem);
GPOS_ASSERT(fInserted);
}
// add required columns to the project list
CColRefArray *pdrgpcrCopy = GPOS_NEW(m_mp) CColRefArray(m_mp);
pdrgpcrCopy->AppendArray(colref_array);
CColRefSet *pcrsOutput = GPOS_NEW(m_mp) CColRefSet(m_mp);
pcrsOutput->Include(colref_array);
CColRefSetIter crsi(*pcrsRequired);
while (crsi.Advance())
{
CColRef *colref = crsi.Pcr();
if (!pcrsOutput->FMember(colref))
{
pdrgpcrCopy->Append(colref);
}
}
// translate project list according to the specified order
CDXLScalarProjList *pdxlopPrL = GPOS_NEW(m_mp) CDXLScalarProjList(m_mp);
CDXLNode *proj_list_dxlnode = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopPrL);
const ULONG num_cols = pdrgpcrCopy->Size();
for (ULONG ul = 0; ul < num_cols; ul++)
{
CColRef *colref = (*pdrgpcrCopy)[ul];
ULONG ulKey = colref->Id();
CDXLNode *pdxlnProjElem = phmComputedColumns->Find(&ulKey);
if (nullptr == pdxlnProjElem)
{
// not a computed column
pdxlnProjElem = CTranslatorExprToDXLUtils::PdxlnProjElem(
m_mp, m_phmcrdxln, colref);
}
else
{
pdxlnProjElem->AddRef();
}
proj_list_dxlnode->AddChild(pdxlnProjElem);
}
// cleanup
pdrgpcrCopy->Release();
pcrsOutput->Release();
phmComputedColumns->Release();
return proj_list_dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnProjList
//
// @doc:
// Translate a project list expression into DXL project list node
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnProjList(const CExpression *pexprProjList,
const CColRefSet *pcrsRequired)
{
CDXLScalarProjList *pdxlopPrL = GPOS_NEW(m_mp) CDXLScalarProjList(m_mp);
CDXLNode *proj_list_dxlnode = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopPrL);
// create a copy of the required output columns
CColRefSet *pcrsOutput = GPOS_NEW(m_mp) CColRefSet(m_mp, *pcrsRequired);
if (nullptr != pexprProjList)
{
// translate defined columns from project list
for (ULONG ul = 0; ul < pexprProjList->Arity(); ul++)
{
CExpression *pexprProjElem = (*pexprProjList)[ul];
// translate proj elem
CDXLNode *pdxlnProjElem = PdxlnProjElem(pexprProjElem);
proj_list_dxlnode->AddChild(pdxlnProjElem);
// exclude proj elem col ref from the output column set as it has been
// processed already
const CScalarProjectElement *popScPrEl =
CScalarProjectElement::PopConvert(pexprProjElem->Pop());
pcrsOutput->Exclude(popScPrEl->Pcr());
}
}
// translate columns which remained after processing the project list: those
// are columns passed from the level below
CColRefSetIter crsi(*pcrsOutput);
while (crsi.Advance())
{
CColRef *colref = crsi.Pcr();
CDXLNode *pdxlnPrEl =
CTranslatorExprToDXLUtils::PdxlnProjElem(m_mp, m_phmcrdxln, colref);
proj_list_dxlnode->AddChild(pdxlnPrEl);
}
// cleanup
pcrsOutput->Release();
return proj_list_dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnProjListFromConstTableGet
//
// @doc:
// Construct a project list node by creating references to the columns
// of the given project list of the child node
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnProjListFromConstTableGet(
CColRefArray *pdrgpcrReqOutput, CColRefArray *pdrgpcrCTGOutput,
IDatumArray *pdrgpdatumValues)
{
GPOS_ASSERT(nullptr != pdrgpcrCTGOutput);
GPOS_ASSERT(nullptr != pdrgpdatumValues);
GPOS_ASSERT(pdrgpcrCTGOutput->Size() == pdrgpdatumValues->Size());
CDXLNode *proj_list_dxlnode = nullptr;
CColRefSet *pcrsOutput = GPOS_NEW(m_mp) CColRefSet(m_mp);
pcrsOutput->Include(pdrgpcrCTGOutput);
if (nullptr != pdrgpcrReqOutput)
{
const ULONG arity = pdrgpcrReqOutput->Size();
IDatumArray *pdrgpdatumOrdered = GPOS_NEW(m_mp) IDatumArray(m_mp);
for (ULONG ul = 0; ul < arity; ul++)
{
CColRef *colref = (*pdrgpcrReqOutput)[ul];
ULONG ulPos = UlPosInArray(colref, pdrgpcrCTGOutput);
GPOS_ASSERT(ulPos < pdrgpcrCTGOutput->Size());
IDatum *datum = (*pdrgpdatumValues)[ulPos];
datum->AddRef();
pdrgpdatumOrdered->Append(datum);
pcrsOutput->Exclude(colref);
}
proj_list_dxlnode = PdxlnProjListFromConstTableGet(
nullptr, pdrgpcrReqOutput, pdrgpdatumOrdered);
pdrgpdatumOrdered->Release();
}
else
{
proj_list_dxlnode = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarProjList(m_mp));
}
// construct project elements for columns which remained after processing the required list
CColRefSetIter crsi(*pcrsOutput);
while (crsi.Advance())
{
CColRef *colref = crsi.Pcr();
ULONG ulPos = UlPosInArray(colref, pdrgpcrCTGOutput);
GPOS_ASSERT(ulPos < pdrgpcrCTGOutput->Size());
IDatum *datum = (*pdrgpdatumValues)[ulPos];
CDXLScalarConstValue *pdxlopConstValue =
colref->RetrieveType()->GetDXLOpScConst(m_mp, datum);
CDXLNode *pdxlnPrEl = PdxlnProjElem(
colref, GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopConstValue));
proj_list_dxlnode->AddChild(pdxlnPrEl);
}
// cleanup
pcrsOutput->Release();
return proj_list_dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnProjElem
//
// @doc:
// Create a project elem from a given col ref and a value
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnProjElem(const CColRef *colref, CDXLNode *pdxlnValue)
{
GPOS_ASSERT(nullptr != colref);
CMDName *mdname = GPOS_NEW(m_mp) CMDName(m_mp, colref->Name().Pstr());
CDXLNode *pdxlnPrEl = GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarProjElem(m_mp, colref->Id(), mdname));
// attach scalar id expression to proj elem
pdxlnPrEl->AddChild(pdxlnValue);
return pdxlnPrEl;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnProjElem
//
// @doc:
// Create a project elem from a given col ref
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnProjElem(const CExpression *pexprProjElem)
{
GPOS_ASSERT(nullptr != pexprProjElem && 1 == pexprProjElem->Arity());
CScalarProjectElement *popScPrEl =
CScalarProjectElement::PopConvert(pexprProjElem->Pop());
CColRef *colref = popScPrEl->Pcr();
CMDName *mdname = GPOS_NEW(m_mp) CMDName(m_mp, colref->Name().Pstr());
CDXLNode *pdxlnPrEl = GPOS_NEW(m_mp) CDXLNode(
m_mp, GPOS_NEW(m_mp) CDXLScalarProjElem(m_mp, colref->Id(), mdname));
CExpression *pexprChild = (*pexprProjElem)[0];
CDXLNode *child_dxlnode = PdxlnScalar(pexprChild);
pdxlnPrEl->AddChild(child_dxlnode);
return pdxlnPrEl;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::GetSortColListDXL
//
// @doc:
// Create a dxl sort column list node from a given order spec
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::GetSortColListDXL(const COrderSpec *pos)
{
GPOS_ASSERT(nullptr != pos);
CDXLNode *sort_col_list_dxlnode = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarSortColList(m_mp));
for (ULONG ul = 0; ul < pos->UlSortColumns(); ul++)
{
// get sort column components
IMDId *sort_op_id = pos->GetMdIdSortOp(ul);
sort_op_id->AddRef();
const CColRef *colref = pos->Pcr(ul);
COrderSpec::ENullTreatment ent = pos->Ent(ul);
GPOS_ASSERT(COrderSpec::EntFirst == ent || COrderSpec::EntLast == ent ||
COrderSpec::EntAuto == ent);
// get sort operator name
const IMDScalarOp *md_scalar_op = m_pmda->RetrieveScOp(sort_op_id);
CWStringConst *sort_op_name = GPOS_NEW(m_mp) CWStringConst(
m_mp, md_scalar_op->Mdname().GetMDName()->GetBuffer());
BOOL fSortNullsFirst = false;
if (COrderSpec::EntFirst == ent)
{
fSortNullsFirst = true;
}
CDXLScalarSortCol *pdxlopSortCol = GPOS_NEW(m_mp) CDXLScalarSortCol(
m_mp, colref->Id(), sort_op_id, sort_op_name, fSortNullsFirst);
CDXLNode *pdxlnSortCol = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopSortCol);
sort_col_list_dxlnode->AddChild(pdxlnSortCol);
}
return sort_col_list_dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::PdxlnHashExprList
//
// @doc:
// Create a dxl hash expr list node from a given array of column references
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::PdxlnHashExprList(const CExpressionArray *pdrgpexpr,
const IMdIdArray *opfamilies)
{
GPOS_ASSERT(nullptr != pdrgpexpr);
GPOS_ASSERT_IMP(GPOS_FTRACE(EopttraceConsiderOpfamiliesForDistribution),
nullptr != opfamilies);
CDXLNode *hash_expr_list = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarHashExprList(m_mp));
for (ULONG ul = 0; ul < pdrgpexpr->Size(); ul++)
{
CExpression *pexpr = (*pdrgpexpr)[ul];
IMDId *opfamily = nullptr;
if (GPOS_FTRACE(EopttraceConsiderOpfamiliesForDistribution))
{
opfamily = (*opfamilies)[ul];
opfamily->AddRef();
}
// constrct a hash expr node for the col ref
CDXLNode *pdxlnHashExpr = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarHashExpr(m_mp, opfamily));
pdxlnHashExpr->AddChild(PdxlnScalar(pexpr));
hash_expr_list->AddChild(pdxlnHashExpr);
}
return hash_expr_list;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::GetSortColListDXL
//
// @doc:
// Create a dxl sort column list node for a given motion operator
//
//---------------------------------------------------------------------------
CDXLNode *
CTranslatorExprToDXL::GetSortColListDXL(CExpression *pexprMotion)
{
CDXLNode *sort_col_list_dxlnode = nullptr;
if (COperator::EopPhysicalMotionGather == pexprMotion->Pop()->Eopid())
{
// construct a sorting column list node
CPhysicalMotionGather *popGather =
CPhysicalMotionGather::PopConvert(pexprMotion->Pop());
sort_col_list_dxlnode = GetSortColListDXL(popGather->Pos());
}
else
{
sort_col_list_dxlnode = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarSortColList(m_mp));
}
return sort_col_list_dxlnode;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::GetOutputSegIdsArray
//
// @doc:
// Construct an array with output segment indices for the given Motion
// expression.
//
//---------------------------------------------------------------------------
IntPtrArray *
CTranslatorExprToDXL::GetOutputSegIdsArray(CExpression *pexprMotion)
{
IntPtrArray *pdrgpi = nullptr;
COperator *pop = pexprMotion->Pop();
switch (pop->Eopid())
{
case COperator::EopPhysicalMotionGather:
{
CPhysicalMotionGather *popGather =
CPhysicalMotionGather::PopConvert(pop);
pdrgpi = GPOS_NEW(m_mp) IntPtrArray(m_mp);
INT iSegmentId = m_iMasterId;
if (CDistributionSpecSingleton::EstSegment == popGather->Est())
{
// gather to first segment
iSegmentId = *((*m_pdrgpiSegments)[0]);
}
pdrgpi->Append(GPOS_NEW(m_mp) INT(iSegmentId));
break;
}
case COperator::EopPhysicalMotionBroadcast:
case COperator::EopPhysicalMotionHashDistribute:
case COperator::EopPhysicalMotionRoutedDistribute:
case COperator::EopPhysicalMotionRandom:
{
m_pdrgpiSegments->AddRef();
pdrgpi = m_pdrgpiSegments;
break;
}
default:
GPOS_ASSERT(!"Unrecognized motion operator");
}
GPOS_ASSERT(nullptr != pdrgpi);
return pdrgpi;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::GetInputSegIdsArray
//
// @doc:
// Construct an array with input segment indices for the given Motion
// expression.
//
//---------------------------------------------------------------------------
IntPtrArray *
CTranslatorExprToDXL::GetInputSegIdsArray(CExpression *pexprMotion)
{
GPOS_ASSERT(1 == pexprMotion->Arity());
// derive the distribution of child expression
CExpression *pexprChild = (*pexprMotion)[0];
CDrvdPropPlan *pdpplan = CDrvdPropPlan::Pdpplan(pexprChild->PdpDerive());
CDistributionSpec *pds = pdpplan->Pds();
if (CDistributionSpec::EdtSingleton == pds->Edt() ||
CDistributionSpec::EdtStrictSingleton == pds->Edt())
{
IntPtrArray *pdrgpi = GPOS_NEW(m_mp) IntPtrArray(m_mp);
INT iSegmentId = m_iMasterId;
CDistributionSpecSingleton *pdss =
CDistributionSpecSingleton::PdssConvert(pds);
if (!pdss->FOnMaster())
{
// non-master singleton is currently fixed to the first segment
iSegmentId = *((*m_pdrgpiSegments)[0]);
}
pdrgpi->Append(GPOS_NEW(m_mp) INT(iSegmentId));
return pdrgpi;
}
if (CUtils::FDuplicateHazardMotion(pexprMotion) ||
CDistributionSpec::EdtTaintedReplicated == pds->Edt())
{
// if Motion is duplicate-hazard, we have to read from one input segment
// to avoid generating duplicate values
//
// Additionally, if the child distribution is tainted-replicated, the
// motion (which cannot be a result hash filter node) will read the
// input from one segment in order to ensure that data is consistent
// after bring read from operator delivering tainted replication.
IntPtrArray *pdrgpi = GPOS_NEW(m_mp) IntPtrArray(m_mp);
INT iSegmentId = *((*m_pdrgpiSegments)[0]);
pdrgpi->Append(GPOS_NEW(m_mp) INT(iSegmentId));
return pdrgpi;
}
m_pdrgpiSegments->AddRef();
return m_pdrgpiSegments;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorExprToDXL::UlPosInArray
//
// @doc:
// Find position of colref in the array
//
//---------------------------------------------------------------------------
ULONG
CTranslatorExprToDXL::UlPosInArray(const CColRef *colref,
const CColRefArray *colref_array)
{
GPOS_ASSERT(nullptr != colref_array);
GPOS_ASSERT(nullptr != colref);
const ULONG size = colref_array->Size();
for (ULONG ul = 0; ul < size; ul++)
{
if (colref == (*colref_array)[ul])
{
return ul;
}
}
// not found
return size;
}
// A wrapper around CTranslatorExprToDXLUtils::PdxlnResult to check if the project list imposes a motion hazard,
// eventually leading to a deadlock. If yes, add a Materialize on the Result child to break the deadlock cycle
CDXLNode *
CTranslatorExprToDXL::PdxlnResult(CDXLPhysicalProperties *dxl_properties,
CDXLNode *pdxlnPrL, CDXLNode *child_dxlnode)
{
CDXLNode *pdxlnMaterialize = nullptr;
CDXLNode *pdxlnScalarOneTimeFilter = GPOS_NEW(m_mp)
CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarOneTimeFilter(m_mp));
// If the result project list contains a subplan with a Broadcast motion,
// along with other projections from the result's child node with a motion as well,
// it may result in a deadlock. In such cases, add a materialize node.
if (FNeedsMaterializeUnderResult(pdxlnPrL, child_dxlnode))
{
pdxlnMaterialize = PdxlnMaterialize(child_dxlnode);
}
return CTranslatorExprToDXLUtils::PdxlnResult(
m_mp, dxl_properties, pdxlnPrL, PdxlnFilter(nullptr),
pdxlnScalarOneTimeFilter,
pdxlnMaterialize ? pdxlnMaterialize : child_dxlnode);
}
CDXLNode *
CTranslatorExprToDXL::PdxlnMaterialize(
CDXLNode *dxlnode // node that needs to be materialized
)
{
GPOS_ASSERT(nullptr != dxlnode);
GPOS_ASSERT(nullptr != dxlnode->GetProperties());
CDXLPhysicalMaterialize *pdxlopMaterialize =
GPOS_NEW(m_mp) CDXLPhysicalMaterialize(m_mp, true /* fEager */);
CDXLNode *pdxlnMaterialize =
GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopMaterialize);
CDXLPhysicalProperties *pdxlpropChild =
CDXLPhysicalProperties::PdxlpropConvert(dxlnode->GetProperties());
pdxlpropChild->AddRef();
pdxlnMaterialize->SetProperties(pdxlpropChild);
// construct an empty filter node
CDXLNode *filter_dxlnode = PdxlnFilter(nullptr /* pdxlnCond */);
CDXLNode *pdxlnProjListChild = (*dxlnode)[0];
CDXLNode *proj_list_dxlnode =
CTranslatorExprToDXLUtils::PdxlnProjListFromChildProjList(
m_mp, m_pcf, m_phmcrdxln, pdxlnProjListChild);
// add children
pdxlnMaterialize->AddChild(proj_list_dxlnode);
pdxlnMaterialize->AddChild(filter_dxlnode);
pdxlnMaterialize->AddChild(dxlnode);
return pdxlnMaterialize;
}
BOOL
CTranslatorExprToDXL::FNeedsMaterializeUnderResult(CDXLNode *proj_list_dxlnode,
CDXLNode *child_dxlnode)
{
if (GPOS_FTRACE(EopttraceMotionHazardHandling))
{
// If motion hazard handling is enabled then optimization framework has
// already handled this, hence no materialize is needed in this case.
return false;
}
BOOL fMotionHazard = false;
// if there is no subplan with a broadcast motion in the project list,
// then don't bother checking for motion hazard
BOOL fPrjListContainsSubplan =
CTranslatorExprToDXLUtils::FProjListContainsSubplanWithBroadCast(
proj_list_dxlnode);
if (fPrjListContainsSubplan)
{
CBitSet *pbsScIdentColIds = GPOS_NEW(m_mp) CBitSet(m_mp);
// recurse into project elements to extract out columns ids of scalar idents
CTranslatorExprToDXLUtils::ExtractIdentColIds(proj_list_dxlnode,
pbsScIdentColIds);
// result node will impose motion hazard only if it projects a Subplan
// and an Ident produced by a tree that contains a motion
if (pbsScIdentColIds->Size() > 0)
{
// motions which can impose a hazard
gpdxl::Edxlopid rgeopid[] = {
EdxlopPhysicalMotionBroadcast,
EdxlopPhysicalMotionRedistribute,
EdxlopPhysicalMotionRandom,
};
fMotionHazard = CTranslatorExprToDXLUtils::FMotionHazard(
m_mp, child_dxlnode, rgeopid, GPOS_ARRAY_SIZE(rgeopid),
pbsScIdentColIds);
}
pbsScIdentColIds->Release();
}
return fMotionHazard;
}
// EOF
相关信息
相关文章
greenplumn CTranslatorDXLToExpr 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦