[ 
https://issues.apache.org/jira/browse/DERBY-6348?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Knut Anders Hatlen updated DERBY-6348:
--------------------------------------

    Attachment: set-activation.diff

I think I see why it's failing now. All the triggers seem to be executed with 
the same statement context. DERBY-3897 changed 
GenericTriggerExecutor.executeSPS() so that the trigger gets executed with 
executeSubStatement() instead of executeStatement(). executeSubStatement() 
records the current activation in the statement context. So when the second 
trigger fires, the current statement context points to the activation of the 
first trigger's SPS instead of the activation of the statement that caused the 
trigger to fire. This inconsistency eventually causes the session context 
lookup to go to the wrong activation, which again causes the assert/NPE.

I tried to reset the current statement context's activation each time we 
retrieve the activation for a trigger SPS, see the attached 
set-activation.diff. This seems to solve all the problem cases mentioned in 
this issue, and it also passes all existing regression tests.

I'm not sure if this is the best fix for the problem, or if it would be better 
to push (and pop) a new statement context for each trigger that's being 
executed. I think pushing a new context is more risky, though, as 
GenericTriggerExecutor.executeSPS() has some code to clean up errors in 
lower-level statement contexts, and changing the context stack may break 
assumptions in that code.

The approach in the patch is less risky, I believe, as it just sets the 
statement context's activation temporarily. It will be overwritten once 
executeSubStatement() is called shortly after, so it should only affect the 
currently executing trigger. Also, all other callers of executeSubStatement() 
(that is, EmbedResultSet's insertRow(), updateRow() and deleteRow() methods) do 
the same trick and temporarily set the statement context's activation while 
creating the nested activation.

> NPE or assert failure in recursive trigger
> ------------------------------------------
>
>                 Key: DERBY-6348
>                 URL: https://issues.apache.org/jira/browse/DERBY-6348
>             Project: Derby
>          Issue Type: Bug
>          Components: SQL
>    Affects Versions: 10.5.1.1, 10.6.1.0, 10.7.1.1, 10.8.1.2, 10.9.1.0, 
> 10.10.1.1
>            Reporter: Knut Anders Hatlen
>         Attachments: set-activation.diff
>
>
> With 10.5.1.1 and newer, the following ij session fails with a 
> NullPointerException (production jars) or an assert failure (debug jars):
> ij version 10.10
> ij> connect 'jdbc:derby:db;create=true';
> ij> create table t(x int);
> 0 rows inserted/updated/deleted
> ij> insert into t values 0;
> 1 row inserted/updated/deleted
> ij> create trigger tr1 after update on t values 1;
> 0 rows inserted/updated/deleted
> ij> create trigger tr2 after update on t for each row update t set x = x + 1 
> where x < 3;
> 0 rows inserted/updated/deleted
> ij> update t set x = x + 1;
> ERROR XJ001: Java exception: ': java.lang.NullPointerException'.
> It does not fail on 10.4.2.0:
> ij version 10.4
> ij> connect 'jdbc:derby:db;create=true';
> ij> create table t(x int);
> 0 rows inserted/updated/deleted
> ij> insert into t values 0;
> 1 row inserted/updated/deleted
> ij> create trigger tr1 after update on t values 1;
> 0 rows inserted/updated/deleted
> ij> create trigger tr2 after update on t for each row update t set x = x + 1 
> where x < 3;
> 0 rows inserted/updated/deleted
> ij> update t set x = x + 1;
> 1 row inserted/updated/deleted
> ij> select * from t;
> X          
> -----------
> 3          
> 1 row selected



--
This message was sent by Atlassian JIRA
(v6.1#6144)

Reply via email to