PostgreSQL Source Code  git master
parse_jsontable.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * parse_jsontable.c
4  * parsing of JSON_TABLE
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/parser/parse_jsontable.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "postgres.h"
17 
18 #include "catalog/pg_collation.h"
19 #include "catalog/pg_type.h"
20 #include "miscadmin.h"
21 #include "nodes/makefuncs.h"
22 #include "nodes/nodeFuncs.h"
23 #include "optimizer/optimizer.h"
24 #include "parser/parse_clause.h"
25 #include "parser/parse_collate.h"
26 #include "parser/parse_expr.h"
27 #include "parser/parse_relation.h"
28 #include "parser/parse_type.h"
29 #include "utils/builtins.h"
30 #include "utils/json.h"
31 #include "utils/lsyscache.h"
32 
33 /* Context for transformJsonTableColumns() */
34 typedef struct JsonTableParseContext
35 {
39  List *pathNames; /* list of all path and columns names */
40  int pathNameId; /* path name id counter */
42 
44  List *columns,
45  List *passingArgs,
46  JsonTablePathSpec *pathspec);
48  List *passingArgs,
49  List *columns);
51  Node *contextItemExpr,
52  List *passingArgs);
53 static bool isCompositeType(Oid typid);
55  bool errorOnError,
56  int colMin, int colMax,
57  JsonTablePlan *childplan);
59  List *columns);
60 static bool LookupPathOrColumnName(JsonTableParseContext *cxt, char *name);
63  JsonTablePlan *rplan);
64 
65 /*
66  * transformJsonTable -
67  * Transform a raw JsonTable into TableFunc
68  *
69  * Mainly, this transforms the JSON_TABLE() document-generating expression
70  * (jt->context_item) and the column-generating expressions (jt->columns) to
71  * populate TableFunc.docexpr and TableFunc.colvalexprs, respectively. Also,
72  * the PASSING values (jt->passing) are transformed and added into
73  * TableFunc.passingvalexprs.
74  */
77 {
78  TableFunc *tf;
79  JsonFuncExpr *jfe;
80  JsonExpr *je;
81  JsonTablePathSpec *rootPathSpec = jt->pathspec;
82  bool is_lateral;
83  JsonTableParseContext cxt = {pstate};
84 
85  Assert(IsA(rootPathSpec->string, A_Const) &&
86  castNode(A_Const, rootPathSpec->string)->val.node.type == T_String);
87 
88  if (jt->on_error &&
92  ereport(ERROR,
93  errcode(ERRCODE_SYNTAX_ERROR),
94  errmsg("invalid ON ERROR behavior"),
95  errdetail("Only EMPTY or ERROR is allowed in the top-level ON ERROR clause."),
96  parser_errposition(pstate, jt->on_error->location));
97 
98  cxt.pathNameId = 0;
99  if (rootPathSpec->name == NULL)
100  rootPathSpec->name = generateJsonTablePathName(&cxt);
101  cxt.pathNames = list_make1(rootPathSpec->name);
103 
104  /*
105  * We make lateral_only names of this level visible, whether or not the
106  * RangeTableFunc is explicitly marked LATERAL. This is needed for SQL
107  * spec compliance and seems useful on convenience grounds for all
108  * functions in FROM.
109  *
110  * (LATERAL can't nest within a single pstate level, so we don't need
111  * save/restore logic here.)
112  */
113  Assert(!pstate->p_lateral_active);
114  pstate->p_lateral_active = true;
115 
116  tf = makeNode(TableFunc);
117  tf->functype = TFT_JSON_TABLE;
118 
119  /*
120  * Transform JsonFuncExpr representing the top JSON_TABLE context_item and
121  * pathspec into a dummy JSON_TABLE_OP JsonExpr.
122  */
123  jfe = makeNode(JsonFuncExpr);
124  jfe->op = JSON_TABLE_OP;
125  jfe->context_item = jt->context_item;
126  jfe->pathspec = (Node *) rootPathSpec->string;
127  jfe->passing = jt->passing;
128  jfe->on_empty = NULL;
129  jfe->on_error = jt->on_error;
130  jfe->location = jt->location;
131  tf->docexpr = transformExpr(pstate, (Node *) jfe, EXPR_KIND_FROM_FUNCTION);
132 
133  /*
134  * Create a JsonTablePlan that will generate row pattern that becomes
135  * source data for JSON path expressions in jt->columns. This also adds
136  * the columns' transformed JsonExpr nodes into tf->colvalexprs.
137  */
138  cxt.jt = jt;
139  cxt.tf = tf;
140  tf->plan = (Node *) transformJsonTableColumns(&cxt, jt->columns,
141  jt->passing,
142  rootPathSpec);
143 
144  /*
145  * Copy the transformed PASSING arguments into the TableFunc node, because
146  * they are evaluated separately from the JsonExpr that we just put in
147  * TableFunc.docexpr. JsonExpr.passing_values is still kept around for
148  * get_json_table().
149  */
150  je = (JsonExpr *) tf->docexpr;
151  tf->passingvalexprs = copyObject(je->passing_values);
152 
153  tf->ordinalitycol = -1; /* undefine ordinality column number */
154  tf->location = jt->location;
155 
156  pstate->p_lateral_active = false;
157 
158  /*
159  * Mark the RTE as LATERAL if the user said LATERAL explicitly, or if
160  * there are any lateral cross-references in it.
161  */
162  is_lateral = jt->lateral || contain_vars_of_level((Node *) tf, 0);
163 
164  return addRangeTableEntryForTableFunc(pstate,
165  tf, jt->alias, is_lateral, true);
166 }
167 
168 /*
169  * Check if a column / path name is duplicated in the given shared list of
170  * names.
171  */
172 static void
174  List *columns)
175 {
176  ListCell *lc1;
177 
178  foreach(lc1, columns)
179  {
181 
182  if (jtc->coltype == JTC_NESTED)
183  {
184  if (jtc->pathspec->name)
185  {
186  if (LookupPathOrColumnName(cxt, jtc->pathspec->name))
187  ereport(ERROR,
188  errcode(ERRCODE_DUPLICATE_ALIAS),
189  errmsg("duplicate JSON_TABLE column or path name: %s",
190  jtc->pathspec->name),
192  jtc->pathspec->name_location));
193  cxt->pathNames = lappend(cxt->pathNames, jtc->pathspec->name);
194  }
195 
197  }
198  else
199  {
200  if (LookupPathOrColumnName(cxt, jtc->name))
201  ereport(ERROR,
202  errcode(ERRCODE_DUPLICATE_ALIAS),
203  errmsg("duplicate JSON_TABLE column or path name: %s",
204  jtc->name),
205  parser_errposition(cxt->pstate, jtc->location));
206  cxt->pathNames = lappend(cxt->pathNames, jtc->name);
207  }
208  }
209 }
210 
211 /*
212  * Lookup a column/path name in the given name list, returning true if already
213  * there.
214  */
215 static bool
217 {
218  ListCell *lc;
219 
220  foreach(lc, cxt->pathNames)
221  {
222  if (strcmp(name, (const char *) lfirst(lc)) == 0)
223  return true;
224  }
225 
226  return false;
227 }
228 
229 /* Generate a new unique JSON_TABLE path name. */
230 static char *
232 {
233  char namebuf[32];
234  char *name = namebuf;
235 
236  snprintf(namebuf, sizeof(namebuf), "json_table_path_%d",
237  cxt->pathNameId++);
238 
239  name = pstrdup(name);
240  cxt->pathNames = lappend(cxt->pathNames, name);
241 
242  return name;
243 }
244 
245 /*
246  * Create a JsonTablePlan that will supply the source row for 'columns'
247  * using 'pathspec' and append the columns' transformed JsonExpr nodes and
248  * their type/collation information to cxt->tf.
249  */
250 static JsonTablePlan *
252  List *passingArgs,
253  JsonTablePathSpec *pathspec)
254 {
255  ParseState *pstate = cxt->pstate;
256  JsonTable *jt = cxt->jt;
257  TableFunc *tf = cxt->tf;
258  ListCell *col;
259  bool ordinality_found = false;
260  bool errorOnError = jt->on_error &&
262  Oid contextItemTypid = exprType(tf->docexpr);
263  int colMin,
264  colMax;
265  JsonTablePlan *childplan;
266 
267  /* Start of column range */
268  colMin = list_length(tf->colvalexprs);
269 
270  foreach(col, columns)
271  {
273  Oid typid;
274  int32 typmod;
275  Oid typcoll = InvalidOid;
276  Node *colexpr;
277 
278  if (rawc->coltype != JTC_NESTED)
279  {
280  Assert(rawc->name);
281  tf->colnames = lappend(tf->colnames,
282  makeString(pstrdup(rawc->name)));
283  }
284 
285  /*
286  * Determine the type and typmod for the new column. FOR ORDINALITY
287  * columns are INTEGER by standard; the others are user-specified.
288  */
289  switch (rawc->coltype)
290  {
291  case JTC_FOR_ORDINALITY:
292  if (ordinality_found)
293  ereport(ERROR,
294  (errcode(ERRCODE_SYNTAX_ERROR),
295  errmsg("cannot use more than one FOR ORDINALITY column"),
296  parser_errposition(pstate, rawc->location)));
297  ordinality_found = true;
298  colexpr = NULL;
299  typid = INT4OID;
300  typmod = -1;
301  break;
302 
303  case JTC_REGULAR:
304  typenameTypeIdAndMod(pstate, rawc->typeName, &typid, &typmod);
305 
306  /*
307  * Use JTC_FORMATTED so as to use JSON_QUERY for this column
308  * if the specified type is one that's better handled using
309  * JSON_QUERY() or if non-default WRAPPER or QUOTES behavior
310  * is specified.
311  */
312  if (isCompositeType(typid) ||
313  rawc->quotes != JS_QUOTES_UNSPEC ||
314  rawc->wrapper != JSW_UNSPEC)
315  rawc->coltype = JTC_FORMATTED;
316 
317  /* FALLTHROUGH */
318  case JTC_FORMATTED:
319  case JTC_EXISTS:
320  {
321  JsonFuncExpr *jfe;
323 
324  param->collation = InvalidOid;
325  param->typeId = contextItemTypid;
326  param->typeMod = -1;
327 
328  jfe = transformJsonTableColumn(rawc, (Node *) param,
329  passingArgs);
330 
331  colexpr = transformExpr(pstate, (Node *) jfe,
333  assign_expr_collations(pstate, colexpr);
334 
335  typid = exprType(colexpr);
336  typmod = exprTypmod(colexpr);
337  typcoll = exprCollation(colexpr);
338  break;
339  }
340 
341  case JTC_NESTED:
342  continue;
343 
344  default:
345  elog(ERROR, "unknown JSON_TABLE column type: %d", (int) rawc->coltype);
346  break;
347  }
348 
349  tf->coltypes = lappend_oid(tf->coltypes, typid);
350  tf->coltypmods = lappend_int(tf->coltypmods, typmod);
351  tf->colcollations = lappend_oid(tf->colcollations, typcoll);
352  tf->colvalexprs = lappend(tf->colvalexprs, colexpr);
353  }
354 
355  /* End of column range. */
356  if (list_length(tf->colvalexprs) == colMin)
357  {
358  /* No columns in this Scan beside the nested ones. */
359  colMax = colMin = -1;
360  }
361  else
362  colMax = list_length(tf->colvalexprs) - 1;
363 
364  /* Recursively transform nested columns */
365  childplan = transformJsonTableNestedColumns(cxt, passingArgs, columns);
366 
367  /* Create a "parent" scan responsible for all columns handled above. */
368  return makeJsonTablePathScan(pathspec, errorOnError, colMin, colMax,
369  childplan);
370 }
371 
372 /*
373  * Check if the type is "composite" for the purpose of checking whether to use
374  * JSON_VALUE() or JSON_QUERY() for a given JsonTableColumn.
375  */
376 static bool
378 {
379  char typtype = get_typtype(typid);
380 
381  return typid == JSONOID ||
382  typid == JSONBOID ||
383  typid == RECORDOID ||
384  type_is_array(typid) ||
385  typtype == TYPTYPE_COMPOSITE ||
386  /* domain over one of the above? */
387  (typtype == TYPTYPE_DOMAIN &&
388  isCompositeType(getBaseType(typid)));
389 }
390 
391 /*
392  * Transform JSON_TABLE column definition into a JsonFuncExpr
393  * This turns:
394  * - regular column into JSON_VALUE()
395  * - FORMAT JSON column into JSON_QUERY()
396  * - EXISTS column into JSON_EXISTS()
397  */
398 static JsonFuncExpr *
400  List *passingArgs)
401 {
402  Node *pathspec;
404 
405  if (jtc->coltype == JTC_REGULAR)
406  jfexpr->op = JSON_VALUE_OP;
407  else if (jtc->coltype == JTC_EXISTS)
408  jfexpr->op = JSON_EXISTS_OP;
409  else
410  jfexpr->op = JSON_QUERY_OP;
411 
412  /* Pass the column name so any runtime JsonExpr errors can print it. */
413  Assert(jtc->name != NULL);
414  jfexpr->column_name = pstrdup(jtc->name);
415 
416  jfexpr->context_item = makeJsonValueExpr((Expr *) contextItemExpr, NULL,
419  -1));
420  if (jtc->pathspec)
421  pathspec = (Node *) jtc->pathspec->string;
422  else
423  {
424  /* Construct default path as '$."column_name"' */
425  StringInfoData path;
426 
427  initStringInfo(&path);
428 
429  appendStringInfoString(&path, "$.");
430  escape_json(&path, jtc->name);
431 
432  pathspec = makeStringConst(path.data, -1);
433  }
434  jfexpr->pathspec = pathspec;
435  jfexpr->passing = passingArgs;
436  jfexpr->output = makeNode(JsonOutput);
437  jfexpr->output->typeName = jtc->typeName;
438  jfexpr->output->returning = makeNode(JsonReturning);
439  jfexpr->output->returning->format = jtc->format;
440  jfexpr->on_empty = jtc->on_empty;
441  jfexpr->on_error = jtc->on_error;
442  jfexpr->quotes = jtc->quotes;
443  jfexpr->wrapper = jtc->wrapper;
444  jfexpr->location = jtc->location;
445 
446  return jfexpr;
447 }
448 
449 /*
450  * Recursively transform nested columns and create child plan(s) that will be
451  * used to evaluate their row patterns.
452  */
453 static JsonTablePlan *
455  List *passingArgs,
456  List *columns)
457 {
458  JsonTablePlan *plan = NULL;
459  ListCell *lc;
460 
461  /*
462  * If there are multiple NESTED COLUMNS clauses in 'columns', their
463  * respective plans will be combined using a "sibling join" plan, which
464  * effectively does a UNION of the sets of rows coming from each nested
465  * plan.
466  */
467  foreach(lc, columns)
468  {
470  JsonTablePlan *nested;
471 
472  if (jtc->coltype != JTC_NESTED)
473  continue;
474 
475  if (jtc->pathspec->name == NULL)
477 
478  nested = transformJsonTableColumns(cxt, jtc->columns, passingArgs,
479  jtc->pathspec);
480 
481  if (plan)
483  else
484  plan = nested;
485  }
486 
487  return plan;
488 }
489 
490 /*
491  * Create a JsonTablePlan for given path and ON ERROR behavior.
492  *
493  * colMin and colMin give the range of columns computed by this scan in the
494  * global flat list of column expressions that will be passed to the
495  * JSON_TABLE's TableFunc. Both are -1 when all of columns are nested and
496  * thus computed by 'childplan'.
497  */
498 static JsonTablePlan *
499 makeJsonTablePathScan(JsonTablePathSpec *pathspec, bool errorOnError,
500  int colMin, int colMax,
501  JsonTablePlan *childplan)
502 {
504  char *pathstring;
505  Const *value;
506 
507  Assert(IsA(pathspec->string, A_Const));
508  pathstring = castNode(A_Const, pathspec->string)->val.sval.sval;
509  value = makeConst(JSONPATHOID, -1, InvalidOid, -1,
511  CStringGetDatum(pathstring)),
512  false, false);
513 
514  scan->plan.type = T_JsonTablePathScan;
515  scan->path = makeJsonTablePath(value, pathspec->name);
516  scan->errorOnError = errorOnError;
517 
518  scan->child = childplan;
519 
520  scan->colMin = colMin;
521  scan->colMax = colMax;
522 
523  return (JsonTablePlan *) scan;
524 }
525 
526 /*
527  * Create a JsonTablePlan that will perform a join of the rows coming from
528  * 'lplan' and 'rplan'.
529  *
530  * The default way of "joining" the rows is to perform a UNION between the
531  * sets of rows from 'lplan' and 'rplan'.
532  */
533 static JsonTablePlan *
535 {
537 
538  join->plan.type = T_JsonTableSiblingJoin;
539  join->lplan = lplan;
540  join->rplan = rplan;
541 
542  return (JsonTablePlan *) join;
543 }
signed int int32
Definition: c.h:494
#define Assert(condition)
Definition: c.h:858
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errcode(int sqlerrcode)
Definition: elog.c:857
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
static struct @155 value
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1549
Datum jsonpath_in(PG_FUNCTION_ARGS)
Definition: jsonpath.c:98
List * lappend(List *list, void *datum)
Definition: list.c:339
List * lappend_int(List *list, int datum)
Definition: list.c:357
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
char get_typtype(Oid typid)
Definition: lsyscache.c:2629
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2521
#define type_is_array(typid)
Definition: lsyscache.h:209
JsonTablePath * makeJsonTablePath(Const *pathvalue, char *pathname)
Definition: makefuncs.c:951
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:301
Node * makeStringConst(char *str, int location)
Definition: makefuncs.c:545
JsonFormat * makeJsonFormat(JsonFormatType type, JsonEncoding encoding, int location)
Definition: makefuncs.c:847
JsonValueExpr * makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr, JsonFormat *format)
Definition: makefuncs.c:863
char * pstrdup(const char *in)
Definition: mcxt.c:1695
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:298
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:816
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define copyObject(obj)
Definition: nodes.h:224
#define makeNode(_type_)
Definition: nodes.h:155
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:121
static JsonTablePlan * makeJsonTableSiblingJoin(JsonTablePlan *lplan, JsonTablePlan *rplan)
static char * generateJsonTablePathName(JsonTableParseContext *cxt)
struct JsonTableParseContext JsonTableParseContext
static bool LookupPathOrColumnName(JsonTableParseContext *cxt, char *name)
static JsonFuncExpr * transformJsonTableColumn(JsonTableColumn *jtc, Node *contextItemExpr, List *passingArgs)
static JsonTablePlan * makeJsonTablePathScan(JsonTablePathSpec *pathspec, bool errorOnError, int colMin, int colMax, JsonTablePlan *childplan)
ParseNamespaceItem * transformJsonTable(ParseState *pstate, JsonTable *jt)
static JsonTablePlan * transformJsonTableColumns(JsonTableParseContext *cxt, List *columns, List *passingArgs, JsonTablePathSpec *pathspec)
static bool isCompositeType(Oid typid)
static void CheckDuplicateColumnOrPathNames(JsonTableParseContext *cxt, List *columns)
static JsonTablePlan * transformJsonTableNestedColumns(JsonTableParseContext *cxt, List *passingArgs, List *columns)
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
@ EXPR_KIND_FROM_FUNCTION
Definition: parse_node.h:45
ParseNamespaceItem * addRangeTableEntryForTableFunc(ParseState *pstate, TableFunc *tf, Alias *alias, bool lateral, bool inFromCl)
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
Definition: parse_type.c:310
@ JTC_FORMATTED
Definition: parsenodes.h:1848
@ JTC_FOR_ORDINALITY
Definition: parsenodes.h:1845
@ JTC_NESTED
Definition: parsenodes.h:1849
@ JTC_EXISTS
Definition: parsenodes.h:1847
@ JTC_REGULAR
Definition: parsenodes.h:1846
@ JS_QUOTES_UNSPEC
Definition: parsenodes.h:1780
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define list_make1(x1)
Definition: pg_list.h:212
#define plan(x)
Definition: pg_regress.c:162
#define snprintf
Definition: port.h:238
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
@ JS_FORMAT_DEFAULT
Definition: primnodes.h:1608
@ TFT_JSON_TABLE
Definition: primnodes.h:100
@ JS_ENC_DEFAULT
Definition: primnodes.h:1596
@ JSW_UNSPEC
Definition: primnodes.h:1716
@ JSON_BEHAVIOR_ERROR
Definition: primnodes.h:1732
@ JSON_BEHAVIOR_EMPTY
Definition: primnodes.h:1733
@ JSON_BEHAVIOR_EMPTY_ARRAY
Definition: primnodes.h:1737
@ JSON_QUERY_OP
Definition: primnodes.h:1769
@ JSON_TABLE_OP
Definition: primnodes.h:1771
@ JSON_EXISTS_OP
Definition: primnodes.h:1768
@ JSON_VALUE_OP
Definition: primnodes.h:1770
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
ParseLoc location
Definition: primnodes.h:1759
JsonBehaviorType btype
Definition: primnodes.h:1756
List * passing_values
Definition: primnodes.h:1802
char * column_name
Definition: parsenodes.h:1794
JsonExprOp op
Definition: parsenodes.h:1793
List * passing
Definition: parsenodes.h:1798
JsonBehavior * on_empty
Definition: parsenodes.h:1800
ParseLoc location
Definition: parsenodes.h:1804
Node * pathspec
Definition: parsenodes.h:1797
JsonBehavior * on_error
Definition: parsenodes.h:1801
JsonValueExpr * context_item
Definition: parsenodes.h:1796
ParseLoc location
Definition: parsenodes.h:1869
JsonTableColumnType coltype
Definition: parsenodes.h:1859
JsonWrapper wrapper
Definition: parsenodes.h:1864
JsonQuotes quotes
Definition: parsenodes.h:1865
TypeName * typeName
Definition: parsenodes.h:1861
JsonTablePathSpec * pathspec
Definition: parsenodes.h:1862
JsonTablePath * path
Definition: primnodes.h:1870
JsonTablePlan * child
Definition: primnodes.h:1879
JsonTablePlan plan
Definition: primnodes.h:1867
ParseLoc name_location
Definition: parsenodes.h:1818
JsonTablePlan * rplan
Definition: primnodes.h:1900
JsonTablePlan * lplan
Definition: primnodes.h:1899
JsonTablePlan plan
Definition: primnodes.h:1897
JsonBehavior * on_error
Definition: parsenodes.h:1833
List * columns
Definition: parsenodes.h:1832
JsonTablePathSpec * pathspec
Definition: parsenodes.h:1830
Alias * alias
Definition: parsenodes.h:1834
bool lateral
Definition: parsenodes.h:1835
List * passing
Definition: parsenodes.h:1831
JsonValueExpr * context_item
Definition: parsenodes.h:1829
ParseLoc location
Definition: parsenodes.h:1836
Definition: pg_list.h:54
Definition: nodes.h:129
bool p_lateral_active
Definition: parse_node.h:203
ParseLoc location
Definition: primnodes.h:145
Node * docexpr
Definition: primnodes.h:119
TableFuncType functype
Definition: primnodes.h:113
String * makeString(char *str)
Definition: value.c:63
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:441
const char * name