I looked a bit at the parser additions, because there were some concerns
expressed that they are quite big.
It looks like the parser rules were mostly literally copied from the BNF
in the SQL standard. That's probably a reasonable place to start, but
now at the end, there is some room for simplification.
Attached are a few patches that apply on top of the 0003 patch. (I
haven't gotten to 0004 in detail yet.) Some explanations:
0001-Put-keywords-in-right-order.patch
This is just an unrelated cleanup.
0002-Remove-js_quotes-union-entry.patch
We usually don't want to put every single node type into the gram.y
%union. This one can be trivially removed.
0003-Move-some-code-from-gram.y-to-parse-analysis.patch
Code like this can be postponed to parse analysis, keeping gram.y
smaller. The error pointer loses a bit of precision, but I think that's
ok. (There is similar code in your 0004 patch, which could be similarly
moved.)
0004-Remove-JsonBehavior-stuff-from-union.patch
Similar to my 0002. This adds a few casts as a result, but that is the
typical style in gram.y.
0005-Get-rid-of-JsonBehaviorClause.patch
I think this two-level wrapping of the behavior clauses is both
confusing and overkill. I was trying to just list the on-empty and
on-error clauses separately in the top-level productions (JSON_VALUE
etc.), but that led to shift/reduce errors. So the existing rule
structure is probably ok. But we don't need a separate node type just
to combine two values and then unpack them again shortly thereafter. So
I just replaced all this with a list.
0006-Get-rid-of-JsonCommon.patch
This is an example where the SQL standard BNF is not sensible to apply
literally. I moved those clauses up directly into their callers, thus
removing one intermediate levels of rules and also nodes. Also, the
path name (AS name) stuff is only for JSON_TABLE, so it's not needed in
this patch. I removed it here, but it would have to be readded in your
0004 patch.
Another thing: In your patch, JSON_EXISTS has a RETURNING clause
(json_returning_clause_opt), but I don't see that in the standard, and
also not in the Oracle or Db2 docs. Where did this come from?
With these changes, I think the grammar complexity in your 0003 patch is
at an acceptable level. Similar simplification opportunities exist in
the 0004 patch, but I haven't worked on that yet. I suggest that you
focus on getting 0001..0003 committed around this commit fest and then
deal with 0004 in the next one. (Also split up the 0005 patch into the
pieces that apply to 0003 and 0004, respectively.)
From 90cd46c91231a29a41118861d5a6122d78f93379 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Tue, 21 Nov 2023 05:19:03 +0100
Subject: [PATCH 1/6] Put keywords in right order
---
src/backend/parser/gram.y | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 1dc3300fde..9a7058b767 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -735,7 +735,7 @@ static Node *makeRecursiveViewSelect(char *relname, List
*aliases, Node *query);
JOIN JSON JSON_ARRAY JSON_ARRAYAGG JSON_EXISTS JSON_OBJECT
JSON_OBJECTAGG
JSON_QUERY JSON_SCALAR JSON_SERIALIZE JSON_VALUE
- KEY KEYS KEEP
+ KEEP KEY KEYS
LABEL LANGUAGE LARGE_P LAST_P LATERAL_P
LEADING LEAKPROOF LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL
--
2.42.1
From b669a45c9603a23db240cf1566b3f2e726254ac4 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Tue, 21 Nov 2023 05:28:17 +0100
Subject: [PATCH 2/6] Remove js_quotes %union entry
---
src/backend/parser/gram.y | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 9a7058b767..a8cce5b00e 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -280,7 +280,6 @@ static Node *makeRecursiveViewSelect(char *relname, List
*aliases, Node *query);
struct KeyAction *keyaction;
JsonBehavior *jsbehavior;
JsonBehaviorClause *jsbehaviorclause;
- JsonQuotes js_quotes;
}
%type <node> stmt toplevel_stmt schema_stmt routine_body_stmt
@@ -662,12 +661,12 @@ static Node *makeRecursiveViewSelect(char *relname, List
*aliases, Node *query);
%type <ival> json_encoding_clause_opt
json_predicate_type_constraint
json_wrapper_behavior
+ json_quotes_clause_opt
%type <boolean> json_key_uniqueness_constraint_opt
json_object_constructor_null_clause_opt
json_array_constructor_null_clause_opt
%type <jsbehavior> json_behavior
%type <jsbehaviorclause> json_behavior_clause_opt
-%type <js_quotes> json_quotes_clause_opt
/*
--
2.42.1
From 7fb1906bab90e539697e6d66d3f2754eb3031603 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Tue, 21 Nov 2023 05:43:10 +0100
Subject: [PATCH 3/6] Move some code from gram.y to parse analysis
---
src/backend/parser/gram.y | 5 -----
src/backend/parser/parse_expr.c | 6 ++++++
src/test/regress/expected/jsonb_sqljson.out | 12 ++++++------
3 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a8cce5b00e..a2d482ab70 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -15778,11 +15778,6 @@ func_expr_common_subexpr:
n->common = (JsonCommon *) $3;
n->output = (JsonOutput *) $4;
n->wrapper = $5;
- if (n->wrapper != JSW_NONE && $6 !=
JS_QUOTES_UNSPEC)
- ereport(ERROR,
-
(errcode(ERRCODE_SYNTAX_ERROR),
-
errmsg("SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is
used"),
-
parser_errposition(@6)));
n->quotes = $6;
n->behavior = $7;
n->location = @1;
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 64571562c5..1c1f38a808 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -4302,6 +4302,12 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr
*func)
case JSON_QUERY_OP:
func_name = "JSON_QUERY";
+ if (func->wrapper != JSW_NONE && func->quotes !=
JS_QUOTES_UNSPEC)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("SQL/JSON QUOTES
behavior must not be specified when WITH WRAPPER is used"),
+ parser_errposition(pstate,
func->location)));
+
jsexpr = transformJsonExprCommon(pstate, func,
func_name);
jsexpr->wrapper = func->wrapper;
jsexpr->omit_quotes = (func->quotes == JS_QUOTES_OMIT);
diff --git a/src/test/regress/expected/jsonb_sqljson.out
b/src/test/regress/expected/jsonb_sqljson.out
index b467971ed9..9bf3fb21db 100644
--- a/src/test/regress/expected/jsonb_sqljson.out
+++ b/src/test/regress/expected/jsonb_sqljson.out
@@ -658,19 +658,19 @@ SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING bytea
FORMAT JSON OMIT QUOTES ERR
SELECT JSON_QUERY(jsonb '[1]', '$' WITH WRAPPER OMIT QUOTES);
ERROR: SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is
used
LINE 1: SELECT JSON_QUERY(jsonb '[1]', '$' WITH WRAPPER OMIT QUOTES)...
- ^
+ ^
SELECT JSON_QUERY(jsonb '[1]', '$' WITH WRAPPER KEEP QUOTES);
ERROR: SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is
used
LINE 1: SELECT JSON_QUERY(jsonb '[1]', '$' WITH WRAPPER KEEP QUOTES)...
- ^
+ ^
SELECT JSON_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER KEEP QUOTES);
ERROR: SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is
used
-LINE 1: ...N_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER KEEP QUOTE...
- ^
+LINE 1: SELECT JSON_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER ...
+ ^
SELECT JSON_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER OMIT QUOTES);
ERROR: SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is
used
-LINE 1: ...N_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER OMIT QUOTE...
- ^
+LINE 1: SELECT JSON_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER ...
+ ^
-- Should succeed
SELECT JSON_QUERY(jsonb '[1]', '$' WITHOUT WRAPPER OMIT QUOTES);
json_query
--
2.42.1
From a7e78b5e9c5cfa191a9580a7b98f6ea663edaa36 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Tue, 21 Nov 2023 05:53:55 +0100
Subject: [PATCH 4/6] Remove JsonBehavior stuff from %union
---
src/backend/parser/gram.y | 36 +++++++++++++++++-------------------
1 file changed, 17 insertions(+), 19 deletions(-)
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a2d482ab70..2866d1345c 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -278,8 +278,6 @@ static Node *makeRecursiveViewSelect(char *relname, List
*aliases, Node *query);
MergeWhenClause *mergewhen;
struct KeyActions *keyactions;
struct KeyAction *keyaction;
- JsonBehavior *jsbehavior;
- JsonBehaviorClause *jsbehaviorclause;
}
%type <node> stmt toplevel_stmt schema_stmt routine_body_stmt
@@ -654,6 +652,8 @@ static Node *makeRecursiveViewSelect(char *relname, List
*aliases, Node *query);
json_aggregate_func
json_api_common_syntax
json_argument
+ json_behavior
+ json_behavior_clause_opt
%type <list> json_name_and_value_list
json_value_expr_list
json_array_aggregate_order_by_clause_opt
@@ -665,8 +665,6 @@ static Node *makeRecursiveViewSelect(char *relname, List
*aliases, Node *query);
%type <boolean> json_key_uniqueness_constraint_opt
json_object_constructor_null_clause_opt
json_array_constructor_null_clause_opt
-%type <jsbehavior> json_behavior
-%type <jsbehaviorclause> json_behavior_clause_opt
/*
@@ -15779,7 +15777,7 @@ func_expr_common_subexpr:
n->output = (JsonOutput *) $4;
n->wrapper = $5;
n->quotes = $6;
- n->behavior = $7;
+ n->behavior = (JsonBehaviorClause *) $7;
n->location = @1;
$$ = (Node *) n;
}
@@ -15794,7 +15792,7 @@ func_expr_common_subexpr:
p->op = JSON_EXISTS_OP;
p->common = (JsonCommon *) $3;
p->output = (JsonOutput *) $4;
- p->behavior = $5;
+ p->behavior = (JsonBehaviorClause *) $5;
p->location = @1;
$$ = (Node *) p;
}
@@ -15809,7 +15807,7 @@ func_expr_common_subexpr:
n->op = JSON_VALUE_OP;
n->common = (JsonCommon *) $3;
n->output = (JsonOutput *) $4;
- n->behavior = $5;
+ n->behavior = (JsonBehaviorClause *) $5;
n->location = @1;
$$ = (Node *) n;
}
@@ -16665,25 +16663,25 @@ json_returning_clause_opt:
;
json_behavior:
- DEFAULT a_expr { $$ =
makeJsonBehavior(JSON_BEHAVIOR_DEFAULT, $2, @1); }
- | ERROR_P { $$ =
makeJsonBehavior(JSON_BEHAVIOR_ERROR, NULL, @1); }
- | NULL_P { $$ =
makeJsonBehavior(JSON_BEHAVIOR_NULL, NULL, @1); }
- | TRUE_P { $$ =
makeJsonBehavior(JSON_BEHAVIOR_TRUE, NULL, @1); }
- | FALSE_P { $$ =
makeJsonBehavior(JSON_BEHAVIOR_FALSE, NULL, @1); }
- | UNKNOWN { $$ =
makeJsonBehavior(JSON_BEHAVIOR_UNKNOWN, NULL, @1); }
- | EMPTY_P ARRAY { $$ =
makeJsonBehavior(JSON_BEHAVIOR_EMPTY_ARRAY, NULL, @1); }
- | EMPTY_P OBJECT_P { $$ =
makeJsonBehavior(JSON_BEHAVIOR_EMPTY_OBJECT, NULL, @1); }
+ DEFAULT a_expr { $$ = (Node *)
makeJsonBehavior(JSON_BEHAVIOR_DEFAULT, $2, @1); }
+ | ERROR_P { $$ = (Node *)
makeJsonBehavior(JSON_BEHAVIOR_ERROR, NULL, @1); }
+ | NULL_P { $$ = (Node *)
makeJsonBehavior(JSON_BEHAVIOR_NULL, NULL, @1); }
+ | TRUE_P { $$ = (Node *)
makeJsonBehavior(JSON_BEHAVIOR_TRUE, NULL, @1); }
+ | FALSE_P { $$ = (Node *)
makeJsonBehavior(JSON_BEHAVIOR_FALSE, NULL, @1); }
+ | UNKNOWN { $$ = (Node *)
makeJsonBehavior(JSON_BEHAVIOR_UNKNOWN, NULL, @1); }
+ | EMPTY_P ARRAY { $$ = (Node *)
makeJsonBehavior(JSON_BEHAVIOR_EMPTY_ARRAY, NULL, @1); }
+ | EMPTY_P OBJECT_P { $$ = (Node *)
makeJsonBehavior(JSON_BEHAVIOR_EMPTY_OBJECT, NULL, @1); }
/* non-standard, for Oracle compatibility only */
- | EMPTY_P { $$ =
makeJsonBehavior(JSON_BEHAVIOR_EMPTY_ARRAY, NULL, @1); }
+ | EMPTY_P { $$ = (Node *)
makeJsonBehavior(JSON_BEHAVIOR_EMPTY_ARRAY, NULL, @1); }
;
json_behavior_clause_opt:
json_behavior ON EMPTY_P
- { $$ = makeJsonBehaviorClause($1, NULL, @1); }
+ { $$ = (Node *)
makeJsonBehaviorClause((JsonBehavior *) $1, NULL, @1); }
| json_behavior ON ERROR_P
- { $$ = makeJsonBehaviorClause(NULL, $1, @1); }
+ { $$ = (Node *) makeJsonBehaviorClause(NULL,
(JsonBehavior *) $1, @1); }
| json_behavior ON EMPTY_P json_behavior ON ERROR_P
- { $$ = makeJsonBehaviorClause($1, $4, @1); }
+ { $$ = (Node *)
makeJsonBehaviorClause((JsonBehavior *) $1, (JsonBehavior *) $4, @1); }
| /* EMPTY */
{ $$ = NULL; }
;
--
2.42.1
From 34795db318b16892926dae9ebc848827771136fa Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Tue, 21 Nov 2023 07:21:03 +0100
Subject: [PATCH 5/6] Get rid of JsonBehaviorClause
---
src/backend/nodes/makefuncs.c | 17 -----------------
src/backend/nodes/nodeFuncs.c | 10 ----------
src/backend/parser/gram.y | 16 ++++++++--------
src/backend/parser/parse_expr.c | 4 ++--
src/include/nodes/makefuncs.h | 3 ---
src/include/nodes/parsenodes.h | 14 +-------------
src/tools/pgindent/typedefs.list | 1 -
7 files changed, 11 insertions(+), 54 deletions(-)
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 746ed3d1da..a3757af6cf 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -857,23 +857,6 @@ makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr,
return jve;
}
-/*
- * makeJsonBehaviorClause -
- * creates a JsonBehaviorClause node
- */
-JsonBehaviorClause *
-makeJsonBehaviorClause(JsonBehavior *on_empty, JsonBehavior *on_error,
- int location)
-{
- JsonBehaviorClause *behavior = makeNode(JsonBehaviorClause);
-
- behavior->on_empty = on_empty;
- behavior->on_error = on_error;
- behavior->location = location;
-
- return behavior;
-}
-
/*
* makeJsonBehavior -
* creates a JsonBehavior node
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index 8e49ef6b95..7cad662e28 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -4093,16 +4093,6 @@ raw_expression_tree_walker_impl(Node *node,
return true;
}
break;
- case T_JsonBehaviorClause:
- {
- JsonBehaviorClause *jbc = (JsonBehaviorClause
*) node;
-
- if (WALK(jbc->on_empty))
- return true;
- if (WALK(jbc->on_error))
- return true;
- }
- break;
case T_JsonBehavior:
{
JsonBehavior *jb = (JsonBehavior *) node;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 2866d1345c..99585308c8 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -653,11 +653,11 @@ static Node *makeRecursiveViewSelect(char *relname, List
*aliases, Node *query);
json_api_common_syntax
json_argument
json_behavior
- json_behavior_clause_opt
%type <list> json_name_and_value_list
json_value_expr_list
json_array_aggregate_order_by_clause_opt
json_arguments
+ json_behavior_clause_opt
%type <ival> json_encoding_clause_opt
json_predicate_type_constraint
json_wrapper_behavior
@@ -15777,7 +15777,7 @@ func_expr_common_subexpr:
n->output = (JsonOutput *) $4;
n->wrapper = $5;
n->quotes = $6;
- n->behavior = (JsonBehaviorClause *) $7;
+ n->behavior = $7;
n->location = @1;
$$ = (Node *) n;
}
@@ -15792,7 +15792,7 @@ func_expr_common_subexpr:
p->op = JSON_EXISTS_OP;
p->common = (JsonCommon *) $3;
p->output = (JsonOutput *) $4;
- p->behavior = (JsonBehaviorClause *) $5;
+ p->behavior = $5;
p->location = @1;
$$ = (Node *) p;
}
@@ -15807,7 +15807,7 @@ func_expr_common_subexpr:
n->op = JSON_VALUE_OP;
n->common = (JsonCommon *) $3;
n->output = (JsonOutput *) $4;
- n->behavior = (JsonBehaviorClause *) $5;
+ n->behavior = $5;
n->location = @1;
$$ = (Node *) n;
}
@@ -16677,13 +16677,13 @@ json_behavior:
json_behavior_clause_opt:
json_behavior ON EMPTY_P
- { $$ = (Node *)
makeJsonBehaviorClause((JsonBehavior *) $1, NULL, @1); }
+ { $$ = list_make2($1, NULL); }
| json_behavior ON ERROR_P
- { $$ = (Node *) makeJsonBehaviorClause(NULL,
(JsonBehavior *) $1, @1); }
+ { $$ = list_make2(NULL, $1); }
| json_behavior ON EMPTY_P json_behavior ON ERROR_P
- { $$ = (Node *)
makeJsonBehaviorClause((JsonBehavior *) $1, (JsonBehavior *) $4, @1); }
+ { $$ = list_make2($1, $4); }
| /* EMPTY */
- { $$ = NULL; }
+ { $$ = list_make2(NULL, NULL); }
;
json_predicate_type_constraint:
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 1c1f38a808..2f4d3cb118 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -4240,8 +4240,8 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr
*func)
if (func->behavior)
{
- on_error = func->behavior->on_error;
- on_empty = func->behavior->on_empty;
+ on_empty = linitial(func->behavior);
+ on_error = lsecond(func->behavior);
}
switch (func->op)
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index 783e82ac92..a850a1928b 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -113,9 +113,6 @@ extern JsonFormat *makeJsonFormat(JsonFormatType type,
JsonEncoding encoding,
extern JsonValueExpr *makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr,
JsonFormat *format);
extern JsonBehavior *makeJsonBehavior(JsonBehaviorType type, Node *expr, int
location);
-extern JsonBehaviorClause *makeJsonBehaviorClause(JsonBehavior *on_empty,
-
JsonBehavior *on_error,
-
int location);
extern Node *makeJsonKeyValue(Node *key, Node *value);
extern Node *makeJsonIsPredicate(Node *expr, JsonFormat *format,
JsonValueType
item_type, bool unique_keys,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ce6893fb91..0f977f935e 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1703,18 +1703,6 @@ typedef enum JsonQuotes
JS_QUOTES_OMIT /* OMIT QUOTES */
} JsonQuotes;
-/*
- * JsonBehaviorClause -
- * representation of JSON ON ERROR / ON EMPTY clause
- */
-typedef struct JsonBehaviorClause
-{
- NodeTag type;
- JsonBehavior *on_empty; /* behavior ON EMPTY */
- JsonBehavior *on_error; /* behavior ON ERROR */
- int location; /* token location, or
-1 if unknown */
-} JsonBehaviorClause;
-
/*
* JsonPathSpec -
* representation of JSON path constant
@@ -1767,7 +1755,7 @@ typedef struct JsonFuncExpr
JsonExprOp op; /* expression type */
JsonCommon *common; /* common syntax */
JsonOutput *output; /* output clause, if specified
*/
- JsonBehaviorClause *behavior; /* ON ERROR / EMPTY behavior, if
specified */
+ List *behavior; /* ON EMPTY / ERROR behavior, list of
two JsonBehavior nodes */
JsonWrapper wrapper; /* array wrapper behavior (JSON_QUERY
only) */
JsonQuotes quotes; /* omit or keep quotes?
(JSON_QUERY only) */
int location; /* token location, or
-1 if unknown */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 3cfa9d756e..9258576b4c 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1260,7 +1260,6 @@ JsonArrayConstructor
JsonArrayQueryConstructor
JsonBaseObjectInfo
JsonBehavior
-JsonBehaviorClause
JsonBehaviorType
JsonCoercion
JsonCoercionState
--
2.42.1
From 87f6b4ad2d85a243b106c933c3f8830e5f64451f Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Tue, 21 Nov 2023 07:25:41 +0100
Subject: [PATCH 6/6] Get rid of JsonCommon
---
src/backend/nodes/nodeFuncs.c | 18 ++----
src/backend/parser/gram.y | 95 ++++++++++----------------------
src/backend/parser/parse_expr.c | 8 +--
src/include/nodes/parsenodes.h | 18 +-----
src/tools/pgindent/typedefs.list | 1 -
5 files changed, 40 insertions(+), 100 deletions(-)
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index 7cad662e28..b6cd8c38d2 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -4081,18 +4081,6 @@ raw_expression_tree_walker_impl(Node *node,
return WALK(((JsonIsPredicate *) node)->expr);
case T_JsonArgument:
return WALK(((JsonArgument *) node)->val);
- case T_JsonCommon:
- {
- JsonCommon *jc = (JsonCommon *) node;
-
- if (WALK(jc->expr))
- return true;
- if (WALK(jc->pathspec))
- return true;
- if (WALK(jc->passing))
- return true;
- }
- break;
case T_JsonBehavior:
{
JsonBehavior *jb = (JsonBehavior *) node;
@@ -4106,7 +4094,11 @@ raw_expression_tree_walker_impl(Node *node,
{
JsonFuncExpr *jfe = (JsonFuncExpr *) node;
- if (WALK(jfe->common))
+ if (WALK(jfe->context_item))
+ return true;
+ if (WALK(jfe->pathspec))
+ return true;
+ if (WALK(jfe->passing))
return true;
if (jfe->output && WALK(jfe->output))
return true;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 99585308c8..4cdf086a42 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -650,7 +650,6 @@ static Node *makeRecursiveViewSelect(char *relname, List
*aliases, Node *query);
json_returning_clause_opt
json_name_and_value
json_aggregate_func
- json_api_common_syntax
json_argument
json_behavior
%type <list> json_name_and_value_list
@@ -658,6 +657,7 @@ static Node *makeRecursiveViewSelect(char *relname, List
*aliases, Node *query);
json_array_aggregate_order_by_clause_opt
json_arguments
json_behavior_clause_opt
+ json_passing_clause_opt
%type <ival> json_encoding_clause_opt
json_predicate_type_constraint
json_wrapper_behavior
@@ -15763,7 +15763,7 @@ func_expr_common_subexpr:
$$ = (Node *) n;
}
| JSON_QUERY '('
- json_api_common_syntax
+ json_value_expr ',' a_expr
json_passing_clause_opt
json_returning_clause_opt
json_wrapper_behavior
json_quotes_clause_opt
@@ -15773,31 +15773,35 @@ func_expr_common_subexpr:
JsonFuncExpr *n =
makeNode(JsonFuncExpr);
n->op = JSON_QUERY_OP;
- n->common = (JsonCommon *) $3;
- n->output = (JsonOutput *) $4;
- n->wrapper = $5;
- n->quotes = $6;
- n->behavior = $7;
+ n->context_item = (JsonValueExpr *) $3;
+ n->pathspec = $5;
+ n->passing = $6;
+ n->output = (JsonOutput *) $7;
+ n->wrapper = $8;
+ n->quotes = $9;
+ n->behavior = $10;
n->location = @1;
$$ = (Node *) n;
}
| JSON_EXISTS '('
- json_api_common_syntax
+ json_value_expr ',' a_expr
json_passing_clause_opt
json_returning_clause_opt
json_behavior_clause_opt
')'
{
- JsonFuncExpr *p =
makeNode(JsonFuncExpr);
+ JsonFuncExpr *n =
makeNode(JsonFuncExpr);
- p->op = JSON_EXISTS_OP;
- p->common = (JsonCommon *) $3;
- p->output = (JsonOutput *) $4;
- p->behavior = $5;
- p->location = @1;
- $$ = (Node *) p;
+ n->op = JSON_EXISTS_OP;
+ n->context_item = (JsonValueExpr *) $3;
+ n->pathspec = $5;
+ n->passing = $6;
+ n->output = (JsonOutput *) $7;
+ n->behavior = $8;
+ n->location = @1;
+ $$ = (Node *) n;
}
| JSON_VALUE '('
- json_api_common_syntax
+ json_value_expr ',' a_expr
json_passing_clause_opt
json_returning_clause_opt
json_behavior_clause_opt
')'
@@ -15805,9 +15809,11 @@ func_expr_common_subexpr:
JsonFuncExpr *n =
makeNode(JsonFuncExpr);
n->op = JSON_VALUE_OP;
- n->common = (JsonCommon *) $3;
- n->output = (JsonOutput *) $4;
- n->behavior = $5;
+ n->context_item = (JsonValueExpr *) $3;
+ n->pathspec = $5;
+ n->passing = $6;
+ n->output = (JsonOutput *) $7;
+ n->behavior = $8;
n->location = @1;
$$ = (Node *) n;
}
@@ -16537,54 +16543,9 @@ opt_asymmetric: ASYMMETRIC
;
/* SQL/JSON support */
-json_api_common_syntax:
- json_value_expr ',' a_expr /* i.e. a json_path */
- {
- JsonCommon *n = makeNode(JsonCommon);
-
- n->expr = (JsonValueExpr *) $1;
- n->pathspec = $3;
- n->pathname = NULL;
- n->passing = NULL;
- n->location = @1;
- $$ = (Node *) n;
- }
- | json_value_expr ',' a_expr AS name
- {
- JsonCommon *n = makeNode(JsonCommon);
-
- n->expr = (JsonValueExpr *) $1;
- n->pathspec = $3;
- n->pathname = $5;
- n->passing = NULL;
- n->location = @1;
- $$ = (Node *) n;
- }
-
- | json_value_expr ',' a_expr /* i.e. a json_path */
- PASSING json_arguments
- {
- JsonCommon *n = makeNode(JsonCommon);
-
- n->expr = (JsonValueExpr *) $1;
- n->pathspec = $3;
- n->pathname = NULL;
- n->passing = $5;
- n->location = @1;
- $$ = (Node *) n;
- }
- | json_value_expr ',' a_expr AS name
- PASSING json_arguments
- {
- JsonCommon *n = makeNode(JsonCommon);
-
- n->expr = (JsonValueExpr *) $1;
- n->pathspec = $3;
- n->pathname = $5;
- n->passing = $7;
- n->location = @1;
- $$ = (Node *) n;
- }
+json_passing_clause_opt:
+ PASSING json_arguments
{ $$ = $2; }
+ | /*EMPTY*/
{ $$ = NIL; }
;
json_arguments:
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 2f4d3cb118..af0843aa3c 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -4384,17 +4384,17 @@ transformJsonExprCommon(ParseState *pstate,
JsonFuncExpr *func,
jsexpr->location = func->location;
jsexpr->op = func->op;
jsexpr->formatted_expr = transformJsonValueExpr(pstate, constructName,
-
func->common->expr,
+
func->context_item,
JS_FORMAT_JSON,
InvalidOid, false);
- jsexpr->format = func->common->expr->format;
+ jsexpr->format = func->context_item->format;
/* Both set in the caller. */
jsexpr->result_coercion = NULL;
jsexpr->omit_quotes = false;
- pathspec = transformExprRecurse(pstate, func->common->pathspec);
+ pathspec = transformExprRecurse(pstate, func->pathspec);
jsexpr->path_spec =
coerce_to_target_type(pstate, pathspec, exprType(pathspec),
@@ -4415,7 +4415,7 @@ transformJsonExprCommon(ParseState *pstate, JsonFuncExpr
*func,
transformJsonPassingArgs(pstate, constructName,
exprType(jsexpr->formatted_expr) == JSONBOID ?
JS_FORMAT_JSONB :
JS_FORMAT_JSON,
- func->common->passing,
+ func->passing,
&jsexpr->passing_values,
&jsexpr->passing_names);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 0f977f935e..83acd17ad4 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1731,20 +1731,6 @@ typedef struct JsonArgument
char *name; /* argument name */
} JsonArgument;
-/*
- * JsonCommon -
- * representation of common syntax of functions using JSON path
- */
-typedef struct JsonCommon
-{
- NodeTag type;
- JsonValueExpr *expr; /* context item expression */
- Node *pathspec; /* JSON path specification expression */
- char *pathname; /* path name, if any */
- List *passing; /* list of PASSING clause arguments, if
any */
- int location; /* token location, or
-1 if unknown */
-} JsonCommon;
-
/*
* JsonFuncExpr -
* untransformed representation of JSON function expressions
@@ -1753,7 +1739,9 @@ typedef struct JsonFuncExpr
{
NodeTag type;
JsonExprOp op; /* expression type */
- JsonCommon *common; /* common syntax */
+ JsonValueExpr *context_item; /* context item expression */
+ Node *pathspec; /* JSON path specification expression */
+ List *passing; /* list of PASSING clause arguments, if
any */
JsonOutput *output; /* output clause, if specified
*/
List *behavior; /* ON EMPTY / ERROR behavior, list of
two JsonBehavior nodes */
JsonWrapper wrapper; /* array wrapper behavior (JSON_QUERY
only) */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 9258576b4c..8186a42659 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1263,7 +1263,6 @@ JsonBehavior
JsonBehaviorType
JsonCoercion
JsonCoercionState
-JsonCommon
JsonConstructorExpr
JsonConstructorExprState
JsonConstructorType
--
2.42.1