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

Mamta A. Satoor updated DERBY-6214:
-----------------------------------

    Attachment: DERBY6214_patch2_diff.txt

Thanks for looking at the patch, Mike. I am attaching another patch which 
addresses most of your comments. The files touched by this patch are as follows
$ svn stat -q
M       java\engine\org\apache\derby\iapi\reference\Limits.java
M       
java\testing\org\apache\derbyTesting\functionTests\tests\jdbcapi\ParameterMappingTest.java
M       java\client\org\apache\derby\client\net\NetStatementRequest.java
M       java\client\org\apache\derby\client\am\CrossConverters.java
M       java\client\org\apache\derby\client\am\ClientPreparedStatement.java

This patch makes PreparedStatement.setObject work same as 
PreparedStatement.setString for small strings(<=10922 characters in length). 
Additionally, I have modularized the tests from the previous patch and made 
changes to verify the updated data for that test. The changes to verify the 
updated data use ResultSet.getString and ResultSet.getObject thus verifying 
that those apis work fine with the changed made for 
PreparedStatement.setObject. In addition, I have added new tests for 
ResultSet.updateString and ResultSet.updateObject to make sure the changes for 
PreparedStatement.setObject has not broken these apis since they share the same 
code. I have added lot more comments into the code changes. I have also created 
a constant in java\engine\org\apache\derby\iapi\reference\Limits.java for the 
length 10922 so in the code, we use that constant rather than the actual 
number. I think it is ok to add the constant in the Limits file since I have 
seen other client code using constants from that file.

Here is the response to some of the questions in your comments
********************************
 o you added the following with no comment as to why, I would prefer not to add 
an extra call level to this high traffic routine if possible. Is it just to 
save some
       typing to change all the callse in the following setObject routine? If 
so I would just rather see the code change made. all the overriding based on 
num arguments can 
       easily lead to bugs when making changes like this, other routine may 
start getting called that you don't expect. :
    final Object setObject(int targetType, Object source) throws SqlException {
        return setObject(targetType, source, false);
    }

Yes, the reason for the new method is so that we don't have to change all the 
callers of CrossConverts.setObject(targetType, source) to have to pass the new 
parameter which will be false for all except ClientPreparedStatement.setObjectX 
method. I do see your point about this causing possible confusion and 
unintentional method being called. I can go ahead and change all the callers to 
pass false when they call this method and just have 
ClientPreparedStatement.setObjectX pass the value true. This will eliminate the 
need for a new method in CrossConverts class.
********************************


********************************
4) what problems result if you don't have the originalSetObject information? It 
would be better if we did not have the special case if we can help it, just 
always send string in small string case.
    It seems likely there are existing problems with updateXXX also. maybe just 
is not right for getXXX, not sure. I'd like to see if there is any way to fix 
this without adding a param/extra call to
this high traffic routine.

When originally I didn't have the check in my code, it caused the existing 
junit test UpdatableResultSetTest to fail. Now, that I have added 
ResultSet.updateXXX calls test in my junit test, I see the same failure with 
that new junit test if I remove the originalSetObject information. The 
exception is as follows. I have not spent the reason behind the class cast 
exception but I can spend some time on it to see if it is easy to fix this 
exception so we do not need to have special parameter originalSetObject anymore.
1) 
testDerby6214updateXXX(org.apache.derbyTesting.functionTests.tests.jdbcapi.ParameterMappingTest)java.lang.ClassCastException:
 java.lang.String incompatible with java.sql.Clob
        at 
org.apache.derby.client.net.NetStatementRequest.computeProtocolTypesAndLengths(NetStatementRequest.java:1462)
        at 
org.apache.derby.client.net.NetStatementRequest.buildSQLDTAcommandData(NetStatementRequest.java:545)
        at 
org.apache.derby.client.net.NetStatementRequest.writeExecute(NetStatementRequest.java:162)
        at 
org.apache.derby.client.net.NetPreparedStatement.writeExecute_(NetPreparedStatement.java:156)
        at 
org.apache.derby.client.am.ClientResultSet.writeUpdateRow(ClientResultSet.java:4357)
        at 
org.apache.derby.client.am.ClientResultSet.positionToCurrentRowAndUpdate(ClientResultSet.java:4098)
        at 
org.apache.derby.client.am.ClientResultSet.updateRowX(ClientResultSet.java:3651)
        at 
org.apache.derby.client.am.ClientResultSet.updateRow(ClientResultSet.java:3555)
        at 
org.apache.derbyTesting.functionTests.tests.jdbcapi.ParameterMappingTest.testDerby6214updateXXX(ParameterMappingTest.java:439)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
        at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
        at 
org.apache.derbyTesting.junit.BaseTestCase.runBare(BaseTestCase.java:117)
        at 
org.apache.derbyTesting.junit.BaseJDBCTestCase.runBareOverridable(BaseJDBCTestCase.java:439)
        at 
org.apache.derbyTesting.junit.BaseJDBCTestCase.runBare(BaseJDBCTestCase.java:456)
        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)
        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 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)
********************************

                
> PreparedStatement.setObject(int, Object, Types.CLOB) fail with DerbyNet
> -----------------------------------------------------------------------
>
>                 Key: DERBY-6214
>                 URL: https://issues.apache.org/jira/browse/DERBY-6214
>             Project: Derby
>          Issue Type: Bug
>    Affects Versions: 10.8.3.0, 10.9.1.0
>            Reporter: Rong Qu
>            Assignee: Mamta A. Satoor
>         Attachments: Derby6214.java, DERBY6214_patch1_diff.txt, 
> DERBY6214_patch1_stat.txt, DERBY6214_patch2_diff.txt, Derby6214_setup.sql, 
> Derby6214_ver2.java, derby.log, DerbyNet_client_test.sql
>
>
> The issue is specific to the DerbyNet client driver, and doesn't seem to 
> occur using embedded Derby.
>  "PreparedStatement.setObject(int, Object, Types.CLOB)". It seems to be a 
> problem updating a CLOB column with a parameterized value using the DerbyNet 
> client driver, and if the update SQL ends up updating more than one row. I 
> attached a simple test case that just uses JDBC to reproduce the error. The 
> exception looks like this:
> 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)
>     ...
> Caused by: org.apache.derby.client.am.SqlException: Error for batch element 
> #0: An unexpected exception was thrown
>     at org.apache.derby.client.am.Statement.completeExecute(Unknown Source)
>     at 
> org.apache.derby.client.net.NetStatementReply.parseEXCSQLSTTreply(Unknown 
> Source)
>     at org.apache.derby.client.net.NetStatementReply.readExecute(Unknown 
> Source)
>     at org.apache.derby.client.net.StatementReply.readExecute(Unknown Source)
>     at org.apache.derby.client.net.NetPreparedStatement.readExecute_(Unknown 
> Source)
>     at org.apache.derby.client.am.PreparedStatement.readExecute(Unknown 
> Source)
>     ... 4 more
> Caused by: org.apache.derby.client.am.SqlException: Error for batch element 
> #0: Java exception: 'Stream has already been read and end-of-file reached and 
> cannot be re-used.: java.io.EOFException'.
>     at org.apache.derby.client.am.SqlException.<init>(Unknown Source)
>     at org.apache.derby.client.am.SqlException.<init>(Unknown Source)
>     ... 10 more

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to