mysql ddl 语法解析工具_sharding-sphere之语法解析器
語法解析器,根據不同類型的語句有不同的語法解析器去解析成成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語句的流程。
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的mysql ddl 语法解析工具_sharding-sphere之语法解析器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 内存条VS硬盘:速度、容量、价格全面对比
- 下一篇: java 返回值 泛型 继承_java泛