Cobar源码分析之AST

本文涉及的产品
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
简介: Cobar是阿里开源的数据库中间件,关于它的介绍这里不再赘述,可以参考之前的文章《Cobar SQL审计的设计与实现》Cobar中利用AST可以获取table名、列名、比较的值进行分库分表,这也是Cobar最重要的功能线上写了一条没有where条件的update或delete,这时可以利用AST进行表达式计算,对没有where条件和where条件恒为true的SQL进行拦截。

背景


Cobar


Cobar是阿里开源的数据库中间件,关于它的介绍这里不再赘述,可以参考之前的文章《Cobar SQL审计的设计与实现》


SQL


SQL是一种领域语言(编程语言),常用于关系型数据库,方便管理结构化数据。数据库执行SQL时先对SQL进行词法分析、语法分析、语义分析生成抽象语法树(Abstract Syntax Tree,简称AST),再被优化器处理生成执行计划,由执行引擎执行。


SQL Parser


将SQL解析为AST的解析器叫SQL Parser,开发这个解析器通常有两种方式:


  • 通过工具自动生成
  • 优点:简单易于实现
  • 缺点:性能不佳,二次开发困难
  • 手工编写
  • 优点:性能好,代码清晰易于扩展
  • 缺点:对开发人员要求高,需要了解编译原理

Cobar中也实现了SQL Parser,它在Cobar中的位置可以从它的架构图中看到

微信截图_20220423134634.png

SQL Parser之后是SQL Router,可以推断出SQL Parser解析出AST的目的是为了分库分表的路由功能。

Cobar的SQL Parser也经历了三个版本的迭代,本质是性能考虑:


  1. 第一版:基于JavaCC生成SQL parser,性能较差,优化不方便
  2. 第二版:仿照ANTLR生成的parser结构手写,中间对象过多
  3. 第三版:基于LL(2)识别器手写


本文不对SQL Parser做过多的介绍,有兴趣可以参考这篇文章《比开源快30倍的自研SQL Parser设计与实践》,这篇文章我也仔细阅读了几遍,附上总结的脑图:

https://github.com/lkxiaolou/reading/tree/main/xmind


Cobar AST


Cobar中的SQL Parser将SQL解析为AST,为了直观感受,先举个例子:

select id,type from goods as g where type in (select type from type_config where status = 0)


经过Cobar SQL Parser后,生成了如下AST对象:

微信截图_20220423134856.png

这个AST的根节点就是select语句,然后每个属性都是叶子节点,叶子节点的属性再分出叶子节点。可能有点绕,需要从代码层面感受。


AST的Node定义如下,这里只有个accept方法,是为了遍历这棵树,暂时不管,后面会说到:

public interface ASTNode {
    void accept(SQLASTVisitor visitor);
}


实现这个ASTNode主要有这几个:

  • SQLStatement:SQL语句,比如select、update、insert等语句,体现在上图的DMLSelectStatement
  • Expression:表达式,比如and、or、比较等语句,体现在InExpression、ComparisionEqualsExpression、LiteralNumber、Identifier
  • TableReference:table相关语句,体现在TableReferences、TableRefFactor

以ComparisionEqualsExpression的实现为例

微信截图_20220423135114.png

其中1是比较的左右表达式,2是判断符,这里是“=”,3是计算该表达式。

evaluationInternal如何实现?其实表达式被结构化和穷举之后这个问题变得简单,比如这里只需要取左右的数值,进行是否相等的比较即可。


AST操作


有了如上对AST的了解,接下来看对AST的操作,最基本的是遍历,利用ASTNode的accept,需要实现SQLASTVisitor接口,这个SQLASTVisitor定义如下:

微信截图_20220423135213.png

其实是利用了java的多态,对每种ASTNode都定义了visit方法,遍历时不同对象对应到不同方法上。

比如MySQLOutputASTVisitor可以遍历AST,将AST还原为SQL输出,只需要这样:

SQLStatement stmt = SQLParserDelegate.parse(sql);
StringBuilder s = new StringBuilder();
stmt.accept(new MySQLOutputASTVisitor(s));
System.out.println(s.toString());

这样执行会输出

SELECT id, type FROM goods AS G WHERE type IN (SELECT type FROM type_config WHERE status = 0)

SQLParserDelegate.parse(sql)解析出来为DMLSelectStatement对象,它的visit方法实现如下:

@Override
public void accept(SQLASTVisitor visitor) {
    visitor.visit(this);
}


再看MySQLOutputASTVisitor的visit(DMLSelectStatement node)实现:

代码比较长,这里就不贴了,总体思路是遇到叶子节点就直接按格式存入StringBuilder中,否则继续调用相应节点的accept继续遍历,是一种深度遍历的思想。


我们可以参考MySQLOutputASTVisitor编写符合自己需求的遍历器。

AST的应用


分库分表


Cobar中利用AST可以获取table名、列名、比较的值进行分库分表,这也是Cobar最重要的功能。


SQL特征生成


除此之外,我了解的AST还可以对原始SQL生成SQL特征,比如原始SQL是这样:

select id, name, age from user as u where age >= 20


或者是

select id, name, age from user as u where age >= 30


都可以被归一化为

select id, name, age from user as u where age >= ?


在进行SQL慢查询或其他的统计、针对SQL进行限流时非常有用。


危险SQL拦截


线上写了一条没有where条件的update或delete,这时可以利用AST进行表达式计算,对没有where条件和where条件恒为true的SQL进行拦截。


最后


本文从SQL AST的来源、结构、遍历原理、应用等方面进行介绍,相信看完文章会对SQL AST有了初步的了解,如果想进一步了解可以参考Cobar项目中的单元测试进行实际的演示感受。


相关实践学习
自建数据库迁移到云数据库
本场景将引导您将网站的自建数据库平滑迁移至云数据库RDS。通过使用RDS,您可以获得稳定、可靠和安全的企业级数据库服务,可以更加专注于发展核心业务,无需过多担心数据库的管理和维护。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
26天前
|
安全 Linux API
OpenClaw能做什么?1分钟阿里云/Win11/Mac/Linux保姆级部署、配置百炼API、集成20个必装Skills及常见问题
“花一下午装好OpenClaw,结果问啥啥不会,让查新闻说没法联网,让整理文件说没权限”——这是很多新手的共同经历。其实,OpenClaw本身只是一个“智能框架”,就像刚出厂的智能手机,只有操作系统却没有任何APP,想要它真正“聪明能干”,关键在于安装和配置合适的Skills(技能)。
476 1
|
设计模式 负载均衡 Nacos
远程调用 OpenFeign 底层原理解析
Feign 是Springcloud 提供一个声明式的伪Http客户端 它使得调用远程服务就像调用本地服务一样简单 只需要创建一个接口 并且添加注解就可以 Nacos 很好的兼容Feign Feign 默认集成了Ribbon 所以在Nacos 下使用Fegin 默认就实现了负载均衡的效果
2370 1
远程调用 OpenFeign 底层原理解析
|
5月前
|
人工智能 自然语言处理 数据可视化
AI 数据分析产品推荐:更高效、更可控的智能报告解决方案
在与客户的共创中,我们发现数据团队仍被困在周报、月报的重复劳动中,AI 生成的报告往往结构松散、缺乏深度,无法直接使用。这引发我们对智能分析范式的重新思考,推出了 「智能融合报告」,确立了一种新的协作方式:您作为“总设计师”编排思路,AI 作为“超级工匠”精准执行。通过这种方式,您能够将业务经验融入分析框架,全程掌控生成过程,获得结构严谨、洞察深入且可复用的分析成果。如果您在寻找更高效、更可控的智能报告解决方案,这篇凝结我们实践思考的文章值得一读。
|
XML 存储 Unix
DBus类型系统以及在Qt和C++ 中的使用(一)
DBus类型系统以及在Qt和C++ 中的使用
1344 0
|
23天前
|
人工智能 Kubernetes 数据可视化
Claude Skills 办公自动化实战:PPT、海报、Logo 一键生成的背后逻辑
Claude Skills 是 Anthropic 为 Claude Code 打造的模块化能力扩展体系,通过本地文件定义能力描述和执行流程。本文以 PPT 生成、海报设计、Logo 创建三个实战案例,演示了 Skills 在办公自动化中的完整落地流程,并对比分析了 Skills、MCP、Slash Commands 三种扩展方式的适用场景。
811 3
Claude Skills 办公自动化实战:PPT、海报、Logo 一键生成的背后逻辑
|
9月前
|
XML 人工智能 Java
Spring Boot集成Aviator实现参数校验
Aviator是一个高性能、轻量级的Java表达式求值引擎,适用于动态表达式计算。其特点包括支持多种运算符、函数调用、正则匹配、自动类型转换及嵌套变量访问,性能优异且依赖小。适用于规则引擎、公式计算和动态脚本控制等场景。本文介绍了如何结合Aviator与AOP实现参数校验,并附有代码示例和仓库链接。
588 0
conda常用操作和配置镜像源
conda常用操作和配置镜像源
33275 0
|
开发框架 Ubuntu 应用服务中间件
FastCGI与spawn-fcgi安装与配置
FastCGI与spawn-fcgi安装与配置
1399 0
FastCGI与spawn-fcgi安装与配置
|
7月前
|
存储 监控 安全
RFID技术让高校电动车进出更简便
RFID电动车进出管理系统利用射频识别技术,为每辆电动车配备唯一电子标签,实现自动识别与权限管控。系统支持无感通行、精准识别、多模式联动及数据记录分析,提升高校电动车管理效率与安全性,有效解决乱停乱放、非法进入等问题,保障校园环境有序。
|
12月前
|
安全 Java API
什么是用于 REST API 的 Bearer Token以及如何通过代码和工具进行调试
Bearer Token 是一种基于 OAuth 2.0 的身份验证机制,广泛应用于 REST API 的授权访问中。它通过在 HTTP 请求头中传递令牌,确保用户凭据安全传输并验证。本文深入解析了 Bearer Token 的概念、实现步骤及调试方法,包括其无状态特性、灵活性与安全性优势。同时,提供了 Java 实现示例和使用 Apipost、cURL 等工具测试的实践指导,帮助开发者掌握这一核心技能,保障 API 系统的安全与高效运行。

热门文章

最新文章