轻松操纵SQL:Druid解析器实践

一、背景

在BI(Business Intelligence)场景中,用户会频繁使用SQL查询语句,但在平台运作过程中,面临着权限管理、多数据源处理和表校验等多种挑战。

例如,用户可能不清楚自身是否具备对特定表(如下图DBA.STUDENT)的访问权限。因为平台不会限制用户编写自定义SQL的能力,故需要后端开发团队可以利用技术手段来解析SQL,提取其中的表名并作出相应处理。

尤其对于涉及多表连接、子查询以及使用别名等复杂SQL语句,准确提取表名变得至关重要。这时,利用SQL语法树解析就成为必不可少的关键环节。

幸运的是,我们常用的数据库连接池——Druid,提供了便捷的接口,使得解析SQL语句变得更加轻松。本文将探讨Druid在SQL语句解析中的关键作用及应用。

在这里插入图片描述

二、Druid

Druid是一种用于Java应用程序的高性能数据库连接池。它是阿里巴巴开源的项目之一,旨在提供高效的数据库连接池管理和监控功能。Druid为应用程序提供了对数据库连接的管理,可以对连接的状态、使用情况进行跟踪和监控,并且可以有效地管理连接的生命周期。

除了作为连接池外,Druid还提供了诸如SQL语句解析、性能监控、SQL防火墙、数据加密、统计分析等功能。它是一个全面的数据库中间件解决方案,为开发者提供了一系列丰富的工具和功能,以提高应用程序与数据库的交互效率和可靠性。

总之,Druid是一种功能强大的Java数据库连接池,为开发者提供了高性能、高可靠性、丰富的监控和管理功能,用于优化应用程序与数据库之间的交互。

三、简单示例

  • 千言万语不如简单示例,让我们先通过一个简单的例子来演示Druid SQL Parser的使用

3.1、Maven

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.0</version>
</dependency>

3.2、解析表名

  • 代码:使用 getTables() 函数可获取所有表的声明类,并输出各表的名称以及相应的 SQL 操作类型。
import java.util.*;

import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.stat.TableStat.Name;
import com.alibaba.druid.stat.TableStat.Column;

import org.junit.Test;


public class MysqlParserExample {

    private final DbType dbType = DbType.mysql;

    @Test
    public void parserTables() {
        // 复杂嵌套sql
        String sql = "SELECT ID,NAME,AGE FROM DBA.STUDENT JOIN (\n" +
                "SELECT ID FROM (\n" +
                "SELECT A.ID,B.ID AS BI FROM DBA.A JOIN DBA.B ON A.ID=B.ID)) AS C ON STUDENT.ID=C.ID";
        SQLStatementParser parser = new MySqlStatementParser(sql);
        SQLStatement sqlStatement = parser.parseStatement();
        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);
        sqlStatement.accept(visitor);
        Map<Name, TableStat> tables = visitor.getTables();
        for (Map.Entry<TableStat.Name, TableStat> tableStatEntry : tables.entrySet()) {
            System.out.println("表名:" + tableStatEntry.getKey().getName());
            System.out.println("操作名:" + tableStatEntry.getValue());
        }
    }

}
  • 打印:表名及操作名
表名:DBA.STUDENT
操作名:Select
表名:DBA.A
操作名:Select
表名:DBA.B
操作名:Select

3.2、解析字段

  • 代码:使用 getColumns() 函数能够获取 SQL 中涉及的所有字段信息,并能输出字段的名称、类型以及相关的表名。
private final DbType dbType = DbType.mysql;

@Test
public void parserColumns() {
    String sql = "CREATE TABLE users (\n" +
            "    user_id INT AUTO_INCREMENT PRIMARY KEY,\n" +
            "    username VARCHAR(50) NOT NULL,\n" +
            "    email VARCHAR(100) NOT NULL,\n" +
            "    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n" +
            ");\n";
    SQLStatementParser parser = new MySqlStatementParser(sql);
    SQLStatement sqlStatement = parser.parseStatement();
    SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);
    sqlStatement.accept(visitor);
    Collection<Column> columns = visitor.getColumns();
    for (Column column : columns) {
        System.out.println("字段:" + column.getName());
        System.out.println("字段类型:" + column.getDataType());
        System.out.println("表名:" + column.getTable());
    }
}
  • 打印:
字段:user_id
字段类型:INT
表名:users
字段:username
字段类型:VARCHAR
表名:users
字段:email
字段类型:VARCHAR
表名:users
字段:created_at
字段类型:TIMESTAMP
表名:users

四、核心模块

4.1、介绍

Druid提供了三个关键类,它们在处理和分析SQL语句中起着关键作用:

  1. SQLParser:这个类是解析SQL语句的入口点。它接收原始的SQL字符串并将其转换为一个抽象语法树(AST),为后续处理和分析做好准备。
  2. SQLStatement:代表着SQL语句的抽象语法树。SQLStatementParser解析SQL语句后生成的结果就是这个抽象语法树。它提供了对SQL语句结构的抽象化描述。
  3. SQLASTVisitor:这个类用于访问和遍历SQL语句的抽象语法树。通过使用SQLASTVisitor,您可以从SQL语句中提取出涉及的表、字段等信息。

4.2、SQLParser

SQLParser是用于将输入文本转换为AST(抽象语法树)的工具。它主要包含两个部分:Parser和Lexer。Lexer负责词法分析,而Parser则负责语法分析。Lexer用于将输入文本分解为词法单元(tokens),如下图:

在这里插入图片描述

SQLStatementParser是用于语法解析的关键类,在上面示例中已经使用过。这个类拥有许多子类,根据不同的下游数据库类型,需要选择相应的实现类进行使用,如下:

在这里插入图片描述

如果我们要解析hiveSql,就需要创建对应的HiveStatementParser

4.2、SQLStatement

SQLStatement 类的实例可以根据 SQL 语句的类型,如 SELECT、INSERT、UPDATE、DELETE 等,来保存对应的语法树节点。这意味着在 Druid 中,SQLStatement 的子类对象会根据 SQL 语句的不同类型分别表示不同的操作,每个子类都对应着该 SQL 类型的语法结构。

例如,如果解析的是一个 SELECT 语句,那么 SQLStatement 的实例将是 SQLSelectStatement 类的对象,它会保存与 SELECT 语句相关的语法树节点,如查询的列、表名、条件等信息。

对于 INSERT、UPDATE、DELETE 等不同类型的 SQL,Druid 会根据语句类型解析出对应的 SQLStatement 子类对象,从而以统一的数据结构表示各种 SQL 语句的语法树,如下图:

在这里插入图片描述

  • 可以看出SQLStatement类提供的接口函数有限,故在实际开发中往往会根据sql类型自行强转后操作,例如:
@Test
public void parserSelect() {
    String sql = "SELECT ID,NAME,AGE FROM DBA.STUDENT WHERE ID >= 10 GROUP BY NAME HAVING AGE >= 18 LIMIT 10;";
    SQLStatementParser parser = new MySqlStatementParser(sql);
    SQLSelectStatement sqlStatement = (SQLSelectStatement) parser.parseStatement();
    SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);
    sqlStatement.accept(visitor);
    SQLSelectQuery query = sqlStatement.getSelect().getQuery();
    System.out.println(query);
}
  • 在该示例中,使用 SQLSelectStatement 可以获取 SQLSelectQuery。这个类将 SQL 中的所有操作转换为变量的形式,为开发人员提供了对 SQL 语句中的各个部分进行访问和处理的能力。这种变量形式的表示方式更易于程序分析和处理 SQL 查询,如下:

在这里插入图片描述

4.3、SQLASTVisitor

在 Druid 中,SQLASTVisitor 接口有多个子类用于不同的 SQL 语句处理和访问需求。这些子类提供了针对不同类型 SQL 语句的访问和解析功能,使得开发人员能够根据具体的 SQL 语法结构进行定制化处理。

以下是 SQLASTVisitor 接口的一些常见子类:

  1. SchemaStatVisitor:用于解析 SQL,提取其中的表名、列名和条件等信息,同时还可以统计 SQL 语句中的访问次数、计算结果等。
  2. ExportParameterVisitor:用于导出 SQL 参数。
  3. WallVisitor:用于对 SQL 进行安全性检查,防止 SQL 注入等安全问题。
  4. ExportTableAliasVisitor:用于导出 SQL 表别名。
  5. SQLASTOutputVisitor:用于将 SQL 语句输出为字符串。

  • 在上面的示例中,我们使用了 SQLUtils.createSchemaStatVisitor(dbType) 工具类来创建一个特定数据库类型的 SchemaStatVisitor 实例。这种方式允许我们根据特定的数据库类型动态获取对应的实现类,以便进行 SQL 语句的解析和访问,如下:
    SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);

在这里插入图片描述

五、结语

在 Drudi 中,SQL 解析是一个强大且重要的功能,它提供了多种工具和类来解析 SQL 语句、访问语法树以及获取详细的 SQL 操作信息。通过了解 Druid SQL 解析的核心类,如 SQLStatementParserSQLStatementSchemaStatVisitor 等,我们能够更高效地处理 SQL 相关的任务。

SQL 解析在开发过程中扮演着至关重要的角色。它使得开发人员能够在处理各种类型的 SQL 语句时更加灵活、高效,帮助开发者更好地理解和操作 SQL 语句,提高代码的可读性和可维护性。

尽管 Druid 提供了强大的 SQL 解析功能,但在实际应用中,需要结合具体的业务场景和需求来灵活使用。学习和掌握 Druid SQL 解析功能对于开发者来说是非常有价值的,它可以提高工作效率,帮助更好地应对各种复杂的 SQL 语句处理需求。

持续深入学习和了解 Druid SQL 解析的特性和用法,结合实际项目经验,将会使您在 SQL 处理方面更加熟练,为开发工作带来更多的便利和效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/228938.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

极简模式,助力宏观数据监控

随着UWA GOT Online采样的参数越来越多样化&#xff0c;为了提升开发者的使用体验&#xff0c;我们最新推出了三种预设数据采集方案&#xff1a;极简模式、CPU模式、内存模式。该更新旨在降低多数据采集对数据准确性的干扰&#xff0c;同时也为大家提供更精准且有针对性的数据指…

15.Eclipse常用基本配置设置

在使用Eclipse进行Java开发之前&#xff0c;经常需要进行一些配置&#xff0c;其中有些配置甚至是必须的&#xff0c;即使开始不编辑之后开发过程中也会出一些因配置导致的小问题。本文梳理了一下Eclipse使用中常用的配置 1 编码配置 1.1 设置工作空间编码格式 打开Eclipse&…

甘草书店:#10 2023年11月24日 星期五 「麦田创业分享2—世界奇奇怪怪,请保持可可爱爱」

今日继续分享麦田创业经验。 如果你问我&#xff0c;创业过程中是否想过放弃。那么答案是&#xff0c;有那么一次。 那时想要放弃的原因并不是辛苦没有回报&#xff0c;或是资金短缺&#xff0c;而是没能理解“异见者”。 其实事情非常简单&#xff0c;现在反观那时的自己&a…

在360极速模式下解决使用sortable拖拽元素会启用360文字拖拽功能问题

拖拽元素禁止时&#xff0c;加提示语句 会弹出搜索页签, 因为360自带选中文字&#xff0c;启用搜索引擎的功能,如图所示 苦恼了两天 问了大佬&#xff0c;实际是使用了自带还原生的H5拖拽功能&#xff0c;而sortable.js组件有一个属性forceFallback , 将该属性设置为true 就…

pwn入门:基本栈溢出之ret2libc详解(以32位+64位程序为例)

目录 写在开头 题目简介 解题思路 前置知识&#xff08;简要了解&#xff09; plt表和got表 延迟绑定 例题详解 32位 64位 总结与思考 写在开头 这篇博客早就想写了&#xff0c;但由于近期事情较多&#xff0c;一直懒得动笔。近期被领导派去临时给合作单位当讲师&a…

Private Set Intersection from Pseudorandom CorrelationGenerators 最快PSI!导览解读

目录 一、概述 二、相关介绍 三、性能对比 四、技术细节 1.KKRT 2.Pseudorandom Correlation Generators 3.A New sVOLE-Based BaRK-OPRF 4.BaRK-OPRF 五、总结 参考文献 一、概述 这篇文章的主要脉络和核心思想是探讨如何利用伪随机相关生成器&#xff08;PCG&#…

在Asp.Net Core中启用Http响应压缩

无论是开发网站&#xff0c;还是开发Api。很多时候为了节约网络流量我们需要对请求金星压缩处理以减少消息传递过程中的资源消耗&#xff0c;并且多数情况有利于应用发挥更好的性能&#xff08;响应压缩在服务端处理&#xff0c;使用服务器资源&#xff09;。 在Asp.Net Core中…

EasyExcel-最简单的读写excel工具类

前言&#xff1a; easyExcel 的官网文档给的示例非常全&#xff0c;可以参考https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read 在此我贴出自己的工具类&#xff0c;可以直接用 导包 <dependency><groupId>com.alibaba</groupId><…

问题:batchnormal训练单个batch_size就会报错吗

Batch Normalization&#xff08;批标准化&#xff09;是一种深度学习中的正则化技巧&#xff0c;它可以改进网络的训练过程。在训练神经网络时&#xff0c;Batch Normalization可以帮助解决内部协变量偏移&#xff08;Internal Covariate Shift&#xff09;的问题。 在标准的…

PyTorch2.0环境搭建

一、安装python并配置环境变量 1、打开python官网&#xff0c;下载并安装 Welcome to Python.org 下载 寻找版本&#xff1a;推荐使用3.9版本&#xff0c;或其他表中显示为安全&#xff08;security&#xff09;的版本 安装&#xff1a;&#xff08;略&#xff09; 2、配置环…

apisix下自定义 Nginx 配置

apisix下自定义 Nginx 配置 在apisix配置文件/conf/config.yaml中添加nginx配置。生成的nginx.conf配置文件如下&#xff1a;说明&#xff1a; APISIX 会通过 apisix/cli/ngx_tpl.lua 这个模板和 conf/config-default.yaml 加 conf/config.yaml 的配置生成 Nginx 配置文件。 在…

爱智EdgerOS之深入解析如何在EdgerOS中使用SQLite3数据库引擎

一、SQLite 简介 数据管理是应用开发者最常遇到的挑战之一&#xff0c;无论是支付宝的余额&#xff0c;或是京东购物车里的商品&#xff0c;都需要存储在对应服务后端的数据库中&#xff0c;以满足用户查询、转账、购买等各种各样的使用场景。EdgerOS 智能边缘计算操作系统内置…

【模型量化】神经网络量化基础及代码学习总结

1 量化的介绍 量化是减少神经网络计算时间和能耗的最有效的方法之一。在神经网络量化中&#xff0c;权重和激活张量存储在比训练时通常使用的16-bit或32-bit更低的比特精度。当从32-bit降低到8-bit&#xff0c;存储张量的内存开销减少了4倍&#xff0c;矩阵乘法的计算成本则二…

【展望2024】,从软件测试用例开始学习起

1. 测试用例的概念 测试用例就是测试人员向被测试系统发起的一组集合&#xff0c;该集合包括测试环境&#xff0c;测试数据&#xff0c;测试步骤&#xff0c;预期结果 2. 设计测试用例的好处 在测试前都要先设计测试用例&#xff0c;设计测试用例有如下好处&#xff1a; 测…

从 0 到 100TB,MatrixOne 助您轻松应对

作者&#xff1a;邓楠MO产品总监 导读 随着传感器和网络技术的大规模应用&#xff0c;海量 IoT 设备产生了巨量数据&#xff0c;传统数据库方案难以满足这些数据的存储和处理需求。MatrixOne 是一款强大的云原生超融合数据库&#xff0c;具备优秀的流式数据写入和加工能力&am…

CLiB中文大模型能力评测榜单

1 引言 目前已囊括48个大模型&#xff0c;覆盖chatgpt、gpt4、谷歌bard、百度文心一言、阿里通义千问、讯飞星火、360智脑、商汤senseChat、微软new-bing、minimax、tigerbot等商用模型&#xff0c; 以及百川、belle、chatglm6b、ziya、guanaco、Phoenix、linly、MOSS、AquilaC…

【开发问题】vue的前端和java的后台,用sm4,实现前台加密,后台解密

sm4加密 vue引入的包代码加密解密 javamaven代码运行结果 vue 引入的包 npm install sm-crypto代码加密解密 加密&#xff1a; key &#xff1a;代表着密钥&#xff0c;必须是16 字节的十六进制密钥 password &#xff1a;加密前的密码 sm4Password &#xff1a;代表sm4加密…

【EMNLP 2023】基于知识迁移的跨语言机器阅读理解算法

近日&#xff0c;阿里云人工智能平台PAI与华南理工大学朱金辉教授团队、达摩院自然语言处理团队合作在自然语言处理顶级会议EMNLP2023上发表基于机器翻译增加的跨语言机器阅读理解算法X-STA。通过利用一个注意力机制的教师来将源语言的答案转移到目标语言的答案输出空间&#x…

外包实在是太坑了,划水三年,感觉人都废了

先说一下自己的情况&#xff0c;专科生&#xff0c;19年通过校招进入杭州某个外包软件公司&#xff0c;干了接近3年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了3年的功…