mysql ddl 语法解析工具_sharding-sphere之语法解析器

本文详细介绍了Sharding-Sphere中的SQL解析过程,包括SQLParser接口和不同的SQLClauseParser,如DQL、DML、DDL、TCL、DAL。通过工厂模式,根据SQL类型和数据库类型选择相应的SQLParser,例如InsertParserFactory用于处理INSERT语句。词法分析器LexerEngine在解析SQL时确定语句类型,并使用SQLParsingEngine进行解析。
摘要由CSDN通过智能技术生成

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

30a89b9af33c?utm_source=oschina-app

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。

如下图:

30a89b9af33c?utm_source=oschina-app

SQLClauseParser.png

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

30a89b9af33c?utm_source=oschina-app

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语句解析的过程如下图:

30a89b9af33c?utm_source=oschina-app

语法解析器.png

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值