文章目錄
- 前言
- 本章節源碼
- 描述
- 認識作者
- 官方文檔
- 快速入門demo案例
- 引入依賴
- 獲取到SQL的AST(抽象語法樹)
- 使用visitor完成表、字段、表達式解析
- 匯總總結
- 一、簡介
- 1.1、和Antlr生成Parser的區別
- 1.2、Druid SQL Parser的使用場景
- 二、各種語法支持
- 三、性能
- 四、Druid SQL Parser的代碼結構
- 4.1、parser
- 4.2、AST
- 4.3、Visitor
- 4.4、自定義Visitor
- 4.5、方言
- 五、SchemaRepository
- 參考文章
- 資料獲取
前言
博主介紹:?目前全網粉絲4W+,csdn博客專家、Java領域優質創作者,博客之星、阿里云平臺優質作者、專注于Java后端技術領域。
涵蓋技術內容:Java后端、大數據、算法、分布式微服務、中間件、前端、運維等。
博主所有博客文件目錄索引:博客目錄索引(持續更新)
CSDN搜索:長路
視頻平臺:b站-Coder長路
本章節源碼
當前文檔配套相關源碼地址:
- gitee:https://gitee.com/changluJava/demo-exer/tree/master/java-sqlparser/demo-druid/demo-druid-simpledemo
- github:https://github.com/changluya/Java-Demos/tree/master/java-sqlparser/demo-druid/demo-druid/demo-druid-simpledemo
描述
Druid 本身并沒有直接內置完善的血緣解析功能,但我們可以結合 Druid 的數據查詢和元數據管理機制,配合一些外部手段實現基本的血緣解析。
認識作者
溫紹錦:初心不改的阿里初代開源人:https://gitee.com/gitee-stars/18
官方文檔
開源地址:https://github.com/alibaba/druid
學習文檔:https://github.com/alibaba/druid/wiki/SQL-Parser
快速入門demo案例
引入依賴
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.0</version>
</dependency>
獲取到SQL的AST(抽象語法樹)
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.parser.SQLParserUtils;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.util.JdbcConstants;public class Main {public static void main(String[] args) {String sql = "select id, name, age from user;";SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcConstants.HIVE);SQLStatement stmt= parser.parseStatementList().get(0);System.out.println(stmt);}
}
使用visitor完成表、字段、表達式解析
public static void main(String[] args) throws Exception{String sql = "select name, age from t_user left join t_user2 on t_user.id = t_user2.id where t_user.id = 1;";List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);SQLStatement stmt = stmtList.get(0);// 構建visitorSchemaStatVisitor statVisitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);stmt.accept(statVisitor);System.out.println(statVisitor.getColumns()); // [t_user.name, t_user.age, t_user.id]System.out.println(statVisitor.getTables()); // {t_user=Select}System.out.println(statVisitor.getConditions()); // [t_user.id = 1]
}
匯總總結
下面內容主要參考Druid的學習wiki:https://github.com/alibaba/druid/wiki/SQL-Parser
一、簡介
SQL Parser是Druid的一個重要組成部分,Druid內置使用SQL Parser來實現防御SQL注入(WallFilter)、合并統計沒有參數化的SQL(StatFilter的mergeSql)、SQL格式化、分庫分表。
1.1、和Antlr生成Parser的區別
和Antlr生成的SQL有很大不同的是,Druid SQL Parser性能非常好,可以用于生產環境直接對SQL進行分析處理。
1.2、Druid SQL Parser的使用場景
- MySql SQL全量統計
- Hive/ODPS SQL執行安全審計
- 分庫分表SQL解析引擎
- 數據庫引擎的SQL Parser
二、各種語法支持
Druid的sql parser是目前支持各種數據語法最完備的SQL Parser。目前對各種數據庫的支持如下:
數據庫 | DML | DDL |
---|---|---|
odps | 完全支持 | 完全支持 |
mysql | 完全支持 | 完全支持 |
postgresql | 完全支持 | 完全支持 |
oracle | 支持大部分 | 支持大部分 |
sql server | 支持常用的 | 支持常用的ddl |
db2 | 支持常用的 | 支持常用的ddl |
hive | 支持常用的 | 支持常用的ddl |
druid還缺省支持sql-92標準的語法,所以也部分支持其他數據庫的sql語法。
三、性能
Druid的SQL Parser是手工編寫,性能非常好,目標就是在生產環境運行時使用的SQL Parser,性能比antlr、javacc之類工具生成的Parser快10倍甚至100倍以上。
SELECT ID, NAME, AGE FROM USER WHERE ID = ?
這樣的SQL,druid parser處理大約是600納秒,也就是說單線程每秒可以處理1500萬次以上。在1.1.3~1.1.4版本中,SQL Parser的性能有極大提升,完全可以適用于生產環境中對SQL進行處理。
四、Druid SQL Parser的代碼結構
Druid SQL Parser分三個模塊:
- Parser
- AST
- Visitor
4.1、parser
parser是將輸入文本轉換為ast(抽象語法樹),parser有包括兩個部分,Parser和Lexer,其中Lexer實現詞法分析,Parser實現語法分析。
4.2、AST
AST是Abstract Syntax Tree的縮寫,也就是抽象語法樹。AST是parser輸出的結果。下面是獲得抽象語法樹的一個例子:
final String dbType = JdbcConstants.MYSQL; // 可以是ORACLE、POSTGRESQL、SQLSERVER、ODPS等
String sql = "select * from t";
List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);
- Druid SQL AST介紹 https://github.com/alibaba/druid/wiki/Druid_SQL_AST
4.3、Visitor
Visitor是遍歷AST的手段,是處理AST最方便的模式,Visitor是一個接口,有缺省什么都沒做的實現VistorAdapter。
我們可以實現不同的Visitor來滿足不同的需求,Druid內置提供了如下Visitor:
- OutputVisitor用來把AST輸出為字符串
- WallVisitor 來分析SQL語意來防御SQL注入攻擊
- ParameterizedOutputVisitor用來合并未參數化的SQL進行統計
- EvalVisitor 用來對SQL表達式求值
- ExportParameterVisitor用來提取SQL中的變量參數
- SchemaStatVisitor 用來統計SQL中使用的表、字段、過濾條件、排序表達式、分組表達式
- SQL格式化 Druid內置了基于語義的SQL格式化功能【字符串拼接模式完成sql格式化處理】
4.4、自定義Visitor
每種方言的Visitor都有一個缺省的VisitorAdapter,使得編寫自定義的Visitor更方便。 https://github.com/alibaba/druid/wiki/SQL_Parser_Demo_visitor
4.5、方言
SQL-92、SQL-99等都是標準SQL,mysql/oracle/pg/sqlserver/odps等都是方言,也就是dialect。parser/ast/visitor都需要針對不同的方言進行特別處理。
五、SchemaRepository
Druid SQL Parser內置了一個SchemaRepository,在內存中緩存SQL Schema信息,用于SQL語義解析中的ColumnResolve等操作。 https://github.com/alibaba/druid/wiki/SQL_Schema_Repository
可以基于Druid SQL Parser之上構造Oracle SQL到其他數據的SQL翻譯。比如Aliyun提供的Oracle到MySql的SQL翻譯功能,就是基于Druid基礎上實現的。https://rainbow-expert.aliyun.com/sqltransform.htm
參考文章
[1]. Druid SQL解析原理以及使用(一):https://blog.csdn.net/qq_25104587/article/details/90577646
[2]. 使用Druid的sql parser做一個表數據血緣分析工具:https://www.cnblogs.com/enhe/p/12141686.html
資料獲取
大家點贊、收藏、關注、評論啦~
精彩專欄推薦訂閱:在下方專欄👇🏻
- 長路-文章目錄匯總(算法、后端Java、前端、運維技術導航):博主所有博客導航索引匯總
- 開源項目Studio-Vue—校園工作室管理系統(含前后臺,SpringBoot+Vue):博主個人獨立項目,包含詳細部署上線視頻,已開源
- 學習與生活-專欄:可以了解博主的學習歷程
- 算法專欄:算法收錄
更多博客與資料可查看👇🏻獲取聯系方式👇🏻,🍅文末獲取開發資源及更多資源博客獲取🍅