PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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-2026, 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_type.h"
19#include "nodes/makefuncs.h"
20#include "nodes/nodeFuncs.h"
21#include "optimizer/optimizer.h"
22#include "parser/parse_clause.h"
24#include "parser/parse_expr.h"
26#include "parser/parse_type.h"
27#include "utils/fmgrprotos.h"
28#include "utils/json.h"
29#include "utils/lsyscache.h"
30
31/* Context for transformJsonTableColumns() */
33{
37 List *pathNames; /* list of all path and columns names */
38 int pathNameId; /* path name id counter */
40
42 JsonTablePlanSpec *planspec,
43 List *columns,
45 JsonTablePathSpec *pathspec);
49 List *columns);
53static bool isCompositeType(Oid typid);
55 JsonTablePathSpec *pathspec,
56 JsonTablePlanSpec *planspec,
57 bool errorOnError,
58 int colMin, int colMax,
61 List *columns);
66 List *columns);
68 JsonTablePlan *lplan,
69 JsonTablePlan *rplan);
70static void
72
73/*
74 * transformJsonTable -
75 * Transform a raw JsonTable into TableFunc
76 *
77 * Mainly, this transforms the JSON_TABLE() document-generating expression
78 * (jt->context_item) and the column-generating expressions (jt->columns) to
79 * populate TableFunc.docexpr and TableFunc.colvalexprs, respectively. Also,
80 * the PASSING values (jt->passing) are transformed and added into
81 * TableFunc.passingvalexprs.
82 */
85{
86 TableFunc *tf;
88 JsonExpr *je;
91 bool is_lateral;
92 JsonTableParseContext cxt = {pstate};
93
94 Assert(IsA(rootPathSpec->string, A_Const) &&
95 castNode(A_Const, rootPathSpec->string)->val.node.type == T_String);
96
97 if (jt->on_error &&
103 errmsg("invalid %s behavior", "ON ERROR"),
104 errdetail("Only EMPTY [ ARRAY ] or ERROR is allowed in the top-level ON ERROR clause."),
105 parser_errposition(pstate, jt->on_error->location));
106
107 cxt.pathNameId = 0;
108
109 /*
110 * Collect the user-supplied path and column names, checking that they are
111 * distinct. If the row pattern path has an explicit name, it shares this
112 * namespace, so seed the list with it.
113 */
114 if (rootPathSpec->name != NULL)
115 cxt.pathNames = list_make1(rootPathSpec->name);
117
118 /*
119 * Generate a name for the row pattern path if it was not given one. Path
120 * names are optional for every path, including when a PLAN clause is
121 * present; a specific PLAN() can only reference named paths, so an
122 * unnamed path that the plan must mention is caught later as a path name
123 * mismatch or a path not covered by the plan. We generate the name only
124 * after collecting the user-supplied names above, so that it cannot
125 * collide with any of them.
126 */
127 if (rootPathSpec->name == NULL)
129
130 /*
131 * We make lateral_only names of this level visible, whether or not the
132 * RangeTableFunc is explicitly marked LATERAL. This is needed for SQL
133 * spec compliance and seems useful on convenience grounds for all
134 * functions in FROM.
135 *
136 * (LATERAL can't nest within a single pstate level, so we don't need
137 * save/restore logic here.)
138 */
139 Assert(!pstate->p_lateral_active);
140 pstate->p_lateral_active = true;
141
142 tf = makeNode(TableFunc);
144
145 /*
146 * Transform JsonFuncExpr representing the top JSON_TABLE context_item and
147 * pathspec into a dummy JSON_TABLE_OP JsonExpr.
148 */
150 jfe->op = JSON_TABLE_OP;
151 jfe->context_item = jt->context_item;
152 jfe->pathspec = (Node *) rootPathSpec->string;
153 jfe->passing = jt->passing;
154 jfe->on_empty = NULL;
155 jfe->on_error = jt->on_error;
156 jfe->location = jt->location;
158
159 /*
160 * Create a JsonTablePlan that will generate row pattern that becomes
161 * source data for JSON path expressions in jt->columns. This also adds
162 * the columns' transformed JsonExpr nodes into tf->colvalexprs.
163 */
164 cxt.jt = jt;
165 cxt.tf = tf;
166 tf->plan = (Node *) transformJsonTableColumns(&cxt, plan, jt->columns,
167 jt->passing,
169
170 /*
171 * Copy the transformed PASSING arguments into the TableFunc node, because
172 * they are evaluated separately from the JsonExpr that we just put in
173 * TableFunc.docexpr. JsonExpr.passing_values is still kept around for
174 * get_json_table().
175 */
176 je = (JsonExpr *) tf->docexpr;
177 tf->passingvalexprs = copyObject(je->passing_values);
178
179 tf->ordinalitycol = -1; /* undefine ordinality column number */
180 tf->location = jt->location;
181
182 pstate->p_lateral_active = false;
183
184 /*
185 * Mark the RTE as LATERAL if the user said LATERAL explicitly, or if
186 * there are any lateral cross-references in it.
187 */
188 is_lateral = jt->lateral || contain_vars_of_level((Node *) tf, 0);
189
190 return addRangeTableEntryForTableFunc(pstate,
191 tf, jt->alias, is_lateral, true);
192}
193
194/*
195 * Check if a column / path name is duplicated in the given shared list of
196 * names.
197 */
198static void
200 List *columns)
201{
202 ListCell *lc1;
203
204 foreach(lc1, columns)
205 {
207
208 if (jtc->coltype == JTC_NESTED)
209 {
210 if (jtc->pathspec->name)
211 {
212 if (LookupPathOrColumnName(cxt, jtc->pathspec->name))
215 errmsg("duplicate JSON_TABLE column or path name: %s",
216 jtc->pathspec->name),
218 jtc->pathspec->name_location));
219 cxt->pathNames = lappend(cxt->pathNames, jtc->pathspec->name);
220 }
221
223 }
224 else
225 {
226 if (LookupPathOrColumnName(cxt, jtc->name))
229 errmsg("duplicate JSON_TABLE column or path name: %s",
230 jtc->name),
231 parser_errposition(cxt->pstate, jtc->location));
232 cxt->pathNames = lappend(cxt->pathNames, jtc->name);
233 }
234 }
235}
236
237/*
238 * Lookup a column/path name in the given name list, returning true if already
239 * there.
240 */
241static bool
243{
244 ListCell *lc;
245
246 foreach(lc, cxt->pathNames)
247 {
248 if (strcmp(name, (const char *) lfirst(lc)) == 0)
249 return true;
250 }
251
252 return false;
253}
254
255/* Generate a new unique JSON_TABLE path name. */
256static char *
258{
259 char namebuf[32];
260 char *name;
261
262 /*
263 * Bump the counter until we produce a name that is not already used as a
264 * path or column name. Otherwise a generated name could coincide with a
265 * user-supplied one, which would confuse PLAN clause matching and could
266 * silently drop a column.
267 */
268 do
269 {
270 snprintf(namebuf, sizeof(namebuf), "json_table_path_%d",
271 cxt->pathNameId++);
272 } while (LookupPathOrColumnName(cxt, namebuf));
273
275 cxt->pathNames = lappend(cxt->pathNames, name);
276
277 return name;
278}
279
280/*
281 * Create a JsonTablePlan that will supply the source row for 'columns'
282 * using 'pathspec' and append the columns' transformed JsonExpr nodes and
283 * their type/collation information to cxt->tf.
284 */
285static JsonTablePlan *
287 JsonTablePlanSpec *planspec,
288 List *columns,
290 JsonTablePathSpec *pathspec)
291{
292 JsonTable *jt = cxt->jt;
293 TableFunc *tf = cxt->tf;
294 JsonTablePathScan *scan;
296 bool defaultPlan = planspec == NULL ||
297 planspec->plan_type == JSTP_DEFAULT;
298 bool errorOnError = jt->on_error &&
300 int colMin,
301 colMax;
303
304 /* Start of column range */
305 colMin = list_length(tf->colvalexprs);
306
307 if (defaultPlan)
308 childPlanSpec = planspec;
309 else
310 {
311 /* validate parent and child plans */
313
314 if (planspec->plan_type == JSTP_JOINED)
315 {
316 if (planspec->join_type != JSTP_JOIN_INNER &&
317 planspec->join_type != JSTP_JOIN_OUTER)
320 errmsg("invalid JSON_TABLE plan clause"),
321 errdetail("Expected INNER or OUTER."),
322 parser_errposition(cxt->pstate, planspec->location)));
323
324 parentPlanSpec = planspec->plan1;
325 childPlanSpec = planspec->plan2;
326
327 Assert(parentPlanSpec->plan_type != JSTP_JOINED);
328 Assert(parentPlanSpec->pathname);
329 }
330 else
331 {
332 parentPlanSpec = planspec;
334 }
335
336 if (strcmp(parentPlanSpec->pathname, pathspec->name) != 0)
339 errmsg("invalid JSON_TABLE plan"),
340 errdetail("PATH name mismatch: expected %s but %s is given.",
341 pathspec->name, parentPlanSpec->pathname),
342 parser_errposition(cxt->pstate, planspec->location)));
343
345 }
346
347 appendJsonTableColumns(cxt, columns, passingArgs);
348
349 /* End of column range. */
350 if (list_length(tf->colvalexprs) == colMin)
351 {
352 /* No columns in this Scan beside the nested ones. */
353 colMax = colMin = -1;
354 }
355 else
356 colMax = list_length(tf->colvalexprs) - 1;
357
359 {
360 /* transform recursively nested columns */
362 columns, passingArgs);
363 }
364
365 /* transform only non-nested columns */
366 scan = (JsonTablePathScan *) makeJsonTablePathScan(cxt, pathspec,
367 planspec,
368 errorOnError,
369 colMin,
370 colMax,
371 childplan);
372
373 return (JsonTablePlan *) scan;
374}
375
376/* Append transformed non-nested JSON_TABLE columns to the TableFunc node */
377static void
379{
380 ListCell *col;
381 ParseState *pstate = cxt->pstate;
382 TableFunc *tf = cxt->tf;
383 bool ordinality_found = false;
385
386 foreach(col, columns)
387 {
389 Oid typid;
390 int32 typmod;
392 Node *colexpr;
393
394 if (rawc->name)
395 tf->colnames = lappend(tf->colnames,
396 makeString(pstrdup(rawc->name)));
397
398 /*
399 * Determine the type and typmod for the new column. FOR ORDINALITY
400 * columns are INTEGER by standard; the others are user-specified.
401 */
402 switch (rawc->coltype)
403 {
408 errmsg("only one FOR ORDINALITY column is allowed"),
409 parser_errposition(pstate, rawc->location)));
410 ordinality_found = true;
411 colexpr = NULL;
412 typid = INT4OID;
413 typmod = -1;
414 break;
415
416 case JTC_REGULAR:
417 typenameTypeIdAndMod(pstate, rawc->typeName, &typid, &typmod);
418
419 /*
420 * Use JTC_FORMATTED so as to use JSON_QUERY for this column
421 * if the specified type is one that's better handled using
422 * JSON_QUERY() or if non-default WRAPPER or QUOTES behavior
423 * is specified.
424 */
425 if (isCompositeType(typid) ||
426 rawc->quotes != JS_QUOTES_UNSPEC ||
427 rawc->wrapper != JSW_UNSPEC)
428 rawc->coltype = JTC_FORMATTED;
429
431 case JTC_FORMATTED:
432 case JTC_EXISTS:
433 {
436
437 param->collation = InvalidOid;
438 param->typeId = contextItemTypid;
439 param->typeMod = -1;
440
443
444 colexpr = transformExpr(pstate, (Node *) jfe,
446 assign_expr_collations(pstate, colexpr);
447
448 typid = exprType(colexpr);
449 typmod = exprTypmod(colexpr);
450 typcoll = exprCollation(colexpr);
451 break;
452 }
453
454 case JTC_NESTED:
455 continue;
456
457 default:
458 elog(ERROR, "unknown JSON_TABLE column type: %d", (int) rawc->coltype);
459 break;
460 }
461
462 tf->coltypes = lappend_oid(tf->coltypes, typid);
463 tf->coltypmods = lappend_int(tf->coltypmods, typmod);
464 tf->colcollations = lappend_oid(tf->colcollations, typcoll);
465 tf->colvalexprs = lappend(tf->colvalexprs, colexpr);
466 }
467}
468
469/*
470 * Check if the type is "composite" for the purpose of checking whether to use
471 * JSON_VALUE() or JSON_QUERY() for a given JsonTableColumn.
472 */
473static bool
475{
476 char typtype = get_typtype(typid);
477
478 return typid == JSONOID ||
479 typid == JSONBOID ||
480 typid == RECORDOID ||
481 type_is_array(typid) ||
482 typtype == TYPTYPE_COMPOSITE ||
483 /* domain over one of the above? */
484 (typtype == TYPTYPE_DOMAIN &&
486}
487
488/*
489 * Transform JSON_TABLE column definition into a JsonFuncExpr
490 * This turns:
491 * - regular column into JSON_VALUE()
492 * - FORMAT JSON column into JSON_QUERY()
493 * - EXISTS column into JSON_EXISTS()
494 */
495static JsonFuncExpr *
498{
499 Node *pathspec;
501
502 if (jtc->coltype == JTC_REGULAR)
503 jfexpr->op = JSON_VALUE_OP;
504 else if (jtc->coltype == JTC_EXISTS)
506 else
507 jfexpr->op = JSON_QUERY_OP;
508
509 /* Pass the column name so any runtime JsonExpr errors can print it. */
510 Assert(jtc->name != NULL);
511 jfexpr->column_name = pstrdup(jtc->name);
512
513 jfexpr->context_item = makeJsonValueExpr((Expr *) contextItemExpr, NULL,
516 -1));
517 if (jtc->pathspec)
518 pathspec = (Node *) jtc->pathspec->string;
519 else
520 {
521 /* Construct default path as '$."column_name"' */
522 StringInfoData path;
523
524 initStringInfo(&path);
525
526 appendStringInfoString(&path, "$.");
527 escape_json(&path, jtc->name);
528
529 pathspec = makeStringConst(path.data, -1);
530 }
531 jfexpr->pathspec = pathspec;
532 jfexpr->passing = passingArgs;
533 jfexpr->output = makeNode(JsonOutput);
534 jfexpr->output->typeName = jtc->typeName;
535 jfexpr->output->returning = makeNode(JsonReturning);
536 jfexpr->output->returning->format = jtc->format;
537 jfexpr->on_empty = jtc->on_empty;
538 jfexpr->on_error = jtc->on_error;
539 jfexpr->quotes = jtc->quotes;
540 jfexpr->wrapper = jtc->wrapper;
541 jfexpr->location = jtc->location;
542
543 return jfexpr;
544}
545
546static JsonTableColumn *
547findNestedJsonTableColumn(List *columns, const char *pathname)
548{
549 ListCell *lc;
550
551 foreach(lc, columns)
552 {
554
555 if (jtc->coltype == JTC_NESTED &&
556 jtc->pathspec->name &&
557 !strcmp(jtc->pathspec->name, pathname))
558 return jtc;
559 }
560
561 return NULL;
562}
563
564/*
565 * Recursively transform nested columns and create child plan(s) that will be
566 * used to evaluate their row patterns.
567 *
568 * Default plan is transformed into a cross/union join of its nested columns.
569 * Simple and outer/inner plans are transformed into a JsonTablePlan by
570 * finding and transforming corresponding nested column.
571 * Sibling plans are recursively transformed into a JsonTableSiblingJoin.
572 */
573static JsonTablePlan *
575 JsonTablePlanSpec *planspec,
576 List *columns,
578{
580
581 if (!planspec || planspec->plan_type == JSTP_DEFAULT)
582 {
583 /* unspecified or default plan */
585 ListCell *lc;
586 bool cross = planspec && (planspec->join_type & JSTP_JOIN_CROSS);
587
588 /*
589 * If there are multiple NESTED COLUMNS clauses in 'columns', their
590 * respective plans will be combined using a "sibling join" plan,
591 * which effectively does a UNION of the sets of rows coming from each
592 * nested plan.
593 */
594 foreach(lc, columns)
595 {
597 JsonTablePlan *nested;
598
599 if (col->coltype != JTC_NESTED)
600 continue;
601
602 if (col->pathspec->name == NULL)
603 {
604 col->pathspec->name = generateJsonTablePathName(cxt);
605 }
606
607 nested = transformJsonTableColumns(cxt, planspec, col->columns,
609 col->pathspec);
610
611 /* Join nested plan with previous sibling nested plans. */
612 if (plan)
613 plan = makeJsonTableSiblingJoin(cross, plan, nested);
614 else
615 plan = nested;
616 }
617
618 return plan;
619 }
620 else if (planspec->plan_type == JSTP_SIMPLE)
621 {
622 jtc = findNestedJsonTableColumn(columns, planspec->pathname);
623 }
624 else if (planspec->plan_type == JSTP_JOINED)
625 {
626 if (planspec->join_type == JSTP_JOIN_INNER ||
627 planspec->join_type == JSTP_JOIN_OUTER)
628 {
629 Assert(planspec->plan1->plan_type == JSTP_SIMPLE);
630 jtc = findNestedJsonTableColumn(columns, planspec->plan1->pathname);
631 }
632 else
633 {
635 planspec->plan1,
636 columns,
639 planspec->plan2,
640 columns,
642
644 lplan, rplan);
645 }
646 }
647 else
648 elog(ERROR, "invalid JSON_TABLE plan type %d", planspec->plan_type);
649
650 /*
651 * The plan's path names were already matched one-to-one against the
652 * nested columns by validateJsonTableChildPlan(), so a nested column with
653 * this path name must exist.
654 */
655 Assert(jtc != NULL);
656
657 return transformJsonTableColumns(cxt, planspec, jtc->columns,
659 jtc->pathspec);
660}
661
662/*
663 * Create transformed JSON_TABLE parent plan node by appending all non-nested
664 * columns to the TableFunc node and remembering their indices in the
665 * colvalexprs list.
666 *
667 * colMin and colMax give the range of columns computed by this scan in the
668 * global flat list of column expressions that will be passed to the
669 * JSON_TABLE's TableFunc. Both are -1 when all of columns are nested and
670 * thus computed by 'childplan'.
671 */
672static JsonTablePlan *
674 JsonTablePlanSpec *planspec,
675 bool errorOnError,
676 int colMin, int colMax,
678{
680 char *pathstring;
681 Const *value;
682
683 Assert(IsA(pathspec->string, A_Const));
684 pathstring = castNode(A_Const, pathspec->string)->val.sval.sval;
688 false, false);
689
690 scan->plan.type = T_JsonTablePathScan;
691 scan->path = makeJsonTablePath(value, pathspec->name);
692 scan->errorOnError = errorOnError;
693
694 scan->child = childplan;
695
696 scan->colMin = colMin;
697 scan->colMax = colMax;
698
699 if (scan->child)
700 scan->outerJoin = planspec == NULL ||
701 (planspec->join_type & JSTP_JOIN_OUTER);
702 /* else: default plan case, no children found */
703
704 return (JsonTablePlan *) scan;
705}
706
707/*
708 * Create a JsonTablePlan that will perform a join of the rows coming from
709 * 'lplan' and 'rplan'.
710 *
711 * The default way of "joining" the rows is to perform a UNION between the
712 * sets of rows from 'lplan' and 'rplan'.
713 */
714static JsonTablePlan *
716{
718
719 join->plan.type = T_JsonTableSiblingJoin;
720 join->lplan = lplan;
721 join->rplan = rplan;
722 join->cross = cross;
723
724 return (JsonTablePlan *) join;
725}
726
727/* Collect sibling path names from plan to the specified list. */
728static void
730{
731 if (plan->plan_type == JSTP_SIMPLE)
732 *paths = lappend(*paths, plan->pathname);
733 else if (plan->plan_type == JSTP_JOINED)
734 {
735 if (plan->join_type == JSTP_JOIN_INNER ||
736 plan->join_type == JSTP_JOIN_OUTER)
737 {
738 Assert(plan->plan1->plan_type == JSTP_SIMPLE);
739 *paths = lappend(*paths, plan->plan1->pathname);
740 }
741 else if (plan->join_type == JSTP_JOIN_CROSS ||
742 plan->join_type == JSTP_JOIN_UNION)
743 {
746 }
747 else
748 elog(ERROR, "invalid JSON_TABLE join type %d",
749 plan->join_type);
750 }
751}
752
753/*
754 * Validate child JSON_TABLE plan by checking that:
755 * - all nested columns have path names specified
756 * - all nested columns have corresponding node in the sibling plan
757 * - plan does not contain duplicate or extra nodes
758 */
759static void
761 List *columns)
762{
763 ParseState *pstate = cxt->pstate;
764 ListCell *lc1;
765 List *siblings = NIL;
766 int nchildren = 0;
767
768 if (plan)
770
771 foreach(lc1, columns)
772 {
774
775 if (jtc->coltype == JTC_NESTED)
776 {
777 ListCell *lc2;
778 bool found = false;
779
780 /*
781 * A NESTED path need not be named; generate a name if it was left
782 * unnamed. A generated name cannot be referenced by a specific
783 * PLAN(), so such a path is reported just below as a nested path
784 * not covered by the plan.
785 */
786 if (jtc->pathspec->name == NULL)
787 jtc->pathspec->name = generateJsonTablePathName(cxt);
788
789 /* find nested path name in the list of sibling path names */
790 foreach(lc2, siblings)
791 {
792 if ((found = !strcmp(jtc->pathspec->name, lfirst(lc2))))
793 break;
794 }
795
796 if (!found)
799 errmsg("invalid JSON_TABLE specification"),
800 errdetail("PLAN clause for nested path %s was not found.",
801 jtc->pathspec->name),
802 parser_errposition(pstate, jtc->location));
803
804 nchildren++;
805 }
806 }
807
811 errmsg("invalid JSON_TABLE plan clause"),
812 errdetail("PLAN clause contains some extra or duplicate sibling nodes."),
813 parser_errposition(pstate, plan ? plan->location : -1));
814}
#define Assert(condition)
Definition c.h:1002
int32_t int32
Definition c.h:679
#define pg_fallthrough
Definition c.h:220
int errcode(int sqlerrcode)
Definition elog.c:875
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:688
static struct @175 value
void escape_json(StringInfo buf, const char *str)
Definition json.c:1572
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:2945
Oid getBaseType(Oid typid)
Definition lsyscache.c:2837
#define type_is_array(typid)
Definition lsyscache.h:223
JsonTablePath * makeJsonTablePath(Const *pathvalue, char *pathname)
Definition makefuncs.c:1083
Node * makeStringConst(char *str, int location)
Definition makefuncs.c:618
JsonValueExpr * makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr, JsonFormat *format)
Definition makefuncs.c:938
JsonFormat * makeJsonFormat(JsonFormatType type, JsonEncoding encoding, int location)
Definition makefuncs.c:922
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition makefuncs.c:350
char * pstrdup(const char *in)
Definition mcxt.c:1910
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:304
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
#define IsA(nodeptr, _type_)
Definition nodes.h:162
#define copyObject(obj)
Definition nodes.h:230
#define makeNode(_type_)
Definition nodes.h:159
#define castNode(_type_, nodeptr)
Definition nodes.h:180
static char * errmsg
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition parse_expr.c:121
static JsonTablePlan * transformJsonTableNestedColumns(JsonTableParseContext *cxt, JsonTablePlanSpec *plan, List *passingArgs, List *columns)
static JsonTablePlan * makeJsonTableSiblingJoin(bool cross, JsonTablePlan *lplan, JsonTablePlan *rplan)
static char * generateJsonTablePathName(JsonTableParseContext *cxt)
ParseNamespaceItem * transformJsonTable(ParseState *pstate, JsonTable *jt)
static bool LookupPathOrColumnName(JsonTableParseContext *cxt, char *name)
static JsonTablePlan * makeJsonTablePathScan(JsonTableParseContext *cxt, JsonTablePathSpec *pathspec, JsonTablePlanSpec *planspec, bool errorOnError, int colMin, int colMax, JsonTablePlan *childplan)
static JsonFuncExpr * transformJsonTableColumn(JsonTableColumn *jtc, Node *contextItemExpr, List *passingArgs)
static bool isCompositeType(Oid typid)
static void appendJsonTableColumns(JsonTableParseContext *cxt, List *columns, List *passingArgs)
static void collectSiblingPathsInJsonTablePlan(JsonTablePlanSpec *plan, List **paths)
static JsonTablePlan * transformJsonTableColumns(JsonTableParseContext *cxt, JsonTablePlanSpec *planspec, List *columns, List *passingArgs, JsonTablePathSpec *pathspec)
static void CheckDuplicateColumnOrPathNames(JsonTableParseContext *cxt, List *columns)
static JsonTableColumn * findNestedJsonTableColumn(List *columns, const char *pathname)
static void validateJsonTableChildPlan(JsonTableParseContext *cxt, JsonTablePlanSpec *plan, 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
@ JTC_FOR_ORDINALITY
@ JTC_NESTED
@ JTC_EXISTS
@ JTC_REGULAR
@ JS_QUOTES_UNSPEC
@ JSTP_JOINED
@ JSTP_DEFAULT
@ JSTP_SIMPLE
@ JSTP_JOIN_CROSS
@ JSTP_JOIN_INNER
@ JSTP_JOIN_OUTER
@ JSTP_JOIN_UNION
#define lfirst(lc)
Definition pg_list.h:172
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define list_make1(x1)
Definition pg_list.h:244
#define plan(x)
Definition pg_regress.c:164
#define snprintf
Definition port.h:261
static Datum CStringGetDatum(const char *X)
Definition postgres.h:383
#define InvalidOid
unsigned int Oid
static int fb(int x)
@ JS_FORMAT_DEFAULT
Definition primnodes.h:1646
@ TFT_JSON_TABLE
Definition primnodes.h:102
@ JS_ENC_DEFAULT
Definition primnodes.h:1634
@ JSW_UNSPEC
Definition primnodes.h:1771
@ JSON_BEHAVIOR_ERROR
Definition primnodes.h:1787
@ JSON_BEHAVIOR_EMPTY
Definition primnodes.h:1788
@ JSON_BEHAVIOR_EMPTY_ARRAY
Definition primnodes.h:1792
@ JSON_QUERY_OP
Definition primnodes.h:1824
@ JSON_TABLE_OP
Definition primnodes.h:1826
@ JSON_EXISTS_OP
Definition primnodes.h:1823
@ JSON_VALUE_OP
Definition primnodes.h:1825
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
ParseLoc location
Definition primnodes.h:1814
JsonBehaviorType btype
Definition primnodes.h:1811
JsonTablePath * path
Definition primnodes.h:1919
JsonTablePlan * child
Definition primnodes.h:1928
JsonTablePlan plan
Definition primnodes.h:1916
JsonTablePlanJoinType join_type
JsonTablePlanType plan_type
struct JsonTablePlanSpec * plan2
struct JsonTablePlanSpec * plan1
JsonTablePlan * rplan
Definition primnodes.h:1950
JsonTablePlan * lplan
Definition primnodes.h:1949
JsonTablePlan plan
Definition primnodes.h:1947
JsonBehavior * on_error
List * columns
JsonTablePathSpec * pathspec
Alias * alias
List * passing
JsonTablePlanSpec * planspec
JsonValueExpr * context_item
ParseLoc location
Definition pg_list.h:54
Definition nodes.h:133
bool p_lateral_active
Definition parse_node.h:224
ParseLoc location
Definition primnodes.h:147
Node * docexpr
Definition primnodes.h:121
TableFuncType functype
Definition primnodes.h:115
String * makeString(char *str)
Definition value.c:63
bool contain_vars_of_level(Node *node, int levelsup)
Definition var.c:444
const char * name