Issue Details (XML | Word | Printable)

Key: DERBY-4095
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Kathey Marsden
Reporter: Kathey Marsden
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
Derby

Trigger fails with ERROR 38000: The exception 'java.sql.SQLException: ResultSet not open during VTIResultSet.getNextRowCore()

Created: 13/Mar/09 02:13 PM   Updated: 30/Jun/09 03:55 PM
Component/s: SQL
Affects Version/s: 10.2.2.1, 10.3.3.1, 10.4.3.0, 10.5.1.1
Fix Version/s: 10.2.2.1, 10.3.3.1, 10.4.2.1, 10.5.1.1

Time Tracking:
Not Specified

File Attachments:
  Size
Text File Licensed for inclusion in ASF works derby-4095_diff.txt 2009-03-18 05:49 PM Kathey Marsden 6 kB
Text File Licensed for inclusion in ASF works derby-4095_diff2.txt 2009-03-20 01:49 AM Kathey Marsden 6 kB
Java Source File Licensed for inclusion in ASF works ReproDerby4095Local.java 2009-03-18 12:13 AM Kathey Marsden 2 kB

Issue & fix info: Patch Available
Bug behavior facts: Regression
Resolution Date: 06/Apr/09 11:51 PM


 Description  « Hide
I don't have a reproduction without the user database yet, but it seems that recompiling the trigger stored prepared statements on upgrade is causing a result set to get closed and is causing the following error when firing a trigger in a global transaction. The holdability in an XA transaction is CLOSE_CURSORS_AT_COMMIT so it may be that there is a commit occurring as part of the process that is causing the problem. I haven't tried yet with a regular transaction and using default holdability CLOSE_CURSORS_AT_COMMIT. The error comes on a delete which fires an after delete statement trigger to insert some values into another table.

Here is the stack trace:

2009-03-13 14:10:49.375 GMT Thread[main,5,main] (XID = 1853834), (SESSIONID = 1), (DATABASE = derby/wpsdb), (DRDAID = null), Cleanup action starting

2009-03-13 14:10:49.375 GMT Thread[main,5,main] (XID = 1853834), (SESSIONID = 1), (DATABASE = derby/wpsdb), (DRDAID = null), Failed Statement is: DELETE FROM XXX WHERE WSID=9

ERROR 38000: The exception 'java.sql.SQLException: ResultSet not open. Operation 'next' not permitted. Verify that autocommit is OFF.' was thrown while evaluating an expression.

at org.apache.derby.iapi.error.StandardException.newException(StandardException.java:294)

at org.apache.derby.iapi.error.StandardException.unexpectedUserException(StandardException.java:554)

at org.apache.derby.impl.sql.execute.VTIResultSet.getNextRowCore(VTIResultSet.java:326)

at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:255)

at org.apache.derby.impl.sql.execute.NestedLoopJoinResultSet.getNextRowCore(NestedLoopJoinResultSet.java:116)

at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:255)

at org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(NormalizeResultSet.java:186)

at org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java:127)

at org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java:496)

at org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:370)

at org.apache.derby.impl.sql.execute.GenericTriggerExecutor.executeSPS(GenericTriggerExecutor.java:173)

at org.apache.derby.impl.sql.execute.StatementTriggerExecutor.fireTrigger(StatementTriggerExecutor.java:80)

at org.apache.derby.impl.sql.execute.TriggerEventActivator.notifyEvent(TriggerEventActivator.java:278)

at org.apache.derby.impl.sql.execute.DeleteResultSet.fireAfterTriggers(DeleteResultSet.java:479)

at org.apache.derby.impl.sql.execute.DeleteResultSet.open(DeleteResultSet.java:167)

at org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:370)

at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1203)

at org.apache.derby.impl.jdbc.EmbedStatement.execute(EmbedStatement.java:596)

at org.apache.derby.impl.jdbc.EmbedStatement.executeUpdate(EmbedStatement.java:176)

at org.apache.derby.iapi.jdbc.BrokeredStatement.executeUpdate(BrokeredStatement.java:113)

at ReproRSClosed.main(ReproRSClosed.java:20)

Caused by: java.sql.SQLException: ResultSet not open. Operation 'next' not permitted. Verify that autocommit is OFF.

at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:95)

at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:88)

at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:94)

at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Util.java:173)

at org.apache.derby.impl.jdbc.EmbedConnection.newSQLException(EmbedConnection.java:2244)

at org.apache.derby.impl.jdbc.ConnectionChild.newSQLException(ConnectionChild.java:151)

at org.apache.derby.impl.jdbc.EmbedResultSet.checkIfClosed(EmbedResultSet.java:4280)

at org.apache.derby.impl.jdbc.EmbedResultSet.checkExecIfClosed(EmbedResultSet.java:4292)

at org.apache.derby.impl.jdbc.EmbedResultSet.movePosition(EmbedResultSet.java:404)

at org.apache.derby.impl.jdbc.EmbedResultSet.next(EmbedResultSet.java:388)

at org.apache.derby.impl.sql.execute.VTIResultSet.getNextRowCore(VTIResultSet.java:308)

... 18 more

Caused by: java.sql.SQLException: ResultSet not open. Operation 'next' not permitted. Verify that autocommit is OFF.

at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:45)

at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(SQLExceptionFactory40.java:135)

at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:70)

... 28 more

============= begin nested exception, level (1) ===========

java.sql.SQLException: ResultSet not open. Operation 'next' not permitted. Verify that autocommit is OFF.

at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:95)

at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:88)

at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:94)

at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Util.java:173)

at org.apache.derby.impl.jdbc.EmbedConnection.newSQLException(EmbedConnection.java:2244)

at org.apache.derby.impl.jdbc.ConnectionChild.newSQLException(ConnectionChild.java:151)

at org.apache.derby.impl.jdbc.EmbedResultSet.checkIfClosed(EmbedResultSet.java:4280)

at org.apache.derby.impl.jdbc.EmbedResultSet.checkExecIfClosed(EmbedResultSet.java:4292)

at org.apache.derby.impl.jdbc.EmbedResultSet.movePosition(EmbedResultSet.java:404)

at org.apache.derby.impl.jdbc.EmbedResultSet.next(EmbedResultSet.java:388)

at org.apache.derby.impl.sql.execute.VTIResultSet.getNextRowCore(VTIResultSet.java:308)

at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:255)

at org.apache.derby.impl.sql.execute.NestedLoopJoinResultSet.getNextRowCore(NestedLoopJoinResultSet.java:116)

at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:255)

at org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(NormalizeResultSet.java:186)

at org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java:127)

at org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java:496)

at org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:370)

at org.apache.derby.impl.sql.execute.GenericTriggerExecutor.executeSPS(GenericTriggerExecutor.java:173)

at org.apache.derby.impl.sql.execute.StatementTriggerExecutor.fireTrigger(StatementTriggerExecutor.java:80)

at org.apache.derby.impl.sql.execute.TriggerEventActivator.notifyEvent(TriggerEventActivator.java:278)

at org.apache.derby.impl.sql.execute.DeleteResultSet.fireAfterTriggers(DeleteResultSet.java:479)

at org.apache.derby.impl.sql.execute.DeleteResultSet.open(DeleteResultSet.java:167)

at org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:370)

at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1203)

at org.apache.derby.impl.jdbc.EmbedStatement.execute(EmbedStatement.java:596)

at org.apache.derby.impl.jdbc.EmbedStatement.executeUpdate(EmbedStatement.java:176)

at org.apache.derby.iapi.jdbc.BrokeredStatement.executeUpdate(BrokeredStatement.java:113)

at ReproRSClosed.main(ReproRSClosed.java:20)

Caused by: java.sql.SQLException: ResultSet not open. Operation 'next' not permitted. Verify that autocommit is OFF.

at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:45)

at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(SQLExceptionFactory40.java:135)

at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:70)

... 28 more

============= end nested exception, level (1) ===========

============= begin nested exception, level (2) ===========

java.sql.SQLException: ResultSet not open. Operation 'next' not permitted. Verify that autocommit is OFF.

at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:45)

at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(SQLExceptionFactory40.java:135)

at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:70)

at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:88)

at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:94)

at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Util.java:173)

at org.apache.derby.impl.jdbc.EmbedConnection.newSQLException(EmbedConnection.java:2244)

at org.apache.derby.impl.jdbc.ConnectionChild.newSQLException(ConnectionChild.java:151)

at org.apache.derby.impl.jdbc.EmbedResultSet.checkIfClosed(EmbedResultSet.java:4280)

at org.apache.derby.impl.jdbc.EmbedResultSet.checkExecIfClosed(EmbedResultSet.java:4292)

at org.apache.derby.impl.jdbc.EmbedResultSet.movePosition(EmbedResultSet.java:404)

at org.apache.derby.impl.jdbc.EmbedResultSet.next(EmbedResultSet.java:388)

at org.apache.derby.impl.sql.execute.VTIResultSet.getNextRowCore(VTIResultSet.java:308)

at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:255)

at org.apache.derby.impl.sql.execute.NestedLoopJoinResultSet.getNextRowCore(NestedLoopJoinResultSet.java:116)

at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:255)

at org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(NormalizeResultSet.java:186)

at org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java:127)

at org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java:496)

at org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:370)

at org.apache.derby.impl.sql.execute.GenericTriggerExecutor.executeSPS(GenericTriggerExecutor.java:173)

at org.apache.derby.impl.sql.execute.StatementTriggerExecutor.fireTrigger(StatementTriggerExecutor.java:80)

at org.apache.derby.impl.sql.execute.TriggerEventActivator.notifyEvent(TriggerEventActivator.java:278)

at org.apache.derby.impl.sql.execute.DeleteResultSet.fireAfterTriggers(DeleteResultSet.java:479)

at org.apache.derby.impl.sql.execute.DeleteResultSet.open(DeleteResultSet.java:167)

at org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:370)

at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1203)

at org.apache.derby.impl.jdbc.EmbedStatement.execute(EmbedStatement.java:596)

at org.apache.derby.impl.jdbc.EmbedStatement.executeUpdate(EmbedStatement.java:176)

at org.apache.derby.iapi.jdbc.BrokeredStatement.executeUpdate(BrokeredStatement.java:113)

at ReproRSClosed.main(ReproRSClosed.java:20)

============= end nested exception, level (2) ===========

Cleanup action completed



 All   Comments   Work Log   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Kathey Marsden added a comment - 13/Mar/09 02:45 PM
It does reproduce with a local transaction, autocommit off, and connection holdability set to ResultSet.CLOSE_CURSORS_AT_COMMIT as well, so apparently there is an unexpected commit occurring.


Kathey Marsden added a comment - 14/Mar/09 12:36 AM
Most of what I have found on this issue today is quite mysterious to me, but I figure I will summarize it here for weekend contemplation and attack it again on Monday.

Here is the little program I use to reproduce the issue. Unfortunately table and trigger information I can't post here, except to say there is a after delete statement trigger that inserts some rows into a table.

import org.apache.derby.jdbc.EmbeddedDataSource;
import java.sql.*;


public class ReproRSClosedLocal {

    public static void main(String[] args) throws Exception {
        EmbeddedDataSource ds = new EmbeddedDataSource();
        ds.setDatabaseName("mydb");
        Connection conn = ds.getConnection();
        conn.setAutoCommit(false);
        conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT);
        Statement s = conn.createStatement();
        s.executeUpdate("DELETE FROM XXX WHERE WSID=9");
        conn.rollback();
        conn.close();



    }

}

Notice the program rolls back so there should be no change from one run to the next in terms of what gets deleted and what trigger fires.

I am not sure yet, what version the user database was upgraded from, just that with the database as I got it from the user, the trigger works fine up until 660483 where the version was bumped and we start getting the error. What I have noticed is.

- With the failing and passing runs we get the same number of commits, so there doesn't seem to be an extra commit.
- If I run the program at 660482 (before the version change) and *then* move up to 660483 the trigger works fine. I have to unzip the db to get the error again.
- If I drop and recreate the trigger, and then run the program it runs fine.
- If I connect with 10.4 with soft upgrade the program works fine.






Kathey Marsden added a comment - 17/Mar/09 08:50 PM
In the failing case we go through VTIResultSet.reopenCore during execution of the trigger and close the ResultSet associated with the TriggerOldTransitionRows VTI. Here is the trace when we go through this code.

java.lang.Exception: TemporaryRowHolderResultSet.close()
at org.apache.derby.impl.sql.execute.TemporaryRowHolderResultSet.close(TemporaryRowHolderResultSet.java:574)
at org.apache.derby.impl.jdbc.EmbedResultSet.close(EmbedResultSet.java:596)
at org.apache.derby.impl.sql.execute.VTIResultSet.reopenCore(VTIResultSet.java:258)
at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.reopenCore(ProjectRestrictResultSet.java:212)
at org.apache.derby.impl.sql.execute.JoinResultSet.openRight(JoinResultSet.java:266)
at org.apache.derby.impl.sql.execute.NestedLoopJoinResultSet.getNextRowCore(NestedLoopJoinResultSet.java:147)
at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:255)
at org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(NormalizeResultSet.java:186)
at org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java:127)
at org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java:496)
at org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:370)
at org.apache.derby.impl.sql.execute.GenericTriggerExecutor.executeSPS(GenericTriggerExecutor.java:173)
at org.apache.derby.impl.sql.execute.StatementTriggerExecutor.fireTrigger(StatementTriggerExecutor.java:81)
at org.apache.derby.impl.sql.execute.TriggerEventActivator.notifyEvent(TriggerEventActivator.java:278)
at org.apache.derby.impl.sql.execute.DeleteResultSet.fireAfterTriggers(DeleteResultSet.java:479)
at org.apache.derby.impl.sql.execute.DeleteResultSet.open(DeleteResultSet.java:167)
at org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:370)
at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1203)
at org.apache.derby.impl.jdbc.EmbedStatement.execute(EmbedStatement.java:596)
at org.apache.derby.impl.jdbc.EmbedStatement.executeUpdate(EmbedStatement.java:176)
at ReproRSClosedLocal.main(ReproRSClosedLocal.java:16)


In VTIResultSet reopenCore we have:

/**
* If the VTI is a version2 vti that does not
* need to be instantiated multiple times then
* we simply close the current ResultSet and
* create a new one via a call to
* PreparedStatement.executeQuery().
*
* @see NoPutResultSet#openCore
* @exception StandardException thrown if cursor finished.
*/
public void reopenCore() throws StandardException
{
if (reuseablePs)
{
/* close the user ResultSet.
*/
if (userVTI != null)
{
try
{
--> We close the RS here userVTI.close();
userVTI = userPS.executeQuery();

/* Save off the target VTI */
if (isTarget)
{
activation.setTargetVTI(userVTI);
}
} catch (SQLException se)
{
throw StandardException.unexpectedUserException(se);
}
}
}
else
{
close();
openCore();
}
}


The TriggerOldTransitionRows VTI seems to have reusablePs set to true, so we close the ResultSet and call executeQuery() on the VTI prepared statement, but our TriggerOldTransitionRows.executeQuery() method only returns the existing resultSet, even if it has been closed and this the issue. It is not really a reusable prepared statement. If I change executeQuery to rebuild the resultSet like:

    public ResultSet executeQuery() throws SQLException {
           TriggerExecutionContext tec = Factory.getTriggerExecutionContext();
           resultSet = tec.getOldRowSet();
           return resultSet;
            
       }


instead of just returning the existing ResultSet, it works ok, but I am not sure that this is the right fix.

In the working case we don't seem to go through this reopenCore code. I'm not entirely sure why, perhaps a different plan?

Also not clear to me is what CLOSE_CURSORS_AT_COMMIT has to do with this, because it doesn't seem to be a commit that is closing the result set.

I will debug more and try to find answers to those questions but thought I would post my findings so far.

Kathey Marsden added a comment - 18/Mar/09 12:13 AM
So yes, the failing case was using a different plan which reopened the VTI multiple times, which just happened to change on upgrade. I was able to construct a reproduction (Derby4095Local.java) by using optimizer directives in the trigger definition.

I think the CLOSE_CURSORS_AT_COMMIT was a red herring. I was able to reproduce with the original user case without setting CLOSE_CURSORS_AT_COMMIT, so that was not really part of it.


Anyway, here is the trunk stack trace.
>java Derby4095Local
Exception in thread "main" java.sql.SQLException: The exception 'java.sql.SQLException: ResultSet not open. Operation 'n
ext' not permitted. Verify that autocommit is OFF.' was thrown while evaluating an expression.
        at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:95)
        at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:87)
        at org.apache.derby.impl.jdbc.Util.seeNextException(Util.java:223)
        at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(TransactionResourceImpl.java:398)
        at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(TransactionResourceImpl.java:346)
        at org.apache.derby.impl.jdbc.EmbedConnection.handleException(EmbedConnection.java:2201)
        at org.apache.derby.impl.jdbc.ConnectionChild.handleException(ConnectionChild.java:81)
        at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1323)
        at org.apache.derby.impl.jdbc.EmbedStatement.execute(EmbedStatement.java:625)
        at org.apache.derby.impl.jdbc.EmbedStatement.executeUpdate(EmbedStatement.java:175)
        at ReproDerby4095Local.main(ReproDerby4095Local.java:14)
Caused by: java.sql.SQLException: The exception 'java.sql.SQLException: ResultSet not open. Operation 'next' not permitt
ed. Verify that autocommit is OFF.' was thrown while evaluating an expression.
        at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:45)
        at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(SQLExceptionFactory40.java:11
9)
        at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:70)
        ... 10 more
Caused by: java.sql.SQLException: ResultSet not open. Operation 'next' not permitted. Verify that autocommit is OFF.
        at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:45)
        at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(SQLExceptionFactory40.java:11
9)
        at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:70)
        at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:87)
        at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:93)
        at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Util.java:172)
        at org.apache.derby.impl.jdbc.EmbedConnection.newSQLException(EmbedConnection.java:2951)
        at org.apache.derby.impl.jdbc.ConnectionChild.newSQLException(ConnectionChild.java:151)
        at org.apache.derby.impl.jdbc.EmbedResultSet.checkIfClosed(EmbedResultSet.java:4275)
        at org.apache.derby.impl.jdbc.EmbedResultSet.checkExecIfClosed(EmbedResultSet.java:4287)
        at org.apache.derby.impl.jdbc.EmbedResultSet.movePosition(EmbedResultSet.java:387)
        at org.apache.derby.impl.jdbc.EmbedResultSet.next(EmbedResultSet.java:371)
        at org.apache.derby.impl.sql.execute.VTIResultSet.getNextRowCore(VTIResultSet.java:338)
        at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:255)
        at org.apache.derby.impl.sql.execute.NestedLoopJoinResultSet.getNextRowCore(NestedLoopJoinResultSet.java:116)
        at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:255)
        at org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java:127)
        at org.apache.derby.impl.sql.execute.InsertResultSet.normalInsertCore(InsertResultSet.java:1058)
        at org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java:495)
        at org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(GenericPreparedStatement.java:416)
        at org.apache.derby.impl.sql.GenericPreparedStatement.executeSubStatement(GenericPreparedStatement.java:286)
        at org.apache.derby.impl.sql.execute.GenericTriggerExecutor.executeSPS(GenericTriggerExecutor.java:159)
        at org.apache.derby.impl.sql.execute.StatementTriggerExecutor.fireTrigger(StatementTriggerExecutor.java:80)
        at org.apache.derby.impl.sql.execute.TriggerEventActivator.notifyEvent(TriggerEventActivator.java:269)
        at org.apache.derby.impl.sql.execute.DeleteResultSet.fireAfterTriggers(DeleteResultSet.java:465)
        at org.apache.derby.impl.sql.execute.DeleteResultSet.open(DeleteResultSet.java:158)
        at org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(GenericPreparedStatement.java:416)
        at org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:297)
        at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1235)


I think I will pursue the fix of having TriggerOldTransitionRows reconstruct the ResultSet on executeQuery. Please let me know if that does not sound acceptable.



Kathey Marsden added a comment - 18/Mar/09 05:49 PM
Attached is a patch for this issue.
It changes TriggerOldTransitionRows.java and TriggerNewTransitionRows.java to intialize the ResultSet on executeQuery to fix the ResultSet not open problem when a nested loop join is performed.
It adds two tests to TriggerTest testDerby4095OldTriggerRows() and testDerby4095NewTriggerRows()

I am running tests now.

Kathey Marsden added a comment - 18/Mar/09 10:04 PM
Tests passed. Please review patch derby-4095_diff.txt.

Knut Anders Hatlen added a comment - 19/Mar/09 12:21 PM
With the patch, we always reinitialize the result set on executeQuery(), even if the existing one has not been closed. Is there a way to avoid it? And is it worth avoiding? (I don't know what the initialization does and if it's a heavy operation.)

Kathey Marsden added a comment - 19/Mar/09 04:02 PM
Well ResultSet.isClosed() is not available in the 1.5 context which this seems to be, so we can''t tell if the ResultSet is closed or not, but I think even if the ResultSet wasn't closed but was positioned on a different row than the first it would need to be reinitialized, so probably safest to do it always.

Mamta A. Satoor added a comment - 19/Mar/09 05:57 PM
Hi Kathey, the patch looks good. I just had one question.

Seems like, during the initialization of the new resultset, the following piece of code gets executed for TriggerNewTransitionRows(very similar code gets executed for TriggerOldTransitionRows). I was just wondering if we should close the old resultset that we are not going to use.
public java.sql.ResultSet getNewRowSet() throws SQLException
{
ensureProperContext();

if (afterResultSet == null)
{
return null;
}
try
{
/* We should really shallow clone the result set, because it could be used
* at multiple places independently in trigger action. This is a bug found
* during the fix of beetle 4373.
*/
CursorResultSet ars = afterResultSet;
if (ars instanceof TemporaryRowHolderResultSet)
ars = (CursorResultSet) ((TemporaryRowHolderResultSet) ars).clone();
else if (ars instanceof TableScanResultSet)
ars = (CursorResultSet) ((TableScanResultSet) ars).clone();
ars.open();
java.sql.ResultSet rs = cc.getResultSet(ars);
resultSetVector.addElement(rs);
return rs;
} catch (StandardException se)
{
throw PublicAPI.wrapStandardException(se);
}
}

Kathey Marsden added a comment - 19/Mar/09 08:33 PM
Thanks Mamta for looking at the patch. I changed it to close the previous ResultSet and am rerunning tests now and will wait to see what Knut says about the performance concern. I hope I can get this checked in tomorrow as there is a user on 10.3 that needs it. Perhaps if more performance work is needed I could check that in as a separate patch? Since we are moving from not working to working the performance is a lot better than it was before #:)



Kathey Marsden added a comment - 19/Mar/09 09:00 PM
Changing the title of the bug since this really could occur on any version if the plan with the problem is chosen. Leaving as regression, since from the user perspective, this was a regression triggered by upgrade.

Mamta A. Satoor added a comment - 19/Mar/09 09:39 PM
Kathey, I agree that performance can be addressed later on so feel free to checkin tomorrow the patch that you are testing.

Kathey Marsden added a comment - 20/Mar/09 01:49 AM
Tests ran fine. Attached is the new patch closing the previous ResultSet (derby-4095_diff2.txt). I'll commit tomorrow morning if I hear no objection.

Kathey Marsden added a comment - 20/Mar/09 10:22 PM
committed to trunk and 10.3. Will commit to 10.5,10.4.10.2, and 10.1 next week. Leaving this issue open until then.


Knut Anders Hatlen added a comment - 22/Mar/09 09:29 AM
Sorry for not responding earlier, I've been on the road for a couple of days.

I'm fine with the patch as it is. The reinitialization of the result set apparently creates a shallow clone of the underlying result set (see InternalTriggerExecutionContext.getNewRowSet()) so it shouldn't be that expensive to perform it twice, even if the before or after image is big.

Kathey Marsden added a comment - 22/Mar/09 04:51 PM
Thanks Knut for looking at the performance issue. I will go ahead and backport and close this out then as is.

Kathey Marsden added a comment - 22/Mar/09 11:56 PM
For 10.1 I don't think this bug exists because TriggerNewTransitionRows and TriggerOldTransitionRows extend VTITemplate insted of UpdatableVTITemplate (This was changed in DERBY-438) so I don't think it will be considered a "version2" style VTI and go through the reOpenCore code and there is no executeQuery for it to execute anyway.

I am not *totally* sure the problematic plan does not have a problem in 10.1 because we don't have optimizer directives in 10.1 so can't try it out, but for now we will leave this just as affecting 10.2