Details
-
Bug
-
Status: Open
-
Minor
-
Resolution: Unresolved
-
10.1.2.1
-
None
-
All
-
Normal
-
Repro attached
Description
Derby uses table intent locks to prevent a table from being dropped while there is an open cursor on it.
However, for holdable cursors, the lock is released after the commit. This allows a drop table command to drop the table. The next call to ResultSet.next then get a NullPointerException from the store module.
A potential fix, could be to handle this situation in store, and to give a meaningful error message.
Transaction history:
T1: select * from table1
T1: cursor.next()
T1: commit
T2: drop table table1
T2: commit
T3: cursor.next()..
Result: T3 get NullPointerException.
To reproduce: Add the following testcase to ConcurrencyTest.java (see DERBY-934) (hopefully someone commits those tests soon)
/**
- Test that as long as an cursor is open on a table, no
- other transaction can delete the table.
*/
public void testTableIntentLockWithHoldableCursor()
throws SQLException
{
con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
con.setAutoCommit(true);
Statement s = con.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = s.executeQuery("select * from t1");
rs.next();
updateTuple(rs);
con.commit();
Connection con2 = getNewConnection();
con2.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
try
{ PreparedStatement ps2 = con2.prepareStatement ("drop table t1"); ps2.executeUpdate(); con2.commit(); // .. WHAT happens ? rs.next(); updateTuple(rs); }catch (SQLException e)
{ System.out.println(e.getMessage() + ":" + e.getSQLState()); printStackTrace(e); assertEquals("Unexpected SQL state", LOCK_TIMEOUT_SQL_STATE, e.getSQLState()); }finally
{ con2.close(); }
}
java.lang.NullPointerException
at org.apache.derby.impl.store.access.conglomerate.OpenConglomerate.latchPageAndRepositionScan(OpenConglomerate.java:264)
at org.apache.derby.impl.store.access.conglomerate.GenericScanController.fetchRows(GenericScanController.java:613)
at org.apache.derby.impl.store.access.heap.HeapScan.fetchNext(HeapScan.java:207)
at org.apache.derby.impl.sql.execute.TableScanResultSet.getNextRowCore(TableScanResultSet.java:681)
at org.apache.derby.impl.sql.execute.BasicNoPutResultSetImpl.getNextRow(BasicNoPutResultSetImpl.java:474)
at org.apache.derby.impl.jdbc.EmbedResultSet.movePosition(EmbedResultSet.java:371)
at org.apache.derby.impl.jdbc.EmbedResultSet.next(EmbedResultSet.java:320)
at org.apache.derbyTesting.functionTests.tests.jdbcapi.ConcurrencyTest.testTableIntentLockWithHoldableCursor(ConcurrencyTest.java:877)
..
The NullPointerException is wrapped in a SQLException, which just makes the bug more confusing for the user.