1.什么是AST
AST是abstract syntax tree的缩写,也就是抽象语法树.和所有的Parser一样,Druid Parser会生成一个抽象语法树。
2.常用的节点类型
在Druid中,AST节点类型主要包括SQLObject,SQLExpr,SQLStatement三种抽象类型。
其中SQLExpr主要针对的是sql表达式。
SQLStatement主要是语句级别的。
package com.alibaba.druid.sql.ast;interface SQLObject {}interface SQLExpr extends SQLObject {}interface SQLStatement extends SQLObject {}interface SQLTableSource extends SQLObject {}class SQLSelect extends SQLObject {}class SQLSelectQueryBlock extends SQLObject {}
常用的SQLExpr

package com.alibaba.druid.sql.ast.expr;// SQLName是一种的SQLExpr的Expr,包括SQLIdentifierExpr、SQLPropertyExpr等public interface SQLName extends SQLExpr {}// 例如 ID = 3 这里的ID是一个SQLIdentifierExprclass SQLIdentifierExpr implements SQLExpr, SQLName {String name;}// 例如 A.ID = 3 这里的A.ID是一个SQLPropertyExprclass SQLPropertyExpr implements SQLExpr, SQLName {SQLExpr owner;String name;}// 例如 ID = 3 这是一个SQLBinaryOpExpr// left是ID (SQLIdentifierExpr)// right是3 (SQLIntegerExpr)class SQLBinaryOpExpr implements SQLExpr {SQLExpr left;SQLExpr right;SQLBinaryOperator operator;}// 例如 select * from where id = ?,这里的?是一个SQLVariantRefExpr,name是'?'class SQLVariantRefExpr extends SQLExprImpl {String name;}// 例如 ID = 3 这里的3是一个SQLIntegerExprpublic class SQLIntegerExpr extends SQLNumericLiteralExpr implements SQLValuableExpr {Number number;// 所有实现了SQLValuableExpr接口的SQLExpr都可以直接调用这个方法求值@Overridepublic Object getValue() {return this.number;}}// 例如 NAME = 'jobs' 这里的'jobs'是一个SQLCharExprpublic class SQLCharExpr extends SQLTextLiteralExpr implements SQLValuableExpr{String text;}
常用的SQLStatemment
语句方面就是我门常用的增删改查了。
`
package com.alibaba.druid.sql.ast.statement;class SQLSelectStatement implements SQLStatement {SQLSelect select;}class SQLUpdateStatement implements SQLStatement {SQLExprTableSource tableSource;List<SQLUpdateSetItem> items;SQLExpr where;}class SQLDeleteStatement implements SQLStatement {SQLTableSource tableSource;SQLExpr where;}class SQLInsertStatement implements SQLStatement {SQLExprTableSource tableSource;List<SQLExpr> columns;SQLSelect query;}
SQLTableSource
常见的SQLTableSource包括SQLExprTableSource、SQLJoinTableSource、SQLSubqueryTableSource、SQLWithSubqueryClause.Entr
class SQLTableSourceImpl extends SQLObjectImpl implements SQLTableSource {String alias;}// 例如 select * from emp where i = 3,这里的from emp是一个SQLExprTableSource// 其中expr是一个name=emp的SQLIdentifierExprclass SQLExprTableSource extends SQLTableSourceImpl {SQLExpr expr;}// 例如 select * from emp e inner join org o on e.org_id = o.id// 其中left 'emp e' 是一个SQLExprTableSource,right 'org o'也是一个SQLExprTableSource// condition 'e.org_id = o.id'是一个SQLBinaryOpExprclass SQLJoinTableSource extends SQLTableSourceImpl {SQLTableSource left;SQLTableSource right;JoinType joinType; // INNER_JOIN/CROSS_JOIN/LEFT_OUTER_JOIN/RIGHT_OUTER_JOIN/...SQLExpr condition;}// 例如 select * from (select * from temp) a,这里第一层from(...)是一个SQLSubqueryTableSourceSQLSubqueryTableSource extends SQLTableSourceImpl {SQLSelect select;}/*例如WITH RECURSIVE ancestors AS (SELECT *FROM orgUNIONSELECT f.*FROM org f, ancestors aWHERE f.id = a.parent_id)SELECT *FROM ancestors;这里的ancestors AS (...) 是一个SQLWithSubqueryClause.Entry*/class SQLWithSubqueryClause {static class Entry extends SQLTableSourceImpl {SQLSelect subQuery;}}
SQLSelect & SQLSelectQuery
class SQLSelect extends SQLObjectImpl {
SQLWithSubqueryClause withSubQuery;
SQLSelectQuery query;
}
interface SQLSelectQuery extends SQLObject {}
class SQLSelectQueryBlock implements SQLSelectQuery {
List<SQLSelectItem> selectList;
SQLTableSource from;
SQLExprTableSource into;
SQLExpr where;
SQLSelectGroupByClause groupBy;
SQLOrderBy orderBy;
SQLLimit limit;
}
class SQLUnionQuery implements SQLSelectQuery {
SQLSelectQuery left;
SQLSelectQuery right;
SQLUnionOperator operator; // UNION/UNION_ALL/MINUS/INTERSECT
}
SQLCreateTableStatement
public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLStatement, SQLCreateStatement {
SQLExprTableSource tableSource;
List<SQLTableElement> tableElementList;
Select select;
// 忽略大小写的查找SQLCreateTableStatement中的SQLColumnDefinition
public SQLColumnDefinition findColumn(String columName) {}
// 忽略大小写的查找SQLCreateTableStatement中的column关联的索引
public SQLTableElement findIndex(String columnName) {}
// 是否外键依赖另外一个表
public boolean isReferenced(String tableName) {}
}
产生AST
通过SQLUtils产生List
import com.alibaba.druid.util.JdbcConstants;
String dbType = JdbcConstants.MYSQL;
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, dbType);
通过SQLStatement我们可以解析一些建表语句这里以建表语句为列子
//循环遍历表元素
for(SQLStatement st:statementList){
if(st instanceof MySqlCreateTableStatement )//判断是不是建表语句的元素
{
MySqlCreateTableStatement stb = (MySqlCreateTableStatement)st;//转换类型
for(SQLTableElement te:stb.getTableElementList()){
if(te instanceof SQLColumnDefinition){ //判定是否是列元素
te.getDataType().getName();//读取字段类型
te.getName();//读取字段名
te.getComment();//读取字段描述
}else if(te instanceof MySqlPrimaryKey) //如果是主键通过遍历的方法提取出来。
for (SQLExpr expr : primaryKey.getColumns()) {
if (expr instanceof SQLIdentifierExpr) {
primaryKeyNames.add(((SQLIdentifierExpr) expr).getSimpleName().replace("`", ""));
}
}
}
}
}
通过SQLUtils产生SQLExpr
String dbType = JdbcConstants.MYSQL;
SQLExpr expr = SQLUtils.toSQLExpr("id=3", dbType);
