ShardingSphere解析SQL示例詳解
引言
ShardingSphere的SQL解析,本篇文章源碼基于4.0.1版本
ShardingSphere的分片引擎從解析引擎到路由引擎到改寫(xiě)引擎到執(zhí)行引擎再到歸并引擎,一步一步對(duì)分片操作進(jìn)行處理,我們這篇文章先從解析引擎開(kāi)始,深入分析一下Sql的解析引擎處理流程。
解析Sql的入口
SQLParseEngine這個(gè)類是sql解析引擎對(duì)應(yīng)的類,通過(guò)看它的parse()方法,我們知道sql解析的過(guò)程就是構(gòu)建SQLStatement對(duì)象的過(guò)程,方法中調(diào)用了SQLParseKernel來(lái)創(chuàng)建對(duì)象,然后調(diào)用它的parse()方法來(lái)完成。因此我們把重心放在這個(gè)方法上
解析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()); }
- 將原始SQL通過(guò)解析器解析為抽象語(yǔ)法樹(shù)
- 使用提取器根據(jù)提取規(guī)則提取Sql片段結(jié)合
- 使用填充器根據(jù)填充規(guī)則填充Sql片段生成SQL解析后的結(jié)果并返回
下面將具體看一下這三步
1. 將 SQL 解析為抽象語(yǔ)法樹(shù)
這一塊是對(duì)應(yīng)的SQLParserEngine的parse()方法,這個(gè)方法的主要邏輯是利用工廠類SQLParserFactory來(lái)創(chuàng)建Sql解析器實(shí)例,由于不同的數(shù)據(jù)庫(kù)對(duì)應(yīng)的SQL解析器也不相同,所以這一塊的邏輯也是利用了Java的SPI機(jī)制來(lái)創(chuàng)建配置的SQLParserEntry實(shí)例對(duì)象,根據(jù)不同的數(shù)據(jù)庫(kù)類型選擇不同的Sql解析器,最終會(huì)生成SQLAST對(duì)象,也就是SQL 的抽象語(yǔ)法樹(shù)。
2. 提取Sql片段
這一步對(duì)應(yīng)的是SQLSegmentsExtractorEngine的extract()方法,返回的是所有的Sql片段的集合。
遍歷抽象語(yǔ)法樹(shù)中的Sql片段的提取器,提取器分為兩種類型,一種是單節(jié)點(diǎn)的Sql片段提取器,這時(shí)候就直接獲取Sql片段,放入集合中就可以了,另一種是樹(shù)狀節(jié)點(diǎn)的Sql片段提取線,這時(shí)候就需要遍歷這棵樹(shù),將結(jié)果放入集合中。看!數(shù)據(jù)結(jié)構(gòu)之樹(shù)的遍歷用到了吧,以后別說(shuō)數(shù)據(jù)結(jié)構(gòu)沒(méi)用了。。
3. 填充Sql片段,生成解析結(jié)果
第三步就是填充得到的Sql片段了,對(duì)應(yīng)的是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; }
- 獲取SQLStatement對(duì)象,對(duì)SQLStatement進(jìn)行合法性進(jìn)行校驗(yàn)
- 設(shè)置結(jié)果的參數(shù)的個(gè)數(shù)
- 將上一步中的SQL片段集合添加到結(jié)果對(duì)象中
- 遍歷Sql片段,根據(jù)數(shù)據(jù)庫(kù)類型和Sql片段找到Sql片段過(guò)濾器,利用Sql片段過(guò)濾器來(lái)填充Sql片段
- 最后返回解析后的SQLStatement
總結(jié)
這篇文章我們講了ShardingSphere的解析Sql的功能,從它的入口開(kāi)始到它具體解析Sql的過(guò)程,分三步走,第一步將原始SQL解析成抽象語(yǔ)法樹(shù),第二步提取Sql片段,第三步根據(jù)數(shù)據(jù)庫(kù)類型和Sql片段選擇相應(yīng)的填充器填充Sql片段,這就是解析Sql的整體過(guò)程了,希望對(duì)你理解ShardingSphere有所幫助。
更多關(guān)于ShardingSphere SQL的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring Cache和EhCache實(shí)現(xiàn)緩存管理方式
這篇文章主要介紹了Spring Cache和EhCache實(shí)現(xiàn)緩存管理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Spring Boot數(shù)據(jù)庫(kù)鏈接池配置方法
這篇文章主要介紹了Spring Boot數(shù)據(jù)庫(kù)鏈接池配置方法,需要的朋友可以參考下2017-04-04總結(jié)Java常用到的六個(gè)加密技術(shù)和代碼
大家要記住現(xiàn)代密碼學(xué)最重要的原則柯克霍夫原則:數(shù)據(jù)的安全基于密鑰而不是算法的保密。也就是說(shuō)即使密碼系統(tǒng)的任何細(xì)節(jié)已為人悉知,只要密匙未洩漏,它也應(yīng)是安全的。這篇文章給大家介紹了6個(gè)常用的加密技術(shù)和代碼。2016-07-07利用Java多線程技術(shù)導(dǎo)入數(shù)據(jù)到Elasticsearch的方法步驟
這篇文章主要介紹了利用Java多線程技術(shù)導(dǎo)入數(shù)據(jù)到Elasticsearch的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07Java實(shí)現(xiàn)猜數(shù)字小游戲(有次數(shù)限制)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)猜數(shù)字小游戲,有次數(shù)限制,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05在springboot中實(shí)現(xiàn)個(gè)別bean懶加載的操作
這篇文章主要介紹了在springboot中實(shí)現(xiàn)個(gè)別bean懶加載的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10Java實(shí)現(xiàn)矩陣順時(shí)針旋轉(zhuǎn)90度的示例
今天小編就為大家分享一篇Java實(shí)現(xiàn)矩陣順時(shí)針旋轉(zhuǎn)90度的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-01-01springboot整合vue2-uploader實(shí)現(xiàn)文件分片上傳、秒傳、斷點(diǎn)續(xù)傳功能
對(duì)于大文件的處理,無(wú)論是用戶端還是服務(wù)端,如果一次性進(jìn)行讀取發(fā)送、接收都是不可取,很容易導(dǎo)致內(nèi)存問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于springboot整合vue2-uploader實(shí)現(xiàn)文件分片上傳、秒傳、斷點(diǎn)續(xù)傳功能的相關(guān)資料,需要的朋友可以參考下2023-06-06java數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)雙向鏈表功能
這篇文章主要為大家詳細(xì)介紹了java數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)雙向鏈表功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11