Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Fixed
-
1.1.9
-
None
-
Sprint connector/j 1.3.0
Description
When performing a batch insert with the rewriteBatchedStatements=true option, the insert can fail if the first value being inserted isn't a parameter. The following test case demonstrates the problem:
@Test
|
public void testInsertWithLeadingConstantValue() throws Exception {
|
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true", "root", "root");
|
Statement stmt = null;
|
PreparedStatement insertStmt = null;
|
try {
|
stmt = conn.createStatement();
|
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS test_table(col1 VARCHAR(32), col2 VARCHAR(32))");
|
|
insertStmt = conn.prepareStatement("INSERT INTO test_table (col1, col2) values('some value', ?)");
|
insertStmt.setString(1, "a");
|
insertStmt.addBatch();
|
insertStmt.setString(1, "b");
|
insertStmt.addBatch();
|
insertStmt.executeBatch();
|
conn.commit();
|
}
|
finally {
|
if (insertStmt != null) {
|
insertStmt.close();
|
}
|
if (stmt != null) {
|
stmt.close();
|
}
|
conn.close();
|
}
|
}
|
The insert attempt results in the following SQL being executed:
INSERT INTO test_table (col1, col2) values('some value', 'a'),('b') |
The SQL fails with the following error:
java.sql.BatchUpdateException: Column count doesn't match value count at row 2
|
at org.mariadb.jdbc.MySQLStatement.executeBatch(MySQLStatement.java:1291)
|
at org.mariadb.jdbc.TestBatchInsert.testInsertWithLeadingConstantValue(TestBatchInsert.java:24)
|
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
|
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
at java.lang.reflect.Method.invoke(Method.java:606)
|
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
|
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
|
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
|
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
|
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
|
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
|
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
|
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:44)
|
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
|
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
|
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
|
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
|
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
|
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
|
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
|
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
|
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
|
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
|
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
|
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
|
Caused by: java.sql.SQLException: Column count doesn't match value count at row 2
|
at org.mariadb.jdbc.internal.SQLExceptionMapper.get(SQLExceptionMapper.java:149)
|
at org.mariadb.jdbc.internal.SQLExceptionMapper.throwException(SQLExceptionMapper.java:106)
|
at org.mariadb.jdbc.MySQLStatement.executeQueryEpilog(MySQLStatement.java:268)
|
at org.mariadb.jdbc.MySQLStatement.execute(MySQLStatement.java:335)
|
at org.mariadb.jdbc.MySQLStatement.executeBatch(MySQLStatement.java:1271)
|
... 25 more
|
Caused by: org.mariadb.jdbc.internal.common.QueryException: Column count doesn't match value count at row 2
|
at org.mariadb.jdbc.internal.mysql.MySQLProtocol.getResult(MySQLProtocol.java:995)
|
at org.mariadb.jdbc.internal.mysql.MySQLProtocol.executeQuery(MySQLProtocol.java:1050)
|
at org.mariadb.jdbc.MySQLStatement.execute(MySQLStatement.java:328)
|
... 26 more
|
This seems to be because the initial part of the values clause up to the first parameter isn't being included in the rewritten SQL. The following patch addresses this issue:
diff --git a/src/main/java/org/mariadb/jdbc/internal/common/query/MySQLParameterizedQuery.java b/src/main/java/org/mariadb/jdbc/internal/common/query/MySQLParameterizedQuery.java
|
index 364a185..8f7dd5a 100644
|
--- a/src/main/java/org/mariadb/jdbc/internal/common/query/MySQLParameterizedQuery.java
|
+++ b/src/main/java/org/mariadb/jdbc/internal/common/query/MySQLParameterizedQuery.java
|
@@ -139,6 +139,9 @@
|
throw new AssertionError("Invalid query, queryParts was empty");
|
}
|
os.write(",(".getBytes());
|
+ if (queryPartsArray[0].length > rewriteOffset) {
|
+ os.write(queryPartsArray[0], rewriteOffset + 1, queryPartsArray[0].length - rewriteOffset - 1);
|
+ }
|
for(int i = 1; i<queryPartsArray.length; i++) {
|
parameters[i-1].writeTo(os);
|
if(queryPartsArray[i].length != 0)
|