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


猜你喜欢
- java.lang.NoClassDefFoundError错误解决办法前言在日常Java开发中,我们经常碰到java.lang.NoCla
- Android上使调用OpenCV 2.4.10 实现二维码区域定位(Z-xing 码),该文章主要用于笔者自己学习中的总结,暂贴出代码部分
- using System;using System.Collections.Generic;using System.Web.Script.
- 一.什么是maven?Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一
- 一、使用Pull解析器读取XML文件除了可以使用SAX或DOM解析XML文件之外,大家也可以使用Android内置的Pull解析器解析XML
- 首先写个单例:public class SingleDemo { private static SingleDemo s =
- 上一篇文章介绍了MediaPlayer相关内容,这次用两篇文章来介绍SurfaceView的用法。网上介绍SurfaceView的用法有很多
- 前言应用系统需要通过Cache来缓存不经常改变得数据来提高系统性能和增加系统吞吐量,避免直接访问数据库等低速存储系统。缓存的数据通常存放在访
- 本章先讲解Java随机数的几种产生方式,然后通过示例对其进行演示。广义上讲,Java中的随机数的有三种产生方式:(01). 通过System
- SpringBoot默认的存放静态资源文件的位置是:注:SpringBoot中的src/main/resources/资源文件夹对应clas
- 本文实例讲述了C#控制台下多线程实现方法。分享给大家供大家参考。具体如下:class Program{ static void
- 目录文件下载文件上传 * * 的配置多个 * 的执行顺序异常处理器基于配置的异常处理基于注解的异常处理总结文件下载使用ResponseEn
- 1.实例1(主要看到[2])1.1.系统功能: 开发一个计算器服务CalculateService,这个服务包含加(plus)、减(minu
- 什么是文件上传?文件上传就是把用户的信息保存起来。为什么需要文件上传?在用户注册的时候,可能需要用户提交照片。那么这张照片就应该要进行保存。
- 目录前言实现思路实现方法最简单的实现方法如果多线程乱入?线程安全的单例模式Lock版本静态构造器版本Lazy版本总结前言Singleton是
- 很久之前也写过一篇使用Jitpack发布Android开源库的文章,详见Android发布项目到jitpack的完整步骤近来因为工作原因,又
- 前言在Android开发中我们可能会有延时执行某个操作的需求,例如我们启动应用的时候,一开始呈现的是一个引导页面,过了两三秒后,会自动跳转到
- 见过一句夸张的话,叫做“没有阅读过jdk源码的人不算学过java”。从今天起开始精读源码。而适合精读的源码无非就是java.io,.util
- 前言为了解决项目当中的权限管理问题,我们一般会选择引入spring security或者shiro框架来帮助我们更好地更快地构建权限管理体系
- C++对string进行大小写转换操作方法方法一:使用C语言之前的方法,使用函数,进行转换#include <iostream>