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

Commit0dfb595

Browse files
committed
Arrange for ValuesScan to keep per-sublist expression eval state in a
temporary context that can be reset when advancing to the next sublist.This is faster and more thorough at recovering space than the previousmethod; moreover it will do the right thing if something in the sublisttries to register an expression context callback.
1 parent9649b18 commit0dfb595

File tree

2 files changed

+87
-73
lines changed

2 files changed

+87
-73
lines changed

‎src/backend/executor/nodeValuesscan.c

Lines changed: 77 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/executor/nodeValuesscan.c,v 1.1 2006/08/0201:59:45 joe Exp $
12+
* $PostgreSQL: pgsql/src/backend/executor/nodeValuesscan.c,v 1.2 2006/08/0218:58:21 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -30,9 +30,6 @@
3030

3131

3232
staticTupleTableSlot*ValuesNext(ValuesScanState*node);
33-
staticvoidExecMakeValuesResult(List*targetlist,
34-
ExprContext*econtext,
35-
TupleTableSlot*slot);
3633

3734

3835
/* ----------------------------------------------------------------
@@ -61,7 +58,7 @@ ValuesNext(ValuesScanState *node)
6158
estate=node->ss.ps.state;
6259
direction=estate->es_direction;
6360
slot=node->ss.ss_ScanTupleSlot;
64-
econtext=node->ss.ps.ps_ExprContext;
61+
econtext=node->rowcontext;
6562

6663
/*
6764
* Get the next tuple. Return NULL if no more tuples.
@@ -85,73 +82,77 @@ ValuesNext(ValuesScanState *node)
8582
exprlist=NIL;
8683
}
8784

88-
if (exprlist)
89-
{
90-
List*init_exprlist;
91-
92-
init_exprlist= (List*)ExecInitExpr((Expr*)exprlist,
93-
(PlanState*)node);
94-
ExecMakeValuesResult(init_exprlist,
95-
econtext,
96-
slot);
97-
list_free_deep(init_exprlist);
98-
}
99-
else
100-
ExecClearTuple(slot);
101-
102-
returnslot;
103-
}
104-
105-
/*
106-
*ExecMakeValuesResult
107-
*
108-
* Evaluate a values list, store into a virtual slot.
109-
*/
110-
staticvoid
111-
ExecMakeValuesResult(List*targetlist,
112-
ExprContext*econtext,
113-
TupleTableSlot*slot)
114-
{
115-
MemoryContextoldContext;
116-
Datum*values;
117-
bool*isnull;
118-
ListCell*lc;
119-
intresind=0;
120-
121-
/* caller should have checked all targetlists are the same length */
122-
Assert(list_length(targetlist)==slot->tts_tupleDescriptor->natts);
123-
12485
/*
125-
* Prepare to build a virtual result tuple.
86+
* Always clear the result slot; this is appropriate if we are at the
87+
* end of the data, and if we're not, we still need it as the first step
88+
* of the store-virtual-tuple protocol. It seems wise to clear the slot
89+
* before we reset the context it might have pointers into.
12690
*/
12791
ExecClearTuple(slot);
128-
values=slot->tts_values;
129-
isnull=slot->tts_isnull;
13092

131-
/*
132-
* Switch to short-lived context for evaluating the row.
133-
* Reset per-tuple memory context before each row.
134-
*/
135-
ResetExprContext(econtext);
136-
oldContext=MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
137-
138-
foreach(lc,targetlist)
93+
if (exprlist)
13994
{
140-
ExprState*estate= (ExprState*)lfirst(lc);
141-
142-
values[resind]=ExecEvalExpr(estate,
143-
econtext,
144-
&isnull[resind],
145-
NULL);
146-
resind++;
95+
MemoryContextoldContext;
96+
List*exprstatelist;
97+
Datum*values;
98+
bool*isnull;
99+
ListCell*lc;
100+
intresind;
101+
102+
/*
103+
* Get rid of any prior cycle's leftovers. We use ReScanExprContext
104+
* not just ResetExprContext because we want any registered shutdown
105+
* callbacks to be called.
106+
*/
107+
ReScanExprContext(econtext);
108+
109+
/*
110+
* Build the expression eval state in the econtext's per-tuple
111+
* memory. This is a tad unusual, but we want to delete the eval
112+
* state again when we move to the next row, to avoid growth of
113+
* memory requirements over a long values list.
114+
*/
115+
oldContext=MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
116+
117+
/*
118+
* Pass NULL, not my plan node, because we don't want anything
119+
* in this transient state linking into permanent state. The
120+
* only possibility is a SubPlan, and there shouldn't be any
121+
* (any subselects in the VALUES list should be InitPlans).
122+
*/
123+
exprstatelist= (List*)ExecInitExpr((Expr*)exprlist,NULL);
124+
125+
/* parser should have checked all sublists are the same length */
126+
Assert(list_length(exprstatelist)==slot->tts_tupleDescriptor->natts);
127+
128+
/*
129+
* Compute the expressions and build a virtual result tuple.
130+
* We already did ExecClearTuple(slot).
131+
*/
132+
values=slot->tts_values;
133+
isnull=slot->tts_isnull;
134+
135+
resind=0;
136+
foreach(lc,exprstatelist)
137+
{
138+
ExprState*estate= (ExprState*)lfirst(lc);
139+
140+
values[resind]=ExecEvalExpr(estate,
141+
econtext,
142+
&isnull[resind],
143+
NULL);
144+
resind++;
145+
}
146+
147+
MemoryContextSwitchTo(oldContext);
148+
149+
/*
150+
* And return the virtual tuple.
151+
*/
152+
ExecStoreVirtualTuple(slot);
147153
}
148154

149-
MemoryContextSwitchTo(oldContext);
150-
151-
/*
152-
* And return the virtual tuple.
153-
*/
154-
ExecStoreVirtualTuple(slot);
155+
returnslot;
155156
}
156157

157158

@@ -186,7 +187,6 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
186187
ListCell*vtl;
187188
inti;
188189
PlanState*planstate;
189-
ExprContext*econtext;
190190

191191
/*
192192
* ValuesScan should not have any children.
@@ -203,12 +203,17 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
203203

204204
/*
205205
* Miscellaneous initialization
206-
*
207-
* create expression context for node
208206
*/
209207
planstate=&scanstate->ss.ps;
208+
209+
/*
210+
* Create expression contexts.We need two, one for per-sublist
211+
* processing and one for execScan.c to use for quals and projections.
212+
* We cheat a little by using ExecAssignExprContext() to build both.
213+
*/
214+
ExecAssignExprContext(estate,planstate);
215+
scanstate->rowcontext=planstate->ps_ExprContext;
210216
ExecAssignExprContext(estate,planstate);
211-
econtext=planstate->ps_ExprContext;
212217

213218
#defineVALUESSCAN_NSLOTS 2
214219

@@ -282,9 +287,11 @@ void
282287
ExecEndValuesScan(ValuesScanState*node)
283288
{
284289
/*
285-
* Freethe exprcontext
290+
* Freeboth exprcontexts
286291
*/
287292
ExecFreeExprContext(&node->ss.ps);
293+
node->ss.ps.ps_ExprContext=node->rowcontext;
294+
ExecFreeExprContext(&node->ss.ps);
288295

289296
/*
290297
* clean out the tuple table

‎src/include/nodes/execnodes.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.156 2006/08/0201:59:47 joe Exp $
10+
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.157 2006/08/0218:58:21 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -1044,18 +1044,25 @@ typedef struct FunctionScanState
10441044
/* ----------------
10451045
* ValuesScanState information
10461046
*
1047-
*Values nodes are used to scan the results of a
1048-
*values list appearing in FROM or INSERT
1047+
*ValuesScan nodes are used to scan the results of a VALUES list
10491048
*
1049+
*rowcontextper-expression-list context
10501050
*exprlistsarray of expression lists being evaluated
10511051
*array_lensize of array
10521052
*curr_idxcurrent array index (0-based)
10531053
*marked_idxmarked position (for mark/restore)
1054+
*
1055+
*Note: ss.ps.ps_ExprContext is used to evaluate any qual or projection
1056+
*expressions attached to the node. We create a second ExprContext,
1057+
*rowcontext, in which to build the executor expression state for each
1058+
*Values sublist. Resetting this context lets us get rid of expression
1059+
*state for each row, avoiding major memory leakage over a long values list.
10541060
* ----------------
10551061
*/
10561062
typedefstructValuesScanState
10571063
{
10581064
ScanStatess;/* its first field is NodeTag */
1065+
ExprContext*rowcontext;
10591066
List**exprlists;
10601067
intarray_len;
10611068
intcurr_idx;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp