diff options
author | Tom Lane | 2025-03-03 23:00:05 +0000 |
---|---|---|
committer | Tom Lane | 2025-03-03 23:00:13 +0000 |
commit | 246dedc5d028800b393920184e5e6319c6805253 (patch) | |
tree | 0339ce27b43220e3eb7f18adbbb417d61b5bc935 | |
parent | b6904afae40d94c2f34bc3c94aee1cdbe0bcfbe9 (diff) |
Allow => syntax for named cursor arguments in plpgsql.
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 <[email protected]>
Reviewed-by: Gilles Darold <[email protected]>
Discussion: https://postgr.es/m/CAFj8pRA3d0ARQEMbABa1n6q25AUdNmyO8aGs56XNf9pD4sRMjQ@mail.gmail.com
-rw-r--r-- | doc/src/sgml/plpgsql.sgml | 8 | ||||
-rw-r--r-- | src/pl/plpgsql/src/pl_gram.y | 13 | ||||
-rw-r--r-- | src/test/regress/expected/plpgsql.out | 6 | ||||
-rw-r--r-- | src/test/regress/sql/plpgsql.sql | 6 |
4 files changed, 21 insertions, 12 deletions
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index 78e4983139b..e937491e6b8 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -3317,7 +3317,7 @@ OPEN curs1 FOR EXECUTE format('SELECT * FROM %I WHERE col1 = $1',tabname) USING <title>Opening a Bound Cursor</title> <synopsis> -OPEN <replaceable>bound_cursorvar</replaceable> <optional> ( <optional> <replaceable>argument_name</replaceable> := </optional> <replaceable>argument_value</replaceable> <optional>, ...</optional> ) </optional>; +OPEN <replaceable>bound_cursorvar</replaceable> <optional> ( <optional> <replaceable>argument_name</replaceable> { := | => } </optional> <replaceable>argument_value</replaceable> <optional>, ...</optional> ) </optional>; </synopsis> <para> @@ -3340,7 +3340,8 @@ OPEN <replaceable>bound_cursorvar</replaceable> <optional> ( <optional> <replace Argument values can be passed using either <firstterm>positional</firstterm> or <firstterm>named</firstterm> notation. In positional notation, all arguments are specified in order. In named notation, - each argument's name is specified using <literal>:=</literal> to + each argument's name is specified using <literal>:=</literal> + or <literal>=></literal> to separate it from the argument expression. Similar to calling functions, described in <xref linkend="sql-syntax-calling-funcs"/>, it is also allowed to mix positional and named notation. @@ -3352,6 +3353,7 @@ OPEN <replaceable>bound_cursorvar</replaceable> <optional> ( <optional> <replace OPEN curs2; OPEN curs3(42); OPEN curs3(key := 42); +OPEN curs3(key => 42); </programlisting> </para> @@ -3672,7 +3674,7 @@ COMMIT; <synopsis> <optional> <<<replaceable>label</replaceable>>> </optional> -FOR <replaceable>recordvar</replaceable> IN <replaceable>bound_cursorvar</replaceable> <optional> ( <optional> <replaceable>argument_name</replaceable> := </optional> <replaceable>argument_value</replaceable> <optional>, ...</optional> ) </optional> LOOP +FOR <replaceable>recordvar</replaceable> IN <replaceable>bound_cursorvar</replaceable> <optional> ( <optional> <replaceable>argument_name</replaceable> { := | => } </optional> <replaceable>argument_value</replaceable> <optional>, ...</optional> ) </optional> LOOP <replaceable>statements</replaceable> END LOOP <optional> <replaceable>label</replaceable> </optional>; </synopsis> diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y index 8048e040f81..5612e66d023 100644 --- a/src/pl/plpgsql/src/pl_gram.y +++ b/src/pl/plpgsql/src/pl_gram.y @@ -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; diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index 0a6945581bd..c5f73fef297 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -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 diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql index 18c91572ae1..d413d995d17 100644 --- a/src/test/regress/sql/plpgsql.sql +++ b/src/test/regress/sql/plpgsql.sql @@ -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 |