DruidSQL解析原理以及使⽤(⼀)
本篇⽂章主要以使⽤为主,⽐如通过解析分析⼀条SQL的组成来完成SQL改写等,现在流⾏的数据中间件中使⽤很⼴泛,Mycat、Dble等。
Druid的SQL解析器主要有三部分组成,如下:
1、Parser
a、词法分析
b、语法分析
2、AST(Abstract Syntax Tree,抽象语法树)
3、Visitor
1、什么是AST
在计算机科学中,抽象语法树(AbstractSyntaxTree,AST),或简称语法树(Syntax tree),是源代码语法结构的⼀种抽象表
⽰,Druid 解析SQL也⼀样,会遵循⼀定的规则将SQL分析并构建成语法树AST。
Parser主要的作⽤是⽣成AST,Parser主要有两部分组成:词法分析、语法分析
Druid收到⼀条SQL后,⽐如select a, b , from userTable where user_id =10 需要解析出没⼀个单词,并记录单词位置等,词法解析阶段,并不需要理解这条SQL的含义,专业术语 Lexer
词法分析完成后就是语法分析,作⽤就是要明确SQL的含义,⽐如"name"这个单词,我们可能知道这个单词知道是由字母n、a、m、e组成,如果不知道含义,那就没实际意义,但是要知道是什么意思,就是语法分析要做的事了,语法分析的结果就是要明确这个单词的含义。
AST 仅仅是语义的表⽰,但如何对这个语义进⾏表达,便需要去访问这棵 AST,看它到底表达什么含义。通常遍历语法树,使⽤VISITOR 模式去遍历,从根节点开始遍历,⼀直到最后⼀个叶⼦节点,在遍历的过程中,便不断地收集信息到⼀个上下⽂中,整个遍历过程完成后,对这棵树所表达的语法含义,已经被保存到上下⽂了。有时候⼀次遍历还不够,需要⼆次遍历。遍历的⽅式,⼴度优先的遍历⽅式是最常见的,或者是不⽤visitor,我们⾃⼰知道AST结构后⾃⼰⼿动遍历AST结构也是没有问题的,就是很繁琐,我觉得⼿动遍历和使⽤的visitor的区别就类似你⽤JQuery和JavaScript实现同⼀个功能的区别⼀个,有时实现⼀个功能使⽤Visitor可能就是⼗⼏⾏代码,⾃⼰遍历Statement可能要上百⾏代码,个⼈理解。
通过Parser⽣成完整的AST抽象语法树。
information的中文
2、Druid SQL中AST节点类型
常⽤的AST节点主要有三种类型:SQLObject、SQLExpr、SQLStatement,其中最常使⽤的就莫过于SQLStatement ,其⼦类常见的有DruidSelectStatement、DruidInsertStatement、DruidUpdateStatement等
public interface SQLStatement extends SQLObject {}
public interface SQLObject {}
public interface SQLExpr extends SQLObject, Cloneable {}
2.1、常见的SQLExpr
官⽹中给出的⽰例
package com.alibaba.druid.pr;
// SQLName是⼀种的SQLExpr的Expr,包括SQLIdentifierExpr、SQLPropertyExpr等
public interface SQLName extends SQLExpr {}
// 例如 ID = 3 这⾥的ID是⼀个SQLIdentifierExpr
小舍得电视剧在线观看完整版
class SQLIdentifierExpr implements SQLExpr, SQLName {
String name;
}
// 例如 A.ID = 3 这⾥的A.ID是⼀个SQLPropertyExpr
class 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是⼀个SQLIntegerExpr
三大java培训机构public class SQLIntegerExpr extends SQLNumericLiteralExpr implements SQLValuableExpr {    Number number;
// 所有实现了SQLValuableExpr接⼝的SQLExpr都可以直接调⽤这个⽅法求值
@Override
public Object getValue() {
return this.number;
}
}
// 例如 NAME = 'jobs' 这⾥的'jobs'是⼀个SQLCharExpr
public class SQLCharExpr extends SQLTextLiteralExpr implements SQLValuableExpr{
String text;
}
2.2、常见的SQLStatement
最常⽤的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
常见的SQLTableSource包括SQLExprTableSource、SQLJoinTableSource、SQLSubqueryTableSource、SQLWithSubqueryClause.Entry
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 _id = o.id
// 其中left 'emp e' 是⼀个SQLExprTableSource,right 'org o'也是⼀个SQLExprTableSourcemysqlschema作用
// 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 aclass在python中是什么意思
WHERE f.id = a.parent_id
)
SELECT *
FROM ancestors;
这⾥的ancestors AS (...) 是⼀个SQLWithSubqueryClause.Entry
*/
class SQLWithSubqueryClause {
static class Entry extends SQLTableSourceImpl {
SQLSelect subQuery;
}
}
2.4、SQLSelect & SQLSelectQuery
SQLSelectStatement包含⼀个SQLSelect,SQLSelect包含⼀个SQLSelectQuery,都是组成的关系。SQLSelectQuery有主要的两个派⽣类,分别是SQLSelectQueryBlock和SQLUnionQuery。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。