We could do something like this. Is this good? I tried to merge WITH and WITHOUT with the precedence class immediately above, but that failed: the main grammar compiles fine and no tests fail, but ECPG does fail to compile the sqljson.pgc test, so there's some problem there. Now, the ecpg grammar stuff *is* absolute black magic to me, so I have no idea what to do about that.
(TBH I don't think the added comments really explain the problems fully. That's most likely because I don't actually understand what the problems are.) -- Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/ Thou shalt study thy libraries and strive not to reinvent them without cause, that thy code may be short and readable and thy days pleasant and productive. (7th Commandment for C Programmers)
>From 3499494625a59e2b5bda85c207b2d0e1181d703d Mon Sep 17 00:00:00 2001 From: Alvaro Herrera <alvhe...@alvh.no-ip.org> Date: Mon, 27 Nov 2023 18:01:44 +0100 Subject: [PATCH v1] Merge JSON-related grammar keyword precedence classes Some of these classes were unnecessary. Grouping them this way also helps us document the reason for these to exist at all. --- src/backend/parser/gram.y | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 8c00b119ec..3060dc88f8 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -821,11 +821,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %nonassoc BETWEEN IN_P LIKE ILIKE SIMILAR NOT_LA %nonassoc ESCAPE /* ESCAPE must be just above LIKE/ILIKE/SIMILAR */ -/* SQL/JSON related keywords */ -%nonassoc UNIQUE JSON -%nonassoc KEYS OBJECT_P SCALAR VALUE_P -%nonassoc WITH WITHOUT - /* * To support target_el without AS, it used to be necessary to assign IDENT an * explicit precedence just less than Op. While that's not really necessary @@ -850,9 +845,22 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); * an explicit priority lower than '(', so that a rule with CUBE '(' will shift * rather than reducing a conflicting rule that takes CUBE as a function name. * Using the same precedence as IDENT seems right for the reasons given above. + * + * We also need to support WITH UNIQUE KEYS and WITHOUT UNIQUE KEYS, where + * KEYS is optional and the whole rule is also optional. We can do this by + * putting UNIQUE above KEYS, and that one above WITH and WITHOUT. We also + * have to declare the precedence of the empty production to be that of KEYS. + * We arbitrarily choose to put UNIQUE together with UNBOUNDED, and KEYS + * together with IDENT, then WITH and WITHOUT in a class of their own. + * + * For IS JSON {VALUE,OBJECT,SCALAR}, we need to split out the latter three + * from JSON; we put JSON with UNBOUNDED and the other three keywords in the + * group below. */ -%nonassoc UNBOUNDED /* ideally would have same precedence as IDENT */ +%nonassoc UNBOUNDED UNIQUE JSON /* ideally would have same precedence as IDENT */ %nonassoc IDENT PARTITION RANGE ROWS GROUPS PRECEDING FOLLOWING CUBE ROLLUP + KEYS OBJECT_P SCALAR VALUE_P +%nonassoc WITH WITHOUT %left Op OPERATOR /* multi-character ops and user-defined operators */ %left '+' '-' %left '*' '/' '%' -- 2.39.2