Druid SQL解析原理分析(二)
概览
续上篇文章后,继续分析Drui的SQL解析原理,如果没有看上篇文章,可以先浏览下上篇文章:Druid SQL解析原理分析(一),有利于概念的连续性,更容易理解。
由于SQL解析流程过于庞大复制,本篇文章只分析访问者访问AST的主要流程。
流程分析
SQLObject 对象
SQLObject对象是Druid体系中的顶层接口,用于描述所有SQL有关的对象,比如:ASTSQLObject的一个继承类。对应访问者模式中的Element,用于接收一个访问者对象(Visitor 的具体实现类)。
访问者遍历AST语法树
- 使用如下方式遍历AST树
sqlStatement.accept(sqlCustomedVisitor);
2.跟踪accept方法里面后发现,accept方法是SQLObjectImpl里面的一个final方法,无法被子类重写,最后进入到了accept0方法,该方法是一个抽象的方法,子类必须重写,这里就使用到了模板方法的设计模式。
3.到一个实现类MySqlUpdateStatement里面去跟踪accept0的具体实现,发现这里会调用visitor.visit(this)方法,把对象自己传进去。visitor同时实现了visitor.visit(MySqlUpdateStatement mySqlUpdateStatement)方法,此时就会进入到visitor的实现里面去。
4. visitor访问完自身节点后,然后再去访问子节点,就如MySqlUpdateStatement实例一样。
this.acceptChild(visitor, this.tableSource);
this.acceptChild(visitor, this.items);
this.acceptChild(visitor, this.where);
this.acceptChild(visitor, this.orderBy);
this.acceptChild(visitor, this.limit);
然后子节点又是一个SQLObject对象,再次调用accept方法,所以又回到了步骤2,以此类推,遍历完整个AST树。
4. 如果我们需要自定义visitor,那么必须实现 SQLASTVisitor接口,该接口是抽象访问者,定义访问者的行为规范。SQLASTVisitorAdapter类已经帮我们实现了SQLASTVisitor,所以需要自定义visitor时,可以选择继承SQLASTVisitorAdapter,然后重写特定接口即可。比如:需要通过自定义visitor获取SQL的limit RowCount数量,可以以如下方式定义visitor,当使用该visitor遍历AST树时,如果遍历到SQLLimit节点,就会调用该重写方法。
// 自定义访问者
class SQLCustomedVisitor extends SQLASTVisitorAdapter {
protected boolean hasLimit = false;
@Override
public boolean visit(SQLLimit x) {
System.out.println(x.getRowCount());
hasLimit = true;
return false;
}
public boolean isHasLimit() {
return hasLimit;
}
}
posted on 2021-08-26 18:45 bigstrong_code 阅读(1497) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现