Subject | RE: [firebird-support] SQLCODE -999 after catching FK exception |
---|---|
Author | Rick Debay |
Post date | 2005-05-02T20:09:01Z |
OK. I'm used to Java, where only one handler would catch an exception.
What I'll do is add a local variable and use it to flag that the second
exception block shouldn't do anything if the first block has executed
and set the variable.
The update statement works, and there are no update triggers on
SXC_CLAIM.
What is the proper way to link to the new inserted row?
I put it in an AFTER trigger, because I wanted to make sure the insert
into SXC_CLAIM was successful.
I'm very pedantic about that. In this case, all data that is valid must
be loaded in to SXC_CLAIM, and any errors that occur during the trigger
processing need human intervention.
-----Original Message-----
From: firebird-support@yahoogroups.com
[mailto:firebird-support@yahoogroups.com] On Behalf Of Helen Borrie
Sent: Friday, April 29, 2005 7:25 PM
To: firebird-support@yahoogroups.com
Subject: Re: [firebird-support] SQLCODE -999 after catching FK exception
At 01:36 PM 28/04/2005 -0400, you wrote:
one-by-one, starting with WHEN blocks immediately following the
exception and working its way outward through any enclosing blocks,
until any possible handler for the exception(s) that occurred is found.
Unless one of the preceding handlers re-raises the exception (by calling
EXCEPTION (Fb 1.5 only) or EXCEPTION aCustomException) the execution of
handlers will continue until there is no applicable handler left. When
an exception is handled, the nesting level at which the last handling
occurs determines where execution returns to afterwards.
handler. The second handler (WHEN ANY) catches literally ANY exception
that remains after the first one executed. It would not have executed
if the first one had been re-raised.
exception would have caused execution to pass to the end of the block at
the next level up. In the case of your trigger, execution would
terminate because there is no outer level handler preceding the final
END statement.
From your description, one assumes that isn't what happened.
sort.
Now, execution moves on to the WHEN ANY handler, which swallows any
other exception, in this case the illegal update statement.
trigger, you're trying to interfere with trigger execution. By the time
an AFTER trigger executes, all changes are complete. The update will
cause your update triggers to fire and trigger off a cascade of
inconsistency. Hence the SQLCODE -999, indicating that the engine has
detected the internal inconsistency but doesn't have an explicit error
code for it.
You should use a WHEN ANY handler with great care. By all means use it
to log the problems, but don't make it swallow exceptions that ought to
terminate the operation in order to prevent an inconsistency.
You have always had the ability to raise a custom exception from within
an error handler; from 1.5, you can also re-raise an internal
exception, using a bare EXCEPTION statement following your logging code.
See the v.1.5 release notes for details.
execute an operation on another table that will affect any NEW.value in
the row being addressed by the trigger, perform this operation in a
BEFORE trigger.
Also, don't forget that, if you are logging to a database table, rather
than to an external table file, all your log records will disappear when
the trigger finally fails.
./heLen
Yahoo! Groups Links
What I'll do is add a local variable and use it to flag that the second
exception block shouldn't do anything if the first block has executed
and set the variable.
> this shouldn't compile. The syntax should beIt compiles, but I'll change it.
> RETURNING_VALUES(:CLAIM_ID);
>By hitting the same table with an update statement in an AFTER INSERTtrigger, you're trying to interfere
>with trigger execution. By the time an AFTER trigger executes, allchanges are complete. The update
>will cause your update triggers to fire and trigger off a cascade ofinconsistency. Hence the SQLCODE -999,
>indicating that the engine has detected the internal inconsistency butdoesn't have an explicit error code for it.
The update statement works, and there are no update triggers on
SXC_CLAIM.
What is the proper way to link to the new inserted row?
>If you have to execute an operation on another table that will affectany NEW.value
>in the row being addressed by the trigger, perform this operation in aBEFORE trigger.
I put it in an AFTER trigger, because I wanted to make sure the insert
into SXC_CLAIM was successful.
>but don't make it swallow exceptions that ought to terminate theoperation in order to prevent an inconsistency.
I'm very pedantic about that. In this case, all data that is valid must
be loaded in to SXC_CLAIM, and any errors that occur during the trigger
processing need human intervention.
-----Original Message-----
From: firebird-support@yahoogroups.com
[mailto:firebird-support@yahoogroups.com] On Behalf Of Helen Borrie
Sent: Friday, April 29, 2005 7:25 PM
To: firebird-support@yahoogroups.com
Subject: Re: [firebird-support] SQLCODE -999 after catching FK exception
At 01:36 PM 28/04/2005 -0400, you wrote:
>I intentionally forced a foreign key violation by inserting one bad rowThe handlers that are in the scope of the exception are executed
>into SXC_CLAIM.
>The first error message was expected. The second was not.
>Why would a firebird error occur immediately after an FK error?
one-by-one, starting with WHEN blocks immediately following the
exception and working its way outward through any enclosing blocks,
until any possible handler for the exception(s) that occurred is found.
Unless one of the preceding handlers re-raises the exception (by calling
EXCEPTION (Fb 1.5 only) or EXCEPTION aCustomException) the execution of
handlers will continue until there is no applicable handler left. When
an exception is handled, the nesting level at which the last handling
occurs determines where execution returns to afterwards.
>If it was raised, why was I able to catch it?It wasn't re-raised. The explicit GDSCODE was handled by the first
handler. The second handler (WHEN ANY) catches literally ANY exception
that remains after the first one executed. It would not have executed
if the first one had been re-raised.
>I'd expect problems thatIf a problem happened inside an error handler (not the case here), that
>happened inside an error handler would not be caught.
exception would have caused execution to pass to the end of the block at
the next level up. In the case of your trigger, execution would
terminate because there is no outer level handler preceding the final
END statement.
From your description, one assumes that isn't what happened.
>CREATE TRIGGER SXCCLAIM_2_PBMCLAIM FOR SXC_CLAIM ACTIVE AFTER INSERTRETURNING_VALUES(:CLAIM_ID);
>POSITION 0 AS
>/* insert the data into PBM_CLAIM and set our FK to same row */ DECLARE
>VARIABLE CLAIM_ID BIGINT; begin
> /* only import paid or reversed claims, not rejects */
> IF (NEW.CLAIMSTS IN ('P','X')) THEN
> BEGIN
> EXECUTE PROCEDURE
> P_PBM_CLAIM_I(
> NEW.PRODUCTID,
> NEW.ACCOUNTID,
> NEW.SRVPROVID,
> NEW.DECIMALQTY,
> NEW.CALINGRCST,
> NEW.GROUPID,
> NEW.RSPPATPAY,
> NEW.RSPDUEAMT,
> NEW.MULTSRCCDE,
> NEW.DATESBM)
> RETURNING_VALUES
> CLAIM_ID; <--- this shouldn't compile. The syntax should be
> UPDATEOK, the first handler picks up and handles *a* FK violation of some
> SXC_CLAIM /* AAAAAARRRRRGH!! */
> SET
> PBM_CLAIM = :CLAIM_ID
> WHERE
> RXCLAIMNBR = NEW.RXCLAIMNBR AND
> CLMSEQNBR = NEW.CLMSEQNBR AND
> CLAIMSTS = NEW.CLAIMSTS;
> END
> WHEN GDSCODE foreign_key DO
> BEGIN
> EXECUTE PROCEDURE
> P_EXCEPTION_LOG_I(
> 'E_BAD_CLAIM',
> 'Unable to import claim due to missing dependancies',
> GDSCODE,NULL);
> END
sort.
Now, execution moves on to the WHEN ANY handler, which swallows any
other exception, in this case the illegal update statement.
> WHEN ANY DOBy hitting the same table with an update statement in an AFTER INSERT
> BEGIN
> EXECUTE PROCEDURE
> P_EXCEPTION_LOG_I(
> 'E_BAD_CLAIM',
> 'Unable to import claim or create fee',
> NULL,SQLCODE);
> END
>End
trigger, you're trying to interfere with trigger execution. By the time
an AFTER trigger executes, all changes are complete. The update will
cause your update triggers to fire and trigger off a cascade of
inconsistency. Hence the SQLCODE -999, indicating that the engine has
detected the internal inconsistency but doesn't have an explicit error
code for it.
You should use a WHEN ANY handler with great care. By all means use it
to log the problems, but don't make it swallow exceptions that ought to
terminate the operation in order to prevent an inconsistency.
You have always had the ability to raise a custom exception from within
an error handler; from 1.5, you can also re-raise an internal
exception, using a bare EXCEPTION statement following your logging code.
See the v.1.5 release notes for details.
>XCEPT MSGGDS_CODE
>SQL_CODE CUR_USER CUR_ROLE TX_TS ACTUAL_TSPM
>-----------------------------------------------------------------------
>-
>-----------------------------------------------------------------------
>-
>-----------------------------------------------------------------------
>-
>-----------------------------------------------------------------------
>-
>---------------
>E_BAD_CLAIM Unable to import claim due to missing dependancies
>335544466 0 SYSDBA NONE 4/28/2005 1:24:05 PM 4/28/2005 1:24:05
>E_BAD_CLAIM Unable to import claim or create fee 0Now, back to the principles involved in this trigger. If you have to
>-999 SYSDBA NONE 4/28/2005 1:24:05 PM 4/28/2005 1:24:05 PM
execute an operation on another table that will affect any NEW.value in
the row being addressed by the trigger, perform this operation in a
BEFORE trigger.
Also, don't forget that, if you are logging to a database table, rather
than to an external table file, all your log records will disappear when
the trigger finally fails.
./heLen
Yahoo! Groups Links