String sql = "insert into t1 values('A\0\0\0B')"; System.out.println(sql); SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcUtils.MYSQL); SQLStatement stmt = parser.parseStatement(); StringBuilder sb = new StringBuilder(); MySqlOutputVisitor v = new MySqlOutputVisitor(sb); v.setPrettyFormat(false); stmt.accept(v); System.out.println(sb);
输出结果为: insert into t1 values('A\0\0\0B') INSERT INTO t1 VALUES ('A000B') MySqlOutputVisitor会把\0换成0
原提问者GitHub用户terryzhu
ruid是一款流行的Java数据库连接池和SQL解析工具,可以用于生成和解析SQL语句。在使用Druid的MySqlOutputVisitor生成SQL语句时,可能会出现转义字符的问题。
如果在生成SQL语句时需要使用转义字符,可以使用VisitorFeature中的QUORUM_SELECT和QUORUM_POINT功能来启用转义字符,例如:
ini
Copy
StringWriter out = new StringWriter();
MySqlOutputVisitor visitor = new MySqlOutputVisitor(out, true);
visitor.getConfig().setFeatures(Arrays.asList(VisitorFeature.QUORUM_SELECT, VisitorFeature.QUORUM_POINT));
visitor.visit(statement);
String sql = out.toString();
启用QUORUM_SELECT和QUORUM_POINT功能后,生成的SQL语句中的转义字符会被正确处理。
和输出结果,可以看出在MySqlOutputVisitor的行为上。MySqlOutputVisitor默认会将转义字符\0
解析为0,导致输出结果中缺失了\
,并且将\替换为了如果你希望输出结果保留转义字符
\0你可以通过自定义OutputVisitor来解决这个问题。下面是一个示例java
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;
public class CustomMySqlOutputVisitor extendsVisitor {
public CustomMySqlOutputVisitor(Appendable appender) {
super(appender);
}
@Override
protected void(String text String escapedText = text.replace("\\", "\\\\");
super.printString(escapedText);
}
public outputSQL(SQLStatement stmt) {
StringBuilder sb = new StringBuilder();
CustomMySqlOutputVisitor visitor = new CustomMySql(sb);
ParameterizedOutputVisitorUtilsVisitor(sb, visitor, DbType.mysql);
stmt.accept(visitor return sb.toString();
}
}
然后,你可以使用CustomMySqlOutputVisitor来SQL语是你的示例代码修改后的版本java
import com.alibaba.druid.sql.dialect.mysql.MySqlOutputVisitor;
import com.alibaba.druid.util.JdbcUtils;
import com.alibaba.druid.SQLParserUtils;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.ast.SQLStatement;
public class Main {
public static void main(String) {
= "insert into t1 values('A\\0\\0B.println SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcUtilsYSQL);
SQLStatement stmt = parser.parse String formattedSqlMyVisitor.outputSQL(stmt);
System.out.println(formatted }
}
运行修改后的代码,输出结果应该如下所示:
insert into t1 values('A\0\0\0B')
insert into values('A\0\0\0B')
```
这样,转义字符`\将被正确解析并保输出结果中。希望这可以帮助到你。
问题已修复,请用新版本 https://github.com/alibaba/druid/releases/tag/1.1.14
原回答者GitHub用户wenshao
您的代码中使用了Druid的MySqlOutputVisitor来格式化生成的SQL语句。然而,您发现在使用MySqlOutputVisitor时,它会将\0
转义为0
。
这是因为在MySQL中,\0
表示空字符,而不是转义字符。因此,MySqlOutputVisitor在格式化过程中将\0
转换为了0
。
如果您希望保留原始的转义字符,可以尝试使用其他方法来格式化SQL语句,或者手动处理转义字符。以下是一个示例代码,演示了如何手动处理转义字符:
String sql = "insert into t1 values('A\\0\\0\\0B')";
System.out.println(sql);
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcUtils.MYSQL);
SQLStatement stmt = parser.parseStatement();
StringBuilder sb = new StringBuilder();
stmt.accept(new SQLASTOutputVisitor(sb) {
@Override
public boolean visit(SQLCharExpr x) {
String text = x.getText();
// 处理转义字符
text = text.replace("\\0", "\\\\0");
print0(text);
return false;
}
});
System.out.println(sb);
在上述代码中,我们继承了SQLASTOutputVisitor并重写了visit(SQLCharExpr x)方法。在这个方法中,我们获取了原始的文本,并手动处理了转义字符。在输出时,我们使用了\\\\0
来表示\0
,这样就可以保留原始的转义字符了。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。