Return-Path: Delivered-To: apmail-db-derby-dev-archive@www.apache.org Received: (qmail 13475 invoked from network); 17 Mar 2010 17:13:53 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 17 Mar 2010 17:13:53 -0000 Received: (qmail 70541 invoked by uid 500); 17 Mar 2010 17:13:53 -0000 Delivered-To: apmail-db-derby-dev-archive@db.apache.org Received: (qmail 70517 invoked by uid 500); 17 Mar 2010 17:13:53 -0000 Mailing-List: contact derby-dev-help@db.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: Delivered-To: mailing list derby-dev@db.apache.org Received: (qmail 70510 invoked by uid 99); 17 Mar 2010 17:13:53 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 17 Mar 2010 17:13:53 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.140] (HELO brutus.apache.org) (140.211.11.140) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 17 Mar 2010 17:13:49 +0000 Received: from brutus.apache.org (localhost [127.0.0.1]) by brutus.apache.org (Postfix) with ESMTP id C756229A0011 for ; Wed, 17 Mar 2010 17:13:27 +0000 (UTC) Message-ID: <1207846673.316471268846007815.JavaMail.jira@brutus.apache.org> Date: Wed, 17 Mar 2010 17:13:27 +0000 (UTC) From: "Kristian Waagan (JIRA)" To: derby-dev@db.apache.org Subject: [jira] Commented: (DERBY-2017) Client driver can insert and commit partial data when a LOB stream throws IOException or does not match the specified length In-Reply-To: <18308033.1162198636492.JavaMail.root@brutus> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 X-Virus-Checked: Checked by ClamAV on apache.org [ 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.