Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8538a63

Browse files
committed
Make Gather node projection-capable.
The original Gather code failed to mark a Gather node as not able todo projection, but it couldn't, even though it did call initialize itsprojection info via ExecAssignProjectionInfo. There doesn't seem tobe any good reason for this node not to have projection capability,so clean things up so that it does. Without this, plans using Gathernodes might need to carry extra Result nodes to do projection.
1 parentc15898c commit8538a63

File tree

3 files changed

+75
-18
lines changed

3 files changed

+75
-18
lines changed

‎src/backend/executor/nodeGather.c

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include"executor/nodeGather.h"
3737
#include"executor/nodeSubplan.h"
3838
#include"executor/tqueue.h"
39+
#include"utils/memutils.h"
3940
#include"utils/rel.h"
4041

4142

@@ -50,6 +51,9 @@ GatherState *
5051
ExecInitGather(Gather*node,EState*estate,inteflags)
5152
{
5253
GatherState*gatherstate;
54+
Plan*outerNode;
55+
boolhasoid;
56+
TupleDesctupDesc;
5357

5458
/* Gather node doesn't have innerPlan node. */
5559
Assert(innerPlan(node)==NULL);
@@ -82,13 +86,14 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
8286
/*
8387
* tuple table initialization
8488
*/
89+
gatherstate->funnel_slot=ExecInitExtraTupleSlot(estate);
8590
ExecInitResultTupleSlot(estate,&gatherstate->ps);
8691

8792
/*
8893
* now initialize outer plan
8994
*/
90-
outerPlanState(gatherstate)=ExecInitNode(outerPlan(node),estate,eflags);
91-
95+
outerNode=outerPlan(node);
96+
outerPlanState(gatherstate)=ExecInitNode(outerNode,estate,eflags);
9297

9398
gatherstate->ps.ps_TupFromTlist= false;
9499

@@ -98,6 +103,14 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
98103
ExecAssignResultTypeFromTL(&gatherstate->ps);
99104
ExecAssignProjectionInfo(&gatherstate->ps,NULL);
100105

106+
/*
107+
* Initialize funnel slot to same tuple descriptor as outer plan.
108+
*/
109+
if (!ExecContextForcesOids(&gatherstate->ps,&hasoid))
110+
hasoid= false;
111+
tupDesc=ExecTypeFromTL(outerNode->targetlist,hasoid);
112+
ExecSetSlotDescriptor(gatherstate->funnel_slot,tupDesc);
113+
101114
returngatherstate;
102115
}
103116

@@ -113,6 +126,9 @@ ExecGather(GatherState *node)
113126
{
114127
inti;
115128
TupleTableSlot*slot;
129+
TupleTableSlot*resultSlot;
130+
ExprDoneCondisDone;
131+
ExprContext*econtext;
116132

117133
/*
118134
* Initialize the parallel context and workers on first execution. We do
@@ -169,7 +185,53 @@ ExecGather(GatherState *node)
169185
node->initialized= true;
170186
}
171187

172-
slot=gather_getnext(node);
188+
/*
189+
* Check to see if we're still projecting out tuples from a previous scan
190+
* tuple (because there is a function-returning-set in the projection
191+
* expressions). If so, try to project another one.
192+
*/
193+
if (node->ps.ps_TupFromTlist)
194+
{
195+
resultSlot=ExecProject(node->ps.ps_ProjInfo,&isDone);
196+
if (isDone==ExprMultipleResult)
197+
returnresultSlot;
198+
/* Done with that source tuple... */
199+
node->ps.ps_TupFromTlist= false;
200+
}
201+
202+
/*
203+
* Reset per-tuple memory context to free any expression evaluation
204+
* storage allocated in the previous tuple cycle. Note we can't do this
205+
* until we're done projecting.
206+
*/
207+
econtext=node->ps.ps_ExprContext;
208+
ResetExprContext(econtext);
209+
210+
/* Get and return the next tuple, projecting if necessary. */
211+
for (;;)
212+
{
213+
/*
214+
* Get next tuple, either from one of our workers, or by running the
215+
* plan ourselves.
216+
*/
217+
slot=gather_getnext(node);
218+
if (TupIsNull(slot))
219+
returnNULL;
220+
221+
/*
222+
* form the result tuple using ExecProject(), and return it --- unless
223+
* the projection produces an empty set, in which case we must loop
224+
* back around for another tuple
225+
*/
226+
econtext->ecxt_outertuple=slot;
227+
resultSlot=ExecProject(node->ps.ps_ProjInfo,&isDone);
228+
229+
if (isDone!=ExprEndResult)
230+
{
231+
node->ps.ps_TupFromTlist= (isDone==ExprMultipleResult);
232+
returnresultSlot;
233+
}
234+
}
173235

174236
returnslot;
175237
}
@@ -201,18 +263,11 @@ ExecEndGather(GatherState *node)
201263
staticTupleTableSlot*
202264
gather_getnext(GatherState*gatherstate)
203265
{
204-
PlanState*outerPlan;
266+
PlanState*outerPlan=outerPlanState(gatherstate);
205267
TupleTableSlot*outerTupleSlot;
206-
TupleTableSlot*slot;
268+
TupleTableSlot*fslot=gatherstate->funnel_slot;
207269
HeapTupletup;
208270

209-
/*
210-
* We can use projection info of Gather for the tuples received from
211-
* worker backends as currently for all cases worker backends sends the
212-
* projected tuple as required by Gather node.
213-
*/
214-
slot=gatherstate->ps.ps_ProjInfo->pi_slot;
215-
216271
while (gatherstate->funnel!=NULL||gatherstate->need_to_scan_locally)
217272
{
218273
if (gatherstate->funnel!=NULL)
@@ -229,19 +284,17 @@ gather_getnext(GatherState *gatherstate)
229284
if (HeapTupleIsValid(tup))
230285
{
231286
ExecStoreTuple(tup,/* tuple to store */
232-
slot,/* slot to storein */
287+
fslot,/* slotin whichto storethe tuple */
233288
InvalidBuffer,/* buffer associated with this
234289
* tuple */
235290
true);/* pfree this pointer if not from heap */
236291

237-
returnslot;
292+
returnfslot;
238293
}
239294
}
240295

241296
if (gatherstate->need_to_scan_locally)
242297
{
243-
outerPlan=outerPlanState(gatherstate);
244-
245298
outerTupleSlot=ExecProcNode(outerPlan);
246299

247300
if (!TupIsNull(outerTupleSlot))
@@ -251,7 +304,7 @@ gather_getnext(GatherState *gatherstate)
251304
}
252305
}
253306

254-
returnExecClearTuple(slot);
307+
returnExecClearTuple(fslot);
255308
}
256309

257310
/* ----------------------------------------------------------------

‎src/backend/optimizer/plan/setrefs.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,12 +602,15 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
602602
set_join_references(root, (Join*)plan,rtoffset);
603603
break;
604604

605+
caseT_Gather:
606+
set_upper_references(root,plan,rtoffset);
607+
break;
608+
605609
caseT_Hash:
606610
caseT_Material:
607611
caseT_Sort:
608612
caseT_Unique:
609613
caseT_SetOp:
610-
caseT_Gather:
611614

612615
/*
613616
* These plan types don't actually bother to evaluate their

‎src/include/nodes/execnodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1964,6 +1964,7 @@ typedef struct GatherState
19641964
boolinitialized;
19651965
structParallelExecutorInfo*pei;
19661966
structTupleQueueFunnel*funnel;
1967+
TupleTableSlot*funnel_slot;
19671968
boolneed_to_scan_locally;
19681969
}GatherState;
19691970

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp