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:
None 
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:10] Eric Jensen
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.
[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 ?

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.049 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.