ShardingSphere的SQL解析

举报
周杰伦本人 发表于 2022/10/30 18:45:59 2022/10/30
【摘要】 ShardingSphere的SQL解析 解析Sql的入口 解析Sql 1. 将 SQL 解析为抽象语法树 2. 提取Sql片段 3. 填充Sql片段,生成解析结果 总结 ShardingSphere的SQL解析本篇文章源码基于4.0.1版本ShardingSphere的分片引擎从解析引擎到路由引擎到改写引擎到执行引擎再到归并引擎,一步一步对分片操作进行处理,我们这篇文章先从解析引擎开始,...

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());
}
  1. 将原始SQL通过解析器解析为抽象语法树
  2. 使用提取器根据提取规则提取Sql片段结合
  3. 使用填充器根据填充规则填充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;
}
  1. 获取SQLStatement对象,对SQLStatement进行合法性进行校验
  2. 设置结果的参数的个数
  3. 将上一步中的SQL片段集合添加到结果对象中
  4. 遍历Sql片段,根据数据库类型和Sql片段找到Sql片段过滤器,利用Sql片段过滤器来填充Sql片段
  5. 最后返回解析后的SQLStatement

总结

这篇文章我们讲了ShardingSphere的解析Sql的功能,从它的入口开始到它具体解析Sql的过程,分三步走,第一步将原始SQL解析成抽象语法树,第二步提取Sql片段,第三步根据数据库类型和Sql片段选择相应的填充器填充Sql片段,这就是解析Sql的整体过程了,希望对你理解ShardingSphere有所帮助。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。