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 <[email protected]> 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: [email protected] For additional commands, e-mail: [email protected]
