diff --git a/pkg/ccl/logictestccl/testdata/logic_test/plpgsql_block b/pkg/ccl/logictestccl/testdata/logic_test/plpgsql_block index 0d515c7f8c2f..feaa7f1a6966 100644 --- a/pkg/ccl/logictestccl/testdata/logic_test/plpgsql_block +++ b/pkg/ccl/logictestccl/testdata/logic_test/plpgsql_block @@ -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; diff --git a/pkg/sql/plpgsql/parser/plpgsql.y b/pkg/sql/plpgsql/parser/plpgsql.y index a8105953eb1e..1e70b913ec8f 100644 --- a/pkg/sql/plpgsql/parser/plpgsql.y +++ b/pkg/sql/plpgsql/parser/plpgsql.y @@ -344,7 +344,7 @@ func (u *plpgsqlSymUnion) sqlStatement() tree.Statement { %type stmt_commit stmt_rollback %type stmt_case stmt_foreach_a -%type decl_stmt decl_statement +%type decl_statement %type <[]plpgsqltree.Statement> decl_sect opt_decl_stmts decl_stmts %type <[]plpgsqltree.Exception> exception_sect proc_exceptions @@ -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{