[
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)