[
https://issues.apache.org/jira/browse/DERBY-2017?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12846476#action_12846476
]
Kristian Waagan commented on DERBY-2017:
----------------------------------------
Thanks for having a look, Knut Anders.
Knut Anders wrote:
-----
One question: If the user stream fails with an exception on the client side,
will the original exception be the one that's reported to the user, or will it
be the synthetic exception produced on the server?
-----
With the current code (preview with some changes), where nothing has been done
to the exception handling, the following exceptions are produced for the
embedded and the client driver:
---------> Client
----- SQLException -----
SQLState: XN015
Error Code: 20000
Message: Network protocol error: the specified size of the InputStream,
parameter #1, is less than the actual InputStream length.
java.sql.SQLException: Network protocol error: the specified size of the
InputStream, parameter #1, is less than the actual InputStream length.
at
org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:96)
at
org.apache.derby.client.am.SqlException.getSQLException(SqlException.java:358)
at
org.apache.derby.client.am.PreparedStatement.executeUpdate(PreparedStatement.java:399)
at
org.apache.derbyTesting.functionTests.tests.jdbcapi.StreamErrRepro.test(StreamErrRepro.java:38)
at
org.apache.derbyTesting.functionTests.tests.jdbcapi.StreamErrRepro.main(StreamErrRepro.java:21)
Caused by: org.apache.derby.client.am.SqlException: Network protocol error: the
specified size of the InputStream, parameter #1, is less than the actual
InputStream length.
at
org.apache.derby.client.net.Request.writePlainScalarStream(Request.java:540)
at
org.apache.derby.client.net.Request.writeScalarStream(Request.java:264)
at
org.apache.derby.client.net.Request.writeScalarStream(Request.java:679)
at
org.apache.derby.client.net.NetStatementRequest.buildEXTDTA(NetStatementRequest.java:1011)
at
org.apache.derby.client.net.NetStatementRequest.writeExecute(NetStatementRequest.java:147)
at
org.apache.derby.client.net.NetPreparedStatement.writeExecute_(NetPreparedStatement.java:178)
at
org.apache.derby.client.am.PreparedStatement.writeExecute(PreparedStatement.java:1855)
at
org.apache.derby.client.am.PreparedStatement.flowExecute(PreparedStatement.java:2085)
at
org.apache.derby.client.am.PreparedStatement.executeUpdateX(PreparedStatement.java:404)
at
org.apache.derby.client.am.PreparedStatement.executeUpdate(PreparedStatement.java:390)
... 2 more
----- SQLException -----
SQLState: XCL30
Error Code: -1
Message: An IOException was thrown when reading a 'java.lang.String' from
an InputStream.
java.sql.SQLException: An IOException was thrown when reading a
'java.lang.String' from an InputStream.
at
org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:96)
at
org.apache.derby.client.am.SqlException.getSQLException(SqlException.java:358)
at
org.apache.derby.client.am.SqlException.getSQLException(SqlException.java:367)
at
org.apache.derby.client.am.PreparedStatement.executeUpdate(PreparedStatement.java:399)
at
org.apache.derbyTesting.functionTests.tests.jdbcapi.StreamErrRepro.test(StreamErrRepro.java:38)
at
org.apache.derbyTesting.functionTests.tests.jdbcapi.StreamErrRepro.main(StreamErrRepro.java:21)
Caused by: org.apache.derby.client.am.SqlException: An IOException was thrown
when reading a 'java.lang.String' from an InputStream.
at
org.apache.derby.client.am.Statement.completeExecute(Statement.java:1601)
at
org.apache.derby.client.net.NetStatementReply.parseEXCSQLSTTreply(NetStatementReply.java:322)
at
org.apache.derby.client.net.NetStatementReply.readExecute(NetStatementReply.java:71)
at
org.apache.derby.client.net.StatementReply.readExecute(StatementReply.java:55)
at
org.apache.derby.client.net.NetPreparedStatement.readExecute_(NetPreparedStatement.java:189)
at
org.apache.derby.client.am.PreparedStatement.readExecute(PreparedStatement.java:1865)
at
org.apache.derby.client.am.PreparedStatement.flowExecute(PreparedStatement.java:2162)
at
org.apache.derby.client.am.PreparedStatement.executeUpdateX(PreparedStatement.java:404)
at
org.apache.derby.client.am.PreparedStatement.executeUpdate(PreparedStatement.java:390)
... 2 more
Caused by: org.apache.derby.client.am.SqlException: Java exception: 'Input
stream did not have exact amount of data as the requested length.:
org.apache.derby.iapi.services.io.DerbyIOException'.
... 11 more
----- SQLException -----
SQLState: XJ001
Error Code: 99999
Message: Java exception: 'Input stream did not have exact amount of data
as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
java.sql.SQLNonTransientConnectionException: Java exception: 'Input stream did
not have exact amount of data as the requested length.:
org.apache.derby.iapi.services.io.DerbyIOException'.
at
org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:70)
at
org.apache.derby.client.am.SqlException.getSQLException(SqlException.java:358)
at
org.apache.derby.client.am.SqlException.getSQLException(SqlException.java:367)
at
org.apache.derby.client.am.SqlException.getSQLException(SqlException.java:367)
at
org.apache.derby.client.am.PreparedStatement.executeUpdate(PreparedStatement.java:399)
at
org.apache.derbyTesting.functionTests.tests.jdbcapi.StreamErrRepro.test(StreamErrRepro.java:38)
at
org.apache.derbyTesting.functionTests.tests.jdbcapi.StreamErrRepro.main(StreamErrRepro.java:21)
Caused by: org.apache.derby.client.am.SqlException: Java exception: 'Input
stream did not have exact amount of data as the requested length.:
org.apache.derby.iapi.services.io.DerbyIOException'.
at
org.apache.derby.client.am.Statement.completeExecute(Statement.java:1601)
at
org.apache.derby.client.net.NetStatementReply.parseEXCSQLSTTreply(NetStatementReply.java:322)
at
org.apache.derby.client.net.NetStatementReply.readExecute(NetStatementReply.java:71)
at
org.apache.derby.client.net.StatementReply.readExecute(StatementReply.java:55)
at
org.apache.derby.client.net.NetPreparedStatement.readExecute_(NetPreparedStatement.java:189)
at
org.apache.derby.client.am.PreparedStatement.readExecute(PreparedStatement.java:1865)
at
org.apache.derby.client.am.PreparedStatement.flowExecute(PreparedStatement.java:2162)
at
org.apache.derby.client.am.PreparedStatement.executeUpdateX(PreparedStatement.java:404)
at
org.apache.derby.client.am.PreparedStatement.executeUpdate(PreparedStatement.java:390)
... 2 more
---------> Embedded
java.sql.SQLException: An IOException was thrown when reading a
'java.lang.String' from an InputStream.
----- SQLException -----
SQLState: XCL30
Error Code: 20000
Message: An IOException was thrown when reading a 'java.lang.String' from
an InputStream.
java.sql.SQLException: An IOException was thrown when reading a
'java.lang.String' from an InputStream.
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:95)
at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:142)
at org.apache.derby.impl.jdbc.Util.seeNextException(Util.java:278)
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:2269)
at
org.apache.derby.impl.jdbc.ConnectionChild.handleException(ConnectionChild.java:81)
at
org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1321)
at
org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeStatement(EmbedPreparedStatement.java:1673)
at
org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeUpdate(EmbedPreparedStatement.java:303)
at
org.apache.derbyTesting.functionTests.tests.jdbcapi.StreamErrRepro.test(StreamErrRepro.java:38)
at
org.apache.derbyTesting.functionTests.tests.jdbcapi.StreamErrRepro.main(StreamErrRepro.java:22)
Caused by: java.sql.SQLException: An IOException was thrown when reading a
'java.lang.String' from an InputStream.
at
org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:45)
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(SQLExceptionFactory40.java:119)
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:70)
... 11 more
Caused by: java.sql.SQLException: Java exception: 'Input stream did not have
exact amount of data as the requested length.:
org.apache.derby.iapi.services.io.DerbyIOException'.
at
org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:45)
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(SQLExceptionFactory40.java:119)
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:70)
at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:142)
at org.apache.derby.impl.jdbc.Util.javaException(Util.java:299)
at
org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(TransactionResourceImpl.java:403)
... 9 more
Caused by: org.apache.derby.iapi.services.io.DerbyIOException: Input stream did
not have exact amount of data as the requested length.
at
org.apache.derby.iapi.types.ReaderToUTF8Stream.checkSufficientData(ReaderToUTF8Stream.java:420)
at
org.apache.derby.iapi.types.ReaderToUTF8Stream.fillBuffer(ReaderToUTF8Stream.java:378)
at
org.apache.derby.iapi.types.ReaderToUTF8Stream.read(ReaderToUTF8Stream.java:197)
at java.io.DataInputStream.readUnsignedShort(Unknown Source)
at org.apache.derby.iapi.types.SQLChar.readExternal(SQLChar.java:1050)
at org.apache.derby.iapi.types.SQLChar.getString(SQLChar.java:695)
at org.apache.derby.iapi.types.SQLVarchar.normalize(SQLVarchar.java:148)
at
org.apache.derby.iapi.types.DataTypeDescriptor.normalize(DataTypeDescriptor.java:648)
at
org.apache.derby.impl.sql.execute.NormalizeResultSet.normalizeColumn(NormalizeResultSet.java:329)
at
org.apache.derby.impl.sql.execute.NormalizeResultSet.normalizeRow(NormalizeResultSet.java:373)
at
org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(NormalizeResultSet.java:188)
at
org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java:127)
at
org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java:494)
at
org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(GenericPreparedStatement.java:436)
at
org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:317)
at
org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1232)
... 4 more
----- SQLException -----
SQLState: XJ001
Error Code: 0
Message: Java exception: 'Input stream did not have exact amount of data
as the requested length.: org.apache.derby.iapi.services.io.DerbyIOException'.
java.sql.SQLException: Java exception: 'Input stream did not have exact amount
of data as the requested length.:
org.apache.derby.iapi.services.io.DerbyIOException'.
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:95)
at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:142)
at org.apache.derby.impl.jdbc.Util.javaException(Util.java:299)
at
org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(TransactionResourceImpl.java:403)
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:2269)
at
org.apache.derby.impl.jdbc.ConnectionChild.handleException(ConnectionChild.java:81)
at
org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1321)
at
org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeStatement(EmbedPreparedStatement.java:1673)
at
org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeUpdate(EmbedPreparedStatement.java:303)
at
org.apache.derbyTesting.functionTests.tests.jdbcapi.StreamErrRepro.test(StreamErrRepro.java:38)
at
org.apache.derbyTesting.functionTests.tests.jdbcapi.StreamErrRepro.main(StreamErrRepro.java:22)
Caused by: java.sql.SQLException: Java exception: 'Input stream did not have
exact amount of data as the requested length.:
org.apache.derby.iapi.services.io.DerbyIOException'.
at
org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:45)
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(SQLExceptionFactory40.java:119)
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:70)
... 12 more
Caused by: org.apache.derby.iapi.services.io.DerbyIOException: Input stream did
not have exact amount of data as the requested length.
at
org.apache.derby.iapi.types.ReaderToUTF8Stream.checkSufficientData(ReaderToUTF8Stream.java:420)
at
org.apache.derby.iapi.types.ReaderToUTF8Stream.fillBuffer(ReaderToUTF8Stream.java:378)
at
org.apache.derby.iapi.types.ReaderToUTF8Stream.read(ReaderToUTF8Stream.java:197)
at java.io.DataInputStream.readUnsignedShort(Unknown Source)
at org.apache.derby.iapi.types.SQLChar.readExternal(SQLChar.java:1050)
at org.apache.derby.iapi.types.SQLChar.getString(SQLChar.java:695)
at org.apache.derby.iapi.types.SQLVarchar.normalize(SQLVarchar.java:148)
at
org.apache.derby.iapi.types.DataTypeDescriptor.normalize(DataTypeDescriptor.java:648)
at
org.apache.derby.impl.sql.execute.NormalizeResultSet.normalizeColumn(NormalizeResultSet.java:329)
at
org.apache.derby.impl.sql.execute.NormalizeResultSet.normalizeRow(NormalizeResultSet.java:373)
at
org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(NormalizeResultSet.java:188)
at
org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java:127)
at
org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java:494)
at
org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(GenericPreparedStatement.java:436)
at
org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:317)
at
org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1232)
... 4 more
When using the client driver, the following stack trace is written to derby.log:
============= begin nested exception, level (1) ===========
org.apache.derby.iapi.services.io.DerbyIOException: Input stream did not have
exact amount of data as the requested length.
at
org.apache.derby.impl.drda.EXTDTAReaderInputStream.checkStatus(EXTDTAReaderInputStream.java:173)
at
org.apache.derby.impl.drda.StandardEXTDTAReaderInputStream.read(StandardEXTDTAReaderInputStream.java:146)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at sun.nio.cs.StreamDecoder.read0(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at
org.apache.derby.iapi.services.io.LimitReader.read(LimitReader.java:57)
at
org.apache.derby.iapi.types.ReaderToUTF8Stream.fillBuffer(ReaderToUTF8Stream.java:352)
at
org.apache.derby.iapi.types.ReaderToUTF8Stream.read(ReaderToUTF8Stream.java:197)
at java.io.DataInputStream.readUnsignedShort(Unknown Source)
at org.apache.derby.iapi.types.SQLChar.readExternal(SQLChar.java:1050)
at org.apache.derby.iapi.types.SQLChar.getString(SQLChar.java:695)
at org.apache.derby.iapi.types.SQLVarchar.normalize(SQLVarchar.java:148)
at
org.apache.derby.iapi.types.DataTypeDescriptor.normalize(DataTypeDescriptor.java:648)
at
org.apache.derby.impl.sql.execute.NormalizeResultSet.normalizeColumn(NormalizeResultSet.java:329)
at
org.apache.derby.impl.sql.execute.NormalizeResultSet.normalizeRow(NormalizeResultSet.java:373)
at
org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(NormalizeResultSet.java:188)
at
org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java:127)
at
org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java:494)
at
org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(GenericPreparedStatement.java:436)
at
org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:317)
at
org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1232)
at
org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeStatement(EmbedPreparedStatement.java:1673)
at
org.apache.derby.impl.jdbc.EmbedPreparedStatement.execute(EmbedPreparedStatement.java:1328)
at
org.apache.derby.impl.drda.DRDAStatement.execute(DRDAStatement.java:672)
at
org.apache.derby.impl.drda.DRDAConnThread.parseEXCSQLSTTobjects(DRDAConnThread.java:4262)
at
org.apache.derby.impl.drda.DRDAConnThread.parseEXCSQLSTT(DRDAConnThread.java:4085)
at
org.apache.derby.impl.drda.DRDAConnThread.processCommands(DRDAConnThread.java:1004)
at
org.apache.derby.impl.drda.DRDAConnThread.run(DRDAConnThread.java:291)
============= end nested exception, level (1) ===========
If we disable the use of the accumulated exception mechanism on the client
(when sending the status byte, i.e. server and client at 10.6+), we get the
same SQL states (XCL30 and XJ001) in both drivers. Looking at the traces, I do
see DerbyIOException. This was introduced to make Derby able to rewrite
IOException to SQLException with the correct state, but this is obviously not
done for this code path. For instance, we may want to differentiate between a
generic read error from a user stream and an error thrown by Derby due to a
mismatch between the specified and the actual stream length.
I would prefer to throw a different exception than the generic XJ001, but I
think this can be handled under a different Jira. For instance, XJ023 may be
better suited.
> Client driver can insert and commit partial data when a LOB stream throws
> IOException or does not match the specified length
> ----------------------------------------------------------------------------------------------------------------------------
>
> Key: DERBY-2017
> URL: https://issues.apache.org/jira/browse/DERBY-2017
> Project: Derby
> Issue Type: Bug
> Components: JDBC, Network Client
> Affects Versions: 10.2.1.6
> Reporter: Knut Anders Hatlen
> Assignee: Kristian Waagan
> Attachments: derby-2017-2a-regression_test.diff,
> derby-2017-stream_status_preview.diff, derby2017_try1.diff,
> Derby_2017_v1.diff, Derby_2017_v1.stat, StreamErrRepro.java
>
>
> When a LOB stream throws an exception or does not match the specified length,
> the client driver does not raise an exception until it has finished executing
> the statement. Therefore, the statement will be executed (and possibly
> committed) on the server even though the client reports that the statement
> failed.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.