Subject [firebird-support] Re : (Helen) how to capture exceptions
Author Adrian Allende
Helen

Thanks for your answer.
I think there is no conceptual problem, I only post a small code to show the idea. (see at end for a "minimal" "real" executable example. Try to guess the resulkts, you may be surprised)
Despite my particular use, must be a need for GDSCODE and SQLCODE, for documentation in Firebird reflects that:

BEGIN
...
WHEN SQLCODE -802 DO
EXCEPTION E_EXCEPTION_1;
WHEN SQLCODE -803 DO
EXCEPTION E_EXCEPTION_2;
WHEN ANY DO
EXECUTE PROCEDURE P_ANY_EXCEPTION(SQLCODE);
END

I can't imagine why the developers (Dmitry Yemanov) created GDS_CODE and SQL_CODE, but no something like "USER_CODE".

(
5. If user-defined exception is thrown, both SQLCODE and GDSCODE
variables contain zero, regardless of the exception handling
block type.
)

What I DESEPERATE need is something like USERCODE, because when an user exception is raised the exception number can not be in any variable, and must be "WHENed" for each one.
So I will very happy to do a EXECUTE PROCEDURE P_ANY_EXCEPTION(SQLCODE,GDS_CODE, USER_CODE);
or better EXECUTE PROCEDURE P_ANY_EXCEPTION(EXCEPTIONCODE); where EXCEPTIONCODE < 0 for user exceptions, or something like this.

Now, I can't put the exception in a parameter for a SP, and I'm forced to do a very hard to mantain code

WHEN EXCEPTION E_EXCEPTION_1 DO
somethig(1)
WHEN EXCEPTION E_EXCEPTION_2 DO
somethig(2)
...


Thanks again to answer

Adrian.

-------------------------------

I use IB/FB since IB 4.2 version, in a 4Gb DB. There are 22K code lines ins SPs and triggers.
My application actual scenario is such that batch operations needs to log exceptions, in constrast to on-line operation, when client application, for example, shows the exception to an user.
I like to create specific exceptions for busines rules, and raise in any part of the system, and then be captured and inserted in a table to off-line inspection.
So, I use a view, that insert to actual tables, where an exception can be raised. In the trigger's "batch insert" view the exception is "handled" in the sense that there is a WHEN, not in the sense that the exception is "fixed", but in the sense that the exception is "logged" in a field, like this (you can try it in a single "paste" in isql )

table A holds real data, table A_LOG is only to reflect errors, view VA is the only thing exposed to client applications, so a
SELECT * FROM VA shows errors and OK data posted.

-------------------------

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

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

create exception f19 'f1>9';
create exception f199 'f1>99';

commit;

set term ! ;
create trigger tr_a for a
before insert or update as
begin
if (new.f1>9)
then exception f19;
if (new.f1>99)
then exception f199;
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 f19 do
insert into a_log values (new.f1,'f1>9');
when exception f199 do
insert into a_log values (new.f1,'f1>99');
when any do
insert into a_log values (new.f1,sqlcode);
end !
set term ; !

insert into va (f1) values (1); /* ok */
insert into va (f1) values (9); /* f19 exception */
insert into va (f1) values (99); /* f199 exception */
insert into va (f1) values (100); /* ok */
insert into va (f1) values (1); /* duplicate pk exception -803 */
commit;

select * from va;

-------------------------------