PostgreSQL Source Code  git master
parse_jsontable.c File Reference
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "miscadmin.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/builtins.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 173 of file parse_jsontable.c.

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 }
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#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:1849
#define lfirst(lc)
Definition: pg_list.h:172
ParseLoc location
Definition: parsenodes.h:1869
JsonTableColumnType coltype
Definition: parsenodes.h:1859
JsonTablePathSpec * pathspec
Definition: parsenodes.h:1862
ParseLoc name_location
Definition: parsenodes.h:1818

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 231 of file parse_jsontable.c.

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 }
char * pstrdup(const char *in)
Definition: mcxt.c:1695
#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 377 of file parse_jsontable.c.

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 }
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 216 of file parse_jsontable.c.

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 }

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 499 of file parse_jsontable.c.

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 }
#define Assert(condition)
Definition: c.h:858
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
static struct @155 value
Datum jsonpath_in(PG_FUNCTION_ARGS)
Definition: jsonpath.c:98
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
#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:1870
JsonTablePlan * child
Definition: primnodes.h:1879
JsonTablePlan plan
Definition: primnodes.h:1867

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 534 of file parse_jsontable.c.

535 {
537 
538  join->plan.type = T_JsonTableSiblingJoin;
539  join->lplan = lplan;
540  join->rplan = rplan;
541 
542  return (JsonTablePlan *) join;
543 }
JsonTablePlan * rplan
Definition: primnodes.h:1900
JsonTablePlan * lplan
Definition: primnodes.h:1899
JsonTablePlan plan
Definition: primnodes.h:1897

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

Referenced by transformJsonTableNestedColumns().

◆ transformJsonTable()

ParseNamespaceItem* transformJsonTable ( ParseState pstate,
JsonTable jt 
)

Definition at line 76 of file parse_jsontable.c.

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 }
int errdetail(const char *fmt,...)
Definition: elog.c:1205
#define copyObject(obj)
Definition: nodes.h:224
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:121
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:1732
@ JSON_BEHAVIOR_EMPTY
Definition: primnodes.h:1733
@ JSON_BEHAVIOR_EMPTY_ARRAY
Definition: primnodes.h:1737
@ JSON_TABLE_OP
Definition: primnodes.h:1771
ParseLoc location
Definition: primnodes.h:1759
JsonBehaviorType btype
Definition: primnodes.h:1756
List * passing_values
Definition: primnodes.h:1802
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
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: 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
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:441

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 399 of file parse_jsontable.c.

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;
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 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1549
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
@ JTC_EXISTS
Definition: parsenodes.h:1847
@ JTC_REGULAR
Definition: parsenodes.h:1846
@ JS_FORMAT_DEFAULT
Definition: primnodes.h:1608
@ JS_ENC_DEFAULT
Definition: primnodes.h:1596
@ JSON_QUERY_OP
Definition: primnodes.h:1769
@ 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
JsonOutput * output
Definition: parsenodes.h:1799
char * column_name
Definition: parsenodes.h:1794
JsonWrapper wrapper
Definition: parsenodes.h:1802
JsonQuotes quotes
Definition: parsenodes.h:1803
JsonReturning * returning
Definition: parsenodes.h:1760
TypeName * typeName
Definition: parsenodes.h:1759
JsonFormat * format
Definition: primnodes.h:1633
JsonBehavior * on_empty
Definition: parsenodes.h:1867
JsonWrapper wrapper
Definition: parsenodes.h:1864
JsonBehavior * on_error
Definition: parsenodes.h:1868
JsonQuotes quotes
Definition: parsenodes.h:1865
JsonFormat * format
Definition: parsenodes.h:1863
TypeName * typeName
Definition: parsenodes.h:1861

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 251 of file parse_jsontable.c.

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 }
signed int int32
Definition: c.h:494
#define elog(elevel,...)
Definition: elog.h:224
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:1848
@ JTC_FOR_ORDINALITY
Definition: parsenodes.h:1845
@ JS_QUOTES_UNSPEC
Definition: parsenodes.h:1780
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:1716
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 454 of file parse_jsontable.c.

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 }
static JsonTablePlan * makeJsonTableSiblingJoin(JsonTablePlan *lplan, JsonTablePlan *rplan)
#define plan(x)
Definition: pg_regress.c:162

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

Referenced by transformJsonTableColumns().