PostgreSQL Source Code git master
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))
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))
200 errcode(ERRCODE_DUPLICATE_ALIAS),
201 errmsg("duplicate JSON_TABLE column or path name: %s",
202 jtc->name),
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:1888
#define lfirst(lc)
Definition: pg_list.h:172
ParseLoc location
Definition: parsenodes.h:1908
JsonTableColumnType coltype
Definition: parsenodes.h:1898
JsonTablePathSpec * pathspec
Definition: parsenodes.h:1901
ParseLoc name_location
Definition: parsenodes.h:1857

References castNode, CheckDuplicateColumnOrPathNames(), 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 CheckDuplicateColumnOrPathNames(), and 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 &&
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(), isCompositeType(), and type_is_array.

Referenced by AlterTypeNamespaceInternal(), isCompositeType(), 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:815
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
static struct @162 value
Datum jsonpath_in(PG_FUNCTION_ARGS)
Definition: jsonpath.c:98
JsonTablePath * makeJsonTablePath(Const *pathvalue, char *pathname)
Definition: makefuncs.c:979
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:303
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define makeNode(_type_)
Definition: nodes.h:155
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
#define InvalidOid
Definition: postgres_ext.h:37
JsonTablePath * path
Definition: primnodes.h:1929
JsonTablePlan * child
Definition: primnodes.h:1938
JsonTablePlan plan
Definition: primnodes.h:1926

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:1959
JsonTablePlan * lplan
Definition: primnodes.h:1958
JsonTablePlan plan
Definition: primnodes.h:1956

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 &&
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."),
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);
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:1797
@ JSON_BEHAVIOR_EMPTY
Definition: primnodes.h:1798
@ JSON_BEHAVIOR_EMPTY_ARRAY
Definition: primnodes.h:1802
@ JSON_TABLE_OP
Definition: primnodes.h:1836
ParseLoc location
Definition: primnodes.h:1824
JsonBehaviorType btype
Definition: primnodes.h:1821
List * passing_values
Definition: primnodes.h:1867
JsonExprOp op
Definition: parsenodes.h:1832
List * passing
Definition: parsenodes.h:1837
JsonBehavior * on_empty
Definition: parsenodes.h:1839
ParseLoc location
Definition: parsenodes.h:1843
Node * pathspec
Definition: parsenodes.h:1836
JsonBehavior * on_error
Definition: parsenodes.h:1840
JsonValueExpr * context_item
Definition: parsenodes.h:1835
JsonBehavior * on_error
Definition: parsenodes.h:1872
List * columns
Definition: parsenodes.h:1871
JsonTablePathSpec * pathspec
Definition: parsenodes.h:1869
Alias * alias
Definition: parsenodes.h:1873
bool lateral
Definition: parsenodes.h:1874
List * passing
Definition: parsenodes.h:1870
JsonValueExpr * context_item
Definition: parsenodes.h:1868
ParseLoc location
Definition: parsenodes.h:1875
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:444

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:571
JsonValueExpr * makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr, JsonFormat *format)
Definition: makefuncs.c:891
JsonFormat * makeJsonFormat(JsonFormatType type, JsonEncoding encoding, int location)
Definition: makefuncs.c:875
@ JTC_EXISTS
Definition: parsenodes.h:1886
@ JTC_REGULAR
Definition: parsenodes.h:1885
@ JS_FORMAT_DEFAULT
Definition: primnodes.h:1669
@ JS_ENC_DEFAULT
Definition: primnodes.h:1657
@ JSON_QUERY_OP
Definition: primnodes.h:1834
@ JSON_EXISTS_OP
Definition: primnodes.h:1833
@ JSON_VALUE_OP
Definition: primnodes.h:1835
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
JsonOutput * output
Definition: parsenodes.h:1838
char * column_name
Definition: parsenodes.h:1833
JsonWrapper wrapper
Definition: parsenodes.h:1841
JsonQuotes quotes
Definition: parsenodes.h:1842
JsonReturning * returning
Definition: parsenodes.h:1799
TypeName * typeName
Definition: parsenodes.h:1798
JsonFormat * format
Definition: primnodes.h:1694
JsonBehavior * on_empty
Definition: parsenodes.h:1906
JsonWrapper wrapper
Definition: parsenodes.h:1903
JsonBehavior * on_error
Definition: parsenodes.h:1907
JsonQuotes quotes
Definition: parsenodes.h:1904
JsonFormat * format
Definition: parsenodes.h:1902
TypeName * typeName
Definition: parsenodes.h:1900

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 {
290 if (ordinality_found)
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}
int32_t int32
Definition: c.h:484
#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:301
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:821
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:1887
@ JTC_FOR_ORDINALITY
Definition: parsenodes.h:1884
@ JS_QUOTES_UNSPEC
Definition: parsenodes.h:1819
static int list_length(const List *l)
Definition: pg_list.h:152
unsigned int Oid
Definition: postgres_ext.h:32
@ JSW_UNSPEC
Definition: primnodes.h:1781
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().