[
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: 10.5.3.0
> 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 10.5.3.0
> 3. Bitronix JTA 1.3.3
> We're actually using Hibernate, but I eliminated it from the equation (and
> the problem persists).
> 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
> Source)
> 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
> Source)
> ... 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
> Source)
> 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.