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/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 214 of file nodeTableFuncscan.c.

References ExecClearTuple(), ExecFreeExprContext(), ScanState::ps, PlanState::ps_ResultTupleSlot, TableFuncScanState::ss, ScanState::ss_ScanTupleSlot, tuplestore_end(), and TableFuncScanState::tupstore.

Referenced by ExecEndNode().

215 {
216  /*
217  * Free the exprcontext
218  */
219  ExecFreeExprContext(&node->ss.ps);
220 
221  /*
222  * clean out the tuple table
223  */
224  if (node->ss.ps.ps_ResultTupleSlot)
227 
228  /*
229  * Release tuplestore resources
230  */
231  if (node->tupstore != NULL)
232  tuplestore_end(node->tupstore);
233  node->tupstore = NULL;
234 }
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1333
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:614
PlanState ps
Definition: execnodes.h:1330
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:977
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:453
Tuplestorestate * tupstore
Definition: execnodes.h:1718

◆ ExecInitTableFuncScan()

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

Definition at line 110 of file nodeTableFuncscan.c.

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

Referenced by ExecInitNode().

111 {
112  TableFuncScanState *scanstate;
113  TableFunc *tf = node->tablefunc;
114  TupleDesc tupdesc;
115  int i;
116 
117  /* check for unsupported flags */
118  Assert(!(eflags & EXEC_FLAG_MARK));
119 
120  /*
121  * TableFuncscan should not have any children.
122  */
123  Assert(outerPlan(node) == NULL);
124  Assert(innerPlan(node) == NULL);
125 
126  /*
127  * create new ScanState for node
128  */
129  scanstate = makeNode(TableFuncScanState);
130  scanstate->ss.ps.plan = (Plan *) node;
131  scanstate->ss.ps.state = estate;
132  scanstate->ss.ps.ExecProcNode = ExecTableFuncScan;
133 
134  /*
135  * Miscellaneous initialization
136  *
137  * create expression context for node
138  */
139  ExecAssignExprContext(estate, &scanstate->ss.ps);
140 
141  /*
142  * initialize source tuple type
143  */
144  tupdesc = BuildDescFromLists(tf->colnames,
145  tf->coltypes,
146  tf->coltypmods,
147  tf->colcollations);
148  /* and the corresponding scan slot */
149  ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc,
151 
152  /*
153  * Initialize result type and projection.
154  */
155  ExecInitResultTypeTL(&scanstate->ss.ps);
156  ExecAssignScanProjectionInfo(&scanstate->ss);
157 
158  /*
159  * initialize child expressions
160  */
161  scanstate->ss.ps.qual =
162  ExecInitQual(node->scan.plan.qual, &scanstate->ss.ps);
163 
164  /* Only XMLTABLE is supported currently */
165  scanstate->routine = &XmlTableRoutine;
166 
167  scanstate->perTableCxt =
169  "TableFunc per value context",
171  scanstate->opaque = NULL; /* initialized at runtime */
172 
173  scanstate->ns_names = tf->ns_names;
174 
175  scanstate->ns_uris =
176  ExecInitExprList(tf->ns_uris, (PlanState *) scanstate);
177  scanstate->docexpr =
178  ExecInitExpr((Expr *) tf->docexpr, (PlanState *) scanstate);
179  scanstate->rowexpr =
180  ExecInitExpr((Expr *) tf->rowexpr, (PlanState *) scanstate);
181  scanstate->colexprs =
182  ExecInitExprList(tf->colexprs, (PlanState *) scanstate);
183  scanstate->coldefexprs =
184  ExecInitExprList(tf->coldefexprs, (PlanState *) scanstate);
185 
186  scanstate->notnulls = tf->notnulls;
187 
188  /* these are allocated now and initialized later */
189  scanstate->in_functions = palloc(sizeof(FmgrInfo) * tupdesc->natts);
190  scanstate->typioparams = palloc(sizeof(Oid) * tupdesc->natts);
191 
192  /*
193  * Fill in the necessary fmgr infos.
194  */
195  for (i = 0; i < tupdesc->natts; i++)
196  {
197  Oid in_funcid;
198 
200  &in_funcid, &scanstate->typioparams[i]);
201  fmgr_info(in_funcid, &scanstate->in_functions[i]);
202  }
203 
204  return scanstate;
205 }
Definition: fmgr.h:56
List * qual
Definition: plannodes.h:141
Plan plan
Definition: plannodes.h:340
#define AllocSetContextCreate
Definition: memutils.h:170
Node * docexpr
Definition: primnodes.h:87
TupleDesc BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
Definition: tupdesc.c:894
List * colnames
Definition: primnodes.h:89
List * coltypmods
Definition: primnodes.h:91
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
TableFunc * tablefunc
Definition: plannodes.h:542
EState * state
Definition: execnodes.h:941
unsigned int Oid
Definition: postgres_ext.h:31
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:207
List * colcollations
Definition: primnodes.h:92
PlanState ps
Definition: execnodes.h:1330
const TableFuncRoutine XmlTableRoutine
Definition: xml.c:207
Bitmapset * notnulls
Definition: execnodes.h:1711
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:272
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:124
List * coldefexprs
Definition: primnodes.h:94
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
List * ns_names
Definition: primnodes.h:86
#define innerPlan(node)
Definition: plannodes.h:169
Node * rowexpr
Definition: primnodes.h:88
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1781
const struct TableFuncRoutine * routine
Definition: execnodes.h:1713
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1725
ExprState * docexpr
Definition: execnodes.h:1705
Bitmapset * notnulls
Definition: primnodes.h:95
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:316
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
Oid atttypid
Definition: pg_attribute.h:49
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2641
#define outerPlan(node)
Definition: plannodes.h:170
MemoryContext perTableCxt
Definition: execnodes.h:1717
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:945
List * coltypes
Definition: primnodes.h:90
Plan * plan
Definition: execnodes.h:939
List * colexprs
Definition: primnodes.h:93
#define makeNode(_type_)
Definition: nodes.h:573
#define Assert(condition)
Definition: c.h:739
#define EXEC_FLAG_MARK
Definition: executor.h:59
List * ns_uris
Definition: primnodes.h:85
FmgrInfo * in_functions
Definition: execnodes.h:1714
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:444
ExprState * qual
Definition: execnodes.h:960
static TupleTableSlot * ExecTableFuncScan(PlanState *pstate)
void * palloc(Size size)
Definition: mcxt.c:949
int i
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:121
ExprState * rowexpr
Definition: execnodes.h:1706
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85

◆ ExecReScanTableFuncScan()

void ExecReScanTableFuncScan ( TableFuncScanState node)

Definition at line 243 of file nodeTableFuncscan.c.

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

Referenced by ExecReScan().

244 {
245  Bitmapset *chgparam = node->ss.ps.chgParam;
246 
247  if (node->ss.ps.ps_ResultTupleSlot)
249  ExecScanReScan(&node->ss);
250 
251  /*
252  * Recompute when parameters are changed.
253  */
254  if (chgparam)
255  {
256  if (node->tupstore != NULL)
257  {
258  tuplestore_end(node->tupstore);
259  node->tupstore = NULL;
260  }
261  }
262 
263  if (node->tupstore != NULL)
265 }
void tuplestore_rescan(Tuplestorestate *state)
Definition: tuplestore.c:1233
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
PlanState ps
Definition: execnodes.h:1330
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:977
Bitmapset * chgParam
Definition: execnodes.h:971
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:453
void ExecScanReScan(ScanState *node)
Definition: execScan.c:299
Tuplestorestate * tupstore
Definition: execnodes.h:1718

◆ ExecTableFuncScan()

static TupleTableSlot* ExecTableFuncScan ( PlanState pstate)
static

Definition at line 96 of file nodeTableFuncscan.c.

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

Referenced by ExecInitTableFuncScan().

97 {
99 
100  return ExecScan(&node->ss,
103 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:594
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:158
static TupleTableSlot * TableFuncNext(TableFuncScanState *node)
static bool TableFuncRecheck(TableFuncScanState *node, TupleTableSlot *slot)
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:426
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:425

◆ TableFuncNext()

static TupleTableSlot * TableFuncNext ( TableFuncScanState node)
static

Definition at line 53 of file nodeTableFuncscan.c.

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

Referenced by ExecTableFuncScan().

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

◆ TableFuncRecheck()

static bool TableFuncRecheck ( TableFuncScanState node,
TupleTableSlot slot 
)
static

Definition at line 80 of file nodeTableFuncscan.c.

Referenced by ExecTableFuncScan().

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

◆ tfuncFetchRows()

static void tfuncFetchRows ( TableFuncScanState tstate,
ExprContext econtext 
)
static

Definition at line 274 of file nodeTableFuncscan.c.

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().

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

◆ tfuncInitialize()

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

Definition at line 345 of file nodeTableFuncscan.c.

References TableFuncScanState::colexprs, ereport, errcode(), errdetail(), errmsg(), ERROR, ExecEvalExpr(), forboth, lfirst, 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().

346 {
347  const TableFuncRoutine *routine = tstate->routine;
348  TupleDesc tupdesc;
349  ListCell *lc1,
350  *lc2;
351  bool isnull;
352  int colno;
353  Datum value;
354  int ordinalitycol =
355  ((TableFuncScan *) (tstate->ss.ps.plan))->tablefunc->ordinalitycol;
356 
357  /*
358  * Install the document as a possibly-toasted Datum into the tablefunc
359  * context.
360  */
361  routine->SetDocument(tstate, doc);
362 
363  /* Evaluate namespace specifications */
364  forboth(lc1, tstate->ns_uris, lc2, tstate->ns_names)
365  {
366  ExprState *expr = (ExprState *) lfirst(lc1);
367  Value *ns_node = (Value *) lfirst(lc2);
368  char *ns_uri;
369  char *ns_name;
370 
371  value = ExecEvalExpr((ExprState *) expr, econtext, &isnull);
372  if (isnull)
373  ereport(ERROR,
374  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
375  errmsg("namespace URI must not be null")));
376  ns_uri = TextDatumGetCString(value);
377 
378  /* DEFAULT is passed down to SetNamespace as NULL */
379  ns_name = ns_node ? strVal(ns_node) : NULL;
380 
381  routine->SetNamespace(tstate, ns_name, ns_uri);
382  }
383 
384  /* Install the row filter expression into the table builder context */
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  * Install the column filter expressions into the table builder context.
395  * If an expression is given, use that; otherwise the column name itself
396  * is the column filter.
397  */
398  colno = 0;
399  tupdesc = tstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
400  foreach(lc1, tstate->colexprs)
401  {
402  char *colfilter;
403  Form_pg_attribute att = TupleDescAttr(tupdesc, colno);
404 
405  if (colno != ordinalitycol)
406  {
407  ExprState *colexpr = lfirst(lc1);
408 
409  if (colexpr != NULL)
410  {
411  value = ExecEvalExpr(colexpr, econtext, &isnull);
412  if (isnull)
413  ereport(ERROR,
414  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
415  errmsg("column filter expression must not be null"),
416  errdetail("Filter for column \"%s\" is null.",
417  NameStr(att->attname))));
418  colfilter = TextDatumGetCString(value);
419  }
420  else
421  colfilter = NameStr(att->attname);
422 
423  routine->SetColumnFilter(tstate, colfilter, colno);
424  }
425 
426  colno++;
427  }
428 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:419
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
void(* SetColumnFilter)(struct TableFuncScanState *state, const char *path, int colnum)
Definition: tablefunc.h:59
static struct @145 value
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:608
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1333
void(* SetDocument)(struct TableFuncScanState *state, Datum value)
Definition: tablefunc.h:55
PlanState ps
Definition: execnodes.h:1330
void(* SetNamespace)(struct TableFuncScanState *state, const char *name, const char *uri)
Definition: tablefunc.h:56
#define ERROR
Definition: elog.h:43
const struct TableFuncRoutine * routine
Definition: execnodes.h:1713
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:285
int errdetail(const char *fmt,...)
Definition: elog.c:955
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
#define ereport(elevel, rest)
Definition: elog.h:141
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:124
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
Plan * plan
Definition: execnodes.h:939
#define lfirst(lc)
Definition: pg_list.h:190
Definition: value.h:42
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define NameStr(name)
Definition: c.h:616
void(* SetRowFilter)(struct TableFuncScanState *state, const char *path)
Definition: tablefunc.h:58
ExprState * rowexpr
Definition: execnodes.h:1706

◆ tfuncLoadRows()

static void tfuncLoadRows ( TableFuncScanState tstate,
ExprContext econtext 
)
static

Definition at line 434 of file nodeTableFuncscan.c.

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().

435 {
436  const TableFuncRoutine *routine = tstate->routine;
437  TupleTableSlot *slot = tstate->ss.ss_ScanTupleSlot;
438  TupleDesc tupdesc = slot->tts_tupleDescriptor;
439  Datum *values = slot->tts_values;
440  bool *nulls = slot->tts_isnull;
441  int natts = tupdesc->natts;
442  MemoryContext oldcxt;
443  int ordinalitycol;
444 
445  ordinalitycol =
446  ((TableFuncScan *) (tstate->ss.ps.plan))->tablefunc->ordinalitycol;
447 
448  /*
449  * We need a short-lived memory context that we can clean up each time
450  * around the loop, to avoid wasting space. Our default per-tuple context
451  * is fine for the job, since we won't have used it for anything yet in
452  * this tuple cycle.
453  */
454  oldcxt = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
455 
456  /*
457  * Keep requesting rows from the table builder until there aren't any.
458  */
459  while (routine->FetchRow(tstate))
460  {
461  ListCell *cell = list_head(tstate->coldefexprs);
462  int colno;
463 
465 
467 
468  /*
469  * Obtain the value of each column for this row, installing them into
470  * the slot; then add the tuple to the tuplestore.
471  */
472  for (colno = 0; colno < natts; colno++)
473  {
474  Form_pg_attribute att = TupleDescAttr(tupdesc, colno);
475 
476  if (colno == ordinalitycol)
477  {
478  /* Fast path for ordinality column */
479  values[colno] = Int32GetDatum(tstate->ordinal++);
480  nulls[colno] = false;
481  }
482  else
483  {
484  bool isnull;
485 
486  values[colno] = routine->GetValue(tstate,
487  colno,
488  att->atttypid,
489  att->atttypmod,
490  &isnull);
491 
492  /* No value? Evaluate and apply the default, if any */
493  if (isnull && cell != NULL)
494  {
495  ExprState *coldefexpr = (ExprState *) lfirst(cell);
496 
497  if (coldefexpr != NULL)
498  values[colno] = ExecEvalExpr(coldefexpr, econtext,
499  &isnull);
500  }
501 
502  /* Verify a possible NOT NULL constraint */
503  if (isnull && bms_is_member(colno, tstate->notnulls))
504  ereport(ERROR,
505  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
506  errmsg("null is not allowed in column \"%s\"",
507  NameStr(att->attname))));
508 
509  nulls[colno] = isnull;
510  }
511 
512  /* advance list of default expressions */
513  if (cell != NULL)
514  cell = lnext(tstate->coldefexprs, cell);
515  }
516 
517  tuplestore_putvalues(tstate->tupstore, tupdesc, values, nulls);
518 
520  }
521 
522  MemoryContextSwitchTo(oldcxt);
523 }
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:321
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:231
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:608
Datum * tts_values
Definition: tuptable.h:126
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1333
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
PlanState ps
Definition: execnodes.h:1330
#define ERROR
Definition: elog.h:43
Bitmapset * notnulls
Definition: execnodes.h:1711
const struct TableFuncRoutine * routine
Definition: execnodes.h:1713
bool * tts_isnull
Definition: tuptable.h:128
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:285
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
#define ereport(elevel, rest)
Definition: elog.h:141
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:124
uintptr_t Datum
Definition: postgres.h:367
Plan * plan
Definition: execnodes.h:939
#define lfirst(lc)
Definition: pg_list.h:190
Datum(* GetValue)(struct TableFuncScanState *state, int colnum, Oid typid, int32 typmod, bool *isnull)
Definition: tablefunc.h:62
bool(* FetchRow)(struct TableFuncScanState *state)
Definition: tablefunc.h:61
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define Int32GetDatum(X)
Definition: postgres.h:479
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define NameStr(name)
Definition: c.h:616
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
Tuplestorestate * tupstore
Definition: execnodes.h:1718
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427