You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudberry.apache.org by ma...@apache.org on 2024/12/24 08:13:28 UTC
(cloudberry) 03/11: Adds Orca support for Dynamic Table Scan
This is an automated email from the ASF dual-hosted git repository.
maxyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git
commit ef95449dba27cea8c81069f5e888c53ec1f4101b
Author: Chris Hajas <ch...@vmware.com>
AuthorDate: Mon May 23 14:47:03 2022 -0700
Adds Orca support for Dynamic Table Scan
---
src/backend/executor/execDynamicScan.c | 158 ---------------------
src/backend/executor/nodeDynamicSeqscan.c | 148 ++++++++-----------
.../gpopt/translate/CTranslatorDXLToPlStmt.cpp | 33 ++++-
.../src/translate/CTranslatorExprToDXL.cpp | 154 +++-----------------
.../dxl/operators/CDXLPhysicalDynamicTableScan.h | 21 ++-
.../dxl/parser/CParseHandlerDynamicTableScan.h | 6 +-
.../src/operators/CDXLPhysicalDynamicTableScan.cpp | 57 +++-----
.../src/parser/CParseHandlerDynamicTableScan.cpp | 30 ++--
src/include/executor/execDynamicScan.h | 28 ----
9 files changed, 163 insertions(+), 472 deletions(-)
diff --git a/src/backend/executor/execDynamicScan.c b/src/backend/executor/execDynamicScan.c
deleted file mode 100644
index d0496f2e50..0000000000
--- a/src/backend/executor/execDynamicScan.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * execDynamicScan.c
- * Support routines for iterating through dynamically chosen partitions of a relation
- *
- * Portions Copyright (c) 2014-Present VMware, Inc. or its affiliates.
- *
- *
- * IDENTIFICATION
- * src/backend/executor/execDynamicScan.c
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "cdb/partitionselection.h"
-#include "executor/executor.h"
-#include "executor/execDynamicScan.h"
-#include "parser/parsetree.h"
-
-/*
- * isDynamicScan
- * Returns true if the scan node is dynamic (i.e., determining
- * relations to scan at runtime).
- */
-bool
-isDynamicScan(const Plan *plan)
-{
- switch (nodeTag(plan))
- {
- case T_DynamicSeqScan:
- case T_DynamicIndexScan:
- case T_DynamicBitmapHeapScan:
- case T_DynamicBitmapIndexScan:
- return true;
-
- default:
- return false;
- }
-}
-
-/*
- * DynamicScan_GetDynamicScanId
- * Returns the index into EState->dynamicTableScanInfo arrays for this
- * dynamic scan node.
- */
-static int
-DynamicScan_GetDynamicScanId(Plan *plan)
-{
- switch (nodeTag(plan))
- {
- case T_DynamicSeqScan:
- return ((DynamicSeqScan *) plan)->partIndex;
-
- case T_DynamicIndexScan:
- return ((DynamicIndexScan *) plan)->partIndex;
-
- case T_DynamicBitmapHeapScan:
- return ((DynamicBitmapHeapScan *) plan)->partIndex;
-
- case T_DynamicBitmapIndexScan:
- return ((DynamicBitmapIndexScan *) plan)->partIndex;
-
- default:
- elog(ERROR, "unknown dynamic scan node type %u", nodeTag(plan));
- }
-}
-
-/*
- * DynamicScan_GetDynamicScanIdPrintable
- * Return "printable" scan id for a node, for EXPLAIN
- */
-int
-DynamicScan_GetDynamicScanIdPrintable(Plan *plan)
-{
- switch (nodeTag(plan))
- {
- case T_DynamicSeqScan:
- return ((DynamicSeqScan *) plan)->partIndexPrintable;
-
- case T_DynamicIndexScan:
- return ((DynamicIndexScan *) plan)->partIndexPrintable;
-
- case T_DynamicBitmapHeapScan:
- return ((DynamicBitmapHeapScan *) plan)->partIndexPrintable;
-
- case T_DynamicBitmapIndexScan:
- return ((DynamicBitmapIndexScan *) plan)->partIndexPrintable;
-
- default:
- elog(ERROR, "unknown dynamic scan node type %u", nodeTag(plan));
- }
-}
-
-/*
- * DynamicScan_GetTableOid
- * Returns the Oid of the table/partition to scan.
- *
- * A partition must have been selected already.
- */
-Oid
-DynamicScan_GetTableOid(ScanState *scanState)
-{
- int partIndex;
- Oid curRelOid;
-
- partIndex = DynamicScan_GetDynamicScanId(scanState->ps.plan);
-
- /* Get the oid of the current relation */
- Assert(NULL != scanState->ps.state->dynamicTableScanInfo);
- Assert(partIndex <= scanState->ps.state->dynamicTableScanInfo->numScans);
-
- curRelOid = scanState->ps.state->dynamicTableScanInfo->curRelOids[partIndex - 1];
- if (!OidIsValid(curRelOid))
- elog(ERROR, "no partition selected for dynamic scan id %d", partIndex);
-
- return curRelOid;
-}
-
-/*
- * DynamicScan_SetTableOid
- * Select a partition to scan in a dynamic scan.
- *
- * This is used to advertise the selected partition in EState->dynamicTableScanInfo.
- */
-void
-DynamicScan_SetTableOid(ScanState *scanState, Oid curRelOid)
-{
- int partIndex;
-
- partIndex = DynamicScan_GetDynamicScanId(scanState->ps.plan);
-
- Assert(NULL != scanState->ps.state->dynamicTableScanInfo);
- Assert(partIndex <= scanState->ps.state->dynamicTableScanInfo->numScans);
-
- scanState->ps.state->dynamicTableScanInfo->curRelOids[partIndex - 1] = curRelOid;
-}
-
-/*
- * DynamicScan_RemapExpression
- * Re-maps the expression using the provided attMap.
- */
-bool
-DynamicScan_RemapExpression(ScanState *scanState, AttrNumber *attMap, Node *expr)
-{
- if (!isDynamicScan(scanState->ps.plan))
- {
- return false;
- }
-
- if (NULL != attMap)
- {
- change_varattnos_of_a_varno((Node*)expr, attMap, ((Scan *)scanState->ps.plan)->scanrelid);
- return true;
- }
-
- return false;
-}
diff --git a/src/backend/executor/nodeDynamicSeqscan.c b/src/backend/executor/nodeDynamicSeqscan.c
index 9a0d31fc1a..717a1849a4 100644
--- a/src/backend/executor/nodeDynamicSeqscan.c
+++ b/src/backend/executor/nodeDynamicSeqscan.c
@@ -8,13 +8,11 @@
* DynamicSeqScan node scans each relation one after the other. For each
* relation, it opens the table, scans the tuple, and returns relevant tuples.
*
- * GPDB_12_MERGE_FIXME: This is currently disabled altogether. If it is
- * resurrected, some changes are needed to GPORCA. The way Partition
- * Selectors work has been heavily rewritten, there's no global hash table
- * of selected partitions anymore. For "static selection", there's a
- * partOids field in the DynamicSeqScan plan node that holds the selected
- * partitions; but none of the code in this file has been fixed to
- * actually work that way. Same with all the other Dynamic*Scan nodes.
+ * This has a smaller plan size than using an append with many partitions.
+ * Instead of determining the column mapping for each partition during planning,
+ * this mapping is determined during execution. When there are many partitions
+ * with many columns, the plan size improvement becomes very large, on the order of
+ * 100+ MB in some cases.
*
* Portions Copyright (c) 2012 - present, EMC/Greenplum
* Portions Copyright (c) 2012-Present VMware, Inc. or its affiliates.
@@ -30,81 +28,16 @@
#include "executor/executor.h"
#include "executor/instrument.h"
#include "nodes/execnodes.h"
-#include "nodes/nodeFuncs.h"
-#include "executor/execDynamicScan.h"
+#include "executor/execPartition.h"
#include "executor/nodeDynamicSeqscan.h"
#include "executor/nodeSeqscan.h"
-#include "utils/hsearch.h"
-#include "parser/parsetree.h"
#include "utils/memutils.h"
#include "utils/rel.h"
-#include "cdb/cdbvars.h"
#include "access/table.h"
#include "access/tableam.h"
static void CleanupOnePartition(DynamicSeqScanState *node);
-/*
- * During attribute re-mapping for heterogeneous partitions, we use
- * this struct to identify which varno's attributes will be re-mapped.
- * Using this struct as a *context* during expression tree walking, we
- * can skip varattnos that do not belong to a given varno.
- */
-typedef struct AttrMapContext
-{
- const AttrNumber *newattno; /* The mapping table to remap the varattno */
- Index varno; /* Which rte's varattno to re-map */
-} AttrMapContext;
-
-/*
- * Remaps the varattno of a varattno in a Var node using an attribute map.
- */
-static bool
-change_varattnos_varno_walker(Node *node, const AttrMapContext *attrMapCxt)
-{
- if (node == NULL)
- return false;
- if (IsA(node, Var))
- {
- Var *var = (Var *) node;
-
- if (var->varlevelsup == 0 && (var->varno == attrMapCxt->varno) &&
- var->varattno > 0)
- {
- /*
- * ??? the following may be a problem when the node is multiply
- * referenced though stringToNode() doesn't create such a node
- * currently.
- */
- Assert(attrMapCxt->newattno[var->varattno - 1] > 0);
- var->varattno = var->varoattno = attrMapCxt->newattno[var->varattno - 1];
- }
- return false;
- }
- return expression_tree_walker(node, change_varattnos_varno_walker,
- (void *) attrMapCxt);
-}
-
-/*
- * Replace varattno values for a given varno RTE index in an expression
- * tree according to the given map array, that is, varattno N is replaced
- * by newattno[N-1]. It is caller's responsibility to ensure that the array
- * is long enough to define values for all user varattnos present in the tree.
- * System column attnos remain unchanged.
- *
- * Note that the passed node tree is modified in-place!
- */
-static void
-change_varattnos_of_a_varno(Node *node, const AttrNumber *newattno, Index varno)
-{
- AttrMapContext attrMapCxt;
-
- attrMapCxt.newattno = newattno;
- attrMapCxt.varno = varno;
-
- (void) change_varattnos_varno_walker(node, &attrMapCxt);
-}
-
DynamicSeqScanState *
ExecInitDynamicSeqScan(DynamicSeqScan *node, EState *estate, int eflags)
{
@@ -120,7 +53,7 @@ ExecInitDynamicSeqScan(DynamicSeqScan *node, EState *estate, int eflags)
state->ss.ps.plan = (Plan *) node;
state->ss.ps.state = estate;
state->ss.ps.ExecProcNode = ExecDynamicSeqScan;
-
+ state->did_pruning = false;
state->scan_state = SCAN_INIT;
/* Initialize child expressions. This is needed to find subplans. */
@@ -150,6 +83,8 @@ ExecInitDynamicSeqScan(DynamicSeqScan *node, EState *estate, int eflags)
state->scanrelid = node->seqscan.scanrelid;
+ state->as_prune_state = NULL;
+
/*
* This context will be reset per-partition to free up per-partition
* qual and targetlist allocations
@@ -159,7 +94,6 @@ ExecInitDynamicSeqScan(DynamicSeqScan *node, EState *estate, int eflags)
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
-
return state;
}
@@ -190,6 +124,13 @@ initNextTableToScan(DynamicSeqScanState *node)
else
return false;
+ /* Collect number of partitions scanned in EXPLAIN ANALYZE */
+ if (NULL != scanState->ps.instrument)
+ {
+ Instrumentation *instr = scanState->ps.instrument;
+ instr->numPartScanned++;
+ }
+
currentRelation = scanState->ss_currentRelation =
table_open(node->partOids[node->whichPart], AccessShareLock);
@@ -211,11 +152,6 @@ initNextTableToScan(DynamicSeqScanState *node)
/* If attribute remapping is not necessary, then do not change the varattno */
if (attMap)
{
- /*
- * FIXME: Ewww, this doesn't really belong in the executor. The optimizer
- * really should explicitly pass a qual and a tlist to us, for each
- * partition
- */
change_varattnos_of_a_varno((Node*)scanState->ps.plan->qual, attMap, node->scanrelid);
change_varattnos_of_a_varno((Node*)scanState->ps.plan->targetlist, attMap, node->scanrelid);
@@ -227,9 +163,9 @@ initNextTableToScan(DynamicSeqScanState *node)
}
/*
- * For the very first partition, the targetlist of planstate is set to null. So, we must
- * initialize quals and targetlist, regardless of remapping requirements. For later
- * partitions, we only initialize quals and targetlist if a column re-mapping is necessary.
+ * For the very first partition, the qual of planstate is set to null. So, we must
+ * initialize quals, regardless of remapping requirements. For later
+ * partitions, we only initialize quals if a column re-mapping is necessary.
*/
if (attMap || node->firstPartition)
{
@@ -247,7 +183,6 @@ initNextTableToScan(DynamicSeqScanState *node)
if (attMap)
pfree(attMap);
-// DynamicScan_SetTableOid(&node->ss, *pid);
node->seqScanState = ExecInitSeqScanForPartition(&plan->seqscan, estate,
currentRelation);
return true;
@@ -260,6 +195,33 @@ ExecDynamicSeqScan(PlanState *pstate)
DynamicSeqScanState *node = castNode(DynamicSeqScanState, pstate);
TupleTableSlot *slot = NULL;
+ DynamicSeqScan *plan = (DynamicSeqScan *) node->ss.ps.plan;
+ node->as_valid_subplans = NULL;
+ if (NULL != plan->join_prune_paramids && !node->did_pruning)
+ {
+ node->did_pruning = true;
+ node->as_valid_subplans =
+ ExecFindMatchingSubPlans(node->as_prune_state,
+ node->ss.ps.state,
+ list_length(plan->partOids),
+ plan->join_prune_paramids);
+
+ int i = 0;
+ int partOidIdx = -1;
+ List *newPartOids = NIL;
+ ListCell *lc;
+ for(i = 0; i < bms_num_members(node->as_valid_subplans); i++)
+ {
+ partOidIdx = bms_next_member(node->as_valid_subplans, partOidIdx);
+ newPartOids = lappend_oid(newPartOids, node->partOids[partOidIdx]);
+ }
+
+ node->partOids = palloc(sizeof(Oid) * list_length(newPartOids));
+ foreach_with_count(lc, newPartOids, i)
+ node->partOids[i] = lfirst_oid(lc);
+ node->nOids = list_length(newPartOids);
+ }
+
/*
* Scan the table to find next tuple to return. If the current table
* is finished, close it and open the next table for scan.
@@ -337,5 +299,21 @@ ExecReScanDynamicSeqScan(DynamicSeqScanState *node)
{
DynamicSeqScanEndCurrentScan(node);
- /* Force reloading the partition hash table */
+ // reset partition internal state
+
+ /*
+ * If any PARAM_EXEC Params used in pruning expressions have changed, then
+ * we'd better unset the valid subplans so that they are reselected for
+ * the new parameter values.
+ */
+ if (node->as_prune_state &&
+ bms_overlap(node->ss.ps.chgParam,
+ node->as_prune_state->execparamids))
+ {
+ bms_free(node->as_valid_subplans);
+ node->as_valid_subplans = NULL;
+ }
+
+ node->whichPart = -1;
+
}
diff --git a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp
index d443c7bd19..7ddfcfccaf 100644
--- a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp
+++ b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp
@@ -4054,9 +4054,36 @@ CTranslatorDXLToPlStmt::TranslateDXLDynTblScan(
DynamicSeqScan *dyn_seq_scan = MakeNode(DynamicSeqScan);
dyn_seq_scan->seqscan.scanrelid = index;
- dyn_seq_scan->partIndex = dyn_tbl_scan_dxlop->GetPartIndexId();
- dyn_seq_scan->partIndexPrintable =
- dyn_tbl_scan_dxlop->GetPartIndexIdPrintable();
+
+ IMdIdArray *parts = dyn_tbl_scan_dxlop->GetParts();
+
+ List *oids_list = NIL;
+
+ for (ULONG ul = 0; ul < parts->Size(); ul++)
+ {
+ Oid part = CMDIdGPDB::CastMdid((*parts)[ul])->Oid();
+ oids_list = gpdb::LAppendOid(oids_list, part);
+ }
+
+ dyn_seq_scan->partOids = oids_list;
+
+ dyn_seq_scan->join_prune_paramids = NIL;
+
+ OID oid_type =
+ CMDIdGPDB::CastMdid(m_md_accessor->PtMDType<IMDTypeInt4>()->MDId())
+ ->Oid();
+
+ const ULongPtrArray *selector_ids = dyn_tbl_scan_dxlop->GetSelectorIds();
+
+ for (ULONG ul = 0; ul < selector_ids->Size(); ++ul)
+ {
+ ULONG selector_id = *(*selector_ids)[ul];
+ ULONG param_id = m_dxl_to_plstmt_context->GetParamIdForSelector(
+ oid_type, selector_id);
+ dyn_seq_scan->join_prune_paramids =
+ gpdb::LAppendInt(dyn_seq_scan->join_prune_paramids, param_id);
+ }
+
Plan *plan = &(dyn_seq_scan->seqscan.plan);
plan->plan_node_id = m_dxl_to_plstmt_context->GetNextPlanId();
diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp
index b322ac5595..bca5ff694a 100644
--- a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp
+++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp
@@ -1358,9 +1358,26 @@ CTranslatorExprToDXL::PdxlnDynamicTableScan(
}
// 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, 0 /* CHRIS */, popDTS->ScanId());
+ 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);
@@ -1390,139 +1407,6 @@ CTranslatorExprToDXL::PdxlnDynamicTableScan(
pdrgpdsBaseTables->Append(pds);
return pdxlnDTS;
-
- /*
- GPOS_ASSERT(nullptr != pexprDTS);
- GPOS_ASSERT_IFF(nullptr != pexprScalarCond, nullptr != dxl_properties);
-
- CPhysicalDynamicTableScan *popDTS =
- CPhysicalDynamicTableScan::PopConvert(pexprDTS->Pop());
-
- 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()));
- }
- }
-
- // 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();
- }
- GPOS_ASSERT(nullptr != pexprDTS->Prpp());
-
- // construct projection list for top-level Append node
- CColRefSet *pcrsOutput = pexprDTS->Prpp()->PcrsRequired();
- CDXLNode *pdxlnPrLAppend = PdxlnProjList(pcrsOutput, colref_array);
- CDXLTableDescr *root_dxl_table_descr = MakeDXLTableDescr(
- popDTS->Ptabdesc(), popDTS->PdrgpcrOutput(), pexprDTS->Prpp());
-
- // Construct the Append node - even when there is only one child partition.
- // This is done for two reasons:
- // * Dynamic partition pruning
- // Even if one partition is present in the statically pruned plan, we could
- // still dynamically prune it away. This needs an Append node.
- // * Col mappings issues
- // When the first selected child partition's cols have different types/order
- // than the root partition, we can no longer re-use the colrefs of the root
- // partition, since colrefs are immutable. Thus, we create new colrefs for
- // this partition. But, if there is no Append (in case of just one selected
- // partition), then we also go through update all references above the DTS
- // with the new colrefs. For simplicity, we decided to keep the Append
- // around to maintain this projection (mapping) from the old root colrefs
- // to the first selected partition colrefs.
- //
- // GPDB_12_MERGE_FIXME: An Append on a single TableScan can be removed in
- // CTranslatorDXLToPlstmt since these points do not apply there.
- CDXLNode *pdxlnAppend = GPOS_NEW(m_mp) CDXLNode(
- m_mp,
- GPOS_NEW(m_mp) CDXLPhysicalAppend(m_mp, false, false, popDTS->ScanId(),
- root_dxl_table_descr, selector_ids));
- pdxlnAppend->SetProperties(pdxlpropDTS);
- pdxlnAppend->AddChild(pdxlnPrLAppend);
- pdxlnAppend->AddChild(PdxlnFilter(nullptr));
-
- IMdIdArray *part_mdids = popDTS->GetPartitionMdids();
- for (ULONG ul = 0; ul < part_mdids->Size(); ++ul)
- {
- IMDId *part_mdid = (*part_mdids)[ul];
- const IMDRelation *part = m_pmda->RetrieveRel(part_mdid);
-
- CTableDescriptor *part_tabdesc =
- MakeTableDescForPart(part, popDTS->Ptabdesc());
-
- // Create new colrefs for the child partition. The ColRefs from root
- // DTS, which may be used in any parent node, can no longer be exported
- // by a child of the Append node. Thus it is exported by the Append
- // node itself, and new colrefs are created here.
- CColRefArray *part_colrefs = GPOS_NEW(m_mp) CColRefArray(m_mp);
- for (ULONG ul_col = 0; ul_col < part_tabdesc->ColumnCount(); ++ul_col)
- {
- const CColumnDescriptor *cd = part_tabdesc->Pcoldesc(ul_col);
- CColRef *cr = m_pcf->PcrCreate(cd->RetrieveType(),
- cd->TypeModifier(), cd->Name());
- part_colrefs->Append(cr);
- }
-
- CDXLTableDescr *dxl_table_descr =
- MakeDXLTableDescr(part_tabdesc, part_colrefs, pexprDTS->Prpp());
- part_tabdesc->Release();
-
- CDXLNode *dxlnode = GPOS_NEW(m_mp) CDXLNode(
- m_mp, GPOS_NEW(m_mp) CDXLPhysicalTableScan(m_mp, dxl_table_descr));
-
- // GPDB_12_MERGE_FIXME: Compute stats & properties per scan
- pdxlpropDTS->AddRef();
- dxlnode->SetProperties(pdxlpropDTS);
-
- // ColRef -> index in child table desc (per partition)
- auto root_col_mapping = (*popDTS->GetRootColMappingPerPart())[ul];
-
- // construct projection list, re-ordered to match root DTS
- CDXLNode *pdxlnPrL = PdxlnProjListForChildPart(
- root_col_mapping, part_colrefs, pcrsOutput, colref_array);
- dxlnode->AddChild(pdxlnPrL); // project list
-
- // construct the filter
- CDXLNode *filter_dxlnode = PdxlnFilter(
- PdxlnCondForChildPart(root_col_mapping, part_colrefs,
- popDTS->PdrgpcrOutput(), pexprScalarCond));
- dxlnode->AddChild(filter_dxlnode); // filter
-
- // add to the other scans under the created Append node
- pdxlnAppend->AddChild(dxlnode);
-
- // cleanup
- part_colrefs->Release();
- }
-
- CDistributionSpec *pds = pexprDTS->GetDrvdPropPlan()->Pds();
- pds->AddRef();
- pdrgpdsBaseTables->Append(pds);
-
- GPOS_ASSERT(pdxlnAppend);
- return pdxlnAppend;
-
- */
}
//---------------------------------------------------------------------------
diff --git a/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLPhysicalDynamicTableScan.h b/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLPhysicalDynamicTableScan.h
index f0b46d9b3f..786659e3af 100644
--- a/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLPhysicalDynamicTableScan.h
+++ b/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLPhysicalDynamicTableScan.h
@@ -44,19 +44,17 @@ private:
// table descriptor for the scanned table
CDXLTableDescr *m_dxl_table_descr;
- // id of partition index structure
- ULONG m_part_index_id;
+ IMdIdArray *m_part_mdids;
- // printable partition index id
- ULONG m_part_index_id_printable;
+ ULongPtrArray *m_selector_ids = nullptr;
public:
CDXLPhysicalDynamicTableScan(CDXLPhysicalDynamicTableScan &) = delete;
// ctor
CDXLPhysicalDynamicTableScan(CMemoryPool *mp, CDXLTableDescr *table_descr,
- ULONG part_idx_id,
- ULONG part_idx_id_printable);
+ IMdIdArray *part_mdids,
+ ULongPtrArray *selector_ids);
// dtor
~CDXLPhysicalDynamicTableScan() override;
@@ -70,12 +68,13 @@ public:
// table descriptor
const CDXLTableDescr *GetDXLTableDescr() const;
- // partition index id
- ULONG GetPartIndexId() const;
-
- // printable partition index id
- ULONG GetPartIndexIdPrintable() const;
+ IMdIdArray *GetParts() const;
+ const ULongPtrArray *
+ GetSelectorIds() const
+ {
+ return m_selector_ids;
+ }
// serialize operator in DXL format
void SerializeToDXL(CXMLSerializer *xml_serializer,
const CDXLNode *node) const override;
diff --git a/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/CParseHandlerDynamicTableScan.h b/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/CParseHandlerDynamicTableScan.h
index 8b5b1d6b4a..c3c1969451 100644
--- a/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/CParseHandlerDynamicTableScan.h
+++ b/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/CParseHandlerDynamicTableScan.h
@@ -36,11 +36,7 @@ class CDXLPhysicalDynamicTableScan;
class CParseHandlerDynamicTableScan : public CParseHandlerPhysicalOp
{
private:
- // the id of the partition index structure
- ULONG m_part_index_id;
-
- // printable partition index id
- ULONG m_part_index_id_printable;
+ ULongPtrArray *m_selector_ids;
// process the start of an element
void StartElement(
diff --git a/src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalDynamicTableScan.cpp b/src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalDynamicTableScan.cpp
index f5dc4d0ae1..4731259db0 100644
--- a/src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalDynamicTableScan.cpp
+++ b/src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalDynamicTableScan.cpp
@@ -12,8 +12,10 @@
#include "naucrates/dxl/operators/CDXLPhysicalDynamicTableScan.h"
+#include "naucrates/dxl/CDXLUtils.h"
#include "naucrates/dxl/operators/CDXLNode.h"
#include "naucrates/dxl/xml/CXMLSerializer.h"
+#include "naucrates/md/IMDCacheObject.h"
using namespace gpos;
using namespace gpdxl;
@@ -28,12 +30,13 @@ using namespace gpdxl;
//
//---------------------------------------------------------------------------
CDXLPhysicalDynamicTableScan::CDXLPhysicalDynamicTableScan(
- CMemoryPool *mp, CDXLTableDescr *table_descr, ULONG part_idx_id,
- ULONG part_idx_id_printable)
+ CMemoryPool *mp, CDXLTableDescr *table_descr, IMdIdArray *part_mdids,
+ ULongPtrArray *selector_ids)
: CDXLPhysical(mp),
m_dxl_table_descr(table_descr),
- m_part_index_id(part_idx_id),
- m_part_index_id_printable(part_idx_id_printable)
+ m_part_mdids(part_mdids),
+ m_selector_ids(selector_ids)
+
{
GPOS_ASSERT(nullptr != table_descr);
}
@@ -50,6 +53,8 @@ CDXLPhysicalDynamicTableScan::CDXLPhysicalDynamicTableScan(
CDXLPhysicalDynamicTableScan::~CDXLPhysicalDynamicTableScan()
{
m_dxl_table_descr->Release();
+ m_part_mdids->Release();
+ CRefCount::SafeRelease(m_selector_ids);
}
//---------------------------------------------------------------------------
@@ -95,32 +100,10 @@ CDXLPhysicalDynamicTableScan::GetDXLTableDescr() const
return m_dxl_table_descr;
}
-//---------------------------------------------------------------------------
-// @function:
-// CDXLPhysicalDynamicTableScan::GetPartIndexId
-//
-// @doc:
-// Id of partition index
-//
-//---------------------------------------------------------------------------
-ULONG
-CDXLPhysicalDynamicTableScan::GetPartIndexId() const
-{
- return m_part_index_id;
-}
-
-//---------------------------------------------------------------------------
-// @function:
-// CDXLPhysicalDynamicTableScan::GetPartIndexIdPrintable
-//
-// @doc:
-// Printable partition index id
-//
-//---------------------------------------------------------------------------
-ULONG
-CDXLPhysicalDynamicTableScan::GetPartIndexIdPrintable() const
+IMdIdArray *
+CDXLPhysicalDynamicTableScan::GetParts() const
{
- return m_part_index_id_printable;
+ return m_part_mdids;
}
//---------------------------------------------------------------------------
@@ -139,16 +122,18 @@ CDXLPhysicalDynamicTableScan::SerializeToDXL(CXMLSerializer *xml_serializer,
xml_serializer->OpenElement(
CDXLTokens::GetDXLTokenStr(EdxltokenNamespacePrefix), element_name);
+ CWStringDynamic *serialized_selector_ids =
+ CDXLUtils::Serialize(m_mp, m_selector_ids);
xml_serializer->AddAttribute(
- CDXLTokens::GetDXLTokenStr(EdxltokenPartIndexId), m_part_index_id);
- if (m_part_index_id_printable != m_part_index_id)
- {
- xml_serializer->AddAttribute(
- CDXLTokens::GetDXLTokenStr(EdxltokenPartIndexIdPrintable),
- m_part_index_id_printable);
- }
+ CDXLTokens::GetDXLTokenStr(EdxltokenSelectorIds),
+ serialized_selector_ids);
+ GPOS_DELETE(serialized_selector_ids);
node->SerializePropertiesToDXL(xml_serializer);
node->SerializeChildrenToDXL(xml_serializer);
+ IMDCacheObject::SerializeMDIdList(
+ xml_serializer, m_part_mdids,
+ CDXLTokens::GetDXLTokenStr(EdxltokenPartitions),
+ CDXLTokens::GetDXLTokenStr(EdxltokenPartition));
m_dxl_table_descr->SerializeToDXL(xml_serializer);
xml_serializer->CloseElement(
CDXLTokens::GetDXLTokenStr(EdxltokenNamespacePrefix), element_name);
diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerDynamicTableScan.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerDynamicTableScan.cpp
index 8cfd57a3a4..9c78c4549e 100644
--- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerDynamicTableScan.cpp
+++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerDynamicTableScan.cpp
@@ -16,6 +16,7 @@
#include "naucrates/dxl/operators/CDXLPhysicalDynamicTableScan.h"
#include "naucrates/dxl/parser/CParseHandlerFactory.h"
#include "naucrates/dxl/parser/CParseHandlerFilter.h"
+#include "naucrates/dxl/parser/CParseHandlerMetadataIdList.h"
#include "naucrates/dxl/parser/CParseHandlerProjList.h"
#include "naucrates/dxl/parser/CParseHandlerProperties.h"
#include "naucrates/dxl/parser/CParseHandlerTableDescr.h"
@@ -67,17 +68,10 @@ CParseHandlerDynamicTableScan::StartElement(
str->GetBuffer());
}
- m_part_index_id = CDXLOperatorFactory::ExtractConvertAttrValueToUlong(
- m_parse_handler_mgr->GetDXLMemoryManager(), attrs, EdxltokenPartIndexId,
+ m_selector_ids = CDXLOperatorFactory::ExtractConvertValuesToArray(
+ m_parse_handler_mgr->GetDXLMemoryManager(), attrs, EdxltokenSelectorIds,
EdxltokenPhysicalDynamicTableScan);
- m_part_index_id_printable =
- CDXLOperatorFactory::ExtractConvertAttrValueToUlong(
- m_parse_handler_mgr->GetDXLMemoryManager(), attrs,
- EdxltokenPartIndexIdPrintable, EdxltokenPhysicalDynamicTableScan,
- true, //is_optional
- m_part_index_id);
-
// create child node parsers in reverse order of their expected occurrence
// parse handler for table descriptor
@@ -87,6 +81,13 @@ CParseHandlerDynamicTableScan::StartElement(
m_parse_handler_mgr, this);
m_parse_handler_mgr->ActivateParseHandler(table_descr_parse_handler);
+ CParseHandlerBase *partition_mdids_parse_handler =
+ CParseHandlerFactory::GetParseHandler(
+ m_mp, CDXLTokens::XmlstrToken(EdxltokenMetadataIdList),
+ m_parse_handler_mgr, this);
+ m_parse_handler_mgr->ActivateParseHandler(partition_mdids_parse_handler);
+
+
// parse handler for the filter
CParseHandlerBase *filter_parse_handler =
CParseHandlerFactory::GetParseHandler(
@@ -112,6 +113,7 @@ CParseHandlerDynamicTableScan::StartElement(
this->Append(prop_parse_handler);
this->Append(proj_list_parse_handler);
this->Append(filter_parse_handler);
+ this->Append(partition_mdids_parse_handler);
this->Append(table_descr_parse_handler);
}
@@ -146,16 +148,22 @@ CParseHandlerDynamicTableScan::EndElement(const XMLCh *const, // element_uri,
dynamic_cast<CParseHandlerProjList *>((*this)[1]);
CParseHandlerFilter *filter_parse_handler =
dynamic_cast<CParseHandlerFilter *>((*this)[2]);
+ CParseHandlerMetadataIdList *partition_mdids_parse_handler =
+ dynamic_cast<CParseHandlerMetadataIdList *>((*this)[3]);
CParseHandlerTableDescr *table_descr_parse_handler =
- dynamic_cast<CParseHandlerTableDescr *>((*this)[3]);
+ dynamic_cast<CParseHandlerTableDescr *>((*this)[4]);
// set table descriptor
CDXLTableDescr *table_descr = table_descr_parse_handler->GetDXLTableDescr();
table_descr->AddRef();
+
+ IMdIdArray *mdid_partitions_array =
+ partition_mdids_parse_handler->GetMdIdArray();
+ mdid_partitions_array->AddRef();
CDXLPhysicalDynamicTableScan *dxl_op =
GPOS_NEW(m_mp) CDXLPhysicalDynamicTableScan(
- m_mp, table_descr, m_part_index_id, m_part_index_id_printable);
+ m_mp, table_descr, mdid_partitions_array, m_selector_ids);
m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op);
// set statictics and physical properties
diff --git a/src/include/executor/execDynamicScan.h b/src/include/executor/execDynamicScan.h
deleted file mode 100644
index f41ae5d34c..0000000000
--- a/src/include/executor/execDynamicScan.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*--------------------------------------------------------------------------
- *
- * execDynamicScan.h
- * Definitions and API functions for execDynamicScan.c
- *
- * Copyright (c) 2014-Present VMware, Inc. or its affiliates.
- *
- *
- * IDENTIFICATION
- * src/include/executor/execDynamicScan.h
- *
- *--------------------------------------------------------------------------
- */
-#ifndef EXECDYNAMICSCAN_H
-#define EXECDYNAMICSCAN_H
-
-#include "access/attnum.h"
-#include "nodes/execnodes.h"
-
-extern bool isDynamicScan(const Plan *p);
-extern int DynamicScan_GetDynamicScanIdPrintable(Plan *plan);
-
-extern Oid DynamicScan_GetTableOid(ScanState *scanState);
-extern void DynamicScan_SetTableOid(ScanState *scanState, Oid curRelOid);
-
-extern bool DynamicScan_RemapExpression(ScanState *scanState, AttrNumber *attMap, Node *expr);
-
-#endif /* EXECDYNAMICSCAN_H */
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cloudberry.apache.org
For additional commands, e-mail: commits-help@cloudberry.apache.org