ShardingSphere解析SQL示例详解
作者:周杰伦本人 发布时间:2023-11-23 13:57:55
引言
ShardingSphere的SQL解析,本篇文章源码基于4.0.1版本
ShardingSphere的分片引擎从解析引擎到路由引擎到改写引擎到执行引擎再到归并引擎,一步一步对分片操作进行处理,我们这篇文章先从解析引擎开始,深入分析一下Sql的解析引擎处理流程。
解析Sql的入口
SQLParseEngine这个类是sql解析引擎对应的类,通过看它的parse()方法,我们知道sql解析的过程就是构建SQLStatement对象的过程,方法中调用了SQLParseKernel来创建对象,然后调用它的parse()方法来完成。因此我们把重心放在这个方法上
解析Sql
SQLParseKernel的parse()方法:
public SQLStatement parse() {
SQLAST ast = parserEngine.parse();
Collection<SQLSegment> sqlSegments = extractorEngine.extract(ast);
Map<ParserRuleContext, Integer> parameterMarkerIndexes = ast.getParameterMarkerIndexes();
return fillerEngine.fill(sqlSegments, parameterMarkerIndexes.size(), ast.getSqlStatementRule());
}
将原始SQL通过解析器解析为抽象语法树
使用提取器根据提取规则提取Sql片段结合
使用填充器根据填充规则填充Sql片段生成SQL解析后的结果并返回
下面将具体看一下这三步
1. 将 SQL 解析为抽象语法树
这一块是对应的SQLParserEngine的parse()方法,这个方法的主要逻辑是利用工厂类SQLParserFactory来创建Sql解析器实例,由于不同的数据库对应的SQL解析器也不相同,所以这一块的逻辑也是利用了Java的SPI机制来创建配置的SQLParserEntry实例对象,根据不同的数据库类型选择不同的Sql解析器,最终会生成SQLAST对象,也就是SQL 的抽象语法树。
2. 提取Sql片段
这一步对应的是SQLSegmentsExtractorEngine的extract()方法,返回的是所有的Sql片段的集合。
遍历抽象语法树中的Sql片段的提取器,提取器分为两种类型,一种是单节点的Sql片段提取器,这时候就直接获取Sql片段,放入集合中就可以了,另一种是树状节点的Sql片段提取线,这时候就需要遍历这棵树,将结果放入集合中。看!数据结构之树的遍历用到了吧,以后别说数据结构没用了。。
3. 填充Sql片段,生成解析结果
第三步就是填充得到的Sql片段了,对应的是SQLStatementFillerEngine的fill()方法
public SQLStatement fill(final Collection<SQLSegment> sqlSegments, final int parameterMarkerCount, final SQLStatementRule rule) {
SQLStatement result = rule.getSqlStatementClass().newInstance();
Preconditions.checkArgument(result instanceof AbstractSQLStatement, "%s must extends AbstractSQLStatement", result.getClass().getName());
((AbstractSQLStatement) result).setParametersCount(parameterMarkerCount);
result.getAllSQLSegments().addAll(sqlSegments);
for (SQLSegment each : sqlSegments) {
Optional<SQLSegmentFiller> filler = parseRuleRegistry.findSQLSegmentFiller(databaseTypeName, each.getClass());
if (filler.isPresent()) {
filler.get().fill(each, result);
}
}
return result;
}
获取SQLStatement对象,对SQLStatement进行合法性进行校验
设置结果的参数的个数
将上一步中的SQL片段集合添加到结果对象中
遍历Sql片段,根据数据库类型和Sql片段找到Sql片段过滤器,利用Sql片段过滤器来填充Sql片段
最后返回解析后的SQLStatement
来源:https://juejin.cn/post/7126532890996768781
猜你喜欢
- 问题描述 在某一天打开电脑后,idea里的代码无缘无故地就爆红了,不但spring框架爆红,就
- 本文实例为大家分享了C# GDI+实现时钟表盘的具体代码,供大家参考,具体内容如下一、设计如下图界面按键“打开时钟&am
- yaml语法注解配置文件两种形式application.properties和.yaml第一种语法 key=value第二种key:空格va
- 类注解@component 标注类,泛指各种组件,类不属于各种分类的时候,用它做标注。@Service 标注类,声明该类为业务层组件,用于处
- 一,使用注解: 在spring的配置文件applicationContext.xml中,加入注解扫描。配
- 前言最近在项目中使用到定时任务,之前一直都是使用Quartz 来实现,最近看Spring 基础发现其实Spring 提供 Spring Sc
- 接收到这样一个需求,就是英文名字中firstName和lastName,其中任何一个为null,就返回Empty。刚拿到需求,这不简单,if
- 一. 为什么要使用接口假如有一个需求:要求实现防盗门的功能。门有"开"和"关"的功能,锁有"
- 本Demo为练手小项目,主要是熟悉目前主流APP的架构模式.此项目中采用MVC设计模式,纯代码和少许XIB方式实现.主要实现了朋友圈功能和摇
- 本文实例为大家分享了java使用字符画一个海绵宝宝的具体代码,供大家参考,具体内容如下用字符画一个海绵宝宝用" &ldqu
- 一、目的本篇文章的目的是记录本人使用flutter加载与调用第三方aar包。二、背景本人go后端,业余时间喜欢玩玩flutter。一直有一个
- 一、案例场景遇到过这样的场景,在定义一个static修饰的Map时,使用了大量的put()方法赋值,就类似这样——public static
- 本文以实例阐述了C++中形参与实参的区别,有助于读者加深对于C++形参与实参的认识。形参出现在函数定义中,在整个函数体内都可以使用, 离开该
- 基于Java的简单的用户管理系统,供大家参考,具体内容如下此系统功能和方法都比较简单本次系统通过控制台输入商品的基本信息,加入管理员的登录与
- 先看代码public class MaxHuiWen {public static void main(String[] args) { &
- 第一种方法:string s=abcdeabcdeabcde;string[] sArray=s.Split(c) ;foreach(str
- springboot启动失败的问题springboot版本是1.3.0.M1,连接的mysql版本为8,用spring-boot-start
- 前言最近项目需要和Oracle数据库进行交互,然后我从Maven中央仓库下载数据库驱动jar包,但怎么都下不下来,我到Oracle官网上一看
- mport java.text.DecimalFormat; DecimalFormat &nb
- 前言悬浮窗是一种比较常见的需求。例如把视频通话界面缩小成一个悬浮窗,然后用户可以在其他界面上处理事情。本文给出一个简单的应用内悬浮窗实现。可