Skip to content

In the PreparedStatementImpl class, the initial length of the parameters is incorrectly changed in the clearParameters method #2299

@CCweixiao

Description

@CCweixiao

Describe the bug

当使用druid连接池时,connection每次close后,会归还连接池,同时,如果connection中的preparedStatement 也需要被池化的时候(由参数druid.maxOpenPreparedStatements决定),会调用clickhouse.PreparedStatementImpl#clearParameters方法,导致初始参数数组的个数多1,最终生成的sql后加了null字符串,引起sql编译错误。

When using a druid connection pool, the connection pool is returned after each close, and clickhouse.PreparedStatementImpl#clearParameters method is called if the preparedStatement in the connection also needs to be pooled (determined by the druid.maxOpenPreparedStatements parameter). the number of initial parameter arrays is increased by 1, and the final generated SQL is added with a null string, which causes SQL compilation errors.

You can focus on the DruidPooledConnection.closePoolableStatement source code
Image

clickhouse.PreparedStatementImpl constructor

    public PreparedStatementImpl(ConnectionImpl connection, String sql) throws SQLException {
        super(connection);
        this.originalSql = sql;
        //Split the sql string into an array of strings around question mark tokens
        this.sqlSegments = sql.split("\\?");

        //Create an array of objects to store the parameters
        if (originalSql.contains("?")) {
            int count = originalSql.length() - originalSql.replace("?", "").length();
            // 每次 new PreparedStatementImpl 之后,parameters数组的初始长度是正确的参数个数
            // After each new PreparedStatementImpl, the initial length of the parameters array is the correct number of parameters
            this.parameters = new Object[count];
        } else {
            this.parameters = new Object[0];
        }
    }

clickhouse.PreparedStatementImpl clearParameters method

    public void clearParameters() throws SQLException {
        checkClosed();
        if (originalSql.contains("?")) {
            // 调用clearParameters方法后,重置parameters数组,此时,数组的初始长度变为sqlSegments.length,比正确的参数个数 + 1
          //  After calling the clearParameters method, reset the parameters array, and the initial length of the array becomes sqlSegments.length, which is more than the correct number of parameters + 1
            this.parameters = new Object[sqlSegments.length];
            // int count = originalSql.length() - originalSql.replace("?", "").length();
            //  this.parameters = new Object[count];
            // sqlSegments.length is 1 more than count
        } else {
            this.parameters = new Object[0];
        }
    }

Configuration

Environment

  • Client version: Latest jdbc v2
  • Language version: java
  • OS:

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions