db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Kristian Waagan (JIRA)" <j...@apache.org>
Subject [jira] Updated: (DERBY-4455) Prepared statement failure with CLOB: Stream has already been read and end-of-file reached and cannot be re-used.
Date Tue, 01 Dec 2009 10:35:20 GMT

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

Kristian Waagan updated DERBY-4455:

    Attachment: derby-4455-1b.diff

Uploading a revised patch 1b, with some changed comments and some trivial changes to the code.
It should be functionally equal to patch 1a.

Knut> The server-side stack trace appears to happen when the session is being closed.

Yes, it appears to, but I don't think it is any more. Printing a stack trace at GenericParameterValueSet.transferDataValue
gives me:
        at org.apache.derby.impl.sql.GenericParameterValueSet.transferDataValues(GenericParameterValueSet.java:249)
        at org.apache.derby.impl.sql.execute.BaseActivation.setParameters(BaseActivation.java:1300)
        at org.apache.derby.impl.sql.GenericActivationHolder.setParameters(GenericActivationHolder.java:246)
        at org.apache.derby.impl.jdbc.EmbedPreparedStatement.transferParameters(EmbedPreparedStatement.java:1662)
        at org.apache.derby.jdbc.XAStatementControl.getRealPreparedStatement(XAStatementControl.java:169)
        at org.apache.derby.iapi.jdbc.BrokeredPreparedStatement.getPreparedStatement(BrokeredPreparedStatement.java:531)
        at org.apache.derby.iapi.jdbc.BrokeredPreparedStatement.setInt(BrokeredPreparedStatement.java:160)
        at org.apache.derby.impl.drda.DRDAConnThread.readAndSetParams(DRDAConnThread.java:4578)
        at org.apache.derby.impl.drda.DRDAConnThread.parseSQLDTA_work(DRDAConnThread.java:4507)
        at org.apache.derby.impl.drda.DRDAConnThread.parseSQLDTA(DRDAConnThread.java:4379)
        at org.apache.derby.impl.drda.DRDAConnThread.parseEXCSQLSTTobjects(DRDAConnThread.java:4254)
        at org.apache.derby.impl.drda.DRDAConnThread.parseEXCSQLSTT(DRDAConnThread.java:4084)
        at org.apache.derby.impl.drda.DRDAConnThread.processCommands(DRDAConnThread.java:1003)
        at org.apache.derby.impl.drda.DRDAConnThread.run(DRDAConnThread.java:290)

Further investigation points to DERBY-4310, DERBY-4155 and DERBY-4334, where a commit for
the former two changed the code closing a statement. The stack trace you refer to must be
from an earlier release. As a side note, I'm not seeing the exception printed to derby.log,
even with derby.error.stream.logSeverityLevel=0.
My understanding of XA isn't as good as it should have been, but running the repro with the
embedded driver (using EmbeddedXADataSource) doesn't trigger the bug. My question then is
whether the "connection switching" behavior (see XAStatementControl.getRealPreparedStatement)
seen with the client driver is a necessity or if the implementation is suboptimal.
Out of curiosity I also enabled the Derby client side JDBC statement cache for XA (requires
some code changes) and disabled the one in Bitronix. I observed the same behavior, including
the bug.

As for the issue addressed by the patch, what happens is that Derby detects that the application
connection has changed when it is about to execute the prepared statement. It then has to
create a new prepared statement on the current connection. After preparing a new statement,
it transfers the arguments that were set on the old statement to the new one. This was done
in a way that would materialize values represented as a stream. In this specific case, the
stream had already been drained and an EOFException was thrown when trying to read it again.

I believe the same bug can be triggered by using only the embedded driver, but it requires
a different repro (switching between global and local XA transactions or something?).

Finally, the regression test run with patch 1a was clean.

> Prepared statement failure with CLOB: Stream has already been read and end-of-file reached
and cannot be re-used.
> -----------------------------------------------------------------------------------------------------------------
>                 Key: DERBY-4455
>                 URL: https://issues.apache.org/jira/browse/DERBY-4455
>             Project: Derby
>          Issue Type: Bug
>          Components: Network Server
>    Affects Versions:
>         Environment: Mac OS X 10.6.2, Java 6, Bitronix JTA
>            Reporter: Brett Wooldridge
>         Attachments: derby-4455-1a.diff, derby-4455-1b.diff, DerbyFailure.zip
> Possibly related to #4332?
> We have encountered an error when using Prepared Statements and CLOBs.  I have read:
> http://db.apache.org/derby/papers/JDBCImplementation.html#setAsciiStream%2CsetBinaryStream%2CsetCharacterStream
> But it does not seem applicable, as we are not re-using a stream.
> The environment is this:
> 1. Java 6
> 2. Derby
> 3. Bitronix JTA 1.3.3
> We're actually using Hibernate, but I eliminated it from the equation (and the problem
> A summary of the failure flow is this:
> 1. Start a transaction
> 2. Obtain a connection from a pool of connections (for this test, the pool size is pinned
at 1)
> 3. Prepare a statement that inserts a CLOB.
> 4. Set the parameters
> 5. Add the prepared statement to a batch (but we only batch 1 -- this is to emulate what
hibernate is doing as closely as possible).
> 6. Execute the batch.
> Everything up to this point works.
> 7. Repeat steps 1-6.  But this time, the connection will be reused from the pool, and
the statement will be gotten from a prepared statement cache (maintained by bitronix).  I.e.
the prepared statement is re-used.
> 8. Observe the following failure:
> org.apache.derby.client.am.BatchUpdateException: Non-atomic batch failure.  The batch
was submitted, but at least one exception occurred on an individual member of the batch. Use
getNextException() to retrieve the exceptions for specific batched elements.
> 	at org.apache.derby.client.am.Agent.endBatchedReadChain(Unknown Source)
> 	at org.apache.derby.client.am.PreparedStatement.executeBatchRequestX(Unknown Source)
> 	at org.apache.derby.client.am.PreparedStatement.executeBatchX(Unknown Source)
> 	at org.apache.derby.client.am.PreparedStatement.executeBatch(Unknown Source)
> 	at bitronix.tm.resource.jdbc.JdbcPreparedStatementHandle.executeBatch(JdbcPreparedStatementHandle.java:248)
> 	at org.dancernetworks.TestFailure.doInsert(TestFailure.java:134)
> 	at org.dancernetworks.TestFailure.doPrepared(TestFailure.java:110)
> 	at org.dancernetworks.TestFailure.main(TestFailure.java:55)
> Nov 30, 2009 10:29:31 PM bitronix.tm.BitronixTransactionManager shutdown
> INFO: shutting down Bitronix Transaction Manager
> An IOException was thrown when reading a 'java.sql.String' from an InputStream.
> java.sql.SQLException: An IOException was thrown when reading a 'java.sql.String' from
an InputStream.
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source)
> 	at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source)
> 	at org.apache.derby.impl.jdbc.Util.seeNextException(Unknown Source)
> 	at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source)
> 	at org.apache.derby.impl.jdbc.EmbedResultSet.noStateChangeException(Unknown Source)
> 	at org.apache.derby.impl.jdbc.EmbedPreparedStatement.transferParameters(Unknown Source)
> 	at org.apache.derby.jdbc.XAStatementControl.getRealPreparedStatement(Unknown Source)
> 	at org.apache.derby.iapi.jdbc.BrokeredPreparedStatement.getPreparedStatement(Unknown
> 	at org.apache.derby.iapi.jdbc.BrokeredPreparedStatement.getStatement(Unknown Source)
> 	at org.apache.derby.iapi.jdbc.BrokeredStatement.close(Unknown Source)
> 	at org.apache.derby.impl.drda.DRDAStatement.close(Unknown Source)
> 	at org.apache.derby.impl.drda.Database.close(Unknown Source)
> 	at org.apache.derby.impl.drda.Session.close(Unknown Source)
> 	at org.apache.derby.impl.drda.DRDAConnThread.closeSession(Unknown Source)
> 	at org.apache.derby.impl.drda.DRDAConnThread.run(Unknown Source)
> Caused by: java.sql.SQLException: An IOException was thrown when reading a 'java.sql.String'
from an InputStream.
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown
> 	... 15 more
> Caused by: java.sql.SQLException: Java exception: 'Stream has already been read and end-of-file
reached and cannot be re-used.: java.io.EOFException'.
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source)
> 	at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source)
> 	at org.apache.derby.impl.jdbc.Util.javaException(Unknown Source)
> 	at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source)
> 	... 12 more
> Caused by: java.io.EOFException: Stream has already been read and end-of-file reached
and cannot be re-used.
> 	at org.apache.derby.iapi.types.ReaderToUTF8Stream.read(Unknown Source)
> 	at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:320)
> 	at org.apache.derby.iapi.types.SQLChar.readExternal(Unknown Source)
> 	at org.apache.derby.iapi.types.SQLChar.getString(Unknown Source)
> 	at org.apache.derby.iapi.types.SQLChar.setFrom(Unknown Source)
> 	at org.apache.derby.iapi.types.DataType.setValue(Unknown Source)
> 	at org.apache.derby.impl.sql.GenericParameterValueSet.transferDataValues(Unknown Source)
> 	at org.apache.derby.impl.sql.execute.BaseActivation.setParameters(Unknown Source)
> 	at org.apache.derby.impl.sql.GenericActivationHolder.setParameters(Unknown Source)
> 	... 10 more
> Attached is an archived Eclipse project of a self-contained reproduction.  It includes
everything needed to run, including the Bitronix 1.3.3 jar.

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

View raw message