PostgreSQL Source Code git master
Loading...
Searching...
No Matches
nodeTableFuncscan.c File Reference
#include "postgres.h"
#include "executor/executor.h"
#include "executor/nodeTableFuncscan.h"
#include "executor/tablefunc.h"
#include "miscadmin.h"
#include "nodes/execnodes.h"
#include "utils/builtins.h"
#include "utils/jsonpath.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/tuplestore.h"
#include "utils/xml.h"
Include dependency graph for nodeTableFuncscan.c:

Go to the source code of this file.

Functions

static TupleTableSlotTableFuncNext (TableFuncScanState *node)
 
static bool TableFuncRecheck (TableFuncScanState *node, TupleTableSlot *slot)
 
static void tfuncFetchRows (TableFuncScanState *tstate, ExprContext *econtext)
 
static void tfuncInitialize (TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
 
static void tfuncLoadRows (TableFuncScanState *tstate, ExprContext *econtext)
 
static TupleTableSlotExecTableFuncScan (PlanState *pstate)
 
TableFuncScanStateExecInitTableFuncScan (TableFuncScan *node, EState *estate, int eflags)
 
void ExecEndTableFuncScan (TableFuncScanState *node)
 
void ExecReScanTableFuncScan (TableFuncScanState *node)
 

Function Documentation

◆ ExecEndTableFuncScan()

void ExecEndTableFuncScan ( TableFuncScanState node)

Definition at line 221 of file nodeTableFuncscan.c.

222{
223 /*
224 * Release tuplestore resources
225 */
226 if (node->tupstore != NULL)
228 node->tupstore = NULL;
229}
static int fb(int x)
Tuplestorestate * tupstore
Definition execnodes.h:2001
void tuplestore_end(Tuplestorestate *state)
Definition tuplestore.c:493

References fb(), tuplestore_end(), and TableFuncScanState::tupstore.

Referenced by ExecEndNode().

◆ ExecInitTableFuncScan()

TableFuncScanState * ExecInitTableFuncScan ( TableFuncScan node,
EState estate,
int  eflags 
)

Definition at line 112 of file nodeTableFuncscan.c.

113{
115 TableFunc *tf = node->tablefunc;
116 TupleDesc tupdesc;
117 int i;
118
119 /* check for unsupported flags */
120 Assert(!(eflags & EXEC_FLAG_MARK));
121
122 /*
123 * TableFuncscan should not have any children.
124 */
125 Assert(outerPlan(node) == NULL);
126 Assert(innerPlan(node) == NULL);
127
128 /*
129 * create new ScanState for node
130 */
132 scanstate->ss.ps.plan = (Plan *) node;
133 scanstate->ss.ps.state = estate;
134 scanstate->ss.ps.ExecProcNode = ExecTableFuncScan;
135
136 /*
137 * Miscellaneous initialization
138 *
139 * create expression context for node
140 */
141 ExecAssignExprContext(estate, &scanstate->ss.ps);
142
143 /*
144 * initialize source tuple type
145 */
146 tupdesc = BuildDescFromLists(tf->colnames,
147 tf->coltypes,
148 tf->coltypmods,
149 tf->colcollations);
150 /* and the corresponding scan slot */
151 ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc,
153
154 /*
155 * Initialize result type and projection.
156 */
159
160 /*
161 * initialize child expressions
162 */
163 scanstate->ss.ps.qual =
164 ExecInitQual(node->scan.plan.qual, &scanstate->ss.ps);
165
166 /* Only XMLTABLE and JSON_TABLE are supported currently */
167 scanstate->routine =
169
170 scanstate->perTableCxt =
172 "TableFunc per value context",
174 scanstate->opaque = NULL; /* initialized at runtime */
175
176 scanstate->ns_names = tf->ns_names;
177
178 scanstate->ns_uris =
179 ExecInitExprList(tf->ns_uris, (PlanState *) scanstate);
180 scanstate->docexpr =
182 scanstate->rowexpr =
184 scanstate->colexprs =
186 scanstate->coldefexprs =
187 ExecInitExprList(tf->coldefexprs, (PlanState *) scanstate);
188 scanstate->colvalexprs =
189 ExecInitExprList(tf->colvalexprs, (PlanState *) scanstate);
190 scanstate->passingvalexprs =
191 ExecInitExprList(tf->passingvalexprs, (PlanState *) scanstate);
192
193 scanstate->notnulls = tf->notnulls;
194
195 /* these are allocated now and initialized later */
196 scanstate->in_functions = palloc_array(FmgrInfo, tupdesc->natts);
197 scanstate->typioparams = palloc_array(Oid, tupdesc->natts);
198
199 /*
200 * Fill in the necessary fmgr infos.
201 */
202 for (i = 0; i < tupdesc->natts; i++)
203 {
205
207 &in_funcid, &scanstate->typioparams[i]);
208 fmgr_info(in_funcid, &scanstate->in_functions[i]);
209 }
210
211 return scanstate;
212}
#define Assert(condition)
Definition c.h:945
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition execExpr.c:143
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition execExpr.c:250
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition execExpr.c:356
void ExecAssignScanProjectionInfo(ScanState *node)
Definition execScan.c:81
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops, uint16 flags)
void ExecInitResultTypeTL(PlanState *planstate)
const TupleTableSlotOps TTSOpsMinimalTuple
Definition execTuples.c:86
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition execUtils.c:490
#define EXEC_FLAG_MARK
Definition executor.h:71
#define palloc_array(type, count)
Definition fe_memutils.h:76
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition fmgr.c:129
int i
Definition isn.c:77
const TableFuncRoutine JsonbTableRoutine
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition lsyscache.c:3096
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
static TupleTableSlot * ExecTableFuncScan(PlanState *pstate)
#define makeNode(_type_)
Definition nodes.h:161
#define innerPlan(node)
Definition plannodes.h:264
#define outerPlan(node)
Definition plannodes.h:265
unsigned int Oid
@ TFT_XMLTABLE
Definition primnodes.h:101
TableFunc * tablefunc
Definition plannodes.h:808
Node * docexpr
Definition primnodes.h:121
Node * rowexpr
Definition primnodes.h:123
List * colexprs
Definition primnodes.h:133
TableFuncType functype
Definition primnodes.h:115
TupleDesc BuildDescFromLists(const List *names, const List *types, const List *typmods, const List *collations)
Definition tupdesc.c:1106
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178
const TableFuncRoutine XmlTableRoutine
Definition xml.c:222

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BuildDescFromLists(), TableFunc::colexprs, CurrentMemoryContext, TableFunc::docexpr, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignScanProjectionInfo(), ExecInitExpr(), ExecInitExprList(), ExecInitQual(), ExecInitResultTypeTL(), ExecInitScanTupleSlot(), ExecTableFuncScan(), fb(), fmgr_info(), TableFunc::functype, getTypeInputInfo(), i, innerPlan, JsonbTableRoutine, makeNode, TupleDescData::natts, outerPlan, palloc_array, TableFunc::rowexpr, TableFuncScan::scan, TableFuncScan::tablefunc, TFT_XMLTABLE, TTSOpsMinimalTuple, TupleDescAttr(), and XmlTableRoutine.

Referenced by ExecInitNode().

◆ ExecReScanTableFuncScan()

void ExecReScanTableFuncScan ( TableFuncScanState node)

Definition at line 238 of file nodeTableFuncscan.c.

239{
241
242 if (node->ss.ps.ps_ResultTupleSlot)
244 ExecScanReScan(&node->ss);
245
246 /*
247 * Recompute when parameters are changed.
248 */
249 if (chgparam)
250 {
251 if (node->tupstore != NULL)
252 {
254 node->tupstore = NULL;
255 }
256 }
257
258 if (node->tupstore != NULL)
260}
void ExecScanReScan(ScanState *node)
Definition execScan.c:108
Bitmapset * chgParam
Definition execnodes.h:1209
TupleTableSlot * ps_ResultTupleSlot
Definition execnodes.h:1215
PlanState ps
Definition execnodes.h:1633
void tuplestore_rescan(Tuplestorestate *state)
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition tuptable.h:476

References PlanState::chgParam, ExecClearTuple(), ExecScanReScan(), fb(), ScanState::ps, PlanState::ps_ResultTupleSlot, TableFuncScanState::ss, tuplestore_end(), tuplestore_rescan(), and TableFuncScanState::tupstore.

Referenced by ExecReScan().

◆ ExecTableFuncScan()

static TupleTableSlot * ExecTableFuncScan ( PlanState pstate)
static

Definition at line 98 of file nodeTableFuncscan.c.

99{
101
102 return ExecScan(&node->ss,
105}
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition execScan.c:47
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition executor.h:583
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition executor.h:582
static bool TableFuncRecheck(TableFuncScanState *node, TupleTableSlot *slot)
static TupleTableSlot * TableFuncNext(TableFuncScanState *node)
#define castNode(_type_, nodeptr)
Definition nodes.h:182

References castNode, ExecScan(), TableFuncScanState::ss, TableFuncNext(), and TableFuncRecheck().

Referenced by ExecInitTableFuncScan().

◆ TableFuncNext()

static TupleTableSlot * TableFuncNext ( TableFuncScanState node)
static

Definition at line 55 of file nodeTableFuncscan.c.

56{
58
60
61 /*
62 * If first time through, read all tuples from function and put them in a
63 * tuplestore. Subsequent calls just fetch tuples from tuplestore.
64 */
65 if (node->tupstore == NULL)
67
68 /*
69 * Get the next tuple from tuplestore.
70 */
72 true,
73 false,
74 scanslot);
75 return scanslot;
76}
static void tfuncFetchRows(TableFuncScanState *tstate, ExprContext *econtext)
ExprContext * ps_ExprContext
Definition execnodes.h:1216
TupleTableSlot * ss_ScanTupleSlot
Definition execnodes.h:1636
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)

References fb(), ScanState::ps, PlanState::ps_ExprContext, TableFuncScanState::ss, ScanState::ss_ScanTupleSlot, tfuncFetchRows(), tuplestore_gettupleslot(), and TableFuncScanState::tupstore.

Referenced by ExecTableFuncScan().

◆ TableFuncRecheck()

static bool TableFuncRecheck ( TableFuncScanState node,
TupleTableSlot slot 
)
static

Definition at line 82 of file nodeTableFuncscan.c.

83{
84 /* nothing to check */
85 return true;
86}

Referenced by ExecTableFuncScan().

◆ tfuncFetchRows()

static void tfuncFetchRows ( TableFuncScanState tstate,
ExprContext econtext 
)
static

Definition at line 269 of file nodeTableFuncscan.c.

270{
271 const TableFuncRoutine *routine = tstate->routine;
273 Datum value;
274 bool isnull;
275
276 Assert(tstate->opaque == NULL);
277
278 /* build tuplestore for the result */
280 tstate->tupstore = tuplestore_begin_heap(false, false, work_mem);
281
282 /*
283 * Each call to fetch a new set of rows - of which there may be very many
284 * if XMLTABLE or JSON_TABLE is being used in a lateral join - will
285 * allocate a possibly substantial amount of memory, so we cannot use the
286 * per-query context here. perTableCxt now serves the same function as
287 * "argcontext" does in FunctionScan - a place to store per-one-call (i.e.
288 * one result table) lifetime data (as opposed to per-query or
289 * per-result-tuple).
290 */
291 MemoryContextSwitchTo(tstate->perTableCxt);
292
293 PG_TRY();
294 {
295 routine->InitOpaque(tstate,
296 tstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor->natts);
297
298 /*
299 * If evaluating the document expression returns NULL, the table
300 * expression is empty and we return immediately.
301 */
302 value = ExecEvalExpr(tstate->docexpr, econtext, &isnull);
303
304 if (!isnull)
305 {
306 /* otherwise, pass the document value to the table builder */
307 tfuncInitialize(tstate, econtext, value);
308
309 /* initialize ordinality counter */
310 tstate->ordinal = 1;
311
312 /* Load all rows into the tuplestore, and we're done */
313 tfuncLoadRows(tstate, econtext);
314 }
315 }
316 PG_CATCH();
317 {
318 if (tstate->opaque != NULL)
319 routine->DestroyOpaque(tstate);
320 PG_RE_THROW();
321 }
322 PG_END_TRY();
323
324 /* clean up and return to original memory context */
325
326 if (tstate->opaque != NULL)
327 {
328 routine->DestroyOpaque(tstate);
329 tstate->opaque = NULL;
330 }
331
333 MemoryContextReset(tstate->perTableCxt);
334}
#define PG_RE_THROW()
Definition elog.h:405
#define PG_TRY(...)
Definition elog.h:372
#define PG_END_TRY(...)
Definition elog.h:397
#define PG_CATCH(...)
Definition elog.h:382
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:396
int work_mem
Definition globals.c:131
static struct @174 value
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:403
static void tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
static void tfuncLoadRows(TableFuncScanState *tstate, ExprContext *econtext)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
uint64_t Datum
Definition postgres.h:70
MemoryContext ecxt_per_query_memory
Definition execnodes.h:291
void(* DestroyOpaque)(TableFuncScanState *state)
Definition tablefunc.h:64
void(* InitOpaque)(TableFuncScanState *state, int natts)
Definition tablefunc.h:54
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition tuplestore.c:331

References Assert, TableFuncRoutine::DestroyOpaque, ExprContext::ecxt_per_query_memory, ExecEvalExpr(), fb(), TableFuncRoutine::InitOpaque, MemoryContextReset(), MemoryContextSwitchTo(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, tfuncInitialize(), tfuncLoadRows(), tuplestore_begin_heap(), value, and work_mem.

Referenced by TableFuncNext().

◆ tfuncInitialize()

static void tfuncInitialize ( TableFuncScanState tstate,
ExprContext econtext,
Datum  doc 
)
static

Definition at line 341 of file nodeTableFuncscan.c.

342{
343 const TableFuncRoutine *routine = tstate->routine;
344 TupleDesc tupdesc;
345 ListCell *lc1,
346 *lc2;
347 bool isnull;
348 int colno;
349 Datum value;
350 int ordinalitycol =
351 ((TableFuncScan *) (tstate->ss.ps.plan))->tablefunc->ordinalitycol;
352
353 /*
354 * Install the document as a possibly-toasted Datum into the tablefunc
355 * context.
356 */
357 routine->SetDocument(tstate, doc);
358
359 /* Evaluate namespace specifications */
360 forboth(lc1, tstate->ns_uris, lc2, tstate->ns_names)
361 {
362 ExprState *expr = (ExprState *) lfirst(lc1);
364 char *ns_uri;
365 char *ns_name;
366
367 value = ExecEvalExpr(expr, econtext, &isnull);
368 if (isnull)
371 errmsg("namespace URI must not be null")));
373
374 /* DEFAULT is passed down to SetNamespace as NULL */
376
377 routine->SetNamespace(tstate, ns_name, ns_uri);
378 }
379
380 /*
381 * Install the row filter expression, if any, into the table builder
382 * context.
383 */
384 if (routine->SetRowFilter)
385 {
386 value = ExecEvalExpr(tstate->rowexpr, econtext, &isnull);
387 if (isnull)
390 errmsg("row filter expression must not be null")));
391
393 }
394
395 /*
396 * Install the column filter expressions into the table builder context.
397 * If an expression is given, use that; otherwise the column name itself
398 * is the column filter.
399 */
400 colno = 0;
401 tupdesc = tstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
402 foreach(lc1, tstate->colexprs)
403 {
404 char *colfilter;
405 Form_pg_attribute att = TupleDescAttr(tupdesc, colno);
406
407 if (colno != ordinalitycol)
408 {
409 ExprState *colexpr = lfirst(lc1);
410
411 if (colexpr != NULL)
412 {
413 value = ExecEvalExpr(colexpr, econtext, &isnull);
414 if (isnull)
417 errmsg("column filter expression must not be null"),
418 errdetail("Filter for column \"%s\" is null.",
419 NameStr(att->attname))));
421 }
422 else
423 colfilter = NameStr(att->attname);
424
425 routine->SetColumnFilter(tstate, colfilter, colno);
426 }
427
428 colno++;
429 }
430}
#define TextDatumGetCString(d)
Definition builtins.h:99
#define NameStr(name)
Definition c.h:837
int errcode(int sqlerrcode)
Definition elog.c:874
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
static char * errmsg
FormData_pg_attribute * Form_pg_attribute
#define lfirst(lc)
Definition pg_list.h:172
#define lfirst_node(type, lc)
Definition pg_list.h:176
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:518
Definition value.h:64
void(* SetNamespace)(TableFuncScanState *state, const char *name, const char *uri)
Definition tablefunc.h:56
void(* SetDocument)(TableFuncScanState *state, Datum value)
Definition tablefunc.h:55
void(* SetColumnFilter)(TableFuncScanState *state, const char *path, int colnum)
Definition tablefunc.h:59
void(* SetRowFilter)(TableFuncScanState *state, const char *path)
Definition tablefunc.h:58
#define strVal(v)
Definition value.h:82

References ereport, errcode(), errdetail(), errmsg, ERROR, ExecEvalExpr(), fb(), forboth, lfirst, lfirst_node, NameStr, TableFuncRoutine::SetColumnFilter, TableFuncRoutine::SetDocument, TableFuncRoutine::SetNamespace, TableFuncRoutine::SetRowFilter, strVal, TextDatumGetCString, TupleDescAttr(), and value.

Referenced by tfuncFetchRows().

◆ tfuncLoadRows()

static void tfuncLoadRows ( TableFuncScanState tstate,
ExprContext econtext 
)
static

Definition at line 436 of file nodeTableFuncscan.c.

437{
438 const TableFuncRoutine *routine = tstate->routine;
439 TupleTableSlot *slot = tstate->ss.ss_ScanTupleSlot;
440 TupleDesc tupdesc = slot->tts_tupleDescriptor;
441 Datum *values = slot->tts_values;
442 bool *nulls = slot->tts_isnull;
443 int natts = tupdesc->natts;
445 int ordinalitycol;
446
448 ((TableFuncScan *) (tstate->ss.ps.plan))->tablefunc->ordinalitycol;
449
450 /*
451 * We need a short-lived memory context that we can clean up each time
452 * around the loop, to avoid wasting space. Our default per-tuple context
453 * is fine for the job, since we won't have used it for anything yet in
454 * this tuple cycle.
455 */
457
458 /*
459 * Keep requesting rows from the table builder until there aren't any.
460 */
461 while (routine->FetchRow(tstate))
462 {
463 ListCell *cell = list_head(tstate->coldefexprs);
464 int colno;
465
467
468 ExecClearTuple(tstate->ss.ss_ScanTupleSlot);
469
470 /*
471 * Obtain the value of each column for this row, installing them into
472 * the slot; then add the tuple to the tuplestore.
473 */
474 for (colno = 0; colno < natts; colno++)
475 {
476 Form_pg_attribute att = TupleDescAttr(tupdesc, colno);
477
478 if (colno == ordinalitycol)
479 {
480 /* Fast path for ordinality column */
481 values[colno] = Int32GetDatum(tstate->ordinal++);
482 nulls[colno] = false;
483 }
484 else
485 {
486 bool isnull;
487
488 values[colno] = routine->GetValue(tstate,
489 colno,
490 att->atttypid,
491 att->atttypmod,
492 &isnull);
493
494 /* No value? Evaluate and apply the default, if any */
495 if (isnull && cell != NULL)
496 {
497 ExprState *coldefexpr = (ExprState *) lfirst(cell);
498
499 if (coldefexpr != NULL)
500 values[colno] = ExecEvalExpr(coldefexpr, econtext,
501 &isnull);
502 }
503
504 /* Verify a possible NOT NULL constraint */
505 if (isnull && bms_is_member(colno, tstate->notnulls))
508 errmsg("null is not allowed in column \"%s\"",
509 NameStr(att->attname))));
510
511 nulls[colno] = isnull;
512 }
513
514 /* advance list of default expressions */
515 if (cell != NULL)
516 cell = lnext(tstate->coldefexprs, cell);
517 }
518
519 tuplestore_putvalues(tstate->tupstore, tupdesc, values, nulls);
520
522 }
523
525}
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
static Datum values[MAXATTR]
Definition bootstrap.c:188
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
static ListCell * list_head(const List *l)
Definition pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition pg_list.h:343
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
MemoryContext ecxt_per_tuple_memory
Definition execnodes.h:292
Datum(* GetValue)(TableFuncScanState *state, int colnum, Oid typid, int32 typmod, bool *isnull)
Definition tablefunc.h:62
bool(* FetchRow)(TableFuncScanState *state)
Definition tablefunc.h:61
TupleDesc tts_tupleDescriptor
Definition tuptable.h:129
bool * tts_isnull
Definition tuptable.h:133
Datum * tts_values
Definition tuptable.h:131
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:785

References bms_is_member(), CHECK_FOR_INTERRUPTS, ExprContext::ecxt_per_tuple_memory, ereport, errcode(), errmsg, ERROR, ExecClearTuple(), ExecEvalExpr(), fb(), TableFuncRoutine::FetchRow, TableFuncRoutine::GetValue, Int32GetDatum(), lfirst, list_head(), lnext(), MemoryContextReset(), MemoryContextSwitchTo(), NameStr, TupleDescData::natts, TupleTableSlot::tts_isnull, TupleTableSlot::tts_tupleDescriptor, TupleTableSlot::tts_values, TupleDescAttr(), tuplestore_putvalues(), and values.

Referenced by tfuncFetchRows().