Druid SQL解析器的解析过程
作者:SegmentFault 发布时间:[ 2017/1/23 11:30:26 ] 推荐标签:数据库 SQL Server
Select 抽象语法树
打开 SQLSelectStatement 的代码,扫描它的子成员,便分析出这样的一棵语法树:
这意味着,在 Druid 眼里,它是这样看待一条 Select 语句的所有成员部分的。
Visitor
从 demo 代码中可以看到,有了 AST 语法树后,则需要一个 visitor 来访问它
// 使用visitor来访问AST
MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
statement.accept(visitor);
System.out.println(visitor.getColumns());
System.out.println(visitor.getOrderByColumns());
statement 调用 accept 方法,以 visitor 作为参数,开始了访问之旅。在这里 statement 的实际类型是 SQLSelectStatement 。
在 Druid 中,一条 SQL 语句中的元素,无论是高层次还是低层次的元素,都是一个 SQLObject ,statement 是一种 SQLObject,表达式 expr 也是一种 SQLObject,函数、字段、条件等等,这些都是一种 SQLObject,SQLObject 是一个接口, accept 方法便是它定义的,目的是为了让访问者在访问 SQLObject 时,告知访问者一些事情,好让访问者在访问的过程中能够收集到关于该 SQLObject 的一些信息。
具体的 accept() 实现,在 SQLObjectImpl 这个类中,代码如下所示:
public final void accept(SQLASTVisitor visitor) {
if (visitor == null) {
throw new IllegalArgumentException();
}
visitor.preVisit(this);
accept0(visitor);
visitor.postVisit(this);
}
这是一个 final 方法,意味着所有的子类都要遵循这个模板,首先 accept 方法前和后,visitor 都会做一些工作。真正的访问流程定义在 accept0() 方法里,而它是一个 抽象方法 。
因此要知道 Druid 中是如何访问 AST 的,先拿 SQLSelectStatement 的 accept0() 方法来探探究竟。
protected void accept0(SQLASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, this.select);
}
visitor.endVisit(this);
}
首先,使 visitor 访问自己,访问自己后,visitor 会决定是否还要访问自己的子元素。
打开 MySqlSchemaStateVisitor 的 visit 方法,可以看到,visitor 做了一些事,初始化了自己的 aliasMap,然后 return true,这意味着还要访问 SQLSelectStatement 的子节点。
public boolean visit(SQLSelectStatement x) {
setAliasMap();
return true;
}
接下来访问子元素
protected final void acceptChild(SQLASTVisitor visitor, SQLObject child) {
if (child == null) {
return;
}
child.accept(visitor);
}
由此可以看出,SQLObject 负责通知 visitor 要访问自己的哪些元素,而 visitor 则负责访问相应元素前,中,后三个过程的逻辑处理。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
远程连接sql server 2000服务器的解决方案SQL Server修改数据库物理文件存在位置探讨SQL Server并发处理队列数据不阻塞解决方案迁移SQL Server到Azure SQL实战SQL SERVER 的前世今生?各版本功能对比SQL Server的WITH (NOLOCK)SQL Server如何用触发器捕获DML操作的会话信息SQL Server里书签查找的性能伤害监控SQL Server事务复制SQL Server数据库镜像下有效的索引维护SQL Server不停机移动镜像数据库SQL Server数据库备份压缩拷贝实例SQL Server数据库优化SQL SERVER的统计信息SQL Server里如何处理死锁SQL SERVER批量生成编号
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南