Skip to content

Druid_SQL_AST

高铁 edited this page Oct 3, 2017 · 26 revisions

1. 什么是AST

AST是abstract syntax tree的缩写,也就是抽象语法树。和所有的Parser一样,Druid Parser会生成一个抽象语法树。

2. 在Druid SQL Parser中有哪些AST节点类型

在Druid中,AST节点类型主要包括SQLObject、SQLExpr、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 {}

2.1. 常用的SQLExpr有哪些

package com.alibaba.druid.sql.ast.expr;

// 比如 ID = 3 这里的ID是一个SQLIdentifierExpr
class SQLIdentifierExpr implements SQLExpr {
    String name;
} 

// A.ID = 3 这里的A.ID是一个SQLPropertyExpr
class SQLPropertyExpr implements SQLExpr {
    SQLExpr owner;
    String name;
} 

// 比如 ID = 3 这是一个SQLBinaryOpExpr
// left是ID (SQLIdentifierExpr)
// right是3 (SQLIntegerExpr)
class SQLBinaryOpExpr implements SQLExpr {
    SQLExpr left;
    SQLExpr right;
    SQLBinaryOperator operator;
}

2.2. 常用的SQLStatemment

最常用的Statement当然是SELECT/UPDATE/DELETE/INSERT,他们分别是

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;
}

2.3. SQLTableSource

class SQLTableSourceImpl extends SQLObjectImpl implements SQLTableSource { 
    String alias;
}

// 例如 select * from emp where i = 3,这里的from emp是一个SQLExprTableSource
// 其中expr是一个name=emp的SQLIdentifierExpr
class 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'是一个SQLBinaryOpExpr
class 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(...)是一个SQLSubqueryTableSource
SQLSubqueryTableSource extends SQLTableSourceImpl {
    SQLSelect select;
}

/* 
例如
WITH RECURSIVE ancestors AS (
    SELECT *
    FROM org
    UNION
    SELECT f.*
    FROM org f, ancestors a
    WHERE f.id = a.parent_id
)
SELECT *
FROM ancestors;

这里的ancestors AS (...) 是一个SQLWithSubqueryClause.Entry
*/
class SQLWithSubqueryClause {
    static class Entry extends SQLTableSourceImpl { 
         SQLSelect subQuery;
    }
}

3. 怎样产生AST

3.1 通过SQLUtils产生List<SQLStatement>

import com.alibaba.druid.util.JdbcConstants;

String dbType = JdbcConstants.MYSQL;
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, dbType);

3.2 通过SQLUtils产生SQLExpr

String dbType = JdbcConstants.MYSQL;
SQLExpr expr = SQLUtils.toSQLExpr("id=3", dbType);
Clone this wiki locally