Thread: The P0004 assert_failure exception assert_failure exception seems to be unhandleable
The P0004 assert_failure exception assert_failure exception seems to be unhandleable
From
Bryn Llewellyn
Date:
I just stumbled on the fact that the "assert_failure" exception seems to be unhandleable. My test is at the end.
Is this intended?
I looked at the section:
«
43.9.2. Checking Assertions
»
It says this:
«
Note that ASSERT is meant for detecting program bugs, not for reporting ordinary error conditions. Use the RAISE statement, described above, for that.
Note that ASSERT is meant for detecting program bugs, not for reporting ordinary error conditions. Use the RAISE statement, described above, for that.
»
But it takes quite a stretch of the imagination to infer that this means that the "assert_failure" exception cannot be handled.
B.t.w. this (in the same "43.9. Errors and Messages" chapter) looks like a typo:
«
If no condition name nor SQLSTATE is specified in a RAISE EXCEPTION command, the default is to use ERRCODE_RAISE_EXCEPTION (P0001).
»
The spelling "errcode_raise_exception()" makes it look like a built-in function. I believe that this is meant:
«
If no condition name nor SQLSTATE is specified in a RAISE EXCEPTION command, the outcome is as if this:
ERRCODE = "RAISE_EXCEPTION"
or this:
ERRCODE = "P0001"
was used
»
----------------------------------------------------------------------
-- The test
returns text
language plpgsql
as $body$
declare
err text not null := '';
msg text not null := '';
hint text not null := '';
n int not null := 0;
begin
case which
when 'OK' then
n := 42;
when 'null_value_not_allowed' then
n := null;
when 'raise_exception' then
raise exception using
errcode = 'raise_exception',
message = 'U1234: Not allowed!',
hint = 'Do something else!';
when 'assert_failure' then
assert false, 'Assert failed';
end case;
return 'no error';
exception when others then
get stacked diagnostics
err = returned_sqlstate,
msg = message_text,
hint = pg_exception_hint;
return 'Handled: '||err||' | '||msg||' | '||hint;
end;
$body$;
\set VERBOSITY verbose
\t on
\o spool.txt
select demo_outcome('OK');
select demo_outcome('null_value_not_allowed');
select demo_outcome('raise_exception');
\o
\t off
\set VERBOSITY verbose
\t on
\o spool.txt
select demo_outcome('OK');
select demo_outcome('null_value_not_allowed');
select demo_outcome('raise_exception');
\o
\t off
It outputs this to "spool.txt".
Handled: 22004 | null value cannot be assigned to variable "n" declared NOT NULL |
Handled: P0001 | U1234: Not allowed! | Do something else!
But doing this:
select demo_outcome('assert_failure');
causes this outcome:
ERROR: P0004: Assert failed
CONTEXT: PL/pgSQL function demo_outcome(text) line 22 at ASSERT
LOCATION: exec_stmt_assert, pl_exec.c:3918
CONTEXT: PL/pgSQL function demo_outcome(text) line 22 at ASSERT
LOCATION: exec_stmt_assert, pl_exec.c:3918
Re: The P0004 assert_failure exception assert_failure exception seems to be unhandleable
From
"David G. Johnston"
Date:
On Sunday, May 8, 2022, Bryn Llewellyn <bryn@yugabyte.com> wrote:
«
Note that ASSERT is meant for detecting program bugs, not for reporting ordinary error conditions. Use the RAISE statement, described above, for that.»But it takes quite a stretch of the imagination to infer that this means that the "assert_failure" exception cannot be handled.
Agreed. But as the pl/pgsql section “trapping errors” notes:
“The special condition name
OTHERS
matches every error type except QUERY_CANCELED
and ASSERT_FAILURE
. (It is possible, but often unwise, to trap those two error types by name.)”i.e., you must trap it explicitly, not as part of others.
«If no condition name nor SQLSTATE is specified in a RAISE EXCEPTION command, the default is to use ERRCODE_RAISE_EXCEPTION (P0001). »The spelling "errcode_raise_exception()" makes it look like a built-in function.
The fix I’d do is remove the “ERRCODE_” from the front of the name since that is an internal symbol that probably doesn’t even work in user code; the actual condition name is just the “raise_exception” part. That P0001 is simply the SQLSTATE for that name is perfectly clear to me and doesn’t warrant the verbosity of the proposal to avoid.
David J.
Re: The P0004 assert_failure exception assert_failure exception seems to be unhandleable
From
Bryn Llewellyn
Date:
david.g.johnston@gmail.com wrote:bryn@yugabyte.com wrote:
«
Note that ASSERT is meant for detecting program bugs, not for reporting ordinary error conditions. Use the RAISE statement, described above, for that.
»
But it takes quite a stretch of the imagination to infer that this means that the "assert_failure" exception cannot be handled.
Agreed. But as the pl/pgsql section “trapping errors” notes:
“The special condition name OTHERS matches every error type except QUERY_CANCELED and ASSERT_FAILURE. (It is possible, but often unwise, to trap those two error types by name.)”
i.e., you must trap it explicitly, not as part of others.
Thanks again, David. I don't yet know my way around the overall PG doc well enough to make sure that I read everything that relates to my current interest. Thanks for reminding me about this:
43.6.8. Trapping Errors
in the section:
43.6. Control Structures
in chapter:
Chapter 43. PL/pgSQL — SQL Procedural Language
All is clear now. And the caveat "It is possible, but often unwise, to trap those two error types by name" makes sense.