From a0f4f072aee73ff4053a0148997b433c71d6594e Mon Sep 17 00:00:00 2001 From: roseduan Date: Mon, 20 Jul 2026 08:17:41 +0000 Subject: [PATCH] Feature: dispatch T_CustomScanState in CBDB parallel walkers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three GP-side walkers used during parallel setup — EstimateGpParallelDSMEntrySize, InitializeGpParallelWorkers, InitializeGpParallelDSMEntry — cased on other scan/join states but skipped T_CustomScanState. A parallel_aware CustomScan therefore silently under-sized its DSM and failed to attach in workers, with no diagnostic. Add T_CustomScanState arms that dispatch to ExecCustomScan{Estimate,InitializeDSM,InitializeWorker}, gated on parallel_aware to match the other node types in these switches. Also handle T_CustomScanState in planstate_walk_kids. Upstream planstate_tree_walker walks only css->custom_ps for a CustomScanState; the CBDB walker previously fell through to default (lefttree/righttree), skipping custom_ps children under stateful walkers (cdbexplain_*, getMotionState, ...). The new case walks custom_ps first, then lefttree/righttree if set, with an Assert that a CustomScanState never populates both — otherwise the child would be walked twice. --- src/backend/executor/execParallel.c | 12 ++++++++++++ src/backend/executor/execProcnode.c | 22 ++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index 16c4abe9b76..8d1a72cced7 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -1551,6 +1551,10 @@ EstimateGpParallelDSMEntrySize(PlanState *planstate, ParallelContext *pctx) case T_SortState: ExecSortEstimate((SortState *) planstate, pctx); break; + case T_CustomScanState: + if (planstate->plan->parallel_aware) + ExecCustomScanEstimate((CustomScanState *) planstate, pctx); + break; default: break; @@ -1604,6 +1608,10 @@ InitializeGpParallelWorkers(PlanState *planstate, ParallelWorkerContext *pwcxt) if (planstate->plan->parallel_aware) ExecHashJoinInitializeWorker((HashJoinState *) planstate, pwcxt); break; + case T_CustomScanState: + if (planstate->plan->parallel_aware) + ExecCustomScanInitializeWorker((CustomScanState *) planstate, pwcxt); + break; default: break; } @@ -1662,6 +1670,10 @@ InitializeGpParallelDSMEntry(PlanState *planstate, ParallelContext *pctx) case T_SortState: ExecSortInitializeDSM((SortState *) planstate, pctx); break; + case T_CustomScanState: + if (planstate->plan->parallel_aware) + ExecCustomScanInitializeDSM((CustomScanState *) planstate, pctx); + break; default: break; } diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 3f98f99f267..954ba935de1 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -1295,6 +1295,28 @@ planstate_walk_kids(PlanState *planstate, Assert(!planstate->lefttree && !planstate->righttree); break; + case T_CustomScanState: + { + CustomScanState *css = (CustomScanState *) planstate; + ListCell *lc; + + Assert(!(css->custom_ps != NIL && + (planstate->lefttree || planstate->righttree))); + + v = CdbVisit_Walk; + foreach(lc, css->custom_ps) + { + v = planstate_walk_node_extended((PlanState *) lfirst(lc), walker, context, flags); + if (v != CdbVisit_Walk) + break; + } + if (v == CdbVisit_Walk && planstate->lefttree) + v = planstate_walk_node_extended(planstate->lefttree, walker, context, flags); + if (v == CdbVisit_Walk && planstate->righttree) + v = planstate_walk_node_extended(planstate->righttree, walker, context, flags); + break; + } + default: /* Left subtree */ v = planstate_walk_node_extended(planstate->lefttree, walker, context, flags);