SQL血缘解析

news2024/9/22 11:31:44

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.coloradmin.cn/o/2078871.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决添加MPJ插件启动报错

在项目中需要用到多数据源的级联查询&#xff0c;所以引入了MPJ插件&#xff0c;MPJ的版本是1.2.4&#xff0c;MP的版本是3.5.3&#xff0c;但却在启动的时候报错&#xff0c;报错如下&#xff1a; 解决办法&#xff1a; 将MP的版本降到3.5.1

【苍穹外卖】Day1 环境搭建 接口文档

1 软件开发整体介绍 1.1 软件开发流程 | 需求分析 | 形成两个文档&#xff1a;需求规格说明书、产品原型 | 设计 | UI 设计、数据库设计、接口设计 | 编码 | 项目代码&#xff0c;单元测试 | 测试 | 测试用例、测试报告 | 运维 | 软件环境安装、配置 1.2 角色分工 1.3 软件…

企业开展TPM管理培训需要什么条件?

在探讨企业如何有效开展TPM管理培训时&#xff0c;我们不得不深入分析几个核心要素&#xff0c;这些要素构成了成功实施TPM管理培训的必要条件。TPM作为一 种追求生产系统效率最大化的现代管理理念&#xff0c;其成功推行不仅依赖于先进的技术手段&#xff0c;更离不开企业内部…

探索最佳数据恢复工具:为您的数据保驾护航

数据已成为我们日常工作和生活中不可或缺的部分,然而&#xff0c;数据丢失的意外却总是让人措手不及——无论是因误操作删除文件&#xff0c;抑或是因病毒攻击或硬件故障而丢失数据&#xff0c;这些情况都可能带来巨大的困扰。所幸&#xff0c;市场上有诸多功能强大的数据恢复工…

FSQ26信号分析仪RS FSU26 20HZ-26.5G频谱分析仪

罗德与施瓦茨Rohde & Schwarz FSQ26信号分析仪&#xff0c;20 Hz - 26.5 GHz ​R&S FSQ26 信号分析仪集两种仪器于一身。它提供高达 120 MHz 解调带宽的信号分析&#xff0c;并具有高端频谱分析仪的动态范围。 频率范围&#xff1a;20 Hz 至 26.5 GHz 高端频谱分析仪…

智慧公厕系统如何应对高峰期游客?

在旅游景区、繁华商圈等场所&#xff0c;高峰期游客的涌入常常给公共设施带来巨大压力&#xff0c;公厕便是其中之一。传统公厕在面对高峰期游客时往往捉襟见肘&#xff0c;出现排队过长、环境脏乱、设施故障等问题。然而&#xff0c;随着科技的不断进步&#xff0c;智慧公厕系…

如何使用ssm实现基于SSM的社区物业管理系统的设计与实现+vue

TOC ssm223基于SSM的社区物业管理系统的设计与实现vue 绪论 1.1 研究背景 现在大家正处于互联网加的时代&#xff0c;这个时代它就是一个信息内容无比丰富&#xff0c;信息处理与管理变得越加高效的网络化的时代&#xff0c;这个时代让大家的生活不仅变得更加地便利化&…

接口测试面试题及参考答案,轻松拿捏面试官

1、你们公司的接口测试流程是&#xff1f; 接口测试我们是在XX项目做的&#xff0c;主要有XX接口&#xff0c;XX接口&#xff0c;XX接口等。 1、首先是从开发那里拿到API接口文档&#xff0c;了解接口业务、包括接口地址、请求方式&#xff0c;入参、出参&#xff0c;token鉴…

【python】数据分析统计

逐行读取’\t’分割的txt 对其中的每个数值都转为六位小数的str 再存入dict 存到excel pip install pandas pip install openpyxl # 用于写入Excel文件import pandas as pd # 假设txt文件的路径是data.txt file_path data.txt # 用于存储数据的字典&#xff0c;假设每…

每天学习一个基础算法之插入排序

目录 前言&#xff1a; 一、插入排序的基本思路与实现方法 1、基本思路 2、实现方法 二、插入排序的执行过程示意图 三、插入排序的实现代码 插入排序代码主体&#xff08;以接口函数的形式&#xff09; 测试部分&#xff08;主函数调用&#xff09; 四、对插入排序复杂度的分析…

Vue中使用el-table自定义序号翻页后又从1开始没有连续

在 ​​el-table​​​ 中&#xff0c;自定义序号列在翻页后会重新从 1 开始是因为每页的数据是重新渲染的&#xff0c;没有保留之前的序号。如果您希望在翻页后保持连续的序号&#xff0c;可以使用 ​​index​​ 属性来获取全局的行索引。 以下是一个示例&#xff0c;演示如…

string题(下)最后一个单词的长度

string类题目&#xff08;下&#xff09; 题目&#xff1a;字符串里面最后一个单词的长度&#xff08;牛客网&#xff09; 然后我们不假思索写出这样的代码&#xff1a; #include <iostream> using namespace std;int main() {string str;cin>>str;size_t pos st…

VS环境中使用QT、OpenCV进行简易图像处理(附源码)

1.背景 在VS2022中&#xff0c;结合QT开发框架&#xff0c;使用OpenCV开源图像处理库&#xff0c;实现在QT界面中完成简易的图像处理&#xff0c;这里展示采用了灰度化处理&#xff0c;其它图像处理操作依据具体场景编写即可。 2.图像格式问题 在QT中&#xff0c;采用的是QI…

详细解读版本控制工具Git+常见命令实操演示

1.版本控制的重要性 版本控制允许开发者查看文件和项目的整个历史记录&#xff0c;包括每次更改的详细记录。在团队项目中&#xff0c;版本控制使得多个开发者可以同时工作在同一个项目上&#xff0c;而不会相互干扰。当引入的错误导致项目出现问题时&#xff0c;版本控制可以…

中吉自动售货机netty对接出货慢问题解决

情景说明&#xff1a; 采购中吉自动售货机&#xff0c;自研对接java代码对接&#xff0c;使用netty方式。&#xff08;注&#xff1a;有需要对接java对接中吉设备代码的可以关注我们的公众号&#xff0c;联系我们。 对接中吉自动售货机&#xff0c;下发 出货指令&#xff0c;要…

代码随想录算法训练营第四十天| 深搜与广搜理论基础以及模板代码

今天是算法学习第四十天&#xff0c;主要的学习内容是深度优先搜索和广度优先搜索&#xff0c;以及对于模板题的讲解。 深度优先搜索&#xff08;DFS) 深搜其实原理就是先往一个方向搜索&#xff0c;直到遇到终止条件再回头。所以深度优先搜索的关键就是递归和回溯。 对于深…

超声波清洗机哪个品牌好用?实用性强的超声波眼镜清洗机推荐

眼镜一类的物品都很难清理&#xff0c;特别容易刮花&#xff0c;此外还有小件的首饰&#xff0c;也很难通过常规的清洁方式去除污渍&#xff0c;这时候就要用到超声波清洗机&#xff0c;这两年这种小工具很流行&#xff0c;而超声波清洗机便是其中的一种热门清洁神器&#xff0…

Kafka命令详解:从零开始,掌握Kafka集群管理、主题操作与监控的全方位技能,理解每一条命令背后的逻辑与最佳实践

本文主要是关于Kafka的命令详解&#xff0c;每个命令都进行了非常详细的注释&#xff0c;帮助大家能更好的理解这些命令背后的含义&#xff0c;从底层去理解&#xff0c;如果大家喜欢&#xff0c;请多多点赞关注&#xff0c;欢迎评论&#xff01; 为大家推荐几篇比较好的Kafka文…

【selenium点选下拉框】解决无法选中对应选项的问题

需求 使用selenium点击下拉框&#xff0c;选中【是】选项。 代码 方法1 # 点击下拉框 driver.find_element(xpath,//*[id"basicProcessDetail"]/div[2]/div[2]/div[1]/div/div[2]/div/div/div/div[1]/div[2]/form/div[11]/div[1]/div/div/div[1]/div[1]/div/i).…

扫描件转word如何操作?分享3个转换技巧,简单高效

在日常工作中&#xff0c;总会遇到扫描件格式的PDF文档&#xff0c;为了方便整理&#xff0c;修改和使用&#xff0c;我们经常需要将扫描件转成可编辑的Word文档&#xff0c;那有哪些方法可以将扫描件转换成Word呢&#xff1f;本期小编就给大家分享3个转换技巧&#xff0c;简单…