|
29 | 29 |
|
30 | 30 | package testsuite.regression; |
31 | 31 |
|
| 32 | +import static org.junit.jupiter.api.Assertions.assertArrayEquals; |
32 | 33 | import static org.junit.jupiter.api.Assertions.assertEquals; |
33 | 34 | import static org.junit.jupiter.api.Assertions.assertFalse; |
34 | 35 | import static org.junit.jupiter.api.Assertions.assertNotNull; |
@@ -12168,4 +12169,120 @@ public void testBug106240() throws Exception { |
12168 | 12169 | () -> testConn.prepareStatement("INSERT INTO testBug106240 VALUES/* (?, ?) */ON DUPLICATE KEY UPDATE").execute()); |
12169 | 12170 | } while (useSPS = !useSPS); |
12170 | 12171 | } |
| 12172 | + |
| 12173 | + /** |
| 12174 | + * Tests for Bug#81468 (23312764), MySQL server fails to rewrite batch insert when column name contains word select. |
| 12175 | + * Resolved by fix for Bug#106240 (33781440), StringIndexOutOfBoundsException when VALUE is at the end of the query. |
| 12176 | + * |
| 12177 | + * @throws Exception |
| 12178 | + */ |
| 12179 | + @Test |
| 12180 | + public void testBug81468() throws Exception { |
| 12181 | + createTable("testBug81468", "(selection INT)"); // Column has to contain "select" in its name. |
| 12182 | + |
| 12183 | + Properties props = new Properties(); |
| 12184 | + props.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name()); |
| 12185 | + props.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true"); |
| 12186 | + props.setProperty(PropertyKey.queryInterceptors.getKeyName(), TestBug81468QueryInterceptor.class.getName()); |
| 12187 | + props.setProperty(PropertyKey.rewriteBatchedStatements.getKeyName(), "true"); |
| 12188 | + props.setProperty(PropertyKey.continueBatchOnError.getKeyName(), "false"); |
| 12189 | + props.setProperty(PropertyKey.emulateUnsupportedPstmts.getKeyName(), "true"); |
| 12190 | + |
| 12191 | + boolean useSPS = false; |
| 12192 | + |
| 12193 | + do { |
| 12194 | + props.setProperty(PropertyKey.useServerPrepStmts.getKeyName(), Boolean.toString(useSPS)); |
| 12195 | + Connection testConn = getConnectionWithProps(props); |
| 12196 | + |
| 12197 | + // Re-writes in a single query with three values. |
| 12198 | + TestBug81468QueryInterceptor.resetExpectedValues(1, 1, 3); |
| 12199 | + PreparedStatement testPStmt = testConn.prepareStatement("INSERT INTO testBug81468 (selection) VALUES (?)"); |
| 12200 | + testPStmt.setInt(1, 11); |
| 12201 | + testPStmt.addBatch(); |
| 12202 | + testPStmt.setInt(1, 12); |
| 12203 | + testPStmt.addBatch(); |
| 12204 | + testPStmt.setInt(1, 13); |
| 12205 | + testPStmt.addBatch(); |
| 12206 | + assertArrayEquals(new int[] { Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO }, testPStmt.executeBatch()); |
| 12207 | + testPStmt.close(); |
| 12208 | + |
| 12209 | + // Re-writes in a single query with five values. |
| 12210 | + TestBug81468QueryInterceptor.resetExpectedValues(1, 1, 5); |
| 12211 | + testPStmt = testConn.prepareStatement("INSERT INTO testBug81468 (selection) VALUES (?)"); |
| 12212 | + testPStmt.setInt(1, 21); |
| 12213 | + testPStmt.addBatch(); |
| 12214 | + testPStmt.setInt(1, 22); |
| 12215 | + testPStmt.addBatch(); |
| 12216 | + testPStmt.setInt(1, 23); |
| 12217 | + testPStmt.addBatch(); |
| 12218 | + testPStmt.setInt(1, 24); |
| 12219 | + testPStmt.addBatch(); |
| 12220 | + testPStmt.setInt(1, 25); |
| 12221 | + testPStmt.addBatch(); |
| 12222 | + assertArrayEquals(new int[] { Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO, |
| 12223 | + Statement.SUCCESS_NO_INFO }, testPStmt.executeBatch()); |
| 12224 | + testPStmt.close(); |
| 12225 | + |
| 12226 | + // Not enough queries to trigger the query re-write feature. |
| 12227 | + TestBug81468QueryInterceptor.resetExpectedValues(3, 1, 1); |
| 12228 | + Statement testStmt = testConn.createStatement(); |
| 12229 | + testStmt.addBatch("INSERT INTO testBug81468 (selection) VALUES (31)"); |
| 12230 | + testStmt.addBatch("INSERT INTO testBug81468 (selection) VALUES (32)"); |
| 12231 | + testStmt.addBatch("INSERT INTO testBug81468 (selection) VALUES (33)"); |
| 12232 | + assertArrayEquals(new int[] { 1, 1, 1 }, testStmt.executeBatch()); |
| 12233 | + testStmt.close(); |
| 12234 | + |
| 12235 | + // Five or more queries triggers the query re-write feature. |
| 12236 | + TestBug81468QueryInterceptor.resetExpectedValues(1, 5, 5); |
| 12237 | + testStmt = testConn.createStatement(); |
| 12238 | + testStmt.addBatch("INSERT INTO testBug81468 (selection) VALUES (41)"); |
| 12239 | + testStmt.addBatch("INSERT INTO testBug81468 (selection) VALUES (42)"); |
| 12240 | + testStmt.addBatch("INSERT INTO testBug81468 (selection) VALUES (43)"); |
| 12241 | + testStmt.addBatch("INSERT INTO testBug81468 (selection) VALUES (44)"); |
| 12242 | + testStmt.addBatch("INSERT INTO testBug81468 (selection) VALUES (45)"); |
| 12243 | + assertArrayEquals(new int[] { 1, 1, 1, 1, 1 }, testStmt.executeBatch()); |
| 12244 | + testStmt.close(); |
| 12245 | + |
| 12246 | + testConn.close(); |
| 12247 | + } while (useSPS = !useSPS); |
| 12248 | + } |
| 12249 | + |
| 12250 | + public static class TestBug81468QueryInterceptor extends BaseQueryInterceptor { |
| 12251 | + private static int expectedNumberOfExecutions = 0; |
| 12252 | + private static int expectedNumberOfQueries = 0; |
| 12253 | + private static int expectedNumberOfValues = 0; |
| 12254 | + private static int executionsCount = 0; |
| 12255 | + |
| 12256 | + static void resetExpectedValues(int expExecs, int expQueries, int expVals) { |
| 12257 | + expectedNumberOfExecutions = expExecs; |
| 12258 | + expectedNumberOfQueries = expQueries; |
| 12259 | + expectedNumberOfValues = expVals; |
| 12260 | + executionsCount = 0; |
| 12261 | + } |
| 12262 | + |
| 12263 | + @Override |
| 12264 | + public <T extends Resultset> T preProcess(Supplier<String> sql, Query interceptedQuery) { |
| 12265 | + String query = sql.get(); |
| 12266 | + if (query.contains("testBug81468")) { |
| 12267 | + assertTrue(++executionsCount <= expectedNumberOfExecutions, |
| 12268 | + "Too many statement executions. The query [" + query + "] should have been re-written"); |
| 12269 | + assertEquals(expectedNumberOfQueries, countQueries(query), "Wrong number of queries in [" + query + "]"); |
| 12270 | + assertEquals(expectedNumberOfValues, countValues(query)); |
| 12271 | + } |
| 12272 | + return super.preProcess(sql, interceptedQuery); |
| 12273 | + } |
| 12274 | + |
| 12275 | + private int countQueries(String query) { |
| 12276 | + return query.split(";").length; |
| 12277 | + } |
| 12278 | + |
| 12279 | + private int countValues(String query) { |
| 12280 | + query += "/* junk */"; // Add some junk to the end of the query so that the following split allows counting the values correctly. |
| 12281 | + if (query.contains("?")) { |
| 12282 | + return query.split("\\(\\?\\)").length - 1; |
| 12283 | + } |
| 12284 | + return query.split("\\(\\d{2}\\)").length - 1; |
| 12285 | + } |
| 12286 | + } |
| 12287 | + |
12171 | 12288 | } |
0 commit comments