druid 最新版本,测试代码如下:
@test public void testMergeSql() { String sql = "select\n" + " ifnull(sum(case when test_time >= '2019-04-01 11:22:33' and test_time < '2019-04-30 12:33:44' then 1 ELSE 0 end),0) today_count,\n" + " ifnull(sum(case when test_time >= '2019-04-01 11:22:33' and test_time < '2019-04-30 12:33:44' then 1 ELSE 0 end),0) month_count,\n" + " ifnull(sum(case when invest_time is not null then test_col1 ELSE 0 end),0) total_amt\n" + " \n" + " from notify_aaa\n" + " where abc='123' "; System.out.println(sql); String mergedSql = ParameterizedOutputVisitorUtils.parameterize(sql, "mysql", null, null); System.out.println(mergedSql); }
执行结果为:
SELECT ifnull(SUM(CASE WHEN test_time >= '2019-04-01 11:22:33' AND test_time < '2019-04-30 12:33:44' THEN 1 ELSE 0 END), ?) AS today_count , ifnull(SUM(CASE WHEN test_time >= '2019-04-01 11:22:33' AND test_time < '2019-04-30 12:33:44' THEN 1 ELSE 0 END), ?) AS month_count , ifnull(SUM(CASE WHEN invest_time IS NOT NULL THEN test_col1 ELSE 0 END), ?) AS total_amt FROM notify_aaa WHERE abc = ?
可以看到test_time字段后面的具体日期没有参数化成问号。
断点分析代码发现,在进入SQLASTOutputVisitor的public boolean visit(SQLAggregateExpr x)方法,this.parameterized = false; 导致不会参数化了。
原提问者GitHub用户lizongbo
若ParameterizedOutputVisitorUtils.parameterize()无法全量参数化SQL语句中的字面值,有以下几种原因:
SQL语句中存在特殊字符未被正确转义。比如单引号会终止字符串,会导致后面的内容无法被正确解析。
存在复合字面值,比如数字链接成字符串。仅仅加上?符号是无法被正确解析的。
SQL存在较为复杂的嵌套结构,ParameterizeOutputVisitor无法识别。
SQL包含数据库特定的函数或关键字,ParameterizeOutputVisitor无法支持。
针对不同的场景,可以尝试以下过程:
简单的查询语句如select能否被完全参数化?
将特殊字符如单引号使用转义字符'转义,重新参数化。
将复合字面值置于括号内作为一个整体提供给ParameterizeOutputVisitor。
将部分SQL使用临时变量,简化结构。
尝试升级ParameterizeOutputVisitorUtils版本。
自行实现基于正则的SQL参数化。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。