Skip to content

Commit

Permalink
parser: allow multiple DECLARE keywords in function definitions
Browse files Browse the repository at this point in the history
Previously, UDFs with multiple DECLARE statements would cause the parser
to panic. This patch allows us to accept these statements, which is what
Postgres does.

Fixes: cockroachdb#129285
Release note (bug fix): Using more than one DECLARE statment in the
definition of a user defined function now correctly declares additional
variables.
  • Loading branch information
mw5h committed Sep 6, 2024
1 parent 870c5fb commit 29d82d6
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 21 deletions.
37 changes: 37 additions & 0 deletions pkg/ccl/logictestccl/testdata/logic_test/plpgsql_block
Original file line number Diff line number Diff line change
Expand Up @@ -693,3 +693,40 @@ BEGIN
END IF;
END;
$$ LANGUAGE PLpgSQL;

subtest multi_declare

statement ok
DROP FUNCTION IF EXISTS f;

statement ok
CREATE FUNCTION f() RETURNS INT AS $$
DECLARE
x INT := 0;
DECLARE
y INT := x + 1;
BEGIN
RAISE NOTICE '% %', x, y;
RETURN 0;
END;
$$ LANGUAGE PLpgSQL;

query T noticetrace
SELECT f();
----
NOTICE: 0 1

statement ok
DROP FUNCTION IF EXISTS f;

statement error pgcode 42601 pq: duplicate declaration at or near "x"
CREATE FUNCTION f() RETURNS INT AS $$
DECLARE
x INT := 0;
DECLARE
x INT := 1;
BEGIN
RAISE NOTICE '%', x;
RETURN 0;
END;
$$ LANGUAGE PLpgSQL;
29 changes: 8 additions & 21 deletions pkg/sql/plpgsql/parser/plpgsql.y
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ func (u *plpgsqlSymUnion) sqlStatement() tree.Statement {
%type <plpgsqltree.Statement> stmt_commit stmt_rollback
%type <plpgsqltree.Statement> stmt_case stmt_foreach_a

%type <plpgsqltree.Statement> decl_stmt decl_statement
%type <plpgsqltree.Statement> decl_statement
%type <[]plpgsqltree.Statement> decl_sect opt_decl_stmts decl_stmts

%type <[]plpgsqltree.Exception> exception_sect proc_exceptions
Expand Down Expand Up @@ -419,36 +419,23 @@ opt_decl_stmts: decl_stmts
}
;

decl_stmts: decl_stmts decl_stmt
opt_declare: DECLARE {}
| {}
;

decl_stmts: decl_stmts opt_declare decl_statement
{
decs := $1.statements()
dec := $2.statement()
dec := $3.statement()
$$.val = append(decs, dec)
}
| decl_stmt
| decl_statement
{
dec := $1.statement()
$$.val = []plpgsqltree.Statement{dec}
}
;

decl_stmt : decl_statement
{
$$.val = $1.statement()
}
| DECLARE
{
// This is to allow useless extra "DECLARE" keywords in the declare section.
$$.val = (plpgsqltree.Statement)(nil)
}
// TODO(drewk): turn this block on and throw useful error if user
// tries to put the block label just before BEGIN instead of before
// DECLARE.
//| LESS_LESS any_identifier GREATER_GREATER
// {
// }
;

decl_statement: decl_varname decl_const decl_datatype decl_collate decl_notnull decl_defval
{
$$.val = &plpgsqltree.Declaration{
Expand Down

0 comments on commit 29d82d6

Please sign in to comment.