最近在看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的关键信息即可.具体的访问者还是要看官方文档.
例子源码
github:https://github.com/znyh113too/sql-parser/tree/master
参考链接
官方说明文档:https://github.com/alibaba/druid/wiki/SQL-Parser
https://www.jianshu.com/p/437aa22ea3ca