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  JsonTableContext
 

Typedefs

typedef struct JsonTableContext JsonTableContext
 

Functions

static JsonTableParenttransformJsonTableColumns (JsonTableContext *cxt, JsonTablePlan *plan, List *columns, char *pathSpec, char **pathName, int location)
 
static NodemakeStringConst (char *str, int location)
 
static NodetransformJsonTableColumn (JsonTableColumn *jtc, Node *contextItemExpr, List *passingArgs, bool errorOnError)
 
static bool isJsonTablePathNameDuplicate (JsonTableContext *cxt, const char *pathname)
 
static void registerJsonTableColumn (JsonTableContext *cxt, char *colname)
 
static void registerAllJsonTableColumns (JsonTableContext *cxt, List *columns)
 
static char * generateJsonTablePathName (JsonTableContext *cxt)
 
static void collectSiblingPathsInJsonTablePlan (JsonTablePlan *plan, List **paths)
 
static void validateJsonTableChildPlan (ParseState *pstate, JsonTablePlan *plan, List *columns)
 
static JsonTableColumnfindNestedJsonTableColumn (List *columns, const char *pathname)
 
static NodetransformNestedJsonTableColumn (JsonTableContext *cxt, JsonTableColumn *jtc, JsonTablePlan *plan)
 
static NodemakeJsonTableSiblingJoin (bool cross, Node *lnode, Node *rnode)
 
static NodetransformJsonTableChildPlan (JsonTableContext *cxt, JsonTablePlan *plan, List *columns)
 
static bool typeIsComposite (Oid typid)
 
static void appendJsonTableColumns (JsonTableContext *cxt, List *columns)
 
static JsonTableParentmakeParentJsonTableNode (JsonTableContext *cxt, char *pathSpec, List *columns)
 
ParseNamespaceItemtransformJsonTable (ParseState *pstate, JsonTable *jt)
 

Typedef Documentation

◆ JsonTableContext

Function Documentation

◆ appendJsonTableColumns()

static void appendJsonTableColumns ( JsonTableContext cxt,
List columns 
)
static

Definition at line 420 of file parse_jsontable.c.

421 {
422  ListCell *col;
423  ParseState *pstate = cxt->pstate;
424  JsonTable *jt = cxt->table;
425  TableFunc *tf = cxt->tablefunc;
426  bool errorOnError = jt->on_error &&
428 
429  foreach(col, columns)
430  {
432  Oid typid;
433  int32 typmod;
434  Node *colexpr;
435 
436  if (rawc->name)
437  {
438  /* make sure column names are unique */
439  ListCell *colname;
440 
441  foreach(colname, tf->colnames)
442  if (!strcmp((const char *) colname, rawc->name))
443  ereport(ERROR,
444  (errcode(ERRCODE_SYNTAX_ERROR),
445  errmsg("column name \"%s\" is not unique",
446  rawc->name),
447  parser_errposition(pstate, rawc->location)));
448 
449  tf->colnames = lappend(tf->colnames,
450  makeString(pstrdup(rawc->name)));
451  }
452 
453  /*
454  * Determine the type and typmod for the new column. FOR ORDINALITY
455  * columns are INTEGER by standard; the others are user-specified.
456  */
457  switch (rawc->coltype)
458  {
459  case JTC_FOR_ORDINALITY:
460  colexpr = NULL;
461  typid = INT4OID;
462  typmod = -1;
463  break;
464 
465  case JTC_REGULAR:
466  typenameTypeIdAndMod(pstate, rawc->typeName, &typid, &typmod);
467 
468  /*
469  * Use implicit FORMAT JSON for composite types (arrays and
470  * records)
471  */
472  if (typeIsComposite(typid))
473  rawc->coltype = JTC_FORMATTED;
474  else if (rawc->wrapper != JSW_NONE)
475  ereport(ERROR,
476  (errcode(ERRCODE_SYNTAX_ERROR),
477  errmsg("cannot use WITH WRAPPER clause with scalar columns"),
478  parser_errposition(pstate, rawc->location)));
479  else if (rawc->omit_quotes)
480  ereport(ERROR,
481  (errcode(ERRCODE_SYNTAX_ERROR),
482  errmsg("cannot use OMIT QUOTES clause with scalar columns"),
483  parser_errposition(pstate, rawc->location)));
484 
485  /* FALLTHROUGH */
486  case JTC_EXISTS:
487  case JTC_FORMATTED:
488  {
489  Node *je;
491 
492  param->collation = InvalidOid;
493  param->typeId = cxt->contextItemTypid;
494  param->typeMod = -1;
495 
496  je = transformJsonTableColumn(rawc, (Node *) param,
497  NIL, errorOnError);
498 
499  colexpr = transformExpr(pstate, je, EXPR_KIND_FROM_FUNCTION);
500  assign_expr_collations(pstate, colexpr);
501 
502  typid = exprType(colexpr);
503  typmod = exprTypmod(colexpr);
504  break;
505  }
506 
507  case JTC_NESTED:
508  continue;
509 
510  default:
511  elog(ERROR, "unknown JSON_TABLE column type: %d", rawc->coltype);
512  break;
513  }
514 
515  tf->coltypes = lappend_oid(tf->coltypes, typid);
516  tf->coltypmods = lappend_int(tf->coltypmods, typmod);
518  tf->colvalexprs = lappend(tf->colvalexprs, colexpr);
519  }
520 }
signed int int32
Definition: c.h:429
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define ereport(elevel,...)
Definition: elog.h:143
List * lappend(List *list, void *datum)
Definition: list.c:336
List * lappend_int(List *list, int datum)
Definition: list.c:354
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:3013
char * pstrdup(const char *in)
Definition: mcxt.c:1305
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:286
#define makeNode(_type_)
Definition: nodes.h:621
#define castNode(_type_, nodeptr)
Definition: nodes.h:642
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:112
static bool typeIsComposite(Oid typid)
static Node * transformJsonTableColumn(JsonTableColumn *jtc, Node *contextItemExpr, List *passingArgs, bool errorOnError)
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
@ EXPR_KIND_FROM_FUNCTION
Definition: parse_node.h:45
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
Definition: parse_type.c:310
@ JTC_FORMATTED
Definition: parsenodes.h:1619
@ JTC_FOR_ORDINALITY
Definition: parsenodes.h:1616
@ JTC_NESTED
Definition: parsenodes.h:1620
@ JTC_EXISTS
Definition: parsenodes.h:1618
@ JTC_REGULAR
Definition: parsenodes.h:1617
#define lfirst(lc)
Definition: pg_list.h:169
#define NIL
Definition: pg_list.h:65
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
@ JSW_NONE
Definition: primnodes.h:1307
@ JSON_BEHAVIOR_ERROR
Definition: primnodes.h:1291
int32 typeMod
Definition: primnodes.h:1028
JsonBehaviorType btype
Definition: primnodes.h:1409
JsonTableColumnType coltype
Definition: parsenodes.h:1683
JsonWrapper wrapper
Definition: parsenodes.h:1689
TypeName * typeName
Definition: parsenodes.h:1685
ParseState * pstate
TableFunc * tablefunc
JsonTable * table
JsonBehavior * on_error
Definition: parsenodes.h:1747
Definition: nodes.h:574
List * colvalexprs
Definition: primnodes.h:102
List * coltypmods
Definition: primnodes.h:98
List * coltypes
Definition: primnodes.h:97
List * colnames
Definition: primnodes.h:96
List * colcollations
Definition: primnodes.h:99
String * makeString(char *str)
Definition: value.c:63

References assign_expr_collations(), JsonBehavior::btype, castNode, TableFunc::colcollations, CaseTestExpr::collation, TableFunc::colnames, JsonTableColumn::coltype, TableFunc::coltypes, TableFunc::coltypmods, TableFunc::colvalexprs, JsonTableContext::contextItemTypid, elog, ereport, errcode(), errmsg(), ERROR, EXPR_KIND_FROM_FUNCTION, exprType(), exprTypmod(), get_typcollation(), InvalidOid, JSON_BEHAVIOR_ERROR, JSW_NONE, JTC_EXISTS, JTC_FOR_ORDINALITY, JTC_FORMATTED, JTC_NESTED, JTC_REGULAR, lappend(), lappend_int(), lappend_oid(), lfirst, JsonTableColumn::location, makeNode, makeString(), JsonTableColumn::name, NIL, JsonTableColumn::omit_quotes, JsonTable::on_error, parser_errposition(), JsonTableContext::pstate, pstrdup(), JsonTableContext::table, JsonTableContext::tablefunc, transformExpr(), transformJsonTableColumn(), CaseTestExpr::typeId, typeIsComposite(), CaseTestExpr::typeMod, JsonTableColumn::typeName, typenameTypeIdAndMod(), and JsonTableColumn::wrapper.

Referenced by makeParentJsonTableNode().

◆ collectSiblingPathsInJsonTablePlan()

static void collectSiblingPathsInJsonTablePlan ( JsonTablePlan plan,
List **  paths 
)
static

Definition at line 194 of file parse_jsontable.c.

195 {
196  if (plan->plan_type == JSTP_SIMPLE)
197  *paths = lappend(*paths, plan->pathname);
198  else if (plan->plan_type == JSTP_JOINED)
199  {
200  if (plan->join_type == JSTPJ_INNER ||
201  plan->join_type == JSTPJ_OUTER)
202  {
203  Assert(plan->plan1->plan_type == JSTP_SIMPLE);
204  *paths = lappend(*paths, plan->plan1->pathname);
205  }
206  else if (plan->join_type == JSTPJ_CROSS ||
207  plan->join_type == JSTPJ_UNION)
208  {
211  }
212  else
213  elog(ERROR, "invalid JSON_TABLE join type %d",
214  plan->join_type);
215  }
216 }
Assert(fmt[strlen(fmt) - 1] !='\n')
static void collectSiblingPathsInJsonTablePlan(JsonTablePlan *plan, List **paths)
@ JSTP_JOINED
Definition: parsenodes.h:1705
@ JSTP_SIMPLE
Definition: parsenodes.h:1704
@ JSTPJ_INNER
Definition: parsenodes.h:1714
@ JSTPJ_UNION
Definition: parsenodes.h:1717
@ JSTPJ_OUTER
Definition: parsenodes.h:1715
@ JSTPJ_CROSS
Definition: parsenodes.h:1716
JsonTablePlanJoinType join_type
Definition: parsenodes.h:1730
JsonTablePlan * plan1
Definition: parsenodes.h:1731
JsonTablePlan * plan2
Definition: parsenodes.h:1732
char * pathname
Definition: parsenodes.h:1733
JsonTablePlanType plan_type
Definition: parsenodes.h:1729

References Assert(), elog, ERROR, JsonTablePlan::join_type, JSTP_JOINED, JSTP_SIMPLE, JSTPJ_CROSS, JSTPJ_INNER, JSTPJ_OUTER, JSTPJ_UNION, lappend(), JsonTablePlan::pathname, JsonTablePlan::plan1, JsonTablePlan::plan2, and JsonTablePlan::plan_type.

Referenced by validateJsonTableChildPlan().

◆ findNestedJsonTableColumn()

static JsonTableColumn* findNestedJsonTableColumn ( List columns,
const char *  pathname 
)
static

Definition at line 277 of file parse_jsontable.c.

278 {
279  ListCell *lc;
280 
281  foreach(lc, columns)
282  {
284 
285  if (jtc->coltype == JTC_NESTED &&
286  jtc->pathname &&
287  !strcmp(jtc->pathname, pathname))
288  return jtc;
289  }
290 
291  return NULL;
292 }

References castNode, JsonTableColumn::coltype, JTC_NESTED, lfirst, and JsonTableColumn::pathname.

Referenced by transformJsonTableChildPlan().

◆ generateJsonTablePathName()

static char* generateJsonTablePathName ( JsonTableContext cxt)
static

Definition at line 175 of file parse_jsontable.c.

176 {
177  char namebuf[32];
178  char *name = namebuf;
179 
180  do
181  {
182  snprintf(namebuf, sizeof(namebuf), "json_table_path_%d",
183  ++cxt->pathNameId);
184  } while (isJsonTablePathNameDuplicate(cxt, name));
185 
186  name = pstrdup(name);
187  cxt->pathNames = lappend(cxt->pathNames, name);
188 
189  return name;
190 }
const char * name
Definition: encode.c:561
static bool isJsonTablePathNameDuplicate(JsonTableContext *cxt, const char *pathname)
#define snprintf
Definition: port.h:225

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

Referenced by transformJsonTable(), and transformJsonTableColumns().

◆ isJsonTablePathNameDuplicate()

static bool isJsonTablePathNameDuplicate ( JsonTableContext cxt,
const char *  pathname 
)
static

Definition at line 123 of file parse_jsontable.c.

124 {
125  ListCell *lc;
126 
127  foreach(lc, cxt->pathNames)
128  {
129  if (!strcmp(pathname, (const char *) lfirst(lc)))
130  return true;
131  }
132 
133  return false;
134 }

References lfirst, and JsonTableContext::pathNames.

Referenced by generateJsonTablePathName(), and registerJsonTableColumn().

◆ makeJsonTableSiblingJoin()

static Node* makeJsonTableSiblingJoin ( bool  cross,
Node lnode,
Node rnode 
)
static

Definition at line 309 of file parse_jsontable.c.

310 {
312 
313  join->larg = lnode;
314  join->rarg = rnode;
315  join->cross = cross;
316 
317  return (Node *) join;
318 }

References JsonTableSibling::cross, JsonTableSibling::larg, makeNode, and JsonTableSibling::rarg.

Referenced by transformJsonTableChildPlan().

◆ makeParentJsonTableNode()

static JsonTableParent* makeParentJsonTableNode ( JsonTableContext cxt,
char *  pathSpec,
List columns 
)
static

Definition at line 528 of file parse_jsontable.c.

529 {
531 
532  node->path = makeConst(JSONPATHOID, -1, InvalidOid, -1,
534  CStringGetDatum(pathSpec)),
535  false, false);
536 
537  /* save start of column range */
538  node->colMin = list_length(cxt->tablefunc->colvalexprs);
539 
540  appendJsonTableColumns(cxt, columns);
541 
542  /* save end of column range */
543  node->colMax = list_length(cxt->tablefunc->colvalexprs) - 1;
544 
545  node->errorOnError =
546  cxt->table->on_error &&
548 
549  return node;
550 }
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:631
Datum jsonpath_in(PG_FUNCTION_ARGS)
Definition: jsonpath.c:95
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:300
static void appendJsonTableColumns(JsonTableContext *cxt, List *columns)
static int list_length(const List *l)
Definition: pg_list.h:149
#define CStringGetDatum(X)
Definition: postgres.h:622

References appendJsonTableColumns(), JsonBehavior::btype, JsonTableParent::colMax, JsonTableParent::colMin, TableFunc::colvalexprs, CStringGetDatum, DirectFunctionCall1, JsonTableParent::errorOnError, InvalidOid, JSON_BEHAVIOR_ERROR, jsonpath_in(), list_length(), makeConst(), makeNode, JsonTable::on_error, JsonTableParent::path, JsonTableContext::table, and JsonTableContext::tablefunc.

Referenced by transformJsonTableColumns().

◆ makeStringConst()

static Node* makeStringConst ( char *  str,
int  location 
)
static

Definition at line 52 of file parse_jsontable.c.

53 {
54  A_Const *n = makeNode(A_Const);
55 
56  n->val.node.type = T_String;
57  n->val.sval.sval = str;
58  n->location = location;
59 
60  return (Node *) n;
61 }
@ T_String
Definition: nodes.h:311
int location
Definition: parsenodes.h:318
union A_Const::ValUnion val
NodeTag type
Definition: nodes.h:575
char * sval
Definition: value.h:60

References A_Const::location, makeNode, A_Const::ValUnion::node, generate_unaccent_rules::str, A_Const::ValUnion::sval, String::sval, T_String, Node::type, and A_Const::val.

Referenced by transformJsonTable(), and transformJsonTableColumn().

◆ registerAllJsonTableColumns()

static void registerAllJsonTableColumns ( JsonTableContext cxt,
List columns 
)
static

Definition at line 151 of file parse_jsontable.c.

152 {
153  ListCell *lc;
154 
155  foreach(lc, columns)
156  {
158 
159  if (jtc->coltype == JTC_NESTED)
160  {
161  if (jtc->pathname)
163 
165  }
166  else
167  {
168  registerJsonTableColumn(cxt, jtc->name);
169  }
170  }
171 }
static void registerJsonTableColumn(JsonTableContext *cxt, char *colname)
static void registerAllJsonTableColumns(JsonTableContext *cxt, List *columns)

References castNode, JsonTableColumn::coltype, JsonTableColumn::columns, JTC_NESTED, lfirst, JsonTableColumn::name, JsonTableColumn::pathname, and registerJsonTableColumn().

Referenced by transformJsonTable().

◆ registerJsonTableColumn()

static void registerJsonTableColumn ( JsonTableContext cxt,
char *  colname 
)
static

Definition at line 138 of file parse_jsontable.c.

139 {
140  if (isJsonTablePathNameDuplicate(cxt, colname))
141  ereport(ERROR,
142  (errcode(ERRCODE_DUPLICATE_ALIAS),
143  errmsg("duplicate JSON_TABLE column name: %s", colname),
144  errhint("JSON_TABLE column names must be distinct from one another")));
145 
146  cxt->pathNames = lappend(cxt->pathNames, colname);
147 }
int errhint(const char *fmt,...)
Definition: elog.c:1151

References ereport, errcode(), errhint(), errmsg(), ERROR, isJsonTablePathNameDuplicate(), lappend(), and JsonTableContext::pathNames.

Referenced by registerAllJsonTableColumns(), and transformJsonTable().

◆ transformJsonTable()

ParseNamespaceItem* transformJsonTable ( ParseState pstate,
JsonTable jt 
)

Definition at line 639 of file parse_jsontable.c.

640 {
641  JsonTableContext cxt;
644  JsonTablePlan *plan = jt->plan;
645  JsonCommon *jscommon;
646  char *rootPathName = jt->common->pathname;
647  char *rootPath;
648  bool is_lateral;
649 
650  cxt.pstate = pstate;
651  cxt.table = jt;
652  cxt.tablefunc = tf;
653  cxt.pathNames = NIL;
654  cxt.pathNameId = 0;
655 
656  if (rootPathName)
657  registerJsonTableColumn(&cxt, rootPathName);
658 
660 
661 #if 0 /* XXX it' unclear from the standard whether
662  * root path name is mandatory or not */
663  if (plan && plan->plan_type != JSTP_DEFAULT && !rootPathName)
664  {
665  /* Assign root path name and create corresponding plan node */
666  JsonTablePlan *rootNode = makeNode(JsonTablePlan);
667  JsonTablePlan *rootPlan = (JsonTablePlan *)
669  (Node *) plan, jt->location);
670 
671  rootPathName = generateJsonTablePathName(&cxt);
672 
673  rootNode->plan_type = JSTP_SIMPLE;
674  rootNode->pathname = rootPathName;
675 
676  plan = rootPlan;
677  }
678 #endif
679 
680  jscommon = copyObject(jt->common);
681  jscommon->pathspec = makeStringConst(pstrdup("$"), -1);
682 
683  jfe->op = JSON_TABLE_OP;
684  jfe->common = jscommon;
685  jfe->on_error = jt->on_error;
686  jfe->location = jt->common->location;
687 
688  /*
689  * We make lateral_only names of this level visible, whether or not the
690  * RangeTableFunc is explicitly marked LATERAL. This is needed for SQL
691  * spec compliance and seems useful on convenience grounds for all
692  * functions in FROM.
693  *
694  * (LATERAL can't nest within a single pstate level, so we don't need
695  * save/restore logic here.)
696  */
697  Assert(!pstate->p_lateral_active);
698  pstate->p_lateral_active = true;
699 
700  tf->functype = TFT_JSON_TABLE;
701  tf->docexpr = transformExpr(pstate, (Node *) jfe, EXPR_KIND_FROM_FUNCTION);
702 
703  cxt.contextItemTypid = exprType(tf->docexpr);
704 
705  if (!IsA(jt->common->pathspec, A_Const) ||
706  castNode(A_Const, jt->common->pathspec)->val.node.type != T_String)
707  ereport(ERROR,
708  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
709  errmsg("only string constants supported in JSON_TABLE path specification"),
710  parser_errposition(pstate,
711  exprLocation(jt->common->pathspec))));
712 
713  rootPath = castNode(A_Const, jt->common->pathspec)->val.sval.sval;
714 
715  tf->plan = (Node *) transformJsonTableColumns(&cxt, plan, jt->columns,
716  rootPath, &rootPathName,
717  jt->common->location);
718 
719  tf->ordinalitycol = -1; /* undefine ordinality column number */
720  tf->location = jt->location;
721 
722  pstate->p_lateral_active = false;
723 
724  /*
725  * Mark the RTE as LATERAL if the user said LATERAL explicitly, or if
726  * there are any lateral cross-references in it.
727  */
728  is_lateral = jt->lateral || contain_vars_of_level((Node *) tf, 0);
729 
730  return addRangeTableEntryForTableFunc(pstate,
731  tf, jt->alias, is_lateral, true);
732 }
Node * makeJsonTableJoinedPlan(JsonTablePlanJoinType type, Node *plan1, Node *plan2, int location)
Definition: makefuncs.c:875
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1343
#define IsA(nodeptr, _type_)
Definition: nodes.h:624
#define copyObject(obj)
Definition: nodes.h:689
static Node * makeStringConst(char *str, int location)
static JsonTableParent * transformJsonTableColumns(JsonTableContext *cxt, JsonTablePlan *plan, List *columns, char *pathSpec, char **pathName, int location)
static char * generateJsonTablePathName(JsonTableContext *cxt)
ParseNamespaceItem * addRangeTableEntryForTableFunc(ParseState *pstate, TableFunc *tf, Alias *alias, bool lateral, bool inFromCl)
@ JSTP_DEFAULT
Definition: parsenodes.h:1703
@ TFT_JSON_TABLE
Definition: primnodes.h:79
@ JSON_TABLE_OP
Definition: primnodes.h:1254
char * pathname
Definition: parsenodes.h:1654
Node * pathspec
Definition: parsenodes.h:1653
JsonExprOp op
Definition: parsenodes.h:1666
JsonBehavior * on_error
Definition: parsenodes.h:1670
JsonCommon * common
Definition: parsenodes.h:1667
List * columns
Definition: parsenodes.h:1745
JsonCommon * common
Definition: parsenodes.h:1744
Alias * alias
Definition: parsenodes.h:1748
bool lateral
Definition: parsenodes.h:1749
JsonTablePlan * plan
Definition: parsenodes.h:1746
int location
Definition: parsenodes.h:1750
bool p_lateral_active
Definition: parse_node.h:189
Node * docexpr
Definition: primnodes.h:94
Node * plan
Definition: primnodes.h:104
int location
Definition: primnodes.h:106
TableFuncType functype
Definition: primnodes.h:91
int ordinalitycol
Definition: primnodes.h:105
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:438

References addRangeTableEntryForTableFunc(), JsonTable::alias, Assert(), castNode, JsonTable::columns, JsonFuncExpr::common, JsonTable::common, contain_vars_of_level(), JsonTableContext::contextItemTypid, copyObject, TableFunc::docexpr, ereport, errcode(), errmsg(), ERROR, EXPR_KIND_FROM_FUNCTION, exprLocation(), exprType(), TableFunc::functype, generateJsonTablePathName(), IsA, JSON_TABLE_OP, JSTP_DEFAULT, JSTP_SIMPLE, JSTPJ_OUTER, JsonTable::lateral, JsonCommon::location, JsonFuncExpr::location, JsonTable::location, TableFunc::location, makeJsonTableJoinedPlan(), makeNode, makeStringConst(), NIL, JsonFuncExpr::on_error, JsonTable::on_error, JsonFuncExpr::op, TableFunc::ordinalitycol, ParseState::p_lateral_active, parser_errposition(), JsonCommon::pathname, JsonTablePlan::pathname, JsonTableContext::pathNameId, JsonTableContext::pathNames, JsonCommon::pathspec, JsonTable::plan, TableFunc::plan, JsonTablePlan::plan_type, JsonTableContext::pstate, pstrdup(), registerAllJsonTableColumns(), registerJsonTableColumn(), T_String, JsonTableContext::table, JsonTableContext::tablefunc, TFT_JSON_TABLE, transformExpr(), and transformJsonTableColumns().

Referenced by transformFromClauseItem().

◆ transformJsonTableChildPlan()

static Node* transformJsonTableChildPlan ( JsonTableContext cxt,
JsonTablePlan plan,
List columns 
)
static

Definition at line 329 of file parse_jsontable.c.

331 {
332  JsonTableColumn *jtc = NULL;
333 
334  if (!plan || plan->plan_type == JSTP_DEFAULT)
335  {
336  /* unspecified or default plan */
337  Node *res = NULL;
338  ListCell *lc;
339  bool cross = plan && (plan->join_type & JSTPJ_CROSS);
340 
341  /* transform all nested columns into cross/union join */
342  foreach(lc, columns)
343  {
345  Node *node;
346 
347  if (jtc->coltype != JTC_NESTED)
348  continue;
349 
350  node = transformNestedJsonTableColumn(cxt, jtc, plan);
351 
352  /* join transformed node with previous sibling nodes */
353  res = res ? makeJsonTableSiblingJoin(cross, res, node) : node;
354  }
355 
356  return res;
357  }
358  else if (plan->plan_type == JSTP_SIMPLE)
359  {
360  jtc = findNestedJsonTableColumn(columns, plan->pathname);
361  }
362  else if (plan->plan_type == JSTP_JOINED)
363  {
364  if (plan->join_type == JSTPJ_INNER ||
365  plan->join_type == JSTPJ_OUTER)
366  {
367  Assert(plan->plan1->plan_type == JSTP_SIMPLE);
368  jtc = findNestedJsonTableColumn(columns, plan->plan1->pathname);
369  }
370  else
371  {
372  Node *node1 = transformJsonTableChildPlan(cxt, plan->plan1,
373  columns);
374  Node *node2 = transformJsonTableChildPlan(cxt, plan->plan2,
375  columns);
376 
378  node1, node2);
379  }
380  }
381  else
382  elog(ERROR, "invalid JSON_TABLE plan type %d", plan->plan_type);
383 
384  if (!jtc)
385  ereport(ERROR,
386  (errcode(ERRCODE_SYNTAX_ERROR),
387  errmsg("invalid JSON_TABLE plan"),
388  errdetail("path name was %s not found in nested columns list",
389  plan->pathname),
390  parser_errposition(cxt->pstate, plan->location)));
391 
392  return transformNestedJsonTableColumn(cxt, jtc, plan);
393 }
int errdetail(const char *fmt,...)
Definition: elog.c:1037
static Node * transformJsonTableChildPlan(JsonTableContext *cxt, JsonTablePlan *plan, List *columns)
static Node * makeJsonTableSiblingJoin(bool cross, Node *lnode, Node *rnode)
static JsonTableColumn * findNestedJsonTableColumn(List *columns, const char *pathname)
static Node * transformNestedJsonTableColumn(JsonTableContext *cxt, JsonTableColumn *jtc, JsonTablePlan *plan)

References Assert(), castNode, JsonTableColumn::coltype, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, findNestedJsonTableColumn(), JsonTablePlan::join_type, JSTP_DEFAULT, JSTP_JOINED, JSTP_SIMPLE, JSTPJ_CROSS, JSTPJ_INNER, JSTPJ_OUTER, JTC_NESTED, lfirst, JsonTablePlan::location, makeJsonTableSiblingJoin(), parser_errposition(), JsonTablePlan::pathname, JsonTablePlan::plan1, JsonTablePlan::plan2, JsonTablePlan::plan_type, JsonTableContext::pstate, res, and transformNestedJsonTableColumn().

Referenced by transformJsonTableColumns().

◆ transformJsonTableColumn()

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

Definition at line 70 of file parse_jsontable.c.

72 {
74  JsonCommon *common = makeNode(JsonCommon);
76  char *pathspec;
77  JsonFormat *default_format;
78 
79  jfexpr->op =
82  jfexpr->common = common;
83  jfexpr->output = output;
84  jfexpr->on_empty = jtc->on_empty;
85  jfexpr->on_error = jtc->on_error;
86  if (!jfexpr->on_error && errorOnError)
88  jfexpr->omit_quotes = jtc->omit_quotes;
89  jfexpr->wrapper = jtc->wrapper;
90  jfexpr->location = jtc->location;
91 
92  output->typeName = jtc->typeName;
93  output->returning = makeNode(JsonReturning);
94  output->returning->format = jtc->format;
95 
96  default_format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
97 
98  common->pathname = NULL;
99  common->expr = makeJsonValueExpr((Expr *) contextItemExpr, default_format);
100  common->passing = passingArgs;
101 
102  if (jtc->pathspec)
103  pathspec = jtc->pathspec;
104  else
105  {
106  /* Construct default path as '$."column_name"' */
107  StringInfoData path;
108 
109  initStringInfo(&path);
110 
111  appendStringInfoString(&path, "$.");
112  escape_json(&path, jtc->name);
113 
114  pathspec = path.data;
115  }
116 
117  common->pathspec = makeStringConst(pathspec, -1);
118 
119  return (Node *) jfexpr;
120 }
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1587
JsonBehavior * makeJsonBehavior(JsonBehaviorType type, Node *default_expr)
Definition: makefuncs.c:860
JsonValueExpr * makeJsonValueExpr(Expr *expr, JsonFormat *format)
Definition: makefuncs.c:844
JsonFormat * makeJsonFormat(JsonFormatType type, JsonEncoding encoding, int location)
Definition: makefuncs.c:828
static void output(uint64 loop_count)
@ JS_FORMAT_DEFAULT
Definition: primnodes.h:1275
@ JS_ENC_DEFAULT
Definition: primnodes.h:1263
@ JSON_QUERY_OP
Definition: primnodes.h:1252
@ JSON_EXISTS_OP
Definition: primnodes.h:1253
@ JSON_VALUE_OP
Definition: primnodes.h:1251
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
JsonValueExpr * expr
Definition: parsenodes.h:1652
List * passing
Definition: parsenodes.h:1655
JsonOutput * output
Definition: parsenodes.h:1668
bool omit_quotes
Definition: parsenodes.h:1672
JsonWrapper wrapper
Definition: parsenodes.h:1671
JsonBehavior * on_empty
Definition: parsenodes.h:1669
JsonBehavior * on_empty
Definition: parsenodes.h:1692
JsonBehavior * on_error
Definition: parsenodes.h:1693
JsonFormat * format
Definition: parsenodes.h:1688

References appendStringInfoString(), JsonTableColumn::coltype, JsonFuncExpr::common, StringInfoData::data, escape_json(), JsonCommon::expr, JsonTableColumn::format, initStringInfo(), JS_ENC_DEFAULT, JS_FORMAT_DEFAULT, JSON_BEHAVIOR_ERROR, JSON_EXISTS_OP, JSON_QUERY_OP, JSON_VALUE_OP, JTC_EXISTS, JTC_REGULAR, JsonFuncExpr::location, JsonTableColumn::location, makeJsonBehavior(), makeJsonFormat(), makeJsonValueExpr(), makeNode, makeStringConst(), JsonTableColumn::name, JsonFuncExpr::omit_quotes, JsonTableColumn::omit_quotes, JsonFuncExpr::on_empty, JsonTableColumn::on_empty, JsonFuncExpr::on_error, JsonTableColumn::on_error, JsonFuncExpr::op, output(), JsonFuncExpr::output, JsonCommon::passing, JsonCommon::pathname, JsonCommon::pathspec, JsonTableColumn::pathspec, JsonTableColumn::typeName, JsonFuncExpr::wrapper, and JsonTableColumn::wrapper.

Referenced by appendJsonTableColumns().

◆ transformJsonTableColumns()

static JsonTableParent * transformJsonTableColumns ( JsonTableContext cxt,
JsonTablePlan plan,
List columns,
char *  pathSpec,
char **  pathName,
int  location 
)
static

Definition at line 553 of file parse_jsontable.c.

556 {
557  JsonTableParent *node;
558  JsonTablePlan *childPlan;
559  bool defaultPlan = !plan || plan->plan_type == JSTP_DEFAULT;
560 
561  if (!*pathName)
562  {
563  if (cxt->table->plan)
564  ereport(ERROR,
565  (errcode(ERRCODE_SYNTAX_ERROR),
566  errmsg("invalid JSON_TABLE expression"),
567  errdetail("JSON_TABLE columns must contain "
568  "explicit AS pathname specification if "
569  "explicit PLAN clause is used"),
570  parser_errposition(cxt->pstate, location)));
571 
572  *pathName = generateJsonTablePathName(cxt);
573  }
574 
575  if (defaultPlan)
576  childPlan = plan;
577  else
578  {
579  /* validate parent and child plans */
580  JsonTablePlan *parentPlan;
581 
582  if (plan->plan_type == JSTP_JOINED)
583  {
584  if (plan->join_type != JSTPJ_INNER &&
585  plan->join_type != JSTPJ_OUTER)
586  ereport(ERROR,
587  (errcode(ERRCODE_SYNTAX_ERROR),
588  errmsg("invalid JSON_TABLE plan"),
589  errdetail("expected INNER or OUTER JSON_TABLE plan node"),
590  parser_errposition(cxt->pstate, plan->location)));
591 
592  parentPlan = plan->plan1;
593  childPlan = plan->plan2;
594 
595  Assert(parentPlan->plan_type != JSTP_JOINED);
596  Assert(parentPlan->pathname);
597  }
598  else
599  {
600  parentPlan = plan;
601  childPlan = NULL;
602  }
603 
604  if (strcmp(parentPlan->pathname, *pathName))
605  ereport(ERROR,
606  (errcode(ERRCODE_SYNTAX_ERROR),
607  errmsg("invalid JSON_TABLE plan"),
608  errdetail("path name mismatch: expected %s but %s is given",
609  *pathName, parentPlan->pathname),
610  parser_errposition(cxt->pstate, plan->location)));
611 
612  validateJsonTableChildPlan(cxt->pstate, childPlan, columns);
613  }
614 
615  /* transform only non-nested columns */
616  node = makeParentJsonTableNode(cxt, pathSpec, columns);
617  node->name = pstrdup(*pathName);
618 
619  if (childPlan || defaultPlan)
620  {
621  /* transform recursively nested columns */
622  node->child = transformJsonTableChildPlan(cxt, childPlan, columns);
623  if (node->child)
624  node->outerJoin = !plan || (plan->join_type & JSTPJ_OUTER);
625  /* else: default plan case, no children found */
626  }
627 
628  return node;
629 }
static JsonTableParent * makeParentJsonTableNode(JsonTableContext *cxt, char *pathSpec, List *columns)
static void validateJsonTableChildPlan(ParseState *pstate, JsonTablePlan *plan, List *columns)

References Assert(), JsonTableParent::child, ereport, errcode(), errdetail(), errmsg(), ERROR, generateJsonTablePathName(), JsonTablePlan::join_type, JSTP_DEFAULT, JSTP_JOINED, JSTPJ_INNER, JSTPJ_OUTER, JsonTablePlan::location, makeParentJsonTableNode(), JsonTableParent::name, JsonTableParent::outerJoin, parser_errposition(), JsonTablePlan::pathname, JsonTable::plan, JsonTablePlan::plan1, JsonTablePlan::plan2, JsonTablePlan::plan_type, JsonTableContext::pstate, pstrdup(), JsonTableContext::table, transformJsonTableChildPlan(), and validateJsonTableChildPlan().

Referenced by transformJsonTable(), and transformNestedJsonTableColumn().

◆ transformNestedJsonTableColumn()

static Node* transformNestedJsonTableColumn ( JsonTableContext cxt,
JsonTableColumn jtc,
JsonTablePlan plan 
)
static

Definition at line 295 of file parse_jsontable.c.

297 {
298  JsonTableParent *node;
299  char *pathname = jtc->pathname;
300 
301  node = transformJsonTableColumns(cxt, plan, jtc->columns, jtc->pathspec,
302  &pathname, jtc->location);
303  node->name = pstrdup(pathname);
304 
305  return (Node *) node;
306 }

References JsonTableColumn::columns, JsonTableColumn::location, JsonTableParent::name, JsonTableColumn::pathname, JsonTableColumn::pathspec, pstrdup(), and transformJsonTableColumns().

Referenced by transformJsonTableChildPlan().

◆ typeIsComposite()

static bool typeIsComposite ( Oid  typid)
static

Definition at line 397 of file parse_jsontable.c.

398 {
399  char typtype;
400 
401  if (typid == JSONOID ||
402  typid == JSONBOID ||
403  typid == RECORDOID ||
404  type_is_array(typid))
405  return true;
406 
407  typtype = get_typtype(typid);
408 
409  if (typtype == TYPTYPE_COMPOSITE)
410  return true;
411 
412  if (typtype == TYPTYPE_DOMAIN)
413  return typeIsComposite(getBaseType(typid));
414 
415  return false;
416 }
char get_typtype(Oid typid)
Definition: lsyscache.c:2586
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2478
#define type_is_array(typid)
Definition: lsyscache.h:202

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

Referenced by appendJsonTableColumns().

◆ validateJsonTableChildPlan()

static void validateJsonTableChildPlan ( ParseState pstate,
JsonTablePlan plan,
List columns 
)
static

Definition at line 225 of file parse_jsontable.c.

227 {
228  ListCell *lc1;
229  List *siblings = NIL;
230  int nchildren = 0;
231 
232  if (plan)
233  collectSiblingPathsInJsonTablePlan(plan, &siblings);
234 
235  foreach(lc1, columns)
236  {
238 
239  if (jtc->coltype == JTC_NESTED)
240  {
241  ListCell *lc2;
242  bool found = false;
243 
244  if (!jtc->pathname)
245  ereport(ERROR,
246  (errcode(ERRCODE_SYNTAX_ERROR),
247  errmsg("nested JSON_TABLE columns must contain an explicit AS pathname specification if an explicit PLAN clause is used"),
248  parser_errposition(pstate, jtc->location)));
249 
250  /* find nested path name in the list of sibling path names */
251  foreach(lc2, siblings)
252  {
253  if ((found = !strcmp(jtc->pathname, lfirst(lc2))))
254  break;
255  }
256 
257  if (!found)
258  ereport(ERROR,
259  (errcode(ERRCODE_SYNTAX_ERROR),
260  errmsg("invalid JSON_TABLE plan"),
261  errdetail("plan node for nested path %s was not found in plan", jtc->pathname),
262  parser_errposition(pstate, jtc->location)));
263 
264  nchildren++;
265  }
266  }
267 
268  if (list_length(siblings) > nchildren)
269  ereport(ERROR,
270  (errcode(ERRCODE_SYNTAX_ERROR),
271  errmsg("invalid JSON_TABLE plan"),
272  errdetail("plan node contains some extra or duplicate sibling nodes"),
273  parser_errposition(pstate, plan ? plan->location : -1)));
274 }
Definition: pg_list.h:51

References castNode, collectSiblingPathsInJsonTablePlan(), JsonTableColumn::coltype, ereport, errcode(), errdetail(), errmsg(), ERROR, JTC_NESTED, lfirst, list_length(), JsonTableColumn::location, JsonTablePlan::location, NIL, parser_errposition(), and JsonTableColumn::pathname.

Referenced by transformJsonTableColumns().