summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Freund2018-11-16 07:10:50 +0000
committerAndres Freund2018-11-16 07:16:41 +0000
commita387a3dff9001225ad571ff2755d139f5bd193b3 (patch)
tree3dac372cd2fa302d2c6cd4ecb4d21d73ca07fd85
parentf92cd7392386147f6a16787c1d5c78d0e9b7cf34 (diff)
Fix slot type assumptions for nodeGather[Merge].
The assumption made in 1a0586de3657c was wrong, as evidenced by buildfarm failure on locust, which runs with force_parallel_mode=regress. The tuples accessed in either nodes are in the outer slot, and we can't trivially rely on the slot type being known because the leader might execute the subsidiary node directly, or via the tuple queue on a worker. In the latter case the tuple will always be a heaptuple slot, but in the former, it'll be whatever the subsidiary node returns.
-rw-r--r--src/backend/executor/nodeGather.c22
-rw-r--r--src/backend/executor/nodeGatherMerge.c14
2 files changed, 31 insertions, 5 deletions
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index e45e07f0a1a..c979a557749 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -91,10 +91,14 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
outerPlanState(gatherstate) = ExecInitNode(outerNode, estate, eflags);
tupDesc = ExecGetResultType(outerPlanState(gatherstate));
- /* this node uses tuples from the tuple queue as scan slot */
- gatherstate->ps.scanops = &TTSOpsHeapTuple;
- gatherstate->ps.scanopsfixed = true;
- gatherstate->ps.scanopsset = true;
+ /*
+ * Leader may access ExecProcNode result directly (if
+ * need_to_scan_locally), or from workers via tuple queue. So we can't
+ * trivially rely on the slot type being fixed for expressions evaluated
+ * within this node.
+ */
+ gatherstate->ps.outeropsset = true;
+ gatherstate->ps.outeropsfixed = false;
/*
* Initialize result type and projection.
@@ -103,6 +107,16 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
ExecConditionalAssignProjectionInfo(&gatherstate->ps, tupDesc, OUTER_VAR);
/*
+ * Without projections result slot type is not trivially known, see
+ * comment above.
+ */
+ if (gatherstate->ps.ps_ProjInfo == NULL)
+ {
+ gatherstate->ps.resultopsset = true;
+ gatherstate->ps.resultopsfixed = false;
+ }
+
+ /*
* Initialize funnel slot to same tuple descriptor as outer plan.
*/
gatherstate->funnel_slot = ExecInitExtraTupleSlot(estate, tupDesc,
diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c
index 651565123be..51d910bd5ee 100644
--- a/src/backend/executor/nodeGatherMerge.c
+++ b/src/backend/executor/nodeGatherMerge.c
@@ -110,6 +110,15 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
outerPlanState(gm_state) = ExecInitNode(outerNode, estate, eflags);
/*
+ * Leader may access ExecProcNode result directly (if
+ * need_to_scan_locally), or from workers via tuple queue. So we can't
+ * trivially rely on the slot type being fixed for expressions evaluated
+ * within this node.
+ */
+ gm_state->ps.outeropsset = true;
+ gm_state->ps.outeropsfixed = false;
+
+ /*
* Store the tuple descriptor into gather merge state, so we can use it
* while initializing the gather merge slots.
*/
@@ -122,7 +131,10 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
ExecInitResultTypeTL(&gm_state->ps);
ExecConditionalAssignProjectionInfo(&gm_state->ps, tupDesc, OUTER_VAR);
- /* leader accesses ExecProcNode result directly, others go through tuple queue */
+ /*
+ * Without projections result slot type is not trivially known, see
+ * comment above.
+ */
if (gm_state->ps.ps_ProjInfo == NULL)
{
gm_state->ps.resultopsset = true;