Allow => syntax for named cursor arguments in plpgsql.
authorTom Lane
Mon, 3 Mar 2025 23:00:05 +0000 (18:00 -0500)
committerTom Lane
Mon, 3 Mar 2025 23:00:13 +0000 (18:00 -0500)
We've traditionally accepted "name := value" syntax for
cursor arguments in plpgsql.  But it turns out that the
equivalent statements in Oracle use "name => value".
Since we accept both forms of punctuation for function
arguments, it makes sense to do the same here.

Author: Pavel Stehule 
Reviewed-by: Gilles Darold
Discussion: https://postgr.es/m/CAFj8pRA3d0ARQEMbABa1n6q25AUdNmyO8aGs56XNf9pD4sRMjQ@mail.gmail.com

doc/src/sgml/plpgsql.sgml
src/pl/plpgsql/src/pl_gram.y
src/test/regress/expected/plpgsql.out
src/test/regress/sql/plpgsql.sql

index 78e4983139b55fa01d19e2e747d2bd458104357d..e937491e6b89e7748df7819133b5b7fd331698dd 100644 (file)
@@ -3317,7 +3317,7 @@ OPEN curs1 FOR EXECUTE format('SELECT * FROM %I WHERE col1 = $1',tabname) USING
      Opening a Bound Cursor
 
 
-OPEN bound_cursorvar  (  argument_name :=  argument_value , ... ) ;
+OPEN bound_cursorvar  (  argument_name { := | => }  argument_value , ... ) ;
 
 
          
@@ -3340,7 +3340,8 @@ OPEN bound_cursorvar  (  
           Argument values can be passed using either positional
           or named notation.  In positional
           notation, all arguments are specified in order.  In named notation,
-          each argument's name is specified using := to
+          each argument's name is specified using :=
+          or => to
           separate it from the argument expression. Similar to calling
           functions, described in , it
           is also allowed to mix positional and named notation.
@@ -3352,6 +3353,7 @@ OPEN bound_cursorvar  (  
 OPEN curs2;
 OPEN curs3(42);
 OPEN curs3(key := 42);
+OPEN curs3(key => 42);
 
          
 
@@ -3672,7 +3674,7 @@ COMMIT;
 
 
  <<label>> 
-FOR recordvar IN bound_cursorvar  (  argument_name :=  argument_value , ... )  LOOP
+FOR recordvar IN bound_cursorvar  (  argument_name { := | => }  argument_value , ... )  LOOP
     statements
 END LOOP  label ;
 
index 8048e040f8101f4f8eb13f029b1fbdf8b0b84478..5612e66d0239d2a78c921f382749fa22058eb1b5 100644 (file)
@@ -3955,9 +3955,12 @@ read_cursor_args(PLpgSQL_var *cursor, int until, YYSTYPE *yylvalp, YYLTYPE *yyll
                    tok2;
        int         arglocation;
 
-       /* Check if it's a named parameter: "param := value" */
+       /*
+        * Check if it's a named parameter: "param := value"
+        * or "param => value"
+        */
        plpgsql_peek2(&tok1, &tok2, &arglocation, NULL, yyscanner);
-       if (tok1 == IDENT && tok2 == COLON_EQUALS)
+       if (tok1 == IDENT && (tok2 == COLON_EQUALS || tok2 == EQUALS_GREATER))
        {
            char       *argname;
            IdentifierLookup save_IdentifierLookup;
@@ -3983,11 +3986,11 @@ read_cursor_args(PLpgSQL_var *cursor, int until, YYSTYPE *yylvalp, YYLTYPE *yyll
                         parser_errposition(*yyllocp)));
 
            /*
-            * Eat the ":=". We already peeked, so the error should never
-            * happen.
+            * Eat the ":=" or "=>".  We already peeked, so the error should
+            * never happen.
             */
            tok2 = yylex(yylvalp, yyllocp, yyscanner);
-           if (tok2 != COLON_EQUALS)
+           if (tok2 != COLON_EQUALS && tok2 != EQUALS_GREATER)
                yyerror(yyllocp, NULL, yyscanner, "syntax error");
 
            any_named = true;
index 0a6945581bd8e27b92499a656a6752d272f901ca..c5f73fef2970baa77d03d5f8b6759e61a2e7341d 100644 (file)
@@ -2419,7 +2419,8 @@ declare
   p2 int4 := 1006;
   n int4;
 begin
-  open c1 (p1 := p1, p2 := p2, debug := 2);
+  -- use both supported syntaxes for named arguments
+  open c1 (p1 := p1, p2 => p2, debug => 2);
   fetch c1 into n;
   return n;
 end $$ language plpgsql;
@@ -3487,7 +3488,8 @@ begin
     raise notice '% from %', r.i, c;
   end loop;
   -- again, to test if cursor was closed properly
-  for r in c(9,10) loop
+  -- (and while we're at it, test named-parameter notation)
+  for r in c(r2 := 10, r1 => 9) loop
     raise notice '% from %', r.i, c;
   end loop;
   -- and test a parameterless cursor
index 18c91572ae14045b5425b3aa4e9f054bca104c21..d413d995d17e0a44867fcc11a060535da7e5335b 100644 (file)
@@ -2072,7 +2072,8 @@ declare
   p2 int4 := 1006;
   n int4;
 begin
-  open c1 (p1 := p1, p2 := p2, debug := 2);
+  -- use both supported syntaxes for named arguments
+  open c1 (p1 := p1, p2 => p2, debug => 2);
   fetch c1 into n;
   return n;
 end $$ language plpgsql;
@@ -2934,7 +2935,8 @@ begin
     raise notice '% from %', r.i, c;
   end loop;
   -- again, to test if cursor was closed properly
-  for r in c(9,10) loop
+  -- (and while we're at it, test named-parameter notation)
+  for r in c(r2 := 10, r1 => 9) loop
     raise notice '% from %', r.i, c;
   end loop;
   -- and test a parameterless cursor