Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * nodeValuesscan.c
4 : * Support routines for scanning Values lists
5 : * ("VALUES (...), (...), ..." in rangetable).
6 : *
7 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : *
11 : * IDENTIFICATION
12 : * src/backend/executor/nodeValuesscan.c
13 : *
14 : *-------------------------------------------------------------------------
15 : */
16 : /*
17 : * INTERFACE ROUTINES
18 : * ExecValuesScan scans a values list.
19 : * ExecValuesNext retrieve next tuple in sequential order.
20 : * ExecInitValuesScan creates and initializes a valuesscan node.
21 : * ExecEndValuesScan releases any storage allocated.
22 : * ExecReScanValuesScan rescans the values list
23 : */
24 : #include "postgres.h"
25 :
26 : #include "executor/executor.h"
27 : #include "executor/nodeValuesscan.h"
28 : #include "utils/expandeddatum.h"
29 :
30 :
31 : static TupleTableSlot *ValuesNext(ValuesScanState *node);
32 :
33 :
34 : /* ----------------------------------------------------------------
35 : * Scan Support
36 : * ----------------------------------------------------------------
37 : */
38 :
39 : /* ----------------------------------------------------------------
40 : * ValuesNext
41 : *
42 : * This is a workhorse for ExecValuesScan
43 : * ----------------------------------------------------------------
44 : */
45 : static TupleTableSlot *
46 32786 : ValuesNext(ValuesScanState *node)
47 : {
48 : TupleTableSlot *slot;
49 : EState *estate;
50 : ExprContext *econtext;
51 : ScanDirection direction;
52 : List *exprlist;
53 :
54 : /*
55 : * get information from the estate and scan state
56 : */
57 32786 : estate = node->ss.ps.state;
58 32786 : direction = estate->es_direction;
59 32786 : slot = node->ss.ss_ScanTupleSlot;
60 32786 : econtext = node->rowcontext;
61 :
62 : /*
63 : * Get the next tuple. Return NULL if no more tuples.
64 : */
65 32786 : if (ScanDirectionIsForward(direction))
66 : {
67 32786 : if (node->curr_idx < node->array_len)
68 32786 : node->curr_idx++;
69 32786 : if (node->curr_idx < node->array_len)
70 22217 : exprlist = node->exprlists[node->curr_idx];
71 : else
72 10569 : exprlist = NIL;
73 : }
74 : else
75 : {
76 0 : if (node->curr_idx >= 0)
77 0 : node->curr_idx--;
78 0 : if (node->curr_idx >= 0)
79 0 : exprlist = node->exprlists[node->curr_idx];
80 : else
81 0 : exprlist = NIL;
82 : }
83 :
84 : /*
85 : * Always clear the result slot; this is appropriate if we are at the end
86 : * of the data, and if we're not, we still need it as the first step of
87 : * the store-virtual-tuple protocol. It seems wise to clear the slot
88 : * before we reset the context it might have pointers into.
89 : */
90 32786 : ExecClearTuple(slot);
91 :
92 32786 : if (exprlist)
93 : {
94 : MemoryContext oldContext;
95 : List *exprstatelist;
96 : Datum *values;
97 : bool *isnull;
98 : ListCell *lc;
99 : int resind;
100 :
101 : /*
102 : * Get rid of any prior cycle's leftovers. We use ReScanExprContext
103 : * not just ResetExprContext because we want any registered shutdown
104 : * callbacks to be called.
105 : */
106 22217 : ReScanExprContext(econtext);
107 :
108 : /*
109 : * Build the expression eval state in the econtext's per-tuple memory.
110 : * This is a tad unusual, but we want to delete the eval state again
111 : * when we move to the next row, to avoid growth of memory
112 : * requirements over a long values list.
113 : */
114 22217 : oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
115 :
116 : /*
117 : * Pass NULL, not my plan node, because we don't want anything in this
118 : * transient state linking into permanent state. The only possibility
119 : * is a SubPlan, and there shouldn't be any (any subselects in the
120 : * VALUES list should be InitPlans).
121 : */
122 22217 : exprstatelist = ExecInitExprList(exprlist, NULL);
123 :
124 : /* parser should have checked all sublists are the same length */
125 22217 : Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
126 :
127 : /*
128 : * Compute the expressions and build a virtual result tuple. We
129 : * already did ExecClearTuple(slot).
130 : */
131 22217 : values = slot->tts_values;
132 22217 : isnull = slot->tts_isnull;
133 :
134 22217 : resind = 0;
135 46150 : foreach(lc, exprstatelist)
136 : {
137 23933 : ExprState *estate = (ExprState *) lfirst(lc);
138 23933 : Form_pg_attribute attr = TupleDescAttr(slot->tts_tupleDescriptor,
139 : resind);
140 :
141 23933 : values[resind] = ExecEvalExpr(estate,
142 : econtext,
143 : &isnull[resind]);
144 :
145 : /*
146 : * We must force any R/W expanded datums to read-only state, in
147 : * case they are multiply referenced in the plan node's output
148 : * expressions, or in case we skip the output projection and the
149 : * output column is multiply referenced in higher plan nodes.
150 : */
151 23933 : values[resind] = MakeExpandedObjectReadOnly(values[resind],
152 : isnull[resind],
153 : attr->attlen);
154 :
155 23933 : resind++;
156 : }
157 :
158 22217 : MemoryContextSwitchTo(oldContext);
159 :
160 : /*
161 : * And return the virtual tuple.
162 : */
163 22217 : ExecStoreVirtualTuple(slot);
164 : }
165 :
166 32786 : return slot;
167 : }
168 :
169 : /*
170 : * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
171 : */
172 : static bool
173 0 : ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
174 : {
175 : /* nothing to check */
176 0 : return true;
177 : }
178 :
179 : /* ----------------------------------------------------------------
180 : * ExecValuesScan(node)
181 : *
182 : * Scans the values lists sequentially and returns the next qualifying
183 : * tuple.
184 : * We call the ExecScan() routine and pass it the appropriate
185 : * access method functions.
186 : * ----------------------------------------------------------------
187 : */
188 : static TupleTableSlot *
189 32642 : ExecValuesScan(PlanState *pstate)
190 : {
191 32642 : ValuesScanState *node = castNode(ValuesScanState, pstate);
192 :
193 32642 : return ExecScan(&node->ss,
194 : (ExecScanAccessMtd) ValuesNext,
195 : (ExecScanRecheckMtd) ValuesRecheck);
196 : }
197 :
198 : /* ----------------------------------------------------------------
199 : * ExecInitValuesScan
200 : * ----------------------------------------------------------------
201 : */
202 : ValuesScanState *
203 587 : ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
204 : {
205 : ValuesScanState *scanstate;
206 : TupleDesc tupdesc;
207 : ListCell *vtl;
208 : int i;
209 : PlanState *planstate;
210 :
211 : /*
212 : * ValuesScan should not have any children.
213 : */
214 587 : Assert(outerPlan(node) == NULL);
215 587 : Assert(innerPlan(node) == NULL);
216 :
217 : /*
218 : * create new ScanState for node
219 : */
220 587 : scanstate = makeNode(ValuesScanState);
221 587 : scanstate->ss.ps.plan = (Plan *) node;
222 587 : scanstate->ss.ps.state = estate;
223 587 : scanstate->ss.ps.ExecProcNode = ExecValuesScan;
224 :
225 : /*
226 : * Miscellaneous initialization
227 : */
228 587 : planstate = &scanstate->ss.ps;
229 :
230 : /*
231 : * Create expression contexts. We need two, one for per-sublist
232 : * processing and one for execScan.c to use for quals and projections. We
233 : * cheat a little by using ExecAssignExprContext() to build both.
234 : */
235 587 : ExecAssignExprContext(estate, planstate);
236 587 : scanstate->rowcontext = planstate->ps_ExprContext;
237 587 : ExecAssignExprContext(estate, planstate);
238 :
239 : /*
240 : * tuple table initialization
241 : */
242 587 : ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
243 587 : ExecInitScanTupleSlot(estate, &scanstate->ss);
244 :
245 : /*
246 : * initialize child expressions
247 : */
248 587 : scanstate->ss.ps.qual =
249 587 : ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
250 :
251 : /*
252 : * get info about values list
253 : */
254 587 : tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
255 :
256 587 : ExecAssignScanType(&scanstate->ss, tupdesc);
257 :
258 : /*
259 : * Other node-specific setup
260 : */
261 587 : scanstate->curr_idx = -1;
262 587 : scanstate->array_len = list_length(node->values_lists);
263 :
264 : /* convert list of sublists into array of sublists for easy addressing */
265 587 : scanstate->exprlists = (List **)
266 587 : palloc(scanstate->array_len * sizeof(List *));
267 587 : i = 0;
268 2867 : foreach(vtl, node->values_lists)
269 : {
270 2280 : scanstate->exprlists[i++] = (List *) lfirst(vtl);
271 : }
272 :
273 : /*
274 : * Initialize result tuple type and projection info.
275 : */
276 587 : ExecAssignResultTypeFromTL(&scanstate->ss.ps);
277 587 : ExecAssignScanProjectionInfo(&scanstate->ss);
278 :
279 587 : return scanstate;
280 : }
281 :
282 : /* ----------------------------------------------------------------
283 : * ExecEndValuesScan
284 : *
285 : * frees any storage allocated through C routines.
286 : * ----------------------------------------------------------------
287 : */
288 : void
289 581 : ExecEndValuesScan(ValuesScanState *node)
290 : {
291 : /*
292 : * Free both exprcontexts
293 : */
294 581 : ExecFreeExprContext(&node->ss.ps);
295 581 : node->ss.ps.ps_ExprContext = node->rowcontext;
296 581 : ExecFreeExprContext(&node->ss.ps);
297 :
298 : /*
299 : * clean out the tuple table
300 : */
301 581 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
302 581 : ExecClearTuple(node->ss.ss_ScanTupleSlot);
303 581 : }
304 :
305 : /* ----------------------------------------------------------------
306 : * ExecReScanValuesScan
307 : *
308 : * Rescans the relation.
309 : * ----------------------------------------------------------------
310 : */
311 : void
312 10025 : ExecReScanValuesScan(ValuesScanState *node)
313 : {
314 10025 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
315 :
316 10025 : ExecScanReScan(&node->ss);
317 :
318 10025 : node->curr_idx = -1;
319 10025 : }
|