我们最近将基础框架升级到了 springboot 3.3.5 和其他相关库。
测试期间向我报告了一个错误。使用 jsqlparser 5.0 时某些查询会失败。
这是一个简单的演示:
public class test { public static void main(string[] args) throws jsqlparserexception { string sql = "select convert(if(bill_type = 2, id, ''), char) from dual"; statement statement2 = ccjsqlparserutil.parse(sql); system.out.println(statement2.tostring()); } }
问题在于 jsqlparser 5.0 不支持 mysql 风格的 convert 语法 convert(expr, type)。它仅支持:
sql server 风格:convert(type, expr)
字符集转换:convert(expr using charset)
这会影响使用 mysql 的 convert 函数的查询,尤其是当表达式很复杂时(例如使用 if 语句)。
jsqlparser 中的当前语法:
{ <k_convert> "(" ( lookahead(coldatatype() ",") ( coldatatype = coldatatype() "," expression = expression() [ "," style = <s_long> ] ) | ( expression = expression() <k_using> transcodingname=identifierchain() ) ) ")" }
这个问题有两种解决方案:
-
使用 cast 而不是 convert
只需将 convert(expr, type) 替换为 cast(expr as type) 即可。如果您使用 mysql -
修改 jsqlparser 语法以支持 convert(expr, type)
需要修改语法规则以支持mysql语法。但是,请小心 transcodingfunction.appendto 方法。当前实现生成 convert(type, expr),这在 sql server 中是合法的,但在 mysql 中是非法的
,这是最简单的解决方案
public StringBuilder appendTo(StringBuilder builder) { if (isTranscodeStyle) { return builder .append("CONVERT( ") .append(expression) .append(" USING ") .append(transcodingName) .append(" )"); } else { return builder .append("CONVERT( ") .append(colDataType) .append(", ") .append(expression) .append(transcodingName != null && !transcodingName.isEmpty() ? ", " + transcodingName : "") .append(" )"); } }