PostgreSQL Source Code  git master
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/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 220 of file nodeTableFuncscan.c.

221 {
222  /*
223  * Release tuplestore resources
224  */
225  if (node->tupstore != NULL)
226  tuplestore_end(node->tupstore);
227  node->tupstore = NULL;
228 }
Tuplestorestate * tupstore
Definition: execnodes.h:2009
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:492

References tuplestore_end(), and TableFuncScanState::tupstore.

Referenced by ExecEndNode().

◆ ExecInitTableFuncScan()

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

Definition at line 111 of file nodeTableFuncscan.c.

112 {
113  TableFuncScanState *scanstate;
114  TableFunc *tf = node->tablefunc;
115  TupleDesc tupdesc;
116  int i;
117 
118  /* check for unsupported flags */
119  Assert(!(eflags & EXEC_FLAG_MARK));
120 
121  /*
122  * TableFuncscan should not have any children.
123  */
124  Assert(outerPlan(node) == NULL);
125  Assert(innerPlan(node) == NULL);
126 
127  /*
128  * create new ScanState for node
129  */
130  scanstate = makeNode(TableFuncScanState);
131  scanstate->ss.ps.plan = (Plan *) node;
132  scanstate->ss.ps.state = estate;
133  scanstate->ss.ps.ExecProcNode = ExecTableFuncScan;
134 
135  /*
136  * Miscellaneous initialization
137  *
138  * create expression context for node
139  */
140  ExecAssignExprContext(estate, &scanstate->ss.ps);
141 
142  /*
143  * initialize source tuple type
144  */
145  tupdesc = BuildDescFromLists(tf->colnames,
146  tf->coltypes,
147  tf->coltypmods,
148  tf->colcollations);
149  /* and the corresponding scan slot */
150  ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc,
152 
153  /*
154  * Initialize result type and projection.
155  */
156  ExecInitResultTypeTL(&scanstate->ss.ps);
157  ExecAssignScanProjectionInfo(&scanstate->ss);
158 
159  /*
160  * initialize child expressions
161  */
162  scanstate->ss.ps.qual =
163  ExecInitQual(node->scan.plan.qual, &scanstate->ss.ps);
164 
165  /* Only XMLTABLE and JSON_TABLE are supported currently */
166  scanstate->routine =
168 
169  scanstate->perTableCxt =
171  "TableFunc per value context",
173  scanstate->opaque = NULL; /* initialized at runtime */
174 
175  scanstate->ns_names = tf->ns_names;
176 
177  scanstate->ns_uris =
178  ExecInitExprList(tf->ns_uris, (PlanState *) scanstate);
179  scanstate->docexpr =
180  ExecInitExpr((Expr *) tf->docexpr, (PlanState *) scanstate);
181  scanstate->rowexpr =
182  ExecInitExpr((Expr *) tf->rowexpr, (PlanState *) scanstate);
183  scanstate->colexprs =
184  ExecInitExprList(tf->colexprs, (PlanState *) scanstate);
185  scanstate->coldefexprs =
186  ExecInitExprList(tf->coldefexprs, (PlanState *) scanstate);
187  scanstate->colvalexprs =
188  ExecInitExprList(tf->colvalexprs, (PlanState *) scanstate);
189  scanstate->passingvalexprs =
190  ExecInitExprList(tf->passingvalexprs, (PlanState *) scanstate);
191 
192  scanstate->notnulls = tf->notnulls;
193 
194  /* these are allocated now and initialized later */
195  scanstate->in_functions = palloc(sizeof(FmgrInfo) * tupdesc->natts);
196  scanstate->typioparams = palloc(sizeof(Oid) * tupdesc->natts);
197 
198  /*
199  * Fill in the necessary fmgr infos.
200  */
201  for (i = 0; i < tupdesc->natts; i++)
202  {
203  Oid in_funcid;
204 
205  getTypeInputInfo(TupleDescAttr(tupdesc, i)->atttypid,
206  &in_funcid, &scanstate->typioparams[i]);
207  fmgr_info(in_funcid, &scanstate->in_functions[i]);
208  }
209 
210  return scanstate;
211 }
#define Assert(condition)
Definition: c.h:812
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:330
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:224
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:138
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:270
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1898
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1842
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:86
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:485
#define EXEC_FLAG_MARK
Definition: executor.h:69
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
int i
Definition: isn.c:72
const TableFuncRoutine JsonbTableRoutine
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2874
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void * palloc(Size size)
Definition: mcxt.c:1317
#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:155
#define innerPlan(node)
Definition: plannodes.h:182
#define outerPlan(node)
Definition: plannodes.h:183
unsigned int Oid
Definition: postgres_ext.h:31
@ TFT_XMLTABLE
Definition: primnodes.h:99
Definition: fmgr.h:57
ExprState * qual
Definition: execnodes.h:1148
Plan * plan
Definition: execnodes.h:1127
EState * state
Definition: execnodes.h:1129
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1133
PlanState ps
Definition: execnodes.h:1574
MemoryContext perTableCxt
Definition: execnodes.h:2008
Bitmapset * notnulls
Definition: execnodes.h:2002
const struct TableFuncRoutine * routine
Definition: execnodes.h:2004
ExprState * rowexpr
Definition: execnodes.h:1995
FmgrInfo * in_functions
Definition: execnodes.h:2005
List * passingvalexprs
Definition: execnodes.h:1999
ExprState * docexpr
Definition: execnodes.h:1994
TableFunc * tablefunc
Definition: plannodes.h:634
Node * docexpr
Definition: primnodes.h:119
Node * rowexpr
Definition: primnodes.h:121
List * colexprs
Definition: primnodes.h:131
TableFuncType functype
Definition: primnodes.h:113
TupleDesc BuildDescFromLists(const List *names, const List *types, const List *typmods, const List *collations)
Definition: tupdesc.c:858
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
const TableFuncRoutine XmlTableRoutine
Definition: xml.c:223

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BuildDescFromLists(), TableFuncScanState::coldefexprs, TableFuncScanState::colexprs, TableFunc::colexprs, TableFuncScanState::colvalexprs, CurrentMemoryContext, TableFuncScanState::docexpr, TableFunc::docexpr, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignScanProjectionInfo(), ExecInitExpr(), ExecInitExprList(), ExecInitQual(), ExecInitResultTypeTL(), ExecInitScanTupleSlot(), PlanState::ExecProcNode, ExecTableFuncScan(), fmgr_info(), TableFunc::functype, getTypeInputInfo(), i, TableFuncScanState::in_functions, innerPlan, JsonbTableRoutine, makeNode, TupleDescData::natts, TableFuncScanState::notnulls, TableFuncScanState::ns_names, TableFuncScanState::ns_uris, TableFuncScanState::opaque, outerPlan, palloc(), TableFuncScanState::passingvalexprs, TableFuncScanState::perTableCxt, PlanState::plan, ScanState::ps, PlanState::qual, TableFuncScanState::routine, TableFuncScanState::rowexpr, TableFunc::rowexpr, TableFuncScan::scan, TableFuncScanState::ss, PlanState::state, TableFuncScan::tablefunc, TFT_XMLTABLE, TTSOpsMinimalTuple, TupleDescAttr, TableFuncScanState::typioparams, and XmlTableRoutine.

Referenced by ExecInitNode().

◆ ExecReScanTableFuncScan()

void ExecReScanTableFuncScan ( TableFuncScanState node)

Definition at line 237 of file nodeTableFuncscan.c.

238 {
239  Bitmapset *chgparam = node->ss.ps.chgParam;
240 
241  if (node->ss.ps.ps_ResultTupleSlot)
243  ExecScanReScan(&node->ss);
244 
245  /*
246  * Recompute when parameters are changed.
247  */
248  if (chgparam)
249  {
250  if (node->tupstore != NULL)
251  {
252  tuplestore_end(node->tupstore);
253  node->tupstore = NULL;
254  }
255  }
256 
257  if (node->tupstore != NULL)
259 }
void ExecScanReScan(ScanState *node)
Definition: execScan.c:297
Bitmapset * chgParam
Definition: execnodes.h:1159
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1165
void tuplestore_rescan(Tuplestorestate *state)
Definition: tuplestore.c:1285
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454

References PlanState::chgParam, ExecClearTuple(), ExecScanReScan(), 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 97 of file nodeTableFuncscan.c.

98 {
100 
101  return ExecScan(&node->ss,
104 }
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:156
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:484
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:485
static bool TableFuncRecheck(TableFuncScanState *node, TupleTableSlot *slot)
static TupleTableSlot * TableFuncNext(TableFuncScanState *node)
#define castNode(_type_, nodeptr)
Definition: nodes.h:176

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

Referenced by ExecInitTableFuncScan().

◆ TableFuncNext()

static TupleTableSlot * TableFuncNext ( TableFuncScanState node)
static

Definition at line 54 of file nodeTableFuncscan.c.

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

References 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 81 of file nodeTableFuncscan.c.

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

Referenced by ExecTableFuncScan().

◆ tfuncFetchRows()

static void tfuncFetchRows ( TableFuncScanState tstate,
ExprContext econtext 
)
static

Definition at line 268 of file nodeTableFuncscan.c.

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

References Assert, TableFuncRoutine::DestroyOpaque, TableFuncScanState::docexpr, ExprContext::ecxt_per_query_memory, ExecEvalExpr(), TableFuncRoutine::InitOpaque, MemoryContextReset(), MemoryContextSwitchTo(), TupleDescData::natts, TableFuncScanState::opaque, TableFuncScanState::ordinal, TableFuncScanState::perTableCxt, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, TableFuncScanState::routine, TableFuncScanState::ss, ScanState::ss_ScanTupleSlot, tfuncInitialize(), tfuncLoadRows(), TupleTableSlot::tts_tupleDescriptor, tuplestore_begin_heap(), TableFuncScanState::tupstore, value, and work_mem.

Referenced by TableFuncNext().

◆ tfuncInitialize()

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

Definition at line 340 of file nodeTableFuncscan.c.

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

References TableFuncScanState::colexprs, ereport, errcode(), errdetail(), errmsg(), ERROR, ExecEvalExpr(), forboth, lfirst, lfirst_node, NameStr, TableFuncScanState::ns_names, TableFuncScanState::ns_uris, PlanState::plan, ScanState::ps, TableFuncScanState::routine, TableFuncScanState::rowexpr, TableFuncRoutine::SetColumnFilter, TableFuncRoutine::SetDocument, TableFuncRoutine::SetNamespace, TableFuncRoutine::SetRowFilter, TableFuncScanState::ss, ScanState::ss_ScanTupleSlot, strVal, TextDatumGetCString, TupleTableSlot::tts_tupleDescriptor, TupleDescAttr, and value.

Referenced by tfuncFetchRows().

◆ tfuncLoadRows()

static void tfuncLoadRows ( TableFuncScanState tstate,
ExprContext econtext 
)
static

Definition at line 435 of file nodeTableFuncscan.c.

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

References bms_is_member(), CHECK_FOR_INTERRUPTS, TableFuncScanState::coldefexprs, ExprContext::ecxt_per_tuple_memory, ereport, errcode(), errmsg(), ERROR, ExecClearTuple(), ExecEvalExpr(), TableFuncRoutine::FetchRow, TableFuncRoutine::GetValue, Int32GetDatum(), lfirst, list_head(), lnext(), MemoryContextReset(), MemoryContextSwitchTo(), NameStr, TupleDescData::natts, TableFuncScanState::notnulls, TableFuncScanState::ordinal, PlanState::plan, ScanState::ps, TableFuncScanState::routine, TableFuncScanState::ss, ScanState::ss_ScanTupleSlot, TupleTableSlot::tts_isnull, TupleTableSlot::tts_tupleDescriptor, TupleTableSlot::tts_values, TupleDescAttr, tuplestore_putvalues(), TableFuncScanState::tupstore, and values.

Referenced by tfuncFetchRows().