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 */
3030
3131
3232static TupleTableSlot * ValuesNext (ValuesScanState * node );
33- static void ExecMakeValuesResult (List * targetlist ,
34- ExprContext * econtext ,
35- TupleTableSlot * slot );
3633
3734
3835/* ----------------------------------------------------------------
@@ -61,7 +58,7 @@ ValuesNext(ValuesScanState *node)
6158estate = node -> ss .ps .state ;
6259direction = estate -> es_direction ;
6360slot = 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)
8582exprlist = 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- 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-
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 */
12791ExecClearTuple (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+ 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 );
147153}
148154
149- MemoryContextSwitchTo (oldContext );
150-
151- /*
152- * And return the virtual tuple.
153- */
154- ExecStoreVirtualTuple (slot );
155+ return slot ;
155156}
156157
157158
@@ -186,7 +187,6 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
186187ListCell * vtl ;
187188int i ;
188189PlanState * 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 */
209207planstate = & 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 ;
210216ExecAssignExprContext (estate ,planstate );
211- econtext = planstate -> ps_ExprContext ;
212217
213218#define VALUESSCAN_NSLOTS 2
214219
@@ -282,9 +287,11 @@ void
282287ExecEndValuesScan (ValuesScanState * node )
283288{
284289/*
285- * Freethe exprcontext
290+ * Freeboth exprcontexts
286291 */
287292ExecFreeExprContext (& node -> ss .ps );
293+ node -> ss .ps .ps_ExprContext = node -> rowcontext ;
294+ ExecFreeExprContext (& node -> ss .ps );
288295
289296/*
290297 * clean out the tuple table