语法解析器,根据不同类型的语句有不同的语法解析器去解析成成SQLStatement,SQL解析器的类图我用脑图画出来如下:

SQLParser.png

可以看到,不同的sql有不同的处理解析器去解析,解析完成之后,会将SQL解析成SQLStatement,看一下SQLParser的定义:

public interface SQLParser {

SQLStatement parse();

}

方法名

说明

SQLType getType()

获取SQL类型,有DDL,DML,DQL,DAL,TCL

Tables getTables();

获取表集合

Conditions getConditions();

获取条件

List getSqlTokens();

获取所有的SQLToken

int getParametersIndex()

获取参数位置

void setParametersIndex(int parametersIndex)

重置参数位置

int increaseParametersIndex()

增加参数位置

除了语法解析器SQLParser,还有SQL从句解析器SQLClauseParser,SQL别名解析器AliasExpressionParser,表达式解析器BasicExpressionParser。

如下图:

SQLClauseParser.png

SQLStatement对象是个超类,具体实现类有很多。按照不同的语句,返回不同的SQLStatement。

SQLStatement.png

api如下:

方法名

说明

SQLType getType()

获取SQL类型,有DDL,DML,DQL,DAL,TCL

Tables getTables();

获取表集合

Conditions getConditions();

获取条件

List getSqlTokens();

获取所有的SQLToken

int getParametersIndex()

获取参数位置

void setParametersIndex(int parametersIndex)

重置参数位置

int increaseParametersIndex()

增加参数位置

不同的语句,ddl,dml,tcl等,有不同的语法解析器SQLParser去解析,Sharding-sphere如何根据不同的SQL去选择不同的SQLParser?

这里和词法分析器一样,同样是使用工厂模式,按照不同类型的SQL选择不同的语法解析器。根据数据库类型,DB类型分词解析器获取语法解析器。

public final class SQLParserFactory {

public static SQLParser newInstance(final DatabaseType dbType, final TokenType tokenType, final ShardingRule shardingRule, final LexerEngine lexerEngine, final ShardingMetaData shardingMetaData) {

//如果是DQL语句 select语句

if (isDQL(tokenType)) {

return getDQLParser(dbType, shardingRule, lexerEngine, shardingMetaData);

}

//DML语句 insert,update,delete语句

if (isDML(tokenType)) {

return getDMLParser(dbType, tokenType, shardingRule, lexerEngine, shardingMetaData);

}

//DDL语句 create,alter,drop,TRUNCATE语句

if (isDDL(tokenType)) {

return getDDLParser(dbType, tokenType, shardingRule, lexerEngine);

}

//TCL语句 set,commit,rollBack,savePoint,begin语句

if (isTCL(tokenType)) {

return getTCLParser(dbType, shardingRule, lexerEngine);

}

//DAL语句,use,desc,describe,show语句

if (isDAL(tokenType)) {

return getDALParser(dbType, (Keyword) tokenType, shardingRule, lexerEngine);

}

throw new SQLParsingUnsupportedException(tokenType);

}

}

这里以insert语句为例,看一下如何通过数据库类型选择不同的SQLParser

private static SQLParser getDMLParser(

final DatabaseType dbType, final TokenType tokenType, final ShardingRule shardingRule, final LexerEngine lexerEngine, final ShardingMetaData shardingMetaData) {

switch ((DefaultKeyword) tokenType) {

case INSERT:

//如果Insert语句

return InsertParserFactory.newInstance(dbType, shardingRule, lexerEngine, shardingMetaData);

case UPDATE:

return UpdateParserFactory.newInstance(dbType, shardingRule, lexerEngine);

case DELETE:

return DeleteParserFactory.newInstance(dbType, shardingRule, lexerEngine);

default:

throw new SQLParsingUnsupportedException(tokenType);

}

}

public final class InsertParserFactory {

public static AbstractInsertParser newInstance(final DatabaseType dbType, final ShardingRule shardingRule, final LexerEngine lexerEngine, final ShardingMetaData shardingMetaData) {

switch (dbType) {

case H2:

case MySQL:

return new MySQLInsertParser(shardingRule, lexerEngine, shardingMetaData);

case Oracle:

return new OracleInsertParser(shardingRule, lexerEngine, shardingMetaData);

case SQLServer:

return new SQLServerInsertParser(shardingRule, lexerEngine, shardingMetaData);

case PostgreSQL:

return new PostgreSQLInsertParser(shardingRule, lexerEngine, shardingMetaData);

default:

throw new UnsupportedOperationException(String.format("Cannot support database [%s].", dbType));

}

}

}

能够看到,通过多个Factory,根据SQL语句类型(DML,DDL)等路由到不同的方法,根据具体类型(Insert,update)等找到对应的工厂模式,按照不同的数据库类型返回具体的语法解析器SQLParser。

一条sql在执行的时候,如何知道是什么类型的语句??

词法分析器Lexer在解析Sql的时候,第一个分词就是SQL的具体类型(select,update),所以在执行sql的时候,首先调用词法分析器解析第一个分词,获取语句类型,然后选择具体的语法解析器解析。和分词器引擎一样,SQL语句解析器也有自己的解析引擎SQLParsingEngine

public final class SQLParsingEngine {

//数据库类型

private final DatabaseType dbType;

//sql

private final String sql;

//分片规则

private final ShardingRule shardingRule;

private final ShardingMetaData shardingMetaData;

public SQLStatement parse(final boolean useCache) {

//是否从缓存中获取

Optional cachedSQLStatement = getSQLStatementFromCache(useCache);

if (cachedSQLStatement.isPresent()) {

return cachedSQLStatement.get();

}

//词法解析器,根据不同的sql,获取不同的词法解析引擎

LexerEngine lexerEngine = LexerEngineFactory.newInstance(dbType, sql);

//解析第一个分词,第一个分词能区分sql类型

lexerEngine.nextToken();

//不同的sql解析器去做解析,完成解析工作,返回SQLStatement

SQLStatement result = SQLParserFactory.newInstance(dbType, lexerEngine.getCurrentToken().getType(), shardingRule, lexerEngine, shardingMetaData).parse();

if (useCache) {

ParsingResultCache.getInstance().put(sql, result);

}

return result;

}

}

所以sql语句解析的过程如下图:

语法解析器.png

终于把sql语法解析器的流程梳理清楚了。

下一篇,分析insert语句的流程。

mysql ddl 语法解析工具_sharding-sphere之语法解析器相关推荐

  1. MySQL——DDL、DML、DQL、DCL语法总结

    文章目录 通用语法及分类 一.DDL(数据定义语言) 1. 数据库操作 2. 表操作 二.DML(数据操作语言) 1. 添加数据 注意事项 2.删除数据 3.修改数据 注意事项 三.DQL(数据查询语 ...

  2. Linux命令行抓包及包解析工具tshark(wireshark)使用实例解析

    在Linux下,当我们需要抓取网络数据包分析时,通常是使用tcpdump抓取网络raw数据包存到一个文件,然后下载到本地使用wireshark界面网络分析工具进行网络包分析. 最近才发现,原来wire ...

  3. 网页html解析工具,一个犀利的 HTML 解析器 —— Less.Html

    一个犀利的 HTML 解析器 -- Less.Html 我写了这个解析器之后才知道,原来 C# 写的 html 解析器有很多.但是因为我没有参照别人的做法,Less.Html 有一个特点,就是它的用法 ...

  4. log解析工具 px4_详解MySQL Binlog解析工具--binlog2sql,基于表级别的数据恢复

    概述 最近碰到某个表需要做数据回退,如果回退整个数据库动作又太大,所以用了binlog2sql来实现,这里先介绍一下binlog2sql的相关内容. binlog2sql是一个开源的Python开发的 ...

  5. mysql binlog2sql_mysql闪回工具binlog2sql安装配置教程详解

    概述 binlog2sql是一个Python开发开源的MySQL Binlog解析工具,能够将Binlog解析为原始的SQL,也支持将Binlog解析为回滚的SQL,去除主键的INSERT SQL,是 ...

  6. 在线EXCEL文件数据转换解析工具

    在线EXCEL文件数据转换解析工具 在线EXCEL文件数据转换解析工具 本工具支持将EXCEL文件转解析成JSON,CSV,HTML以及公式格式,直接将文件拖入文件上传区即可实时转换, 数据仅在客户端 ...

  7. MySQL Binlog 解析工具 Maxwell 详解

    maxwell 简介 Maxwell是一个能实时读取MySQL二进制日志binlog,并生成 JSON 格式的消息,作为生产者发送给 Kafka,Kinesis.RabbitMQ.Redis.Goog ...

  8. canal应用一:基于mysql binlog的日志解析工具

    文章目录 前言 mysql 配置 canal 下载安装 canal client canal admin 常见问题 前言 canal 是阿里巴巴开发的MySQL数据实时同步工具,基于binlog增量日 ...

  9. java mysql 语句解析器_几种基于Java的SQL解析工具的比较与调用

    1.sqlparser http://www.sqlparser.com/ 优点:支持的数据库最多,除了传统数据库外还支持hive和greenplum一类比较新的数据库,调用比较方便,功能不错 缺点: ...

最新文章

  1. Angular多个页面引入同一个组件报错The Component ‘MyComponentComponent‘ is declared by more than one NgModule怎么办?
  2. android下载源代码
  3. 【Paper】2021_Synchronization of Resilient Complex Networks Under Attacks
  4. c 调用java post方法_C#调用Java方法(详细实例)
  5. boost::mpl模块实现list_c相关的测试程序
  6. Ubuntu中的密钥环密码与登陆密码不同
  7. 华为上机试---购物单(算法:背包问题)
  8. 使用Addressable更好的管理内存
  9. 12、testng.xml指定运行测试包、测试类、测试方法
  10. IEEE745浮点数格式
  11. Linux查看某个进程的磁盘IO读写情况
  12. Jenkins构建风格自由的项目
  13. 基于ricequant神经网络量化交易
  14. 【Excel】五种方法添加打勾方框(其他符号差不多)
  15. matlab指标之间的关系分析,基于相关性分析和主成分分析的变量筛选方法
  16. 系统配置microsoft服务器,Windows 评估服务设置和配置
  17. windows内核开发学习笔记十七:IRP 和 IO_STACK_LOCATION 的交互
  18. Cadence OrCAD Capture 检索和定位功能的介绍图文视频教程
  19. 随笔杂记(十)——C++:C4996报错解决方法
  20. 机器学习实战——数据探索之数据泄露(Data Leakage)

热门文章

  1. Spring+Mybatis多数据源配置(二)——databaseIdProvider的使用
  2. 从 wiscKey 看 LSMtree 的不足
  3. C++突破private的方案
  4. 视频会议未来趋势不完全预测
  5. 通过改进视频质量评估提升编码效率
  6. 音视频技术开发周刊 82期
  7. LiveVideoStackCon讲师热身分享 ( 十三 ) —— Intel QSV技术在FFmpeg中的实现与使用
  8. 腾讯技术课|基于Elastic Stack 搭建日志分析平台
  9. 编程语言代码编写指南
  10. 你所不知道的getResource()在maven下的黑洞!