summaryrefslogtreecommitdiff
path: root/src/include/nodes
diff options
context:
space:
mode:
authorAmit Langote2024-04-04 10:57:08 +0000
committerAmit Langote2024-04-04 11:20:15 +0000
commitde3600452b61d1bc3967e9e37e86db8956c8f577 (patch)
treedf9df5969dcc64b6b6a3e7b0903fda98a2fd513a /src/include/nodes
parenta9d6c3868451a494641b498a15f9ee1c151949a7 (diff)
Add basic JSON_TABLE() functionality
JSON_TABLE() allows JSON data to be converted into a relational view and thus used, for example, in a FROM clause, like other tabular data. Data to show in the view is selected from a source JSON object using a JSON path expression to get a sequence of JSON objects that's called a "row pattern", which becomes the source to compute the SQL/JSON values that populate the view's output columns. Column values themselves are computed using JSON path expressions applied to each of the JSON objects comprising the "row pattern", for which the SQL/JSON query functions added in 6185c9737cf4 are used. To implement JSON_TABLE() as a table function, this augments the TableFunc and TableFuncScanState nodes that are currently used to support XMLTABLE() with some JSON_TABLE()-specific fields. Note that the JSON_TABLE() spec includes NESTED COLUMNS and PLAN clauses, which are required to provide more flexibility to extract data out of nested JSON objects, but they are not implemented here to keep this commit of manageable size. Author: Nikita Glukhov <n.gluhov@postgrespro.ru> Author: Teodor Sigaev <teodor@sigaev.ru> Author: Oleg Bartunov <obartunov@gmail.com> Author: Alexander Korotkov <aekorotkov@gmail.com> Author: Andrew Dunstan <andrew@dunslane.net> Author: Amit Langote <amitlangote09@gmail.com> Author: Jian He <jian.universality@gmail.com> Reviewers have included (in no particular order): Andres Freund, Alexander Korotkov, Pavel Stehule, Andrew Alsup, Erik Rijkers, Zihong Yu, Himanshu Upadhyaya, Daniel Gustafsson, Justin Pryzby, Álvaro Herrera, Jian He Discussion: https://postgr.es/m/cd0bb935-0158-78a7-08b5-904886deac4b@postgrespro.ru Discussion: https://postgr.es/m/20220616233130.rparivafipt6doj3@alap3.anarazel.de Discussion: https://postgr.es/m/abd9b83b-aa66-f230-3d6d-734817f0995d%40postgresql.org Discussion: https://postgr.es/m/CA+HiwqE4XTdfb1nW=Ojoy_tQSRhYt-q_kb6i5d4xcKyrLC1Nbg@mail.gmail.com
Diffstat (limited to 'src/include/nodes')
-rw-r--r--src/include/nodes/execnodes.h2
-rw-r--r--src/include/nodes/makefuncs.h5
-rw-r--r--src/include/nodes/parsenodes.h66
-rw-r--r--src/include/nodes/primnodes.h56
4 files changed, 128 insertions, 1 deletions
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e7ff8e4992f..e57ebd72887 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1963,6 +1963,8 @@ typedef struct TableFuncScanState
ExprState *rowexpr; /* state for row-generating expression */
List *colexprs; /* state for column-generating expression */
List *coldefexprs; /* state for column default expressions */
+ List *colvalexprs; /* state for column value expressions */
+ List *passingvalexprs; /* state for PASSING argument expressions */
List *ns_names; /* same as TableFunc.ns_names */
List *ns_uris; /* list of states of namespace URI exprs */
Bitmapset *notnulls; /* nullability flag for each output column */
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index fdc78270e5b..5209d3de89c 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -100,6 +100,7 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
bool isready, bool concurrent,
bool summarizing);
+extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
extern DefElem *makeDefElemExtended(char *nameSpace, char *name, Node *arg,
DefElemAction defaction, int location);
@@ -118,5 +119,9 @@ extern Node *makeJsonIsPredicate(Node *expr, JsonFormat *format,
int location);
extern JsonBehavior *makeJsonBehavior(JsonBehaviorType btype, Node *expr,
int location);
+extern JsonTablePath *makeJsonTablePath(Const *pathvalue, char *pathname);
+extern JsonTablePathSpec *makeJsonTablePathSpec(char *string, char *name,
+ int string_location,
+ int name_location);
#endif /* MAKEFUNC_H */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index a690ebc6e51..76d91e547b7 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -648,6 +648,9 @@ typedef struct RangeFunction
/*
* RangeTableFunc - raw form of "table functions" such as XMLTABLE
+ *
+ * Note: JSON_TABLE is also a "table function", but it uses JsonTable node,
+ * not RangeTableFunc.
*/
typedef struct RangeTableFunc
{
@@ -1787,6 +1790,69 @@ typedef struct JsonFuncExpr
} JsonFuncExpr;
/*
+ * JsonTablePathSpec
+ * untransformed specification of JSON path expression with an optional
+ * name
+ */
+typedef struct JsonTablePathSpec
+{
+ NodeTag type;
+
+ Node *string;
+ char *name;
+ int name_location;
+ int location; /* location of 'string' */
+} JsonTablePathSpec;
+
+/*
+ * JsonTable -
+ * untransformed representation of JSON_TABLE
+ */
+typedef struct JsonTable
+{
+ NodeTag type;
+ JsonValueExpr *context_item; /* context item expression */
+ JsonTablePathSpec *pathspec; /* JSON path specification */
+ List *passing; /* list of PASSING clause arguments, if any */
+ List *columns; /* list of JsonTableColumn */
+ JsonBehavior *on_error; /* ON ERROR behavior */
+ Alias *alias; /* table alias in FROM clause */
+ bool lateral; /* does it have LATERAL prefix? */
+ int location; /* token location, or -1 if unknown */
+} JsonTable;
+
+/*
+ * JsonTableColumnType -
+ * enumeration of JSON_TABLE column types
+ */
+typedef enum JsonTableColumnType
+{
+ JTC_FOR_ORDINALITY,
+ JTC_REGULAR,
+ JTC_EXISTS,
+ JTC_FORMATTED,
+} JsonTableColumnType;
+
+/*
+ * JsonTableColumn -
+ * untransformed representation of JSON_TABLE column
+ */
+typedef struct JsonTableColumn
+{
+ NodeTag type;
+ JsonTableColumnType coltype; /* column type */
+ char *name; /* column name */
+ TypeName *typeName; /* column type name */
+ JsonTablePathSpec *pathspec; /* JSON path specification */
+ JsonFormat *format; /* JSON format clause, if specified */
+ JsonWrapper wrapper; /* WRAPPER behavior for formatted columns */
+ JsonQuotes quotes; /* omit or keep quotes on scalar strings? */
+ JsonBehavior *on_empty; /* ON EMPTY behavior */
+ JsonBehavior *on_error; /* ON ERROR behavior */
+ int location; /* token location, or -1 if unknown */
+} JsonTableColumn;
+
+/*
* JsonKeyValue -
* untransformed representation of JSON object key-value pair for
* JSON_OBJECT() and JSON_OBJECTAGG()
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index aa727e722cc..6657f34103f 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -94,8 +94,14 @@ typedef struct RangeVar
ParseLoc location;
} RangeVar;
+typedef enum TableFuncType
+{
+ TFT_XMLTABLE,
+ TFT_JSON_TABLE,
+} TableFuncType;
+
/*
- * TableFunc - node for a table function, such as XMLTABLE.
+ * TableFunc - node for a table function, such as XMLTABLE and JSON_TABLE.
*
* Entries in the ns_names list are either String nodes containing
* literal namespace names, or NULL pointers to represent DEFAULT.
@@ -103,6 +109,8 @@ typedef struct RangeVar
typedef struct TableFunc
{
NodeTag type;
+ /* XMLTABLE or JSON_TABLE */
+ TableFuncType functype;
/* list of namespace URI expressions */
List *ns_uris pg_node_attr(query_jumble_ignore);
/* list of namespace names or NULL */
@@ -123,8 +131,14 @@ typedef struct TableFunc
List *colexprs;
/* list of column default expressions */
List *coldefexprs pg_node_attr(query_jumble_ignore);
+ /* JSON_TABLE: list of column value expressions */
+ List *colvalexprs pg_node_attr(query_jumble_ignore);
+ /* JSON_TABLE: list of PASSING argument expressions */
+ List *passingvalexprs pg_node_attr(query_jumble_ignore);
/* nullability flag for each output column */
Bitmapset *notnulls pg_node_attr(query_jumble_ignore);
+ /* JSON_TABLE plan */
+ Node *plan pg_node_attr(query_jumble_ignore);
/* counts from 0; -1 if none specified */
int ordinalitycol pg_node_attr(query_jumble_ignore);
/* token location, or -1 if unknown */
@@ -1754,6 +1768,7 @@ typedef enum JsonExprOp
JSON_EXISTS_OP, /* JSON_EXISTS() */
JSON_QUERY_OP, /* JSON_QUERY() */
JSON_VALUE_OP, /* JSON_VALUE() */
+ JSON_TABLE_OP, /* JSON_TABLE() */
} JsonExprOp;
/*
@@ -1813,6 +1828,45 @@ typedef struct JsonExpr
int location;
} JsonExpr;
+/*
+ * JsonTablePath
+ * A JSON path expression to be computed as part of evaluating
+ * a JSON_TABLE plan node
+ */
+typedef struct JsonTablePath
+{
+ NodeTag type;
+
+ Const *value;
+ char *name;
+} JsonTablePath;
+
+/*
+ * JsonTablePlan -
+ * Abstract class to represent different types of JSON_TABLE "plans".
+ * A plan is used to generate a "row pattern" value by evaluating a JSON
+ * path expression against an input JSON document, which is then used for
+ * populating JSON_TABLE() columns
+ */
+typedef struct JsonTablePlan
+{
+ pg_node_attr(abstract)
+
+ NodeTag type;
+} JsonTablePlan;
+
+/* JSON_TABLE plan to evaluate a JSON path expression */
+typedef struct JsonTablePathScan
+{
+ JsonTablePlan plan;
+
+ /* JSON path to evaluate */
+ JsonTablePath *path;
+
+ /* ERROR/EMPTY ON ERROR behavior */
+ bool errorOnError;
+} JsonTablePathScan;
+
/* ----------------
* NullTest
*