开发者社区> 问答> 正文

druid格式化MySqlOutputVisitor生成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(); 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

展开
收起
山海行 2023-07-05 21:51:23 68 0
4 条回答
写回答
取消 提交回答
  • 北京阿里云ACE会长

    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语句中的转义字符会被正确处理。

    2023-07-30 09:38:26
    赞同 展开评论 打赏
  • 值得去的地方都没有捷径

    和输出结果,可以看出在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')
    ```

    这样,转义字符`\将被正确解析并保输出结果中。希望这可以帮助到你。

    2023-07-11 16:50:15
    赞同 展开评论 打赏
  • 问题已修复,请用新版本 https://github.com/alibaba/druid/releases/tag/1.1.14

    原回答者GitHub用户wenshao

    2023-07-06 12:29:35
    赞同 展开评论 打赏
  • 您的代码中使用了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,这样就可以保留原始的转义字符了。

    2023-07-06 11:01:52
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
SQL Server 2017 立即下载
GeoMesa on Spark SQL 立即下载
原生SQL on Hadoop引擎- Apache HAWQ 2.x最新技术解密malili 立即下载