db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Dag H. Wanvik (JIRA)" <j...@apache.org>
Subject [jira] Commented: (DERBY-4198) When using the FOR UPDATE OF clause, the updateRow() method crashes
Date Fri, 08 May 2009 16:50:45 GMT

    [ https://issues.apache.org/jira/browse/DERBY-4198?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12707410#action_12707410
] 

Dag H. Wanvik commented on DERBY-4198:
--------------------------------------

Given CREATE TABLE mytab (id int primary key, name varchar(50)), some
failure modes and observations:

a) rs = s.executeQuery("SELECT name from mytab for update of name");
   rs.next();
   rs.updateString(1,"foobar");

   fails because sourceRow of
   ScrollInsensitiveResultSet.addRowToHashTable is null, because
   ScrollInsensitiveResultSet.updateRow calls:

           prRS.doBaseRowProjection(row);

   but here the passed down row (UpdateResultSet.newBaseRow) is only 1
   long, so projection as done in the SELECT (projecting "name" out of
   the underlying base tables columns; which is what
   prRS.doBaseRowProjection does) is wrong.

   But projection is needed (see case f) if one does not use FOR
   UPDATE OF <col> since then one gets handed down a row whose # of
   columns is that of the basetable, and the hash table only wants the
   # of rows selected, i.e. a projection is necessary.

   This one runs correct if the call to prRS.doBaseRowProjection(row)
   is removed.


b) rs = s.executeQuery("SELECT id from mytab for update of id");
   rs.next();
   rs.updateString(1,20);

   works OK, but only accidentally, since projection of col 1 is a
   no-op.

c) rs = s.executeQuery("SELECT * from mytab for update of id");
   rs.next();
   rs.updateInt(1,20);

   fails with empty pointer since hashRowArray is now one column
   longer (and the vacant position left in hash table is never set;
   the row passed down is only 1 long (it does not contain a value for
   column 2)

d) rs = s.executeQuery("SELECT * from mytab for update of name");
   rs.next();
   rs.updateInt(2,"foobar");

   fails similarly to c, but in addition, column 2's ("name") new value
   is now set in the position of column 1 in the hash table.

e) rs = s.executeQuery("SELECT * from mytab for update of id, name");
   rs.next();
   rs.updateInt(1, 20);
   rs.updateString(2,"foobar");
   rs.updateRow();

   works OK, since now both columns are updated.

f) rs = s.executeQuery("SELECT * from mytab for update of id, name");
   rs.next();
   rs.updateInt(1, 20);
   // rs.updateString(2,"foobar");
   rs.updateRow();

   again fails.


g) If we remove prRS.doBaseRowProjection(row); this query(for example)
   fails with arrayOutOfBounds

   rs = s.executeQuery("SELECT id from mytab for update");
   rs.next();
   rs.updateInt(1,20);
   rs.updateRow();

   because passed down row now has 2 columns, whereas hashRowArray
   only has space for one.

h) rs = s.executeQuery("SELECT id from mytab for update of id, name");
   String cursorname = rs.getCursorName();
   rs.next();
   con.createStatement().executeUpdate("update mytab set name='foobar' where current of "
+
                                        cursorname);

                                        
   This case should not touch hash table at all since it does not
   contain the "name" column.  In fact, it seems to work, but write the "name"
   column to the "id" column in the hash table, which gives type error
   when trying to read it later.

i) rs = s.executeQuery("SELECT id from mytab for update");
   String cursorname = rs.getCursorName();
   rs.next();
   con.createStatement().executeUpdate("update mytab set name='foobar' where current of "
+
                                              cursorname);


   This works correctly because the passed down row has two columns, and
   ScrollInsensitiveResultSet the updated col 2 ("name"), effectively updating
   column 1 ("id") with its existing value.


For update of the baserow, UpdateResultSet.collectAffectedRows (and
updateDeferredRows) uses the object RowChanger:

   :
   source.updateRow(newBaseRow);     -- updates hash table
   rowChanger.updateRow(row, newBaseRow, baseRowLocation);  -- updates base row
   :   

which contains info on row column mappings between base table, select
list and and columns to be updated. I think ScrollInsensitiveResultSet
needs similar (but not identical) information: The row to be updated
in the hash table has a (sub)set of the columns of the basetable
determined by the SELECT list.

The naming is a bit misleading, too, because "newBaseRow" has
cardinality 1 in the cases where one specifies FOR UPDATE OF
<col-list> *and* updates only one column, no matter how many columns
are specified in <col-list>. So, even mentioning all columns leads to
a different code path that omitting the OF <col-list>.  Omitting it,
makes newBaseRow always ahve the cardinality of the underlying base
table, as the name would suggest.


> When using the FOR UPDATE OF clause, the updateRow() method crashes
> -------------------------------------------------------------------
>
>                 Key: DERBY-4198
>                 URL: https://issues.apache.org/jira/browse/DERBY-4198
>             Project: Derby
>          Issue Type: Bug
>          Components: JDBC, Network Client
>    Affects Versions: 10.6.0.0
>            Reporter: Tiago R. Espinha
>            Assignee: Dag H. Wanvik
>         Attachments: derby-4198-throwable.diff, derby-4198-throwable.stat, ErrorOutput_Client.tar.gz,
ErrorOutput_Embedded.tar.gz, ReproHoldCursorBug.java
>
>
> This problem occurs on both Client/Server and Embedded.
> With the Embedded driver, the JVM crashes with the following error:
> -------------------------------------8<------------------------------------
> 1) testReproduction(org.apache.derbyTesting.functionTests.tests.store.ReproHoldCursorBug)org.apache.derby.shared.common.sanity.AssertFailure:
ASSERT FAILED statementContext is not expected to equal statementContexts[0]
> 	at org.apache.derby.shared.common.sanity.SanityManager.ASSERT(SanityManager.java:120)
> 	at org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.popStatementContext(GenericLanguageConnectionContext.java:2286)
> 	at org.apache.derby.impl.jdbc.EmbedResultSet.updateRow(EmbedResultSet.java:3740)
> 	at org.apache.derbyTesting.functionTests.tests.store.ReproHoldCursorBug.testReproduction(ReproHoldCursorBug.java:71)
> 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> 	at org.apache.derbyTesting.junit.BaseTestCase.runBare(BaseTestCase.java:105)
> 	at junit.extensions.TestDecorator.basicRun(TestDecorator.java:24)
> 	at junit.extensions.TestSetup$1.protect(TestSetup.java:21)
> 	at junit.extensions.TestSetup.run(TestSetup.java:25)
> 	at org.apache.derbyTesting.junit.BaseTestSetup.run(BaseTestSetup.java:57)
> ------------------------------------8<---------------------------------------------
> (It shows a stack trace after this, but I'm attaching the result folders since those
are more thorough.)[1]
> On the client driver, the JVM does not crash but it also errors out:
> 1) testReproduction(org.apache.derbyTesting.functionTests.tests.store.ReproHoldCursorBug)java.sql.SQLException:
DERBY SQL error: SQLCODE: -1, SQLSTATE: XJ001, SQLERRMC: java.lang.NullPointerExceptionXJ001.U
> (more detail on the log files)[2]
> The error does not show as long as the "OF DATA" isn't specified. It also won't show
if the whole FOR UPDATE clause is omitted.
> I would also like some comments and advice on how to proceed on converting holdCursorJDBC30.sql
as it is affected by this problem. The original test does an update on a cursor with the "FOR
UPDATE OF DATA" clause, and this isn't working on the Java version of the test. Do I go around
it by removing the FOR UPDATE clause or should I wait for this bug to get fixed?
> Attachments:
> [1] - ErrorOutput_Embedded.tar.gz - Error output files of the Embedded run
> [2] - ErrorOutput_Client.tar.gz - Error output files of the Client/Server run
> [3] - ReproHoldCursorBug.java - The reproduction of the errors

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


Mime
View raw message