BUG #19558: User-defined prefix operators "|" and "->" no longer parse in 19beta2 (SQL/PGQ grammar change)

Started by PG Bug reporting form8 days ago5 messagesbugs
Jump to latest
#1PG Bug reporting form
noreply@postgresql.org

The following bug has been logged on the website:

Bug reference: 19558
Logged by: Pierre Senellart
Email address: pierre@senellart.com
PostgreSQL version: 19beta2
Operating system: Linux
Description:

The following works on PostgreSQL <= 18 but raises a syntax error on
19beta1/19beta2 (tested: PostgreSQL 19beta2, Ubuntu package
19~beta2-1.pgdg26.04+1, x86_64-linux):

CREATE FUNCTION identity_int(int) RETURNS int
LANGUAGE sql IMMUTABLE AS 'SELECT $1';
CREATE OPERATOR | (RIGHTARG = int, FUNCTION = identity_int);
CREATE OPERATOR -> (RIGHTARG = int, FUNCTION = identity_int);

SELECT | 5; -- 18: returns 5; 19beta2: syntax error at or near "|"
SELECT -> 5; -- 18: returns 5; 19beta2: syntax error at or near "->"

Cause: the SQL/PGQ property graph patch turned "|" and "->" into dedicated
grammar tokens (RIGHT_ARROW), declared in the precedence list alongside Op.
Explicit binary productions (a_expr '|' a_expr, a_expr RIGHT_ARROW a_expr)
preserve infix use, and both tokens were added to the operator-name
productions, so binary use and the OPERATOR() syntax still work:

SELECT OPERATOR(public.|) 5; -- still returns 5 on 19beta2
SELECT OPERATOR(public.->) 5; -- still returns 5 on 19beta2

But no unary counterparts of these productions were added, so a user-defined
*prefix* operator spelled exactly "|" or "->" can no longer be invoked by
its bare name. Note the inconsistency: CREATE OPERATOR still accepts both
names for prefix operators; the resulting operator just cannot be called
except through OPERATOR().

If the tokenization is here to stay, could unary productions ('|' a_expr,
RIGHT_ARROW a_expr) be added to restore the pre-19 behaviour? Failing that,
this seems worth an entry in the release notes' incompatibilities section,
since nothing currently documents it.

Motivation: https://pgxn.org/dist/provsql/ which I am developing uses prefix
| as a probabilistic “given” operator. This works on all PostgreSQL versions
from 10 to 18, but fails on 19beta2.

#2Pierre Forstmann
pierre.forstmann@gmail.com
In reply to: PG Bug reporting form (#1)
Re:[patch] BUG #19558: User-defined prefix operators "|" and "->" no longer parse in 19beta2 (SQL/PGQ grammar change)

Hello,

I propose following patch that adds missing grammar rules:

 src/backend/parser/gram.y | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ff4e138..331da79 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -15873,6 +15873,10 @@ a_expr:        c_expr                   { $$ = 
$1; }
                  { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, 
$2, @1); }
              | '-' a_expr                    %prec UMINUS
                  { $$ = doNegate($2, @1); }
+            | '|' a_expr                  %prec UMINUS
+                 { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "|", NULL , 
$2, @1); }
+            | RIGHT_ARROW a_expr                  %prec UMINUS
+                 { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "->", NULL 
, $2, @1); }
              | a_expr '+' a_expr
                  { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", $1, 
$3, @2); }
              | a_expr '-' a_expr
@@ -15902,6 +15906,7 @@ a_expr:        c_expr                 { $$ = $1; }
              | a_expr '|' a_expr
                  { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "|", $1, 
$3, @2); }
+
              | a_expr qual_Op a_expr                %prec Op
                  { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2); }
              | qual_Op a_expr                    %prec Op
@@ -16355,6 +16360,10 @@ b_expr:        c_expr
                  { $$ = makeTypeCast($1, $3, @2); }
              | '+' b_expr                    %prec UMINUS
                  { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "+", NULL, 
$2, @1); }
+            | '|' b_expr                    %prec UMINUS
+                { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "|", NULL, 
$2, @1); }
+            | RIGHT_ARROW b_expr                    %prec UMINUS
+                { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "->", NULL, 
$2, @1); }
              | '-' b_expr                    %prec UMINUS
                  { $$ = doNegate($2, @1); }
              | b_expr '+' b_expr
-- 
2.52.0

Test case says:

CREATE FUNCTION identity_int(int) RETURNS int
      LANGUAGE sql IMMUTABLE AS 'SELECT $1';
CREATE FUNCTION
CREATE OPERATOR |  (RIGHTARG = int, FUNCTION = identity_int);
CREATE OPERATOR
CREATE OPERATOR -> (RIGHTARG = int, FUNCTION = identity_int);
CREATE OPERATOR
SELECT | 5;
 ?column?
----------
        5
(1 row)

SELECT -> 5;
 ?column?
----------
        5
(1 row)

Le 18/07/2026 à 10:39, PG Bug reporting form a écrit :

Show quoted text

The following bug has been logged on the website:

Bug reference: 19558
Logged by: Pierre Senellart
Email address: pierre@senellart.com
PostgreSQL version: 19beta2
Operating system: Linux
Description:

The following works on PostgreSQL <= 18 but raises a syntax error on
19beta1/19beta2 (tested: PostgreSQL 19beta2, Ubuntu package
19~beta2-1.pgdg26.04+1, x86_64-linux):

CREATE FUNCTION identity_int(int) RETURNS int
LANGUAGE sql IMMUTABLE AS 'SELECT $1';
CREATE OPERATOR | (RIGHTARG = int, FUNCTION = identity_int);
CREATE OPERATOR -> (RIGHTARG = int, FUNCTION = identity_int);

SELECT | 5; -- 18: returns 5; 19beta2: syntax error at or near "|"
SELECT -> 5; -- 18: returns 5; 19beta2: syntax error at or near "->"

Cause: the SQL/PGQ property graph patch turned "|" and "->" into dedicated
grammar tokens (RIGHT_ARROW), declared in the precedence list alongside Op.
Explicit binary productions (a_expr '|' a_expr, a_expr RIGHT_ARROW a_expr)
preserve infix use, and both tokens were added to the operator-name
productions, so binary use and the OPERATOR() syntax still work:

SELECT OPERATOR(public.|) 5; -- still returns 5 on 19beta2
SELECT OPERATOR(public.->) 5; -- still returns 5 on 19beta2

But no unary counterparts of these productions were added, so a user-defined
*prefix* operator spelled exactly "|" or "->" can no longer be invoked by
its bare name. Note the inconsistency: CREATE OPERATOR still accepts both
names for prefix operators; the resulting operator just cannot be called
except through OPERATOR().

If the tokenization is here to stay, could unary productions ('|' a_expr,
RIGHT_ARROW a_expr) be added to restore the pre-19 behaviour? Failing that,
this seems worth an entry in the release notes' incompatibilities section,
since nothing currently documents it.

Motivation: https://pgxn.org/dist/provsql/ which I am developing uses prefix
| as a probabilistic “given” operator. This works on all PostgreSQL versions
from 10 to 18, but fails on 19beta2.

Attachments:

0001-bug-19558-Fix-user-defined-prefix-operators-and.patchtext/x-patch; charset=UTF-8; name=0001-bug-19558-Fix-user-defined-prefix-operators-and.patchDownload+9-1
#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Pierre Forstmann (#2)
Re: [patch] BUG #19558: User-defined prefix operators "|" and "->" no longer parse in 19beta2 (SQL/PGQ grammar change)

Pierre Forstmann <pierre.forstmann@gmail.com> writes:

I propose following patch that adds missing grammar rules:

Why are you promoting these to UMINUS binding precedence?
AFAICS they would have had Op precedence before v19
(and still do, as binary operators).

regards, tom lane

#4Pierre Forstmann
pierre.forstmann@gmail.com
In reply to: Tom Lane (#3)
Re: [patch] BUG #19558: User-defined prefix operators "|" and "->" no longer parse in 19beta2 (SQL/PGQ grammar change)

No good reason: I have fixed my mistake in patch v002.

Thanks.

Le 18/07/2026 à 17:42, Tom Lane a écrit :

Show quoted text

Pierre Forstmann <pierre.forstmann@gmail.com> writes:

I propose following patch that adds missing grammar rules:

Why are you promoting these to UMINUS binding precedence?
AFAICS they would have had Op precedence before v19
(and still do, as binary operators).

regards, tom lane

Attachments:

0002-bug-19558-Fix-user-defined-prefix-operators-and-fixe.patchtext/x-patch; charset=UTF-8; name=0002-bug-19558-Fix-user-defined-prefix-operators-and-fixe.patchDownload+2-5
#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Pierre Forstmann (#4)
Re: [patch] BUG #19558: User-defined prefix operators "|" and "->" no longer parse in 19beta2 (SQL/PGQ grammar change)

Pierre Forstmann <pierre.forstmann@gmail.com> writes:

Le 18/07/2026 à 17:42, Tom Lane a écrit :

Why are you promoting these to UMINUS binding precedence?
AFAICS they would have had Op precedence before v19
(and still do, as binary operators).

No good reason: I have fixed my mistake in patch v002.

OK. You don't need the explicit %prec specs, because these operators
already have the same precedence as Op:

%left Op OPERATOR RIGHT_ARROW '|' /* multi-character ops and user-defined operators */

and a bison rule takes the precedence of its rightmost terminal
symbol by default. More importantly, you missed adding the
same productions to b_expr, so that there would have been contexts
where these symbols still didn't work like they used to.

I fixed both those things and pushed it. Thanks for the
report and the patch!

regards, tom lane