9
9
*
10
10
*
11
11
* IDENTIFICATION
12
- * $PostgreSQL: pgsql/src/backend/executor/nodeValuesscan.c,v 1.1 2006/08/02 01:59:45 joe Exp $
12
+ * $PostgreSQL: pgsql/src/backend/executor/nodeValuesscan.c,v 1.2 2006/08/02 18:58:21 tgl Exp $
13
13
*
14
14
*-------------------------------------------------------------------------
15
15
*/
30
30
31
31
32
32
static TupleTableSlot * ValuesNext (ValuesScanState * node );
33
- static void ExecMakeValuesResult (List * targetlist ,
34
- ExprContext * econtext ,
35
- TupleTableSlot * slot );
36
33
37
34
38
35
/* ----------------------------------------------------------------
@@ -61,7 +58,7 @@ ValuesNext(ValuesScanState *node)
61
58
estate = node -> ss .ps .state ;
62
59
direction = estate -> es_direction ;
63
60
slot = node -> ss .ss_ScanTupleSlot ;
64
- econtext = node -> ss . ps . ps_ExprContext ;
61
+ econtext = node -> rowcontext ;
65
62
66
63
/*
67
64
* Get the next tuple. Return NULL if no more tuples.
@@ -85,73 +82,77 @@ ValuesNext(ValuesScanState *node)
85
82
exprlist = NIL ;
86
83
}
87
84
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
- return slot ;
103
- }
104
-
105
- /*
106
- * ExecMakeValuesResult
107
- *
108
- * Evaluate a values list, store into a virtual slot.
109
- */
110
- static void
111
- ExecMakeValuesResult (List * targetlist ,
112
- ExprContext * econtext ,
113
- TupleTableSlot * slot )
114
- {
115
- MemoryContext oldContext ;
116
- Datum * values ;
117
- bool * isnull ;
118
- ListCell * lc ;
119
- int resind = 0 ;
120
-
121
- /* caller should have checked all targetlists are the same length */
122
- Assert (list_length (targetlist ) == slot -> tts_tupleDescriptor -> natts );
123
-
124
85
/*
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.
126
90
*/
127
91
ExecClearTuple (slot );
128
- values = slot -> tts_values ;
129
- isnull = slot -> tts_isnull ;
130
92
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 )
139
94
{
140
- ExprState * estate = (ExprState * ) lfirst (lc );
141
-
142
- values [resind ] = ExecEvalExpr (estate ,
143
- econtext ,
144
- & isnull [resind ],
145
- NULL );
146
- resind ++ ;
95
+ MemoryContext oldContext ;
96
+ List * exprstatelist ;
97
+ Datum * values ;
98
+ bool * isnull ;
99
+ ListCell * lc ;
100
+ int resind ;
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 );
147
153
}
148
154
149
- MemoryContextSwitchTo (oldContext );
150
-
151
- /*
152
- * And return the virtual tuple.
153
- */
154
- ExecStoreVirtualTuple (slot );
155
+ return slot ;
155
156
}
156
157
157
158
@@ -186,7 +187,6 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
186
187
ListCell * vtl ;
187
188
int i ;
188
189
PlanState * planstate ;
189
- ExprContext * econtext ;
190
190
191
191
/*
192
192
* ValuesScan should not have any children.
@@ -203,12 +203,17 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
203
203
204
204
/*
205
205
* Miscellaneous initialization
206
- *
207
- * create expression context for node
208
206
*/
209
207
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 ;
210
216
ExecAssignExprContext (estate , planstate );
211
- econtext = planstate -> ps_ExprContext ;
212
217
213
218
#define VALUESSCAN_NSLOTS 2
214
219
@@ -282,9 +287,11 @@ void
282
287
ExecEndValuesScan (ValuesScanState * node )
283
288
{
284
289
/*
285
- * Free the exprcontext
290
+ * Free both exprcontexts
286
291
*/
287
292
ExecFreeExprContext (& node -> ss .ps );
293
+ node -> ss .ps .ps_ExprContext = node -> rowcontext ;
294
+ ExecFreeExprContext (& node -> ss .ps );
288
295
289
296
/*
290
297
* clean out the tuple table
0 commit comments