1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * nodeFunctionscan.c |
4 | * Support routines for scanning RangeFunctions (functions in rangetable). |
5 | * |
6 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
7 | * Portions Copyright (c) 1994, Regents of the University of California |
8 | * |
9 | * |
10 | * IDENTIFICATION |
11 | * src/backend/executor/nodeFunctionscan.c |
12 | * |
13 | *------------------------------------------------------------------------- |
14 | */ |
15 | /* |
16 | * INTERFACE ROUTINES |
17 | * ExecFunctionScan scans a function. |
18 | * ExecFunctionNext retrieve next tuple in sequential order. |
19 | * ExecInitFunctionScan creates and initializes a functionscan node. |
20 | * ExecEndFunctionScan releases any storage allocated. |
21 | * ExecReScanFunctionScan rescans the function |
22 | */ |
23 | #include "postgres.h" |
24 | |
25 | #include "catalog/pg_type.h" |
26 | #include "executor/nodeFunctionscan.h" |
27 | #include "funcapi.h" |
28 | #include "nodes/nodeFuncs.h" |
29 | #include "utils/builtins.h" |
30 | #include "utils/memutils.h" |
31 | |
32 | |
33 | /* |
34 | * Runtime data for each function being scanned. |
35 | */ |
36 | typedef struct FunctionScanPerFuncState |
37 | { |
38 | SetExprState *setexpr; /* state of the expression being evaluated */ |
39 | TupleDesc tupdesc; /* desc of the function result type */ |
40 | int colcount; /* expected number of result columns */ |
41 | Tuplestorestate *tstore; /* holds the function result set */ |
42 | int64 rowcount; /* # of rows in result set, -1 if not known */ |
43 | TupleTableSlot *func_slot; /* function result slot (or NULL) */ |
44 | } FunctionScanPerFuncState; |
45 | |
46 | static TupleTableSlot *FunctionNext(FunctionScanState *node); |
47 | |
48 | |
49 | /* ---------------------------------------------------------------- |
50 | * Scan Support |
51 | * ---------------------------------------------------------------- |
52 | */ |
53 | /* ---------------------------------------------------------------- |
54 | * FunctionNext |
55 | * |
56 | * This is a workhorse for ExecFunctionScan |
57 | * ---------------------------------------------------------------- |
58 | */ |
59 | static TupleTableSlot * |
60 | FunctionNext(FunctionScanState *node) |
61 | { |
62 | EState *estate; |
63 | ScanDirection direction; |
64 | TupleTableSlot *scanslot; |
65 | bool alldone; |
66 | int64 oldpos; |
67 | int funcno; |
68 | int att; |
69 | |
70 | /* |
71 | * get information from the estate and scan state |
72 | */ |
73 | estate = node->ss.ps.state; |
74 | direction = estate->es_direction; |
75 | scanslot = node->ss.ss_ScanTupleSlot; |
76 | |
77 | if (node->simple) |
78 | { |
79 | /* |
80 | * Fast path for the trivial case: the function return type and scan |
81 | * result type are the same, so we fetch the function result straight |
82 | * into the scan result slot. No need to update ordinality or |
83 | * rowcounts either. |
84 | */ |
85 | Tuplestorestate *tstore = node->funcstates[0].tstore; |
86 | |
87 | /* |
88 | * If first time through, read all tuples from function and put them |
89 | * in a tuplestore. Subsequent calls just fetch tuples from |
90 | * tuplestore. |
91 | */ |
92 | if (tstore == NULL) |
93 | { |
94 | node->funcstates[0].tstore = tstore = |
95 | ExecMakeTableFunctionResult(node->funcstates[0].setexpr, |
96 | node->ss.ps.ps_ExprContext, |
97 | node->argcontext, |
98 | node->funcstates[0].tupdesc, |
99 | node->eflags & EXEC_FLAG_BACKWARD); |
100 | |
101 | /* |
102 | * paranoia - cope if the function, which may have constructed the |
103 | * tuplestore itself, didn't leave it pointing at the start. This |
104 | * call is fast, so the overhead shouldn't be an issue. |
105 | */ |
106 | tuplestore_rescan(tstore); |
107 | } |
108 | |
109 | /* |
110 | * Get the next tuple from tuplestore. |
111 | */ |
112 | (void) tuplestore_gettupleslot(tstore, |
113 | ScanDirectionIsForward(direction), |
114 | false, |
115 | scanslot); |
116 | return scanslot; |
117 | } |
118 | |
119 | /* |
120 | * Increment or decrement ordinal counter before checking for end-of-data, |
121 | * so that we can move off either end of the result by 1 (and no more than |
122 | * 1) without losing correct count. See PortalRunSelect for why we can |
123 | * assume that we won't be called repeatedly in the end-of-data state. |
124 | */ |
125 | oldpos = node->ordinal; |
126 | if (ScanDirectionIsForward(direction)) |
127 | node->ordinal++; |
128 | else |
129 | node->ordinal--; |
130 | |
131 | /* |
132 | * Main loop over functions. |
133 | * |
134 | * We fetch the function results into func_slots (which match the function |
135 | * return types), and then copy the values to scanslot (which matches the |
136 | * scan result type), setting the ordinal column (if any) as well. |
137 | */ |
138 | ExecClearTuple(scanslot); |
139 | att = 0; |
140 | alldone = true; |
141 | for (funcno = 0; funcno < node->nfuncs; funcno++) |
142 | { |
143 | FunctionScanPerFuncState *fs = &node->funcstates[funcno]; |
144 | int i; |
145 | |
146 | /* |
147 | * If first time through, read all tuples from function and put them |
148 | * in a tuplestore. Subsequent calls just fetch tuples from |
149 | * tuplestore. |
150 | */ |
151 | if (fs->tstore == NULL) |
152 | { |
153 | fs->tstore = |
154 | ExecMakeTableFunctionResult(fs->setexpr, |
155 | node->ss.ps.ps_ExprContext, |
156 | node->argcontext, |
157 | fs->tupdesc, |
158 | node->eflags & EXEC_FLAG_BACKWARD); |
159 | |
160 | /* |
161 | * paranoia - cope if the function, which may have constructed the |
162 | * tuplestore itself, didn't leave it pointing at the start. This |
163 | * call is fast, so the overhead shouldn't be an issue. |
164 | */ |
165 | tuplestore_rescan(fs->tstore); |
166 | } |
167 | |
168 | /* |
169 | * Get the next tuple from tuplestore. |
170 | * |
171 | * If we have a rowcount for the function, and we know the previous |
172 | * read position was out of bounds, don't try the read. This allows |
173 | * backward scan to work when there are mixed row counts present. |
174 | */ |
175 | if (fs->rowcount != -1 && fs->rowcount < oldpos) |
176 | ExecClearTuple(fs->func_slot); |
177 | else |
178 | (void) tuplestore_gettupleslot(fs->tstore, |
179 | ScanDirectionIsForward(direction), |
180 | false, |
181 | fs->func_slot); |
182 | |
183 | if (TupIsNull(fs->func_slot)) |
184 | { |
185 | /* |
186 | * If we ran out of data for this function in the forward |
187 | * direction then we now know how many rows it returned. We need |
188 | * to know this in order to handle backwards scans. The row count |
189 | * we store is actually 1+ the actual number, because we have to |
190 | * position the tuplestore 1 off its end sometimes. |
191 | */ |
192 | if (ScanDirectionIsForward(direction) && fs->rowcount == -1) |
193 | fs->rowcount = node->ordinal; |
194 | |
195 | /* |
196 | * populate the result cols with nulls |
197 | */ |
198 | for (i = 0; i < fs->colcount; i++) |
199 | { |
200 | scanslot->tts_values[att] = (Datum) 0; |
201 | scanslot->tts_isnull[att] = true; |
202 | att++; |
203 | } |
204 | } |
205 | else |
206 | { |
207 | /* |
208 | * we have a result, so just copy it to the result cols. |
209 | */ |
210 | slot_getallattrs(fs->func_slot); |
211 | |
212 | for (i = 0; i < fs->colcount; i++) |
213 | { |
214 | scanslot->tts_values[att] = fs->func_slot->tts_values[i]; |
215 | scanslot->tts_isnull[att] = fs->func_slot->tts_isnull[i]; |
216 | att++; |
217 | } |
218 | |
219 | /* |
220 | * We're not done until every function result is exhausted; we pad |
221 | * the shorter results with nulls until then. |
222 | */ |
223 | alldone = false; |
224 | } |
225 | } |
226 | |
227 | /* |
228 | * ordinal col is always last, per spec. |
229 | */ |
230 | if (node->ordinality) |
231 | { |
232 | scanslot->tts_values[att] = Int64GetDatumFast(node->ordinal); |
233 | scanslot->tts_isnull[att] = false; |
234 | } |
235 | |
236 | /* |
237 | * If alldone, we just return the previously-cleared scanslot. Otherwise, |
238 | * finish creating the virtual tuple. |
239 | */ |
240 | if (!alldone) |
241 | ExecStoreVirtualTuple(scanslot); |
242 | |
243 | return scanslot; |
244 | } |
245 | |
246 | /* |
247 | * FunctionRecheck -- access method routine to recheck a tuple in EvalPlanQual |
248 | */ |
249 | static bool |
250 | FunctionRecheck(FunctionScanState *node, TupleTableSlot *slot) |
251 | { |
252 | /* nothing to check */ |
253 | return true; |
254 | } |
255 | |
256 | /* ---------------------------------------------------------------- |
257 | * ExecFunctionScan(node) |
258 | * |
259 | * Scans the function sequentially and returns the next qualifying |
260 | * tuple. |
261 | * We call the ExecScan() routine and pass it the appropriate |
262 | * access method functions. |
263 | * ---------------------------------------------------------------- |
264 | */ |
265 | static TupleTableSlot * |
266 | ExecFunctionScan(PlanState *pstate) |
267 | { |
268 | FunctionScanState *node = castNode(FunctionScanState, pstate); |
269 | |
270 | return ExecScan(&node->ss, |
271 | (ExecScanAccessMtd) FunctionNext, |
272 | (ExecScanRecheckMtd) FunctionRecheck); |
273 | } |
274 | |
275 | /* ---------------------------------------------------------------- |
276 | * ExecInitFunctionScan |
277 | * ---------------------------------------------------------------- |
278 | */ |
279 | FunctionScanState * |
280 | ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) |
281 | { |
282 | FunctionScanState *scanstate; |
283 | int nfuncs = list_length(node->functions); |
284 | TupleDesc scan_tupdesc; |
285 | int i, |
286 | natts; |
287 | ListCell *lc; |
288 | |
289 | /* check for unsupported flags */ |
290 | Assert(!(eflags & EXEC_FLAG_MARK)); |
291 | |
292 | /* |
293 | * FunctionScan should not have any children. |
294 | */ |
295 | Assert(outerPlan(node) == NULL); |
296 | Assert(innerPlan(node) == NULL); |
297 | |
298 | /* |
299 | * create new ScanState for node |
300 | */ |
301 | scanstate = makeNode(FunctionScanState); |
302 | scanstate->ss.ps.plan = (Plan *) node; |
303 | scanstate->ss.ps.state = estate; |
304 | scanstate->ss.ps.ExecProcNode = ExecFunctionScan; |
305 | scanstate->eflags = eflags; |
306 | |
307 | /* |
308 | * are we adding an ordinality column? |
309 | */ |
310 | scanstate->ordinality = node->funcordinality; |
311 | |
312 | scanstate->nfuncs = nfuncs; |
313 | if (nfuncs == 1 && !node->funcordinality) |
314 | scanstate->simple = true; |
315 | else |
316 | scanstate->simple = false; |
317 | |
318 | /* |
319 | * Ordinal 0 represents the "before the first row" position. |
320 | * |
321 | * We need to track ordinal position even when not adding an ordinality |
322 | * column to the result, in order to handle backwards scanning properly |
323 | * with multiple functions with different result sizes. (We can't position |
324 | * any individual function's tuplestore any more than 1 place beyond its |
325 | * end, so when scanning backwards, we need to know when to start |
326 | * including the function in the scan again.) |
327 | */ |
328 | scanstate->ordinal = 0; |
329 | |
330 | /* |
331 | * Miscellaneous initialization |
332 | * |
333 | * create expression context for node |
334 | */ |
335 | ExecAssignExprContext(estate, &scanstate->ss.ps); |
336 | |
337 | scanstate->funcstates = palloc(nfuncs * sizeof(FunctionScanPerFuncState)); |
338 | |
339 | natts = 0; |
340 | i = 0; |
341 | foreach(lc, node->functions) |
342 | { |
343 | RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); |
344 | Node *funcexpr = rtfunc->funcexpr; |
345 | int colcount = rtfunc->funccolcount; |
346 | FunctionScanPerFuncState *fs = &scanstate->funcstates[i]; |
347 | TypeFuncClass functypclass; |
348 | Oid funcrettype; |
349 | TupleDesc tupdesc; |
350 | |
351 | fs->setexpr = |
352 | ExecInitTableFunctionResult((Expr *) funcexpr, |
353 | scanstate->ss.ps.ps_ExprContext, |
354 | &scanstate->ss.ps); |
355 | |
356 | /* |
357 | * Don't allocate the tuplestores; the actual calls to the functions |
358 | * do that. NULL means that we have not called the function yet (or |
359 | * need to call it again after a rescan). |
360 | */ |
361 | fs->tstore = NULL; |
362 | fs->rowcount = -1; |
363 | |
364 | /* |
365 | * Now determine if the function returns a simple or composite type, |
366 | * and build an appropriate tupdesc. Note that in the composite case, |
367 | * the function may now return more columns than it did when the plan |
368 | * was made; we have to ignore any columns beyond "colcount". |
369 | */ |
370 | functypclass = get_expr_result_type(funcexpr, |
371 | &funcrettype, |
372 | &tupdesc); |
373 | |
374 | if (functypclass == TYPEFUNC_COMPOSITE || |
375 | functypclass == TYPEFUNC_COMPOSITE_DOMAIN) |
376 | { |
377 | /* Composite data type, e.g. a table's row type */ |
378 | Assert(tupdesc); |
379 | Assert(tupdesc->natts >= colcount); |
380 | /* Must copy it out of typcache for safety */ |
381 | tupdesc = CreateTupleDescCopy(tupdesc); |
382 | } |
383 | else if (functypclass == TYPEFUNC_SCALAR) |
384 | { |
385 | /* Base data type, i.e. scalar */ |
386 | tupdesc = CreateTemplateTupleDesc(1); |
387 | TupleDescInitEntry(tupdesc, |
388 | (AttrNumber) 1, |
389 | NULL, /* don't care about the name here */ |
390 | funcrettype, |
391 | -1, |
392 | 0); |
393 | TupleDescInitEntryCollation(tupdesc, |
394 | (AttrNumber) 1, |
395 | exprCollation(funcexpr)); |
396 | } |
397 | else if (functypclass == TYPEFUNC_RECORD) |
398 | { |
399 | tupdesc = BuildDescFromLists(rtfunc->funccolnames, |
400 | rtfunc->funccoltypes, |
401 | rtfunc->funccoltypmods, |
402 | rtfunc->funccolcollations); |
403 | |
404 | /* |
405 | * For RECORD results, make sure a typmod has been assigned. (The |
406 | * function should do this for itself, but let's cover things in |
407 | * case it doesn't.) |
408 | */ |
409 | BlessTupleDesc(tupdesc); |
410 | } |
411 | else |
412 | { |
413 | /* crummy error message, but parser should have caught this */ |
414 | elog(ERROR, "function in FROM has unsupported return type" ); |
415 | } |
416 | |
417 | fs->tupdesc = tupdesc; |
418 | fs->colcount = colcount; |
419 | |
420 | /* |
421 | * We only need separate slots for the function results if we are |
422 | * doing ordinality or multiple functions; otherwise, we'll fetch |
423 | * function results directly into the scan slot. |
424 | */ |
425 | if (!scanstate->simple) |
426 | { |
427 | fs->func_slot = ExecInitExtraTupleSlot(estate, fs->tupdesc, |
428 | &TTSOpsMinimalTuple); |
429 | } |
430 | else |
431 | fs->func_slot = NULL; |
432 | |
433 | natts += colcount; |
434 | i++; |
435 | } |
436 | |
437 | /* |
438 | * Create the combined TupleDesc |
439 | * |
440 | * If there is just one function without ordinality, the scan result |
441 | * tupdesc is the same as the function result tupdesc --- except that we |
442 | * may stuff new names into it below, so drop any rowtype label. |
443 | */ |
444 | if (scanstate->simple) |
445 | { |
446 | scan_tupdesc = CreateTupleDescCopy(scanstate->funcstates[0].tupdesc); |
447 | scan_tupdesc->tdtypeid = RECORDOID; |
448 | scan_tupdesc->tdtypmod = -1; |
449 | } |
450 | else |
451 | { |
452 | AttrNumber attno = 0; |
453 | |
454 | if (node->funcordinality) |
455 | natts++; |
456 | |
457 | scan_tupdesc = CreateTemplateTupleDesc(natts); |
458 | |
459 | for (i = 0; i < nfuncs; i++) |
460 | { |
461 | TupleDesc tupdesc = scanstate->funcstates[i].tupdesc; |
462 | int colcount = scanstate->funcstates[i].colcount; |
463 | int j; |
464 | |
465 | for (j = 1; j <= colcount; j++) |
466 | TupleDescCopyEntry(scan_tupdesc, ++attno, tupdesc, j); |
467 | } |
468 | |
469 | /* If doing ordinality, add a column of type "bigint" at the end */ |
470 | if (node->funcordinality) |
471 | { |
472 | TupleDescInitEntry(scan_tupdesc, |
473 | ++attno, |
474 | NULL, /* don't care about the name here */ |
475 | INT8OID, |
476 | -1, |
477 | 0); |
478 | } |
479 | |
480 | Assert(attno == natts); |
481 | } |
482 | |
483 | /* |
484 | * Initialize scan slot and type. |
485 | */ |
486 | ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc, |
487 | &TTSOpsMinimalTuple); |
488 | |
489 | /* |
490 | * Initialize result slot, type and projection. |
491 | */ |
492 | ExecInitResultTypeTL(&scanstate->ss.ps); |
493 | ExecAssignScanProjectionInfo(&scanstate->ss); |
494 | |
495 | /* |
496 | * initialize child expressions |
497 | */ |
498 | scanstate->ss.ps.qual = |
499 | ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate); |
500 | |
501 | /* |
502 | * Create a memory context that ExecMakeTableFunctionResult can use to |
503 | * evaluate function arguments in. We can't use the per-tuple context for |
504 | * this because it gets reset too often; but we don't want to leak |
505 | * evaluation results into the query-lifespan context either. We just |
506 | * need one context, because we evaluate each function separately. |
507 | */ |
508 | scanstate->argcontext = AllocSetContextCreate(CurrentMemoryContext, |
509 | "Table function arguments" , |
510 | ALLOCSET_DEFAULT_SIZES); |
511 | |
512 | return scanstate; |
513 | } |
514 | |
515 | /* ---------------------------------------------------------------- |
516 | * ExecEndFunctionScan |
517 | * |
518 | * frees any storage allocated through C routines. |
519 | * ---------------------------------------------------------------- |
520 | */ |
521 | void |
522 | ExecEndFunctionScan(FunctionScanState *node) |
523 | { |
524 | int i; |
525 | |
526 | /* |
527 | * Free the exprcontext |
528 | */ |
529 | ExecFreeExprContext(&node->ss.ps); |
530 | |
531 | /* |
532 | * clean out the tuple table |
533 | */ |
534 | if (node->ss.ps.ps_ResultTupleSlot) |
535 | ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); |
536 | ExecClearTuple(node->ss.ss_ScanTupleSlot); |
537 | |
538 | /* |
539 | * Release slots and tuplestore resources |
540 | */ |
541 | for (i = 0; i < node->nfuncs; i++) |
542 | { |
543 | FunctionScanPerFuncState *fs = &node->funcstates[i]; |
544 | |
545 | if (fs->func_slot) |
546 | ExecClearTuple(fs->func_slot); |
547 | |
548 | if (fs->tstore != NULL) |
549 | { |
550 | tuplestore_end(node->funcstates[i].tstore); |
551 | fs->tstore = NULL; |
552 | } |
553 | } |
554 | } |
555 | |
556 | /* ---------------------------------------------------------------- |
557 | * ExecReScanFunctionScan |
558 | * |
559 | * Rescans the relation. |
560 | * ---------------------------------------------------------------- |
561 | */ |
562 | void |
563 | ExecReScanFunctionScan(FunctionScanState *node) |
564 | { |
565 | FunctionScan *scan = (FunctionScan *) node->ss.ps.plan; |
566 | int i; |
567 | Bitmapset *chgparam = node->ss.ps.chgParam; |
568 | |
569 | if (node->ss.ps.ps_ResultTupleSlot) |
570 | ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); |
571 | for (i = 0; i < node->nfuncs; i++) |
572 | { |
573 | FunctionScanPerFuncState *fs = &node->funcstates[i]; |
574 | |
575 | if (fs->func_slot) |
576 | ExecClearTuple(fs->func_slot); |
577 | } |
578 | |
579 | ExecScanReScan(&node->ss); |
580 | |
581 | /* |
582 | * Here we have a choice whether to drop the tuplestores (and recompute |
583 | * the function outputs) or just rescan them. We must recompute if an |
584 | * expression contains changed parameters, else we rescan. |
585 | * |
586 | * XXX maybe we should recompute if the function is volatile? But in |
587 | * general the executor doesn't conditionalize its actions on that. |
588 | */ |
589 | if (chgparam) |
590 | { |
591 | ListCell *lc; |
592 | |
593 | i = 0; |
594 | foreach(lc, scan->functions) |
595 | { |
596 | RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); |
597 | |
598 | if (bms_overlap(chgparam, rtfunc->funcparams)) |
599 | { |
600 | if (node->funcstates[i].tstore != NULL) |
601 | { |
602 | tuplestore_end(node->funcstates[i].tstore); |
603 | node->funcstates[i].tstore = NULL; |
604 | } |
605 | node->funcstates[i].rowcount = -1; |
606 | } |
607 | i++; |
608 | } |
609 | } |
610 | |
611 | /* Reset ordinality counter */ |
612 | node->ordinal = 0; |
613 | |
614 | /* Make sure we rewind any remaining tuplestores */ |
615 | for (i = 0; i < node->nfuncs; i++) |
616 | { |
617 | if (node->funcstates[i].tstore != NULL) |
618 | tuplestore_rescan(node->funcstates[i].tstore); |
619 | } |
620 | } |
621 | |