Druid的SQL Parser

最近在看zebra的分库分表源码部分所使用的sql解析就是采用的SQL Parser,这里写个简单的举例方便新手理解

简单使用举例

public class SqlParser {

    public static void main(String[] args) {
        String sql = "select * from t where id=1 and name=ming group by uid limit 1,200 order by ctime";

        // 新建 MySQL Parser
        SQLStatementParser parser = new MySqlStatementParser(sql);

        // 使用Parser解析生成AST,这里SQLStatement就是AST
        SQLStatement sqlStatement = parser.parseStatement();

        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
        sqlStatement.accept(visitor);

        System.out.println("getTables:" + visitor.getTables());
        System.out.println("getParameters:" + visitor.getParameters());
        System.out.println("getOrderByColumns:" + visitor.getOrderByColumns());
        System.out.println("getGroupByColumns:" + visitor.getGroupByColumns());
        System.out.println("---------------------------------------------------------------------------");

        // 使用select访问者进行select的关键信息打印
        SelectPrintVisitor selectPrintVisitor = new SelectPrintVisitor();
        sqlStatement.accept(selectPrintVisitor);

        System.out.println("---------------------------------------------------------------------------");
        // 最终sql输出
        StringWriter out = new StringWriter();
        TableNameVisitor outputVisitor = new TableNameVisitor(out);
        sqlStatement.accept(outputVisitor);
        System.out.println(out.toString());
    }

}

/**
 * 查询语句访问者
 * 
 * @author xiezhengchao
 * @since 2018/6/1 12:08
 */
public class SelectPrintVisitor extends SQLASTVisitorAdapter {

    @Override
    public boolean visit(SQLSelectQueryBlock x) {
        List<SQLSelectItem> selectItemList = x.getSelectList();
        selectItemList.forEach(selectItem -> {
            System.out.println("attr:" + selectItem.getAttributes());
            System.out.println("expr:" + SQLUtils.toMySqlString(selectItem.getExpr()));
        });

        System.out.println("table:" + SQLUtils.toMySqlString(x.getFrom()));
        System.out.println("where:" + SQLUtils.toMySqlString(x.getWhere()));
        System.out.println("order by:" + SQLUtils.toMySqlString(x.getOrderBy().getItems().get(0)));
        System.out.println("limit:" + SQLUtils.toMySqlString(x.getLimit()));

        return true;
    }

}

/**
 * 数据库表名访问者
 * 
 * @author xiezhengchao
 * @since 2018/6/1 11:52
 */
public class TableNameVisitor extends MySqlOutputVisitor {

    public TableNameVisitor(Appendable appender) {
        super(appender);
    }

    @Override
    public boolean visit(SQLExprTableSource x) {
        SQLName table = (SQLName) x.getExpr();
        String tableName = table.getSimpleName();

        // 改写tableName
        print0("new_" + tableName.toUpperCase());

        return true;
    }

}

这里只是简单的使用举例,对于初学者理解了通过访问者对象去获取sql的关键信息即可.具体的访问者还是要看官方文档.

《Druid的SQL Parser》 实际运行结果

例子源码

github:https://github.com/znyh113too/sql-parser/tree/master

参考链接

官方说明文档:https://github.com/alibaba/druid/wiki/SQL-Parser
https://www.jianshu.com/p/437aa22ea3ca

点赞