Subject Re: [firebird-support] Re : (Helen) how to capture exceptions
Author Adrian Allende
Helen.
Thanks again :-)
I think it's practical to have the exception in a variable, despite the real application. No matter the exception is system, sql or user.
Having a lot of WHEN clauses in some places is very hard to mantain, and should be simplfied by an implicit var.
Of course, I develop (as you suggest) a lot of code to "word aroud" this fact, having a SELECT from RDB$EXCEPTIONS that generates
the WHEN code for all my exceptions at design time, and must be run when exceptions are added, to generate code to paste in every place where exceptions must be log. Also, at runtime, there is a COUNT()
in order to kwnow if the WHEN clauses are up to date against the rdb$exceptions table.
All this code may be simplified having a implicit variable like SQLCODE or GDSCODE, or if GDSCODE informs > 0 for
user exceptions.

Note the core of the example code

trigger for view VA = union between A and A_LOG
begin
insert into a values (new.f1);
when exception f9 do
insert into a_log values (new.f1,'f=9');
when exception f99 do
insert into a_log values (new.f1,'f=99');
when any do
insert into a_log values (new.f1,sqlcode);
end

insert into va (f1) values (1); /* not fail */
shows
(1,'ok')
in VA

insert into va (f1) values (9); /* fails because f1=9 exception */
shows
(9,'f1=9')
(9,'-999')
in VA

that is, SQLCODE = -999 when an user exception raises, and the TWO when clauses are excecuted (A BUG?)

insert into va (f1) values (1); /* fails because duplicate pk exception */
shows
(1,'-803')
in VA

So, now the question is ... can/must I post the feature request/bug in firebird-architect?

==============

This is the new version of the code if you like to try the example

create database "test_exceptions-02.fdb" user "sysdba" password "masterkey";

create table a ( f1 integer not null primary key );

create exception f9 'f1=9';
create exception f99 'f1=99';

commit;

set term ! ;
create trigger tr_a for a
before insert or update as
begin
if (new.f1=9) then exception f9;
if (new.f1=99) then exception f99;
end !
set term ; !

create table a_log ( f1 integer , err varchar(100) );

create view va (f1,err) as
select f1, cast ('ok' as varchar(100) ) err from a
union
select f1, err from a_log ;
commit;

set term ! ;
create trigger tr_va for va
before insert or update as
begin
insert into a values (new.f1);
when exception f9 do
insert into a_log values (new.f1,'f1=9');
when exception f99 do
insert into a_log values (new.f1,'f1=99');
when any do
insert into a_log values (new.f1,sqlcode);
end !
set term ; !

delete from a;
delete from a_log;

insert into va (f1) values (1);
insert into va (f1) values (9);
insert into va (f1) values (99);
insert into va (f1) values (100);
insert into va (f1) values (1);
commit;

select * from va;


F1 ERR
============ ===============================================================================

1 -803
1 ok
9 -999
9 f1=9
99 -999
99 f1=99
100 ok