v11-0008-Add-as-a-new-token-in-scanners.patch
application/x-patch
Filename: v11-0008-Add-as-a-new-token-in-scanners.patch
Type: application/x-patch
Part: 7
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v11-0008
Subject: Add "**" as a new token in scanners
| File | + | − |
|---|---|---|
| src/backend/parser/gram.y | 8 | 1 |
| src/backend/parser/scan.l | 6 | 0 |
| src/include/parser/scanner.h | 1 | 1 |
| src/interfaces/ecpg/preproc/pgc.l | 5 | 0 |
| src/interfaces/ecpg/test/expected/sql-sqljson.c | 11 | 1 |
| src/interfaces/ecpg/test/expected/sql-sqljson.stderr | 11 | 0 |
| src/interfaces/ecpg/test/sql/sqljson.pgc | 3 | 0 |
| src/pl/plpgsql/src/pl_gram.y | 1 | 1 |
| src/test/regress/expected/jsonb.out | 1 | 1 |
From c88047f7fb45363e836aef0eb2422099106e544b Mon Sep 17 00:00:00 2001
From: Alexandra Wang <alexandra.wang.oss@gmail.com>
Date: Mon, 10 Mar 2025 07:00:03 -0500
Subject: [PATCH v11 8/8] Add "**" as a new token in scanners
DOUBLE_ASTERISK is now recognized but not yet implemented.
This change improves error message readability, as "**" is supported
in jsonpath_scan.l as ANY_P. However, the SQL standard for simplified
JSON accessors does not specify "**", so it is not supported in that
context.
---
src/backend/parser/gram.y | 9 ++++++++-
src/backend/parser/scan.l | 6 ++++++
src/include/parser/scanner.h | 2 +-
src/interfaces/ecpg/preproc/pgc.l | 5 +++++
src/interfaces/ecpg/test/expected/sql-sqljson.c | 12 +++++++++++-
src/interfaces/ecpg/test/expected/sql-sqljson.stderr | 11 +++++++++++
src/interfaces/ecpg/test/sql/sqljson.pgc | 3 +++
src/pl/plpgsql/src/pl_gram.y | 2 +-
src/test/regress/expected/jsonb.out | 2 +-
9 files changed, 47 insertions(+), 5 deletions(-)
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 44840bc1b25..4635616d93a 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -687,7 +687,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
*/
%token <str> IDENT UIDENT FCONST SCONST USCONST BCONST XCONST Op
%token <ival> ICONST PARAM
-%token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER
+%token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER DOUBLE_ASTERISK
%token LESS_EQUALS GREATER_EQUALS NOT_EQUALS
/*
@@ -16969,6 +16969,13 @@ indirection_el:
{
$$ = (Node *) makeNode(A_Star);
}
+ | '.' DOUBLE_ASTERISK
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("arbitrary depth wild card in simple json accessor not supported"),
+ parser_errposition(@2)));
+ }
| '[' a_expr ']'
{
A_Indices *ai = makeNode(A_Indices);
diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l
index 08990831fe8..c58ba233153 100644
--- a/src/backend/parser/scan.l
+++ b/src/backend/parser/scan.l
@@ -338,6 +338,7 @@ identifier {ident_start}{ident_cont}*
typecast "::"
dot_dot \.\.
colon_equals ":="
+double_asterisk "**"
/*
* These operator-like tokens (unlike the above ones) also match the {operator}
@@ -851,6 +852,11 @@ other .
return COLON_EQUALS;
}
+{double_asterisk} {
+ SET_YYLLOC();
+ return DOUBLE_ASTERISK;
+ }
+
{equals_greater} {
SET_YYLLOC();
return EQUALS_GREATER;
diff --git a/src/include/parser/scanner.h b/src/include/parser/scanner.h
index 74ad86698ac..2f9b7baa1a9 100644
--- a/src/include/parser/scanner.h
+++ b/src/include/parser/scanner.h
@@ -50,7 +50,7 @@ typedef union core_YYSTYPE
* the ASCII characters plus these:
* %token <str> IDENT UIDENT FCONST SCONST USCONST BCONST XCONST Op
* %token <ival> ICONST PARAM
- * %token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER
+ * %token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER DOUBLE_ASTERISK
* %token LESS_EQUALS GREATER_EQUALS NOT_EQUALS
* The above token definitions *must* be the first ones declared in any
* bison parser built atop this scanner, so that they will have consistent
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index 63283a4a1e5..1415cbe2808 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -321,6 +321,7 @@ array ({ident_cont}|{whitespace}|[\[\]\+\-\*\%\/\(\)\>\.])*
typecast "::"
dot_dot \.\.
colon_equals ":="
+double_asterisk "**"
/*
* These operator-like tokens (unlike the above ones) also match the {operator}
@@ -832,6 +833,10 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
return COLON_EQUALS;
}
+{double_asterisk} {
+ return DOUBLE_ASTERISK;
+ }
+
{equals_greater} {
return EQUALS_GREATER;
}
diff --git a/src/interfaces/ecpg/test/expected/sql-sqljson.c b/src/interfaces/ecpg/test/expected/sql-sqljson.c
index 748b2e2bee6..f772305c209 100644
--- a/src/interfaces/ecpg/test/expected/sql-sqljson.c
+++ b/src/interfaces/ecpg/test/expected/sql-sqljson.c
@@ -527,12 +527,22 @@ if (sqlca.sqlcode < 0) sqlprint();}
printf("Found json=%s\n", json);
- { ECPGdisconnect(__LINE__, "CURRENT");
+ { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select json ( ( '{\"a\": {\"b\": 1, \"c\": 2}, \"b\": [{\"x\": 1}, {\"x\": [12, {\"y\":1}]}]}' :: jsonb ) . ** . b )", ECPGt_EOIT,
+ ECPGt_char,(json),(long)1024,(long)1,(1024)*sizeof(char),
+ ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 151 "sqljson.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 151 "sqljson.pgc"
+ // error
+
+ { ECPGdisconnect(__LINE__, "CURRENT");
+#line 154 "sqljson.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 154 "sqljson.pgc"
+
return 0;
}
diff --git a/src/interfaces/ecpg/test/expected/sql-sqljson.stderr b/src/interfaces/ecpg/test/expected/sql-sqljson.stderr
index 92c5d1520c4..d9a2fe21915 100644
--- a/src/interfaces/ecpg/test/expected/sql-sqljson.stderr
+++ b/src/interfaces/ecpg/test/expected/sql-sqljson.stderr
@@ -359,5 +359,16 @@ SQL error: schema "jsonb" does not exist on line 121
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 148: RESULT: [1, [12, {"y": 1}]] offset: -1; array: no
[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 151: query: select json ( ( '{"a": {"b": 1, "c": 2}, "b": [{"x": 1}, {"x": [12, {"y":1}]}]}' :: jsonb ) . ** . b ); with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 151: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_check_PQresult on line 151: bad response - ERROR: arbitrary depth wild card in simple json accessor not supported
+LINE 1: ...b": [{"x": 1}, {"x": [12, {"y":1}]}]}' :: jsonb ) . ** . b )
+ ^
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlstate 0A000 (sqlcode -400): arbitrary depth wild card in simple json accessor not supported on line 151
+[NO_PID]: sqlca: code: -400, state: 0A000
+SQL error: arbitrary depth wild card in simple json accessor not supported on line 151
[NO_PID]: ecpg_finish: connection ecpg1_regression closed
[NO_PID]: sqlca: code: 0, state: 00000
diff --git a/src/interfaces/ecpg/test/sql/sqljson.pgc b/src/interfaces/ecpg/test/sql/sqljson.pgc
index 4e7427d237d..65443d30055 100644
--- a/src/interfaces/ecpg/test/sql/sqljson.pgc
+++ b/src/interfaces/ecpg/test/sql/sqljson.pgc
@@ -148,6 +148,9 @@ EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT JSON(('{"a": {"b": 1, "c": 2}, "b": [{"x": 1}, {"x": [12, {"y":1}]}]}'::jsonb).*.x) INTO :json;
printf("Found json=%s\n", json);
+ EXEC SQL SELECT JSON(('{"a": {"b": 1, "c": 2}, "b": [{"x": 1}, {"x": [12, {"y":1}]}]}'::jsonb).**.b) INTO :json;
+ // error
+
EXEC SQL DISCONNECT;
return 0;
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index 5612e66d023..13e06ad5b0b 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -245,7 +245,7 @@ static void check_raise_parameters(PLpgSQL_stmt_raise *stmt);
*/
%token <str> IDENT UIDENT FCONST SCONST USCONST BCONST XCONST Op
%token <ival> ICONST PARAM
-%token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER
+%token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER DOUBLE_ASTERISK
%token LESS_EQUALS GREATER_EQUALS NOT_EQUALS
/*
diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out
index 1a9452937d5..0729d7251c6 100644
--- a/src/test/regress/expected/jsonb.out
+++ b/src/test/regress/expected/jsonb.out
@@ -6181,7 +6181,7 @@ SELECT (jb).a.b.c.* FROM test_jsonb_dot_notation;
(1 row)
SELECT (jb).a.**.x FROM test_jsonb_dot_notation; -- not supported
-ERROR: syntax error at or near "**"
+ERROR: arbitrary depth wild card in simple json accessor not supported
LINE 1: SELECT (jb).a.**.x FROM test_jsonb_dot_notation;
^
-- explains should work
--
2.39.5 (Apple Git-154)