I noticed that JSON_TABLE uses an explicit FORMAT JSON in one of the
rules, instead of using json_format_clause_opt like everywhere else.  I
wondered why, and noticed that it's because it wants to set coltype
JTC_FORMATTED when the clause is present but JTC_REGULAR otherwise.
This seemed a little odd, but I thought to split json_format_clause_opt
in two productions, one without the empty rule (json_format_clause) and
another with it.  This is not a groundbreaking improvement, but it seems
more natural, and it helps contain the FORMAT stuff a little better.

I also noticed while at it that we can do away not only with the
json_encoding_clause_opt clause, but also with makeJsonEncoding().

The attach patch does it.  This is not derived from the patches you're
currently working on; it's more of a revise of the previous SQL/JSON
code I committed in 7081ac46ace8.

It goes before your 0003 and has a couple of easily resolved conflicts
with both 0003 and 0004; then in 0004 you have to edit the JSON_TABLE
rule that has FORMAT_LA and replace that with json_format_clause.

-- 
Álvaro Herrera         PostgreSQL Developer  —  https://www.EnterpriseDB.com/
"El que vive para el futuro es un iluso, y el que vive para el pasado,
un imbécil" (Luis Adler, "Los tripulantes de la noche")
>From 06e0814e06d04e5ec268e08323eba1b62a656926 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvhe...@alvh.no-ip.org>
Date: Thu, 7 Dec 2023 15:56:15 +0100
Subject: [PATCH] simplify json_format_clause by removing the 'opt' part

---
 src/backend/nodes/makefuncs.c | 21 ---------------
 src/backend/parser/gram.y     | 51 +++++++++++++++++++++++------------
 src/include/nodes/makefuncs.h |  1 -
 3 files changed, 34 insertions(+), 39 deletions(-)

diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index c6fb571982..89e77adbc7 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -857,27 +857,6 @@ makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr,
 	return jve;
 }
 
-/*
- * makeJsonEncoding -
- *	  converts JSON encoding name to enum JsonEncoding
- */
-JsonEncoding
-makeJsonEncoding(char *name)
-{
-	if (!pg_strcasecmp(name, "utf8"))
-		return JS_ENC_UTF8;
-	if (!pg_strcasecmp(name, "utf16"))
-		return JS_ENC_UTF16;
-	if (!pg_strcasecmp(name, "utf32"))
-		return JS_ENC_UTF32;
-
-	ereport(ERROR,
-			errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-			errmsg("unrecognized JSON encoding: %s", name));
-
-	return JS_ENC_DEFAULT;
-}
-
 /*
  * makeJsonKeyValue -
  *	  creates a JsonKeyValue node
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index d631ac89a9..f16bbd3cdd 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -645,7 +645,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <list>		hash_partbound
 %type <defelt>		hash_partbound_elem
 
-%type <node>	json_format_clause_opt
+%type <node>	json_format_clause
+				json_format_clause_opt
 				json_value_expr
 				json_returning_clause_opt
 				json_name_and_value
@@ -653,8 +654,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <list>	json_name_and_value_list
 				json_value_expr_list
 				json_array_aggregate_order_by_clause_opt
-%type <ival>	json_encoding_clause_opt
-				json_predicate_type_constraint
+%type <ival>	json_predicate_type_constraint
 %type <boolean>	json_key_uniqueness_constraint_opt
 				json_object_constructor_null_clause_opt
 				json_array_constructor_null_clause_opt
@@ -14962,12 +14962,11 @@ a_expr:		c_expr									{ $$ = $1; }
 			/*
 			 * Required by SQL/JSON, but there are conflicts
 			| a_expr
-				FORMAT_LA JSON json_encoding_clause_opt
+				json_format_clause
 				IS  json_predicate_type_constraint
 					json_key_uniqueness_constraint_opt		%prec IS
 				{
-					$3.location = @2;
-					$$ = makeJsonIsPredicate($1, $3, $5, $6, @1);
+					$$ = makeJsonIsPredicate($1, $2, $4, $5, @1);
 				}
 			*/
 			| a_expr IS NOT
@@ -14981,13 +14980,12 @@ a_expr:		c_expr									{ $$ = $1; }
 			/*
 			 * Required by SQL/JSON, but there are conflicts
 			| a_expr
-				FORMAT_LA JSON json_encoding_clause_opt
+				json_format_clause
 				IS NOT
 					json_predicate_type_constraint
 					json_key_uniqueness_constraint_opt		%prec IS
 				{
-					$3.location = @2;
-					$$ = makeNotExpr(makeJsonIsPredicate($1, $3, $6, $7, @1), @1);
+					$$ = makeNotExpr(makeJsonIsPredicate($1, $2, $5, $6, @1), @1);
 				}
 			*/
 			| DEFAULT
@@ -16503,10 +16501,34 @@ json_value_expr:
 			}
 		;
 
-json_format_clause_opt:
-			FORMAT_LA JSON json_encoding_clause_opt
+json_format_clause:
+			FORMAT_LA JSON ENCODING name
 				{
-					$$ = (Node *) makeJsonFormat(JS_FORMAT_JSON, $3, @1);
+					int		encoding;
+
+					if (!pg_strcasecmp($4, "utf8"))
+						encoding = JS_ENC_UTF8;
+					else if (!pg_strcasecmp($4, "utf16"))
+						encoding = JS_ENC_UTF16;
+					else if (!pg_strcasecmp($4, "utf32"))
+						encoding = JS_ENC_UTF32;
+					else
+						ereport(ERROR,
+								errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+								errmsg("unrecognized JSON encoding: %s", $4));
+
+					$$ = (Node *) makeJsonFormat(JS_FORMAT_JSON, encoding, @1);
+				}
+			| FORMAT_LA JSON
+				{
+					$$ = (Node *) makeJsonFormat(JS_FORMAT_JSON, JS_ENC_DEFAULT, @1);
+				}
+		;
+
+json_format_clause_opt:
+			json_format_clause
+				{
+					$$ = $1;
 				}
 			| /* EMPTY */
 				{
@@ -16514,11 +16536,6 @@ json_format_clause_opt:
 				}
 		;
 
-json_encoding_clause_opt:
-			ENCODING name					{ $$ = makeJsonEncoding($2); }
-			| /* EMPTY */					{ $$ = JS_ENC_DEFAULT; }
-		;
-
 json_returning_clause_opt:
 			RETURNING Typename json_format_clause_opt
 				{
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index 3180703005..aca0ee54df 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -116,6 +116,5 @@ extern Node *makeJsonKeyValue(Node *key, Node *value);
 extern Node *makeJsonIsPredicate(Node *expr, JsonFormat *format,
 								 JsonValueType item_type, bool unique_keys,
 								 int location);
-extern JsonEncoding makeJsonEncoding(char *name);
 
 #endif							/* MAKEFUNC_H */
-- 
2.39.2

Reply via email to