Bug #109818 rewritableAsMultiValues wrongfully set to false if columnname contains "value"
Submitted: 27 Jan 7:33 Modified: 30 Jan 9:55
Reporter: Gustaf Sörensen Email Updates:
Status: Analyzing Impact on me:
None 
Category:Connector / J Severity:S3 (Non-critical)
Version:8.0.32 OS:Any
Assigned to: MySQL Verification Team CPU Architecture:Any

[27 Jan 7:33] Gustaf Sörensen
Description:
After bumping the version of mysql-connector-j to 8.0.32 we noticed that batch inserts made by prepared statements took much longer time to execute. After a bit of investigation we found that this only happens on some of our inserts. Namely inserts where we have column names that have the word "value" in them and where the query takes placeholders "?".

This bug seems to have been introduced in 8.0.29.

How to repeat:
Test reproducing the bug:

import static org.junit.jupiter.api.Assertions.assertTrue;

import com.mysql.cj.jdbc.ClientPreparedStatement;
import com.mysql.cj.jdbc.MysqlDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.junit.jupiter.api.Test;

class RewritableAsMultiValuesTest {
  @Test
  void rewritableAsMultiValuesBug() throws SQLException {
    MysqlDataSource dataSource = new MysqlDataSource();
    String url = "DB CONNECTION STRING HERE";
    dataSource.setURL(url);
    dataSource.setRewriteBatchedStatements(true);
    Connection connection = dataSource.getConnection();

    //QUERY THAT IS EVALUATED CORRECT
    PreparedStatement preparedStatement = connection.prepareStatement(
        "INSERT INTO test (a, b) VALUES (?, ?)"
    );
    ClientPreparedStatement clientPreparedStatement = (ClientPreparedStatement) preparedStatement;
    boolean isRewritable = clientPreparedStatement.getQueryInfo()
        .isRewritableWithMultiValuesClause();
    assertTrue(isRewritable);
    connection.close();

    //QUERY THAT IS EVALUATED INCORRECTLY
    connection = dataSource.getConnection();
    PreparedStatement preparedStatementBug = connection.prepareStatement(
        "INSERT INTO test (a_value, bvalue) VALUES (?, ?)"
    );
    ClientPreparedStatement clientPreparedStatementBug = (ClientPreparedStatement) preparedStatementBug;
    boolean isRewritableBug = clientPreparedStatementBug.getQueryInfo()
        .isRewritableWithMultiValuesClause();
    assertTrue(isRewritableBug);

  }

}

Suggested fix:
The problem lies in QueryInfo.class. The valuesClauseEnd gets set too early in the query parsing.