aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-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;