Inside the format string, <literal>%</literal> is replaced by the
string representation of the next optional argument's value. Write
<literal>%%</literal> to emit a literal <literal>%</literal>.
+ The number of arguments must match the number of <literal>%</>
+ placeholders in the format string, or an error is raised during
+ the compilation of the function.
</para>
<para>
continue;
}
+ /* should have been checked at compile time */
if (current_param == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("too few parameters specified for RAISE")));
+ elog(ERROR, "unexpected RAISE parameter list length");
paramvalue = exec_eval_expr(estate,
(PLpgSQL_expr *) lfirst(current_param),
appendStringInfoChar(&ds, cp[0]);
}
- /*
- * If more parameters were specified than were required to process the
- * format string, throw an error
- */
+ /* should have been checked at compile time */
if (current_param != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("too many parameters specified for RAISE")));
+ elog(ERROR, "unexpected RAISE parameter list length");
err_message = ds.data;
/* No pfree(ds.data), the pfree(err_message) does it */
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);
%}
new->options = read_raise_options();
}
+ check_raise_parameters(new);
+
$$ = (PLpgSQL_stmt *)new;
}
;
return result;
}
+/*
+ * Check that the number of parameter placeholders in the message matches the
+ * number of parameters passed to it, if a message was given.
+ */
+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] == '%')
+ {
+ /* ignore literal % characters */
+ if (cp[1] == '%')
+ cp++;
+ else
+ 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
*/
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
+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;
-select raise_test2(10);
ERROR: too few parameters specified for RAISE
-CONTEXT: PL/pgSQL function raise_test2(integer) line 3 at 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 $$
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;
end;
$$ language plpgsql;
-select raise_test2(10);
+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.