Bug #37458 | with server 5.1, getGeneratedKeys returns them in ascending order | ||
---|---|---|---|
Submitted: | 17 Jun 2008 20:12 | Modified: | 3 Aug 2009 18:03 |
Reporter: | Eric Jensen | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | Connector / J | Severity: | S1 (Critical) |
Version: | 5.1.6 | OS: | Any (only with mysql server 5.1) |
Assigned to: | CPU Architecture: | Any |
[17 Jun 2008 20:12]
Eric Jensen
[18 Jun 2008 6:54]
Tonci Grgin
Hi Eric and thanks for spotting this. True, regression test for your original Bug#34093 fails against MySQL server 5.1.26 while, on the same box and same c/J sources, works with 5.0.64... junit.framework.AssertionFailedError: expected:<4> but was:<1> at junit.framework.Assert.fail(Assert.java:47) at junit.framework.Assert.failNotEquals(Assert.java:282) at junit.framework.Assert.assertEquals(Assert.java:64) at junit.framework.Assert.assertEquals(Assert.java:71) at testsuite.BaseTestCase.assertResultSetsEqual(BaseTestCase.java:694) at testsuite.regression.StatementRegressionTest.testBug34093(StatementRegressionTest.java:5381) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at junit.framework.TestCase.runTest(TestCase.java:154) at junit.framework.TestCase.runBare(TestCase.java:127) at junit.framework.TestResult$1.protect(TestResult.java:106) at junit.framework.TestResult.runProtected(TestResult.java:124) at junit.framework.TestResult.run(TestResult.java:109) at junit.framework.TestCase.run(TestCase.java:118) at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196) The problem is in "bigger" nonRewrittenRsKeys: nonRewrittenRsKeys ResultSetImpl (id=51) catalog "test" columnLabelToIndex null columnNameToIndex null columnUsed null connection ConnectionImpl (id=58) connectionId 5 currentRow -1 defaultTimeZone ZoneInfo (id=95) doingUpdates false eventSink null fastDateCal null fetchDirection 1000 fetchSize 0 fields Field[1] (id=98) firstCharOfQuery fullColumnNameToIndex null gmtCalendar null hasBuiltIndexMapping false invalidRowReason "Before start of result set" isBinaryEncoded false isClosed false jdbcCompliantTruncationForReads true nextResultSet null onInsertRow false onValidRow false owningStatement PreparedStatement (id=102) padCharsWithSpace false pointOfOrigin null profileSql false reallyResult true resultId 0 resultSetConcurrency 0 resultSetType 0 retainOwningStatement false rowData RowDataStatic (id=54) index -1 metadata Field[1] (id=98) owner ResultSetImpl (id=51) rows ArrayList<E> (id=64) elementData Object[11] (id=73) [0] ByteArrayRow (id=75) internalRowData byte[1][] (id=85) [0] byte[1] (id=88) [0] 51 metadata null [1] ByteArrayRow (id=77) internalRowData byte[1][] (id=81) [0] byte[1] (id=87) [0] 52 metadata null [2] ByteArrayRow (id=78) internalRowData byte[1][] (id=84) [0] byte[1] (id=89) [0] 49 metadata null [3] ByteArrayRow (id=79) internalRowData byte[1][] (id=86) [0] byte[1] (id=90) [0] 50 metadata null [4] ByteArrayRow (id=108) internalRowData byte[1][] (id=127) [0] byte[1] (id=128) [0] 52 metadata null [5] ByteArrayRow (id=109) internalRowData byte[1][] (id=129) [0] byte[1] (id=130) [0] 53 metadata null [6] ByteArrayRow (id=110) internalRowData byte[1][] (id=131) [0] byte[1] (id=132) [0] 50 metadata null [7] ByteArrayRow (id=111) internalRowData byte[1][] (id=133) [0] byte[1] (id=134) [0] 51 metadata null [8] null [9] null [10] null modCount 8 size 8 serverInfo null serverTimeZoneTz null statementUsedForFetchingRows null thisRow null updateCount 8 updateId -1 useColumnNamesInFindColumn false useFastDateParsing true useFastIntParsing true useLegacyDatetimeCode true useStrictFloatingPoint false useUsageAdvisor false warningChain null wasNullFlag false wrapperStatement null while rewrittenRsKeys remains the same between versions: rewrittenRsKeys ResultSetImpl (id=92) catalog "test" columnLabelToIndex null columnNameToIndex null columnUsed null connection ConnectionImpl (id=91) connectionId 6 currentRow -1 defaultTimeZone ZoneInfo (id=113) doingUpdates false eventSink null fastDateCal null fetchDirection 1000 fetchSize 0 fields Field[1] (id=114) firstCharOfQuery fullColumnNameToIndex null gmtCalendar null hasBuiltIndexMapping false invalidRowReason "Before start of result set" isBinaryEncoded false isClosed false jdbcCompliantTruncationForReads true nextResultSet null onInsertRow false onValidRow false owningStatement PreparedStatement (id=115) padCharsWithSpace false pointOfOrigin null profileSql false reallyResult true resultId 0 resultSetConcurrency 0 resultSetType 0 retainOwningStatement false rowData RowDataStatic (id=116) index -1 metadata Field[1] (id=114) owner ResultSetImpl (id=92) rows ArrayList<E> (id=117) elementData Object[4] (id=118) [0] ByteArrayRow (id=119) internalRowData byte[1][] (id=123) [0] byte[1] (id=124) [0] 51 metadata null [1] ByteArrayRow (id=120) internalRowData byte[1][] (id=125) [0] byte[1] (id=126) [0] 49 metadata null [2] ByteArrayRow (id=121) [3] ByteArrayRow (id=122) modCount 4 size 4 serverInfo null serverTimeZoneTz null statementUsedForFetchingRows null thisRow null updateCount 4 updateId -1 useColumnNamesInFindColumn false useFastDateParsing true useFastIntParsing true useLegacyDatetimeCode true useStrictFloatingPoint false useUsageAdvisor false warningChain null wasNullFlag false wrapperStatement null
[19 Jun 2008 13:56]
Mark Matthews
This is more complex than it looks. It seems prior to 5.1, the server returned "normal" update counts for "ON DUPLICATE KEY UPDATE", and now it returns *2*. This confuses the JDBC driver's code for creating the result set for getGeneratedKeys(), because it also has to support statements of the form "INSERT INTO ... VALUES (...), (....), (...)...", which will also have an update count > 1. The server only returns the "first" generated key for a statement, the rest have to be "computed" (more like "divined" in the case of REPLACE, and now it seems for "ON DUPLICATE KEY UPDATE", so to make this work we'll have to scan the statement for "ON DUPLICATE KEY UPDATE" clauses.
[28 Nov 2008 7:00]
Eric Jensen
Now that 5.1 is GA, this could become a fairly widespread issue.
[30 Jul 2009 16:34]
Eric Jensen
any update on this? now that 5.1 is GA should this be critical? it does indeed result in invalid results.
[2 Aug 2009 22:41]
Jess Balint
Eric, Can you elaborate on what stack you expected to see, and how you obtained it? I'm not sure of the relevance here. Regarding the bug, I have run the attached test program without a problem. Can you review this test to see if it differs from your situation? Also, have you tried the recently released Connector/J 5.1.8? Thanks, Jess Test: int ids[] = {13, 1, 8}; createTable("testBug37458", "(id int not null auto_increment, primary key (id))"); stmt.executeUpdate("insert into testBug37458 values (1), (8), (13)"); pstmt = conn.prepareStatement("insert into testBug37458 values (?) on duplicate key update id = last_insert_id(id)", PreparedStatement.RETURN_GENERATED_KEYS); for(int i = 0; i < ids.length; ++i) { pstmt.setInt(1, ids[i]); pstmt.addBatch(); } pstmt.executeBatch(); ResultSet keys = pstmt.getGeneratedKeys(); for(int i = 0; i < ids.length; ++i) { assertTrue(keys.next()); assertEquals(ids[i], keys.getInt(1)); System.out.println("Key " + (i+1) + " = " + keys.getInt(1)); }
[3 Aug 2009 17:25]
Eric Jensen
your test appears to cover the situation i was describing, so maybe it is fixed. my particular use case is inserting into a unique key string value to get back the autogenerated id for it, but i'm not sure if there's a particular bug with that or not. there was a test case that covered this and was failing on 5.1, is this still true? [18 Jun 2008 8:54] Tonci Grgin Hi Eric and thanks for spotting this. True, regression test for your original Bug#34093 fails against MySQL server 5.1.26 while, on the same box and same c/J sources, works with 5.0.64...
[3 Aug 2009 18:03]
Jess Balint
Eric, All tests are passing. I will add this new test to prevent a regression and close this bug report. Feel free to re-open it if you still have an issue.