当前位置: 首页 > news >正文

SQL血缘解析

Druid 作为使用率特别高的的数据库连接池工具,在具备完善的连接池管理功能外,同时Druid 的 SQL解析功能可以用来防止 SQL注入等安全风险。通过对 SQL 语句进行解析和检查,Druid 可以识别并阻止潜在的恶意 SQL 语句执行,黑名单(阻止特定的 SQL 语句执行)、白名单(仅允许特定的 SQL 语句执行)等功能,从而提升数据库的安全性。

可以利用 Druid 的 SQL 解析结果,进行进一步的二次解析和组合,从而形成脚本的血缘关系和影响关系
在这里插入图片描述

测试访问地址:http://43.139.19.48:8888/#/
Gitee:https://gitee.com/javalxy/sql-lineage-show

前置知识

AST抽象语法树

官方文档链接:Druid_SQL_AST · alibaba/druid Wiki · GitHub

抽象语法树(AST, Abstract Syntax Tree) 是编程语言解析和编译过程中产生的一种树状数据结构,它表示源代码的语法结构。AST 抽象出代码的语法特征,同时剔除不必要的语法细节,提供了程序结构的抽象表示。

SQLTableSource

常见的SQLTableSource包括SQLExprTableSource、SQLJoinTableSource、SQLSubqueryTableSource、SQLUnionQuery

主要为表的关联类型,针对与不同的SQL,分支处理。

if (tableSource instanceof SQLExprTableSource) {SQLExpr sqlExpr = ((SQLExprTableSource) tableSource).getExpr();processTableExpression(tableName, sqlExpr);
} else if (tableSource instanceof SQLSubqueryTableSource) {List<SQLSelectItem> selectList = queryBlock.getSelectList();selectList.forEach(item -> processTableExpression(tableName, item.getExpr()));
} else if (tableSource instanceof SQLUnionQuery) {SQLUnionQuery sqlUnionQuery = (SQLUnionQuery) tableSource;List<SQLSelectQuery> relations = sqlUnionQuery.getRelations();for (SQLSelectQuery relation : relations) {if (relation instanceof SQLSelectQueryBlock) {SQLTableSource nestedTableSource = ((SQLSelectQueryBlock) relation).getFrom();if (nestedTableSource instanceof SQLExprTableSource) {SQLExpr sqlExpr = ((SQLExprTableSource) nestedTableSource).getExpr();processTableExpression(tableName, sqlExpr);}}}
}

SQLSelect & SQLSelectQuery

SQLSelectStatement包含一个SQLSelect,SQLSelect包含一个SQLSelectQuery,都是组成的关系。SQLSelectQuery有主要的两个派生类,分别是SQLSelectQueryBlockSQLUnionQuery

此对象是一个查询主体,其主要的关联关系就是查询的关系。这种关系由查询字段衍生出来,涵盖了查询字段、关系字段、函数、组成等(也就是可解析的字段类型,后文会详细说明,即:SQLExpr)。除此之外,还有表关系(如上文提到的 SQLTableSource)、分组关系等。这些关系共同构成了 SQL 语句的结构和逻辑。此对象也可看做是解析的中流砥柱,很多向下的衍生关系也都通过此封装。

if (sqlSelectQuery instanceof SQLSelectQueryBlock) {disposeSelectQuery((SQLSelectQueryBlock) sqlSelectQuery, sqlItems, fieldModels);
} else if (sqlSelectQuery instanceof SQLUnionQuery) {disposeSQLUnionQuery((SQLUnionQuery) sqlSelectQuery, sqlItems, fieldModels);
}

SQLExpr

解析代码中大约 80% 的内容可能都围绕着 SQLExpr 进行。在所有的 SQLExpr 子对象中,通常存在多层次的继承关系。因此,无论表达式多么复杂,都可以通过递归层层向下,找到基本类型进行处理。这种处理方式相当繁琐,因为需要针对每种类型进行细致的拆解和处理。对于几种基本类型,可以直接进行处理;但对于聚合函数或二元操作这样的复杂类型,则需要逐层拆解,获取其下层类型后再判断并处理,如此反复,直至解析到基本类型为止,形成一个完整的闭环。

目前已处理类型如下:

SQLAggregateExpr、SQLBinaryOpExpr、SQLPropertyExpr、SQLMethodInvokeExpr、SQLAllColumnExpr、SQLIdentifierExpr、SQLCaseExpr、SQLInListExpr、SQLCastExpr、SQLBetweenExpr、SQLQueryExpr、SQLCharExpr、SQLNullExpr、SQLIntegerExpr、SQLNumberExpr

其中也存在无法处理的情况,如常量类型,All类型(*),需要其他逻辑支持。

if (sqlExpr instanceof SQLAggregateExpr) {// 处理聚合函数表达式dispose((SQLAggregateExpr) sqlExpr, itemFieldModels);
} else if (sqlExpr instanceof SQLBinaryOpExpr) {// 处理二元操作表达式dispose((SQLBinaryOpExpr) sqlExpr, itemFieldModels);
} else if (sqlExpr instanceof SQLPropertyExpr) {// 处理属性表达式dispose((SQLPropertyExpr) sqlExpr, itemFieldModels);
} else if (sqlExpr instanceof SQLMethodInvokeExpr) {// 处理方法调用表达式dispose((SQLMethodInvokeExpr) sqlExpr, itemFieldModels);
} else if (sqlExpr instanceof SQLAllColumnExpr) {// 处理所有列(*)表达式dispose((SQLAllColumnExpr) sqlExpr, itemFieldModels);
} else if (sqlExpr instanceof SQLIdentifierExpr) {// 处理标识符表达式dispose((SQLIdentifierExpr) sqlExpr, itemFieldModels);
}
// 略...

示例

此示例和druid解析无关系。

SELECT name, age FROM users WHERE age > 18;

对应的 AST

这个 SQL 查询的 AST(抽象语法树)可以表示如下:

SelectStatement├── SelectClause│   ├── Column (name)│   └── Column (age)├── FromClause│   └── Table (users)└── WhereClause└── BinaryExpression (>)├── Column (age)└── Literal (18)

一条正确的 SQL 语句可以通过抽象语法树(AST)进行概括(通常使用 ANTLR 作为底层支持,排除 g4 模板解析失败的情况)。对于较复杂的语句,如关联查询、子查询和函数处理等,这些语句基本上是层层嵌套的。理论上,通过支持各种类型的解析后,可以使用递归方式遍历整个抽象语法树,从而完整地获取字段结构并进行二次处理。

二次处理Druid AST抽象语法树

使用Druid解析SQL

List<SQLStatement> stmts = SQLUtils.parseStatements(sqlText, enumDbType.getDbType());
for (SQLStatement stmt : stmts) {SchemaStatVisitor statVisitor = SQLUtils.createSchemaStatVisitor(enumDbType.getDbType());stmt.accept(statVisitor);
}

处理结果如下图所示,将 SQL 进行了细粒度的拆分以可视化结构展示出来,包括来源表、表的状态(如:SELECTUPDATEDELETE 等)、处理字段、条件等。
在这里插入图片描述

表影响关系处理

当前解析工具针对于表关系处理了 HAVINGGROUPWHEREJOIN及查询 这五种,后续按需再更新。

// 处理 HAVING 条件
disposeConditions(statVisitor, tableModels

http://www.mrgr.cn/news/12480.html

相关文章:

  • 美国洛杉矶服务器地址在哪里?
  • 成功解决:删除WSL2 Ubuntu中的文件后C磁盘空间不释放的问题
  • 畅玩游戏:2024四大远程控制软件推荐!
  • 大模型实战-FinGLM解析金融财报做RAG经验参考篇
  • 深度学习100问10-什么是CBOW模型
  • CAS5和CAS6自定义异常提示消息
  • Mysql的查询指令
  • WiFi标签注册(电脑版)
  • 【人工智能】Transformers之Pipeline(十三):填充蒙版(fill-mask)
  • mac在终端中使用vscode打开文件或者文件夹
  • AI 大模型时代,对前端工程师有哪些机遇和挑战?
  • C++系列-const所有用法总结
  • 如何汽车保养?
  • 短视频SDK解决方案,原开发团队,一对一技术支持
  • 【案例63】SSL RC4 加密套件支持检测 (Bar Mitzvah)修复方案
  • 支持IPD的项目管理软件都有哪些?奥博思 PowerProject 项目管理系统助力正浩创新 IPD 变革高效落地
  • 快速幂算法【算法 08】
  • redis作为缓存,mysql的数据如何与redis同步
  • 编程学习之路上的挫折:如何在Bug迷宫中找到出口
  • Oracle发邮件时SMTP服务器配置方法与步骤?