Me again,
Here's a patch for making PL/PgSQL throw an error during compilation
(instead of runtime) if the number of parameters passed to RAISE don't
match the number of placeholders in error message. I'm sure people can
see the pros of doing it this way.
.marko
*** 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.
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers