| Bug #39426 | executeBatch passes most recent PreparedStatement params to StatementInterceptor | ||
|---|---|---|---|
| Submitted: | 12 Sep 2008 19:10 | Modified: | 4 Aug 2009 15:39 |
| Reporter: | Eric Jensen | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | Connector / J | Severity: | S2 (Serious) |
| Version: | 5.1.6 | OS: | Any |
| Assigned to: | Jess Balint | CPU Architecture: | Any |
| Tags: | executeBatch, PreparedStatement, StatementInterceptor | ||
[12 Sep 2008 19:20]
Eric Jensen
I've verified that not only is the String sql passed to my interceptor just duplicated for the last set of params, but even the ((com.mysql.jdbc.PreparedStatement)interceptedStatement).getParameterBindings() are the same across interceptions of an executeBatch
[15 Sep 2008 7:20]
Tonci Grgin
Hi Eric and thanks for your report. Please attach small but self-sufficient test case proving your point.
[15 Sep 2008 16:56]
Eric Jensen
the psuedocode testcase below is the best i can do within the next few weeks...it's pretty straightforward to reproduce from that. i may get to a real code test case someday, but not anytime soon. sorry...
[15 Sep 2008 16:57]
Eric Jensen
guess i should have said "above" not "below"....i.e., the original test case i provided in the description.
[15 Sep 2008 20:04]
Tonci Grgin
Eric, without test case this is not a valid bug report... I will wait for you as I too am off to DevCon for next ~10 days or so. I have to be fair to others too, especially ones that provided test cases and all the necessary info. If I'm to write everything by myself none's to get any answers...
[15 Oct 2008 23:00]
Bugs System
No feedback was provided for this bug for over a month, so it is being suspended automatically. If you are able to provide the information that was originally requested, please do so and change the status of the bug back to "Open".
[28 Nov 2008 7:49]
Eric Jensen
test case
Attachment: StatementInterceptorTest.java (text/plain), 3.52 KiB.
[28 Nov 2008 7:50]
Eric Jensen
the test is attached, it fails as follows:
.Loading JDBC driver 'com.mysql.jdbc.Driver'
Done.
Done.
Connected to 5.0.27-log
E
Time: 0.519
There was 1 error:
1) testStatementInterceptorPreparedStatementExecuteBatch(testsuite.simple.StatementInterceptorTest)java.sql.BatchUpdateException: Duplicate entry '2' for key 1
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1669)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1085)
at testsuite.simple.StatementInterceptorTest.testStatementInterceptorPreparedStatementExecuteBatch(StatementInterceptorTest.java:73)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at testsuite.simple.StatementInterceptorTest.main(StatementInterceptorTest.java:23)
FAILURES!!!
Tests run: 1, Failures: 0, Errors: 1
[8 Apr 2009 16:42]
Tonci Grgin
Hi Eric. I am unable to reproduce this behavior using following test case and latest c/J sources:
try {
createTable("bug39426", "(strdata1 VARCHAR(100) PRIMARY KEY, strdata2 VARCHAR(100))");
this.pstmt = this.conn.prepareStatement("INSERT INTO "
+ "bug39426 (strdata1, strdata2) VALUES (?,?)");
for (int i = 0; i < 1000; i++) {
this.pstmt.setString(1, "batch_" + i);
this.pstmt.setString(2, "batch_" + i);
this.pstmt.addBatch();
}
int[] updateCounts = this.pstmt.executeBatch();
for (int i = 0; i < updateCounts.length; i++) {
assertTrue("Update count must be '1', was '" + updateCounts[i]
+ "'", (updateCounts[i] == 1));
}
System.out.println("Done");
} finally {
closeMemberJDBCResources();
}
Output:
Loading JDBC driver 'com.mysql.jdbc.Driver'
Done.
Done.
Connected to 5.1.31-log
java.vm.version : 1.5.0_17-b04
java.vm.vendor : Sun Microsystems Inc.
java.runtime.version : 1.5.0_17-b04
os.name : Windows Server 2008
os.version : null
sun.management.compiler : HotSpot Client Compiler
Done
General query log on server shows all correct updates.
[8 Apr 2009 17:04]
Eric Jensen
I don't see a StatementInterceptor in your test? Does the testcase I provided pass for you? It fails for me.
[9 Apr 2009 6:28]
Tonci Grgin
Eric, > I don't see a StatementInterceptor in your test? Does the testcase I provided pass for you? It fails for me. I am not allowed to do code reviews (you need support contract for that) and I'm obliged to boil-down each test case to it's simplest possible form, to the best of my knowledge. This version I posted is actually from our regression test suite and I think it covers the essentials completely. Now, did you tried my test case? Do you have any objections to it? Finally, do not be alarmed with "Can't repeat", I am monitoring this report regardless of ruling made.
[9 Apr 2009 16:03]
Eric Jensen
your test case does not have a StatementInterceptor in it. this bug is specific to StatementInterceptors. i believe the test case i provided represents the simplest possible form. thanks.
[9 Apr 2009 16:10]
Tonci Grgin
Eric, true, and I have already asked for consult.
[9 Apr 2009 21:16]
Jess Balint
verified as described
[13 Apr 2009 3:51]
Jess Balint
fix + test
Attachment: bug39426.diff (text/x-diff), 9.59 KiB.
[2 Jun 2009 5:59]
Jess Balint
Pushed for release in 5.1.8
[4 Aug 2009 15:39]
Tony Bedford
An entry was added to the 5.1.8 changelog: A statement interceptor received the incorrect parameters when used with a batched statement.
[15 Apr 2010 9:19]
han huiwen
Server version: 5.1.37-1ubuntu5 (Ubuntu) also has this issue
[15 Apr 2010 9:33]
Tonci Grgin
Han, I see no connection between server version and this bug...
[15 Apr 2010 13:48]
han huiwen
hi,Tonci is it driver's issue ?

Description: When using a PreparedStatement to do for i in 1 to n {setBlah; addBatch}; executeBatch any StatementInterceptors defined will only be passed the most recent addBatch parameters, but they will be passed them n times, effectively intercepting duplicates of the last statement values and never receiving the previous ones. The call stack leading up to a "java.sql.BatchUpdateException: Duplicate entry" error due to this in my application is: at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1666) at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1082) at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297) at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297) How to repeat: use executeBatch with prepared statements and a statement interceptor. Suggested fix: pass the right parameters, not just the last ones.