Hi Tatsuo,

> I will look into these after finishing post patch release review for
> v51.

Before you start, one thing has changed under us.  SQL/PGQ was
reverted from master yesterday (b1f106c80cb).  Rebasing v51 and the
increment onto current master raises a handful of conflicts, all
mechanical, and then breaks on something that raised none.

The conflicts first.  Five hunks in three commits, all of the same
shape: SQL/PGQ had added something, RPR added its own entry next to
it, and the revert took the SQL/PGQ half away.

  gram.y        the %type block, the keyword token list (DESTINATION
                next to our DEFINE), and the %nonassoc list before
                %left Op OPERATOR
  parse_agg.c   EXPR_KIND_PROPGRAPH_PROPERTY next to
                EXPR_KIND_RPR_DEFINE
  parse_expr.c  the same
  nodeFuncs.c   T_GraphElementPattern and T_GraphPattern next to
                T_RPCommonSyntax and T_RPRPatternNode

In each, the resolution is to keep our side and drop theirs.

"|" is the one that did not announce itself.  The lexer change lives
in scan.l, which no RPR commit touches, so it came away with the
revert and raised no conflict at all.  RPR still needs it.

Without it a lone "|" arrives as an Op, row_pattern_alt never fires,
and PATTERN (A | B) fails with "unsupported quantifier".

What made it work was SQL/PGQ (2f094e7ac69).  It needed a lone "|"
for label disjunction in GRAPH_TABLE, so that an element pattern
could be written as MATCH (a IS vl1 | vl2).

RPR's alternation was then written against that token.
row_pattern_alt does the same thing one level up, and the handling
around it assumes "|" arrives separately.  We extended what SQL/PGQ
had put in place, so with SQL/PGQ gone RPR has to carry the
groundwork itself.

The attached nocfbot-0002-pipe-single-character-token.txt does that.

Best regards,
Henson
From 04abbe1adfaeb2d3c257d2ad4fd8e052d7925c46 Mon Sep 17 00:00:00 2001
From: Henson Choi <[email protected]>
Date: Tue, 8 Sep 2026 11:22:42 +0900
Subject: [PATCH] Return "|" as a single-character token

Row pattern recognition spells pattern alternation with "|", and
row_pattern_alt matches it as the character token '|'.  The lexer,
however, lists "|" in op_chars but not in self, so a "|" standing on
its own arrives as an Op and that production never fires.  PATTERN
(A | B) then fails with "unsupported quantifier".

Add "|" to the self character class, and to the one-character fallback
in the rule for "operator", so that a lone "|" is returned as a
character token.  That stops it from being lexed as an operator, so
restore its use as one: prefix and infix productions in a_expr and
b_expr, an entry in MathOp, and "|" in the precedence declaration for
Op.

This lexer behavior was in the tree as part of SQL/PGQ, which used "|"
for label disjunction, and row pattern alternation has been relying on
it.  SQL/PGQ was reverted in b1f106c80cb, so the change has to be
carried here.
---
 src/backend/parser/gram.y | 11 ++++++++++-
 src/backend/parser/scan.l |  4 ++--
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 41f46d242fa..3a5fcfc9c81 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -924,7 +924,7 @@ static bool rpr_is_quantifier_token(const char *tok);
 %nonassoc      IDENT PARTITION RANGE ROWS GROUPS PRECEDING FOLLOWING CUBE 
ROLLUP
                        SET KEYS OBJECT_P SCALAR TO USING VALUE_P WITH WITHOUT 
PATH
                        AFTER INITIAL_P SEEK PATTERN_P PERMUTE
-%left          Op OPERATOR             /* multi-character ops and user-defined 
operators */
+%left          Op OPERATOR '|' /* multi-character ops and user-defined 
operators */
 %left          '+' '-'
 %left          '*' '/' '%'
 %left          '^'
@@ -15482,6 +15482,10 @@ a_expr:                c_expr                          
                                        { $$ = $1; }
                                { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, 
">=", $1, $3, @2); }
                        | a_expr NOT_EQUALS a_expr
                                { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, 
"<>", $1, $3, @2); }
+                       | '|' a_expr
+                               { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "|", 
NULL, $2, @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); }
@@ -15962,6 +15966,10 @@ b_expr:                c_expr
                                { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, 
">=", $1, $3, @2); }
                        | b_expr NOT_EQUALS b_expr
                                { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, 
"<>", $1, $3, @2); }
+                       | '|' b_expr
+                               { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "|", 
NULL, $2, @1); }
+                       | b_expr '|' b_expr
+                               { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "|", 
$1, $3, @2); }
                        | b_expr qual_Op b_expr                         %prec Op
                                { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, 
$3, @2); }
                        | qual_Op b_expr                                        
%prec Op
@@ -17627,6 +17635,7 @@ MathOp:          '+'                                    
                                { $$ = "+"; }
                        | LESS_EQUALS                                           
        { $$ = "<="; }
                        | GREATER_EQUALS                                        
        { $$ = ">="; }
                        | NOT_EQUALS                                            
        { $$ = "<>"; }
+                       | '|'                                                   
                { $$ = "|"; }
                ;
 
 qual_Op:       Op
diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l
index 6c162f48342..78654b45ad0 100644
--- a/src/backend/parser/scan.l
+++ b/src/backend/parser/scan.l
@@ -359,7 +359,7 @@ not_equals          "!="
  * If you change either set, adjust the character lists appearing in the
  * rule for "operator"!
  */
-self                   [,()\[\].;\:\+\-\*\/\%\^\<\>\=]
+self                   [,()\[\].;\:\|\+\-\*\/\%\^\<\>\=]
 op_chars               [\~\!\@\#\^\&\|\`\?\+\-\*\/\%\<\>\=]
 operator               {op_chars}+
 
@@ -930,7 +930,7 @@ other                       .
                                                 * that the "self" rule would 
have.
                                                 */
                                                if (nchars == 1 &&
-                                                       
strchr(",()[].;:+-*/%^<>=", yytext[0]))
+                                                       
strchr(",()[].;:|+-*/%^<>=", yytext[0]))
                                                        return yytext[0];
                                                /*
                                                 * Likewise, if what we have 
left is two chars, and

Reply via email to