-
Notifications
You must be signed in to change notification settings - Fork 592
Description
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
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: