*** a/src/pl/plpgsql/src/pl_gram.y --- b/src/pl/plpgsql/src/pl_gram.y *************** *** 106,111 **** static void check_labels(const char *start_label, --- 106,112 ---- static PLpgSQL_expr *read_cursor_args(PLpgSQL_var *cursor, int until, const char *expected); static List *read_raise_options(void); + static void check_raise_parameters(PLpgSQL_stmt_raise *stmt); %} *************** *** 1849,1854 **** stmt_raise : K_RAISE --- 1850,1857 ---- new->options = read_raise_options(); } + check_raise_parameters(new); + $$ = (PLpgSQL_stmt *)new; } ; *************** *** 3768,3773 **** read_raise_options(void) --- 3771,3812 ---- } /* + * Check that the number of parameter placeholders in the message matches the + * number of parameters passed to it, if message was defined. + */ + static void + check_raise_parameters(PLpgSQL_stmt_raise *stmt) + { + char *cp; + int expected_nparams = 0; + + if (stmt->message == NULL) + return; + + for (cp = stmt->message; *cp; cp++) + { + if (cp[0] != '%') + continue; + /* literal %, ignore */ + if (cp[1] == '%') + { + cp++; + continue; + } + expected_nparams++; + } + + if (expected_nparams < list_length(stmt->params)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("too many parameters specified for RAISE"))); + if (expected_nparams > list_length(stmt->params)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("too few parameters specified for RAISE"))); + } + + /* * Fix up CASE statement */ static PLpgSQL_stmt * *** a/src/test/regress/expected/plpgsql.out --- b/src/test/regress/expected/plpgsql.out *************** *** 2446,2463 **** begin return $1; end; $$ language plpgsql; - select raise_test1(5); ERROR: too many parameters specified for RAISE ! CONTEXT: PL/pgSQL function raise_test1(integer) line 3 at RAISE create function raise_test2(int) returns int as $$ begin raise notice 'This message has too few parameters: %, %, %', $1, $1; return $1; end; $$ language plpgsql; - select raise_test2(10); ERROR: too few parameters specified for RAISE ! CONTEXT: PL/pgSQL function raise_test2(integer) line 3 at RAISE -- Test re-RAISE inside a nested exception block. This case is allowed -- by Oracle's PL/SQL but was handled differently by PG before 9.1. CREATE FUNCTION reraise_test() RETURNS void AS $$ --- 2446,2474 ---- return $1; end; $$ language plpgsql; ERROR: too many parameters specified for RAISE ! CONTEXT: compilation of PL/pgSQL function "raise_test1" near line 3 create function raise_test2(int) returns int as $$ begin raise notice 'This message has too few parameters: %, %, %', $1, $1; return $1; end; $$ language plpgsql; ERROR: too few parameters specified for RAISE ! CONTEXT: compilation of PL/pgSQL function "raise_test2" near line 3 ! create function raise_test3(int) returns int as $$ ! begin ! raise notice 'This message has no parameters (despite having %% signs in it)!'; ! return $1; ! end; ! $$ language plpgsql; ! select raise_test3(1); ! NOTICE: This message has no parameters (despite having % signs in it)! ! raise_test3 ! ------------- ! 1 ! (1 row) ! -- Test re-RAISE inside a nested exception block. This case is allowed -- by Oracle's PL/SQL but was handled differently by PG before 9.1. CREATE FUNCTION reraise_test() RETURNS void AS $$ *** a/src/test/regress/sql/plpgsql.sql --- b/src/test/regress/sql/plpgsql.sql *************** *** 2078,2085 **** begin end; $$ language plpgsql; - select raise_test1(5); - create function raise_test2(int) returns int as $$ begin raise notice 'This message has too few parameters: %, %, %', $1, $1; --- 2078,2083 ---- *************** *** 2087,2093 **** begin end; $$ language plpgsql; ! select raise_test2(10); -- Test re-RAISE inside a nested exception block. This case is allowed -- by Oracle's PL/SQL but was handled differently by PG before 9.1. --- 2085,2098 ---- end; $$ language plpgsql; ! create function raise_test3(int) returns int as $$ ! begin ! raise notice 'This message has no parameters (despite having %% signs in it)!'; ! return $1; ! end; ! $$ language plpgsql; ! ! select raise_test3(1); -- Test re-RAISE inside a nested exception block. This case is allowed -- by Oracle's PL/SQL but was handled differently by PG before 9.1.