PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
parse_jsontable.c File Reference
#include "postgres.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "parser/parse_clause.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
#include "parser/parse_type.h"
#include "utils/fmgrprotos.h"
#include "utils/json.h"
#include "utils/lsyscache.h"
Include dependency graph for parse_jsontable.c:

Go to the source code of this file.

Data Structures

struct  JsonTableParseContext
 

Typedefs

typedef struct JsonTableParseContext JsonTableParseContext
 

Functions

static JsonTablePlantransformJsonTableColumns (JsonTableParseContext *cxt, List *columns, List *passingArgs, JsonTablePathSpec *pathspec)
 
static JsonTablePlantransformJsonTableNestedColumns (JsonTableParseContext *cxt, List *passingArgs, List *columns)
 
static JsonFuncExprtransformJsonTableColumn (JsonTableColumn *jtc, Node *contextItemExpr, List *passingArgs)
 
static bool isCompositeType (Oid typid)
 
static JsonTablePlanmakeJsonTablePathScan (JsonTablePathSpec *pathspec, bool errorOnError, int colMin, int colMax, JsonTablePlan *childplan)
 
static void CheckDuplicateColumnOrPathNames (JsonTableParseContext *cxt, List *columns)
 
static bool LookupPathOrColumnName (JsonTableParseContext *cxt, char *name)
 
static char * generateJsonTablePathName (JsonTableParseContext *cxt)
 
static JsonTablePlanmakeJsonTableSiblingJoin (JsonTablePlan *lplan, JsonTablePlan *rplan)
 
ParseNamespaceItemtransformJsonTable (ParseState *pstate, JsonTable *jt)
 

Typedef Documentation

◆ JsonTableParseContext

Function Documentation

◆ CheckDuplicateColumnOrPathNames()

static void CheckDuplicateColumnOrPathNames ( JsonTableParseContext cxt,
List columns 
)
static

Definition at line 171 of file parse_jsontable.c.

173 {
174  ListCell *lc1;
175 
176  foreach(lc1, columns)
177  {
179 
180  if (jtc->coltype == JTC_NESTED)
181  {
182  if (jtc->pathspec->name)
183  {
184  if (LookupPathOrColumnName(cxt, jtc->pathspec->name))
185  ereport(ERROR,
186  errcode(ERRCODE_DUPLICATE_ALIAS),
187  errmsg("duplicate JSON_TABLE column or path name: %s",
188  jtc->pathspec->name),
190  jtc->pathspec->name_location));
191  cxt->pathNames = lappend(cxt->pathNames, jtc->pathspec->name);
192  }
193 
195  }
196  else
197  {
198  if (LookupPathOrColumnName(cxt, jtc->name))
199  ereport(ERROR,
200  errcode(ERRCODE_DUPLICATE_ALIAS),
201  errmsg("duplicate JSON_TABLE column or path name: %s",
202  jtc->name),
203  parser_errposition(cxt->pstate, jtc->location));
204  cxt->pathNames = lappend(cxt->pathNames, jtc->name);
205  }
206  }
207 }
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
List * lappend(List *list, void *datum)
Definition: list.c:339
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
static bool LookupPathOrColumnName(JsonTableParseContext *cxt, char *name)
static void CheckDuplicateColumnOrPathNames(JsonTableParseContext *cxt, List *columns)
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
@ JTC_NESTED
Definition: parsenodes.h:1844
#define lfirst(lc)
Definition: pg_list.h:172
ParseLoc location
Definition: parsenodes.h:1864
JsonTableColumnType coltype
Definition: parsenodes.h:1854
JsonTablePathSpec * pathspec
Definition: parsenodes.h:1857
ParseLoc name_location
Definition: parsenodes.h:1813

References castNode, JsonTableColumn::coltype, JsonTableColumn::columns, ereport, errcode(), errmsg(), ERROR, JTC_NESTED, lappend(), lfirst, JsonTableColumn::location, LookupPathOrColumnName(), JsonTablePathSpec::name, JsonTableColumn::name, JsonTablePathSpec::name_location, parser_errposition(), JsonTableParseContext::pathNames, JsonTableColumn::pathspec, and JsonTableParseContext::pstate.

Referenced by transformJsonTable().

◆ generateJsonTablePathName()

static char * generateJsonTablePathName ( JsonTableParseContext cxt)
static

Definition at line 229 of file parse_jsontable.c.

230 {
231  char namebuf[32];
232  char *name = namebuf;
233 
234  snprintf(namebuf, sizeof(namebuf), "json_table_path_%d",
235  cxt->pathNameId++);
236 
237  name = pstrdup(name);
238  cxt->pathNames = lappend(cxt->pathNames, name);
239 
240  return name;
241 }
char * pstrdup(const char *in)
Definition: mcxt.c:1696
#define snprintf
Definition: port.h:238
const char * name

References lappend(), name, JsonTableParseContext::pathNameId, JsonTableParseContext::pathNames, pstrdup(), and snprintf.

Referenced by transformJsonTable(), and transformJsonTableNestedColumns().

◆ isCompositeType()

static bool isCompositeType ( Oid  typid)
static

Definition at line 375 of file parse_jsontable.c.

376 {
377  char typtype = get_typtype(typid);
378 
379  return typid == JSONOID ||
380  typid == JSONBOID ||
381  typid == RECORDOID ||
382  type_is_array(typid) ||
383  typtype == TYPTYPE_COMPOSITE ||
384  /* domain over one of the above? */
385  (typtype == TYPTYPE_DOMAIN &&
386  isCompositeType(getBaseType(typid)));
387 }
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
static bool isCompositeType(Oid typid)

References get_typtype(), getBaseType(), and type_is_array.

Referenced by AlterTypeNamespaceInternal(), and transformJsonTableColumns().

◆ LookupPathOrColumnName()

static bool LookupPathOrColumnName ( JsonTableParseContext cxt,
char *  name 
)
static

Definition at line 214 of file parse_jsontable.c.

215 {
216  ListCell *lc;
217 
218  foreach(lc, cxt->pathNames)
219  {
220  if (strcmp(name, (const char *) lfirst(lc)) == 0)
221  return true;
222  }
223 
224  return false;
225 }

References lfirst, name, and JsonTableParseContext::pathNames.

Referenced by CheckDuplicateColumnOrPathNames().

◆ makeJsonTablePathScan()

static JsonTablePlan * makeJsonTablePathScan ( JsonTablePathSpec pathspec,
bool  errorOnError,
int  colMin,
int  colMax,
JsonTablePlan childplan 
)
static

Definition at line 497 of file parse_jsontable.c.

500 {
502  char *pathstring;
503  Const *value;
504 
505  Assert(IsA(pathspec->string, A_Const));
506  pathstring = castNode(A_Const, pathspec->string)->val.sval.sval;
507  value = makeConst(JSONPATHOID, -1, InvalidOid, -1,
509  CStringGetDatum(pathstring)),
510  false, false);
511 
512  scan->plan.type = T_JsonTablePathScan;
513  scan->path = makeJsonTablePath(value, pathspec->name);
514  scan->errorOnError = errorOnError;
515 
516  scan->child = childplan;
517 
518  scan->colMin = colMin;
519  scan->colMax = colMax;
520 
521  return (JsonTablePlan *) scan;
522 }
#define Assert(condition)
Definition: c.h:863
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
static struct @160 value
Datum jsonpath_in(PG_FUNCTION_ARGS)
Definition: jsonpath.c:98
JsonTablePath * makeJsonTablePath(Const *pathvalue, char *pathname)
Definition: makefuncs.c:976
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:301
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define makeNode(_type_)
Definition: nodes.h:155
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
#define InvalidOid
Definition: postgres_ext.h:36
JsonTablePath * path
Definition: primnodes.h:1898
JsonTablePlan * child
Definition: primnodes.h:1907
JsonTablePlan plan
Definition: primnodes.h:1895

References Assert, castNode, JsonTablePathScan::child, JsonTablePathScan::colMax, JsonTablePathScan::colMin, CStringGetDatum(), DirectFunctionCall1, JsonTablePathScan::errorOnError, InvalidOid, IsA, jsonpath_in(), makeConst(), makeJsonTablePath(), makeNode, JsonTablePathSpec::name, JsonTablePathScan::path, JsonTablePathScan::plan, JsonTablePathSpec::string, and value.

Referenced by transformJsonTableColumns().

◆ makeJsonTableSiblingJoin()

static JsonTablePlan * makeJsonTableSiblingJoin ( JsonTablePlan lplan,
JsonTablePlan rplan 
)
static

Definition at line 532 of file parse_jsontable.c.

533 {
535 
536  join->plan.type = T_JsonTableSiblingJoin;
537  join->lplan = lplan;
538  join->rplan = rplan;
539 
540  return (JsonTablePlan *) join;
541 }
JsonTablePlan * rplan
Definition: primnodes.h:1928
JsonTablePlan * lplan
Definition: primnodes.h:1927
JsonTablePlan plan
Definition: primnodes.h:1925

References JsonTableSiblingJoin::lplan, makeNode, JsonTableSiblingJoin::plan, and JsonTableSiblingJoin::rplan.

Referenced by transformJsonTableNestedColumns().

◆ transformJsonTable()

ParseNamespaceItem* transformJsonTable ( ParseState pstate,
JsonTable jt 
)

Definition at line 74 of file parse_jsontable.c.

75 {
76  TableFunc *tf;
77  JsonFuncExpr *jfe;
78  JsonExpr *je;
79  JsonTablePathSpec *rootPathSpec = jt->pathspec;
80  bool is_lateral;
81  JsonTableParseContext cxt = {pstate};
82 
83  Assert(IsA(rootPathSpec->string, A_Const) &&
84  castNode(A_Const, rootPathSpec->string)->val.node.type == T_String);
85 
86  if (jt->on_error &&
90  ereport(ERROR,
91  errcode(ERRCODE_SYNTAX_ERROR),
92  errmsg("invalid %s behavior", "ON ERROR"),
93  errdetail("Only EMPTY [ ARRAY ] or ERROR is allowed in the top-level ON ERROR clause."),
94  parser_errposition(pstate, jt->on_error->location));
95 
96  cxt.pathNameId = 0;
97  if (rootPathSpec->name == NULL)
98  rootPathSpec->name = generateJsonTablePathName(&cxt);
99  cxt.pathNames = list_make1(rootPathSpec->name);
101 
102  /*
103  * We make lateral_only names of this level visible, whether or not the
104  * RangeTableFunc is explicitly marked LATERAL. This is needed for SQL
105  * spec compliance and seems useful on convenience grounds for all
106  * functions in FROM.
107  *
108  * (LATERAL can't nest within a single pstate level, so we don't need
109  * save/restore logic here.)
110  */
111  Assert(!pstate->p_lateral_active);
112  pstate->p_lateral_active = true;
113 
114  tf = makeNode(TableFunc);
115  tf->functype = TFT_JSON_TABLE;
116 
117  /*
118  * Transform JsonFuncExpr representing the top JSON_TABLE context_item and
119  * pathspec into a dummy JSON_TABLE_OP JsonExpr.
120  */
121  jfe = makeNode(JsonFuncExpr);
122  jfe->op = JSON_TABLE_OP;
123  jfe->context_item = jt->context_item;
124  jfe->pathspec = (Node *) rootPathSpec->string;
125  jfe->passing = jt->passing;
126  jfe->on_empty = NULL;
127  jfe->on_error = jt->on_error;
128  jfe->location = jt->location;
129  tf->docexpr = transformExpr(pstate, (Node *) jfe, EXPR_KIND_FROM_FUNCTION);
130 
131  /*
132  * Create a JsonTablePlan that will generate row pattern that becomes
133  * source data for JSON path expressions in jt->columns. This also adds
134  * the columns' transformed JsonExpr nodes into tf->colvalexprs.
135  */
136  cxt.jt = jt;
137  cxt.tf = tf;
138  tf->plan = (Node *) transformJsonTableColumns(&cxt, jt->columns,
139  jt->passing,
140  rootPathSpec);
141 
142  /*
143  * Copy the transformed PASSING arguments into the TableFunc node, because
144  * they are evaluated separately from the JsonExpr that we just put in
145  * TableFunc.docexpr. JsonExpr.passing_values is still kept around for
146  * get_json_table().
147  */
148  je = (JsonExpr *) tf->docexpr;
149  tf->passingvalexprs = copyObject(je->passing_values);
150 
151  tf->ordinalitycol = -1; /* undefine ordinality column number */
152  tf->location = jt->location;
153 
154  pstate->p_lateral_active = false;
155 
156  /*
157  * Mark the RTE as LATERAL if the user said LATERAL explicitly, or if
158  * there are any lateral cross-references in it.
159  */
160  is_lateral = jt->lateral || contain_vars_of_level((Node *) tf, 0);
161 
162  return addRangeTableEntryForTableFunc(pstate,
163  tf, jt->alias, is_lateral, true);
164 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
#define copyObject(obj)
Definition: nodes.h:224
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:118
static char * generateJsonTablePathName(JsonTableParseContext *cxt)
static JsonTablePlan * transformJsonTableColumns(JsonTableParseContext *cxt, List *columns, List *passingArgs, JsonTablePathSpec *pathspec)
@ EXPR_KIND_FROM_FUNCTION
Definition: parse_node.h:45
ParseNamespaceItem * addRangeTableEntryForTableFunc(ParseState *pstate, TableFunc *tf, Alias *alias, bool lateral, bool inFromCl)
#define list_make1(x1)
Definition: pg_list.h:212
@ TFT_JSON_TABLE
Definition: primnodes.h:100
@ JSON_BEHAVIOR_ERROR
Definition: primnodes.h:1766
@ JSON_BEHAVIOR_EMPTY
Definition: primnodes.h:1767
@ JSON_BEHAVIOR_EMPTY_ARRAY
Definition: primnodes.h:1771
@ JSON_TABLE_OP
Definition: primnodes.h:1805
ParseLoc location
Definition: primnodes.h:1793
JsonBehaviorType btype
Definition: primnodes.h:1790
List * passing_values
Definition: primnodes.h:1836
JsonExprOp op
Definition: parsenodes.h:1788
List * passing
Definition: parsenodes.h:1793
JsonBehavior * on_empty
Definition: parsenodes.h:1795
ParseLoc location
Definition: parsenodes.h:1799
Node * pathspec
Definition: parsenodes.h:1792
JsonBehavior * on_error
Definition: parsenodes.h:1796
JsonValueExpr * context_item
Definition: parsenodes.h:1791
JsonBehavior * on_error
Definition: parsenodes.h:1828
List * columns
Definition: parsenodes.h:1827
JsonTablePathSpec * pathspec
Definition: parsenodes.h:1825
Alias * alias
Definition: parsenodes.h:1829
bool lateral
Definition: parsenodes.h:1830
List * passing
Definition: parsenodes.h:1826
JsonValueExpr * context_item
Definition: parsenodes.h:1824
ParseLoc location
Definition: parsenodes.h:1831
Definition: nodes.h:129
bool p_lateral_active
Definition: parse_node.h:221
ParseLoc location
Definition: primnodes.h:145
Node * docexpr
Definition: primnodes.h:119
TableFuncType functype
Definition: primnodes.h:113
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:446

References addRangeTableEntryForTableFunc(), JsonTable::alias, Assert, JsonBehavior::btype, castNode, CheckDuplicateColumnOrPathNames(), JsonTable::columns, contain_vars_of_level(), JsonFuncExpr::context_item, JsonTable::context_item, copyObject, TableFunc::docexpr, ereport, errcode(), errdetail(), errmsg(), ERROR, EXPR_KIND_FROM_FUNCTION, TableFunc::functype, generateJsonTablePathName(), IsA, JSON_BEHAVIOR_EMPTY, JSON_BEHAVIOR_EMPTY_ARRAY, JSON_BEHAVIOR_ERROR, JSON_TABLE_OP, JsonTableParseContext::jt, JsonTable::lateral, list_make1, JsonFuncExpr::location, JsonTable::location, TableFunc::location, JsonBehavior::location, makeNode, JsonTablePathSpec::name, JsonFuncExpr::on_empty, JsonFuncExpr::on_error, JsonTable::on_error, JsonFuncExpr::op, ParseState::p_lateral_active, parser_errposition(), JsonFuncExpr::passing, JsonTable::passing, JsonExpr::passing_values, JsonTableParseContext::pathNameId, JsonTableParseContext::pathNames, JsonFuncExpr::pathspec, JsonTable::pathspec, JsonTablePathSpec::string, JsonTableParseContext::tf, TFT_JSON_TABLE, transformExpr(), and transformJsonTableColumns().

Referenced by transformFromClauseItem().

◆ transformJsonTableColumn()

static JsonFuncExpr * transformJsonTableColumn ( JsonTableColumn jtc,
Node contextItemExpr,
List passingArgs 
)
static

Definition at line 397 of file parse_jsontable.c.

399 {
400  Node *pathspec;
402 
403  if (jtc->coltype == JTC_REGULAR)
404  jfexpr->op = JSON_VALUE_OP;
405  else if (jtc->coltype == JTC_EXISTS)
406  jfexpr->op = JSON_EXISTS_OP;
407  else
408  jfexpr->op = JSON_QUERY_OP;
409 
410  /* Pass the column name so any runtime JsonExpr errors can print it. */
411  Assert(jtc->name != NULL);
412  jfexpr->column_name = pstrdup(jtc->name);
413 
414  jfexpr->context_item = makeJsonValueExpr((Expr *) contextItemExpr, NULL,
417  -1));
418  if (jtc->pathspec)
419  pathspec = (Node *) jtc->pathspec->string;
420  else
421  {
422  /* Construct default path as '$."column_name"' */
423  StringInfoData path;
424 
425  initStringInfo(&path);
426 
427  appendStringInfoString(&path, "$.");
428  escape_json(&path, jtc->name);
429 
430  pathspec = makeStringConst(path.data, -1);
431  }
432  jfexpr->pathspec = pathspec;
433  jfexpr->passing = passingArgs;
434  jfexpr->output = makeNode(JsonOutput);
435  jfexpr->output->typeName = jtc->typeName;
437  jfexpr->output->returning->format = jtc->format;
438  jfexpr->on_empty = jtc->on_empty;
439  jfexpr->on_error = jtc->on_error;
440  jfexpr->quotes = jtc->quotes;
441  jfexpr->wrapper = jtc->wrapper;
442  jfexpr->location = jtc->location;
443 
444  return jfexpr;
445 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1602
Node * makeStringConst(char *str, int location)
Definition: makefuncs.c:568
JsonFormat * makeJsonFormat(JsonFormatType type, JsonEncoding encoding, int location)
Definition: makefuncs.c:872
JsonValueExpr * makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr, JsonFormat *format)
Definition: makefuncs.c:888
@ JTC_EXISTS
Definition: parsenodes.h:1842
@ JTC_REGULAR
Definition: parsenodes.h:1841
@ JS_FORMAT_DEFAULT
Definition: primnodes.h:1638
@ JS_ENC_DEFAULT
Definition: primnodes.h:1626
@ JSON_QUERY_OP
Definition: primnodes.h:1803
@ JSON_EXISTS_OP
Definition: primnodes.h:1802
@ JSON_VALUE_OP
Definition: primnodes.h:1804
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:179
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56
JsonOutput * output
Definition: parsenodes.h:1794
char * column_name
Definition: parsenodes.h:1789
JsonWrapper wrapper
Definition: parsenodes.h:1797
JsonQuotes quotes
Definition: parsenodes.h:1798
JsonReturning * returning
Definition: parsenodes.h:1755
TypeName * typeName
Definition: parsenodes.h:1754
JsonFormat * format
Definition: primnodes.h:1663
JsonBehavior * on_empty
Definition: parsenodes.h:1862
JsonWrapper wrapper
Definition: parsenodes.h:1859
JsonBehavior * on_error
Definition: parsenodes.h:1863
JsonQuotes quotes
Definition: parsenodes.h:1860
JsonFormat * format
Definition: parsenodes.h:1858
TypeName * typeName
Definition: parsenodes.h:1856

References appendStringInfoString(), Assert, JsonTableColumn::coltype, JsonFuncExpr::column_name, JsonFuncExpr::context_item, escape_json(), initStringInfo(), JS_ENC_DEFAULT, JS_FORMAT_DEFAULT, JSON_EXISTS_OP, JSON_QUERY_OP, JSON_VALUE_OP, JTC_EXISTS, JTC_REGULAR, makeJsonFormat(), makeJsonValueExpr(), makeNode, makeStringConst(), JsonTableColumn::name, JsonFuncExpr::op, JsonTableColumn::pathspec, pstrdup(), and JsonTablePathSpec::string.

Referenced by transformJsonTableColumns().

◆ transformJsonTableColumns()

static JsonTablePlan * transformJsonTableColumns ( JsonTableParseContext cxt,
List columns,
List passingArgs,
JsonTablePathSpec pathspec 
)
static

Definition at line 249 of file parse_jsontable.c.

252 {
253  ParseState *pstate = cxt->pstate;
254  JsonTable *jt = cxt->jt;
255  TableFunc *tf = cxt->tf;
256  ListCell *col;
257  bool ordinality_found = false;
258  bool errorOnError = jt->on_error &&
260  Oid contextItemTypid = exprType(tf->docexpr);
261  int colMin,
262  colMax;
263  JsonTablePlan *childplan;
264 
265  /* Start of column range */
266  colMin = list_length(tf->colvalexprs);
267 
268  foreach(col, columns)
269  {
271  Oid typid;
272  int32 typmod;
273  Oid typcoll = InvalidOid;
274  Node *colexpr;
275 
276  if (rawc->coltype != JTC_NESTED)
277  {
278  Assert(rawc->name);
279  tf->colnames = lappend(tf->colnames,
280  makeString(pstrdup(rawc->name)));
281  }
282 
283  /*
284  * Determine the type and typmod for the new column. FOR ORDINALITY
285  * columns are INTEGER by standard; the others are user-specified.
286  */
287  switch (rawc->coltype)
288  {
289  case JTC_FOR_ORDINALITY:
290  if (ordinality_found)
291  ereport(ERROR,
292  (errcode(ERRCODE_SYNTAX_ERROR),
293  errmsg("only one FOR ORDINALITY column is allowed"),
294  parser_errposition(pstate, rawc->location)));
295  ordinality_found = true;
296  colexpr = NULL;
297  typid = INT4OID;
298  typmod = -1;
299  break;
300 
301  case JTC_REGULAR:
302  typenameTypeIdAndMod(pstate, rawc->typeName, &typid, &typmod);
303 
304  /*
305  * Use JTC_FORMATTED so as to use JSON_QUERY for this column
306  * if the specified type is one that's better handled using
307  * JSON_QUERY() or if non-default WRAPPER or QUOTES behavior
308  * is specified.
309  */
310  if (isCompositeType(typid) ||
311  rawc->quotes != JS_QUOTES_UNSPEC ||
312  rawc->wrapper != JSW_UNSPEC)
313  rawc->coltype = JTC_FORMATTED;
314 
315  /* FALLTHROUGH */
316  case JTC_FORMATTED:
317  case JTC_EXISTS:
318  {
319  JsonFuncExpr *jfe;
321 
322  param->collation = InvalidOid;
323  param->typeId = contextItemTypid;
324  param->typeMod = -1;
325 
326  jfe = transformJsonTableColumn(rawc, (Node *) param,
327  passingArgs);
328 
329  colexpr = transformExpr(pstate, (Node *) jfe,
331  assign_expr_collations(pstate, colexpr);
332 
333  typid = exprType(colexpr);
334  typmod = exprTypmod(colexpr);
335  typcoll = exprCollation(colexpr);
336  break;
337  }
338 
339  case JTC_NESTED:
340  continue;
341 
342  default:
343  elog(ERROR, "unknown JSON_TABLE column type: %d", (int) rawc->coltype);
344  break;
345  }
346 
347  tf->coltypes = lappend_oid(tf->coltypes, typid);
348  tf->coltypmods = lappend_int(tf->coltypmods, typmod);
349  tf->colcollations = lappend_oid(tf->colcollations, typcoll);
350  tf->colvalexprs = lappend(tf->colvalexprs, colexpr);
351  }
352 
353  /* End of column range. */
354  if (list_length(tf->colvalexprs) == colMin)
355  {
356  /* No columns in this Scan beside the nested ones. */
357  colMax = colMin = -1;
358  }
359  else
360  colMax = list_length(tf->colvalexprs) - 1;
361 
362  /* Recursively transform nested columns */
363  childplan = transformJsonTableNestedColumns(cxt, passingArgs, columns);
364 
365  /* Create a "parent" scan responsible for all columns handled above. */
366  return makeJsonTablePathScan(pathspec, errorOnError, colMin, colMax,
367  childplan);
368 }
signed int int32
Definition: c.h:508
#define elog(elevel,...)
Definition: elog.h:225
List * lappend_int(List *list, int datum)
Definition: list.c:357
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
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
void assign_expr_collations(ParseState *pstate, Node *expr)
static JsonFuncExpr * transformJsonTableColumn(JsonTableColumn *jtc, Node *contextItemExpr, List *passingArgs)
static JsonTablePlan * makeJsonTablePathScan(JsonTablePathSpec *pathspec, bool errorOnError, int colMin, int colMax, JsonTablePlan *childplan)
static JsonTablePlan * transformJsonTableNestedColumns(JsonTableParseContext *cxt, List *passingArgs, List *columns)
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
Definition: parse_type.c:310
@ JTC_FORMATTED
Definition: parsenodes.h:1843
@ JTC_FOR_ORDINALITY
Definition: parsenodes.h:1840
@ JS_QUOTES_UNSPEC
Definition: parsenodes.h:1775
static int list_length(const List *l)
Definition: pg_list.h:152
unsigned int Oid
Definition: postgres_ext.h:31
@ JSW_UNSPEC
Definition: primnodes.h:1750
String * makeString(char *str)
Definition: value.c:63

References Assert, assign_expr_collations(), JsonBehavior::btype, castNode, JsonTableColumn::coltype, TableFunc::docexpr, elog, ereport, errcode(), errmsg(), ERROR, EXPR_KIND_FROM_FUNCTION, exprCollation(), exprType(), exprTypmod(), InvalidOid, isCompositeType(), JS_QUOTES_UNSPEC, JSON_BEHAVIOR_ERROR, JSW_UNSPEC, JsonTableParseContext::jt, JTC_EXISTS, JTC_FOR_ORDINALITY, JTC_FORMATTED, JTC_NESTED, JTC_REGULAR, lappend(), lappend_int(), lappend_oid(), lfirst, list_length(), JsonTableColumn::location, makeJsonTablePathScan(), makeNode, makeString(), JsonTableColumn::name, JsonTable::on_error, parser_errposition(), JsonTableParseContext::pstate, pstrdup(), JsonTableColumn::quotes, JsonTableParseContext::tf, transformExpr(), transformJsonTableColumn(), transformJsonTableNestedColumns(), CaseTestExpr::typeId, JsonTableColumn::typeName, typenameTypeIdAndMod(), and JsonTableColumn::wrapper.

Referenced by transformJsonTable(), and transformJsonTableNestedColumns().

◆ transformJsonTableNestedColumns()

static JsonTablePlan * transformJsonTableNestedColumns ( JsonTableParseContext cxt,
List passingArgs,
List columns 
)
static

Definition at line 452 of file parse_jsontable.c.

455 {
456  JsonTablePlan *plan = NULL;
457  ListCell *lc;
458 
459  /*
460  * If there are multiple NESTED COLUMNS clauses in 'columns', their
461  * respective plans will be combined using a "sibling join" plan, which
462  * effectively does a UNION of the sets of rows coming from each nested
463  * plan.
464  */
465  foreach(lc, columns)
466  {
468  JsonTablePlan *nested;
469 
470  if (jtc->coltype != JTC_NESTED)
471  continue;
472 
473  if (jtc->pathspec->name == NULL)
475 
476  nested = transformJsonTableColumns(cxt, jtc->columns, passingArgs,
477  jtc->pathspec);
478 
479  if (plan)
481  else
482  plan = nested;
483  }
484 
485  return plan;
486 }
static JsonTablePlan * makeJsonTableSiblingJoin(JsonTablePlan *lplan, JsonTablePlan *rplan)
#define plan(x)
Definition: pg_regress.c:161

References castNode, JsonTableColumn::coltype, JsonTableColumn::columns, generateJsonTablePathName(), JTC_NESTED, lfirst, makeJsonTableSiblingJoin(), JsonTablePathSpec::name, JsonTableColumn::pathspec, plan, and transformJsonTableColumns().

Referenced by transformJsonTableColumns().