一、突如其来的兴趣
自从上周写了一个 ShardingSphere 简单入门之后,突然对这个产品产生了浓厚的兴趣。
在阅读官方文档的过程,看到这么一段描述:“核心由SQL解析 => 执行器优化 => SQL路由 => SQL改写 => SQL执行 => 结果归并的流程组成”。
就这么简简单单的6个步骤就能完美解决数据库数据分片问题了?那么这6个步骤的实现代码得有多少呢?
抱着内心这样奇奇怪怪的疑问,让我们来通过本篇文章来剖析“SQL解析器”的源代码吧!
二、官方文档解释
官方使用这个图片来解释,分库分表后的数据查询过程。这里引用下图片以及步骤的简单说明。
SQL解析,分为词法解析和语法解析。
执行器优化,合并和优化分片条件,如OR等。
SQL路由,根据解析上下文匹配用户配置的分片策略,并生成路由路径
SQL改写,将SQL改写为在真实数据库中可以正确执行的语句。
SQL执行,通过多线程执行器异步执行。
结果归并,将多个执行结果集归并以便于通过统一的JDBC接口输出。
三、先找本文的对象
通过对测试代码的逐步调试,可以找到 SQLParserExecutor 这个类。它将原始的 SQL 字符串拆解成了 ParseTree 的对象。
SQLParserExecutor 文件定位,也就得到了 shardingsphere-sql-parser-engine.jar 这个解析引擎包。
四、jar 源码解析
pom.xml
parent 项目是 shardingsphere-sql-parser 工程。
SQLParserEngineFactory
使用简单工厂与单例的组合模式,根据传入的数据库类型名称获取 SQLParserEngine 对象。
SQLParserEngine
SQL 解析引擎,会将 SQL 语句解析成 ParseTree 对象,然后再通过 ParseTreeVisitorFactory 解析成 SQLStatement 对象进行返回。
同时,最终的解析结果 SQLStatement 对象可以进行缓存。
SPIParskingHook
提供了一个 Hook 钩子的机制。会触发实现 ParsingHook 接口的三个方法,分别是 start、finishSuccess、finishFailure。
ParsingHook
定义的 Hook 接口。
SQLParseResultCache
使用 cache 对 SQL 语句的解析做一个缓存 SQLStatement。
ParseASTNode
封装了一个第三方 antlr 的根节点。
SQLParserExecutor
SQL 的解析器,使用了antlr 的第三方解析插件。
SQLParserFactory
工厂类,根据数据库类型名称、SQL获取 SQLParser 对象。
ParseTreeVisitorFactory
工厂类,根据数据库类型名称、访问规则获取不同的 ParseTreeVisitor 接口实现类。
VisitorRule
数据库 DML、DDL、TCL、DCL、DAL、DML、RL 关键字的枚举。
SQLParsingException
自定义的错误类。
五、总结
以上是“SQL解析器”的源代码内容,这部分代码主要运用到了工厂模式、单例模式、cache 缓存,以及 antlr 解析 SQL 语法的第三方插件来实现的。
同时,也预留了 Hook 的接口便于后续加载 Plugin 插件来实现一些新的功能。