sharding-jdbc源碼解析之sql改寫(xiě)

sql改寫(xiě)源碼解析

找到這個(gè)方法

com.dangdang.ddframe.rdb.sharding.routing.PreparedStatementRoutingEngine#route

/**

* SQL路由.

* 當(dāng)?shù)谝淮温酚蓵r(shí)進(jìn)行SQL解析,之后的路由復(fù)用第一次的解析結(jié)果.

*

* @param parameters SQL中的參數(shù)

* @return 路由結(jié)果

*/

public SQLRouteResultroute(final List parameters) {//sql路由業(yè)務(wù)方法

? ?if (null ==sqlStatement) {

sqlStatement =sqlRouter.parse(logicSQL, parameters.size());

? ?}

return sqlRouter.route(logicSQL, parameters, sqlStatement);

}

return sqlRouter.route(logicSQL, parameters, sqlStatement);

進(jìn)入到這個(gè)方法

com.dangdang.ddframe.rdb.sharding.routing.router.ParsingSQLRouter#route(java.lang.String, java.util.List, com.dangdang.ddframe.rdb.sharding.parsing.parser.statement.SQLStatement)

@Override

? ?public SQLRouteResultroute(final String logicSQL, final List parameters, final SQLStatement sqlStatement) {

final Context context = MetricsContext.start("Route SQL");

? ? ? ?SQLRouteResult result =new SQLRouteResult(sqlStatement);

// ? ? ? ?如果是insert語(yǔ)句去生成分布式逐漸的邏輯

? ? ? ?if (sqlStatementinstanceof InsertStatement &&null != ((InsertStatement) sqlStatement).getGeneratedKey()) {

processGeneratedKey(parameters, (InsertStatement) sqlStatement, result);

? ? ? ?}

// ? ? ? ?進(jìn)行sql路由返回路由結(jié)果

? ? ? ?RoutingResult routingResult = route(parameters, sqlStatement);

? ? ? ?SQLRewriteEngine rewriteEngine =new SQLRewriteEngine(shardingRule, logicSQL, sqlStatement);

? ? ? ?boolean isSingleRouting = routingResult.isSingleRouting();

? ? ? ?if (sqlStatementinstanceof SelectStatement &&null != ((SelectStatement) sqlStatement).getLimit()) {

processLimit(parameters, (SelectStatement) sqlStatement, isSingleRouting);

? ? ? ?}

SQLBuilder sqlBuilder = rewriteEngine.rewrite(!isSingleRouting);

? ? ? ?if (routingResultinstanceof CartesianRoutingResult) {

for (CartesianDataSource cartesianDataSource : ((CartesianRoutingResult) routingResult).getRoutingDataSources()) {

for (CartesianTableReference cartesianTableReference : cartesianDataSource.getRoutingTableReferences()) {

result.getExecutionUnits().add(new SQLExecutionUnit(cartesianDataSource.getDataSource(), rewriteEngine.generateSQL(cartesianTableReference, sqlBuilder)));

? ? ? ? ? ? ? ?}

}

}else {

for (TableUnit each : routingResult.getTableUnits().getTableUnits()) {

result.getExecutionUnits().add(new SQLExecutionUnit(each.getDataSourceName(), rewriteEngine.generateSQL(each, sqlBuilder)));

? ? ? ? ? ?}

}

MetricsContext.stop(context);

? ? ? ?if (showSQL) {

SQLLogger.logSQL(logicSQL, sqlStatement, result.getExecutionUnits(), parameters);

? ? ? ?}

return result;

? ?}

// ? ? ? ?sql改寫(xiě)

? ? ? ?SQLRewriteEngine rewriteEngine =new SQLRewriteEngine(shardingRule, logicSQL, sqlStatement);

sql路由完畢后會(huì)進(jìn)行sql改寫(xiě)妥凳,sql改寫(xiě)的部分主要是內(nèi)部實(shí)現(xiàn)為了結(jié)果集歸并的一些操作,涉及性能問(wèn)題干发,還有就是分頁(yè)的實(shí)現(xiàn)实胸,接下來(lái)我們跟蹤下sql改寫(xiě)的源碼實(shí)現(xiàn)郎任。

創(chuàng)建sql改寫(xiě)引擎

SQLRewriteEngine rewriteEngine =new SQLRewriteEngine(shardingRule, logicSQL, sqlStatement);

**

* SQL重寫(xiě)引擎.

*

* @author zhangliang

*/

public final class SQLRewriteEngine {

// ? ?分庫(kù)分表配置對(duì)象

? ?private final ShardingRuleshardingRule;

// ? ?sql改寫(xiě)之前的sql

? ?private final StringoriginalSQL;

// ? ?sql標(biāo)記對(duì)象集合

? ?private final ListsqlTokens =new LinkedList<>();

// ? ?sql語(yǔ)句對(duì)象

? ?private final SQLStatementsqlStatement;

// ? ? ? ?判斷是否為單庫(kù)表路由

? ? ? ?boolean isSingleRouting = routingResult.isSingleRouting();

if (sqlStatementinstanceof SelectStatement &&null != ((SelectStatement) sqlStatement).getLimit()) {

// ? ? ? ? ? ?處理分頁(yè)

? ? ? ? ? ?processLimit(parameters, (SelectStatement) sqlStatement, isSingleRouting);

? ? ? ?}

private void processLimit(final List parameters, final SelectStatement selectStatement, final boolean isSingleRouting) {

// ? ? ? ?select語(yǔ)句排序項(xiàng)不為空 ? ?或者聚合選擇項(xiàng)不為空 ?或者排序項(xiàng)和分組項(xiàng)不一致

? ? ? ?boolean isNeedFetchAll = (!selectStatement.getGroupByItems().isEmpty() || !selectStatement.getAggregationSelectItems().isEmpty()) && !selectStatement.isSameGroupByAndOrderByItems();

// ? ? ? ?填充改寫(xiě)分頁(yè)參數(shù),!isSingleRouting注意這里只要不是單庫(kù)表操作分頁(yè)sql都會(huì)進(jìn)行sql改寫(xiě)秧耗,改寫(xiě)成這樣,改寫(xiě)前0舶治,10分井,改寫(xiě)后0,10霉猛,改寫(xiě)前10尺锚,20 改寫(xiě)后0,20

? ? ? ?selectStatement.getLimit().processParameters(parameters, !isSingleRouting, isNeedFetchAll);

? ?}

不是單庫(kù)表路由惜浅,slq改寫(xiě)引擎返回一個(gè)sql構(gòu)造器

? ? ? ?SQLBuilder sqlBuilder = rewriteEngine.rewrite(!isSingleRouting);

public SQLBuilderrewrite(final boolean isRewriteLimit) {

SQLBuilder result =new SQLBuilder();

? ? ? ?if (sqlTokens.isEmpty()) {

result.appendLiterals(originalSQL);

? ? ? ? ? ?return result;

? ? ? ?}

int count =0;

? ? ? ?sortByBeginPosition();

? ? ? ?for (SQLToken each :sqlTokens) {

if (0 == count) {

// ? ? ? ? ? ? ? ?拼接字面量

? ? ? ? ? ? ? ?result.appendLiterals(originalSQL.substring(0, each.getBeginPosition()));

? ? ? ? ? ?}

if (eachinstanceof TableToken) {

// ? ? ? ? ? ? ? ?拼裝table

? ? ? ? ? ? ? ?appendTableToken(result, (TableToken) each, count, sqlTokens);

? ? ? ? ? ?}else if (eachinstanceof ItemsToken) {

// ? ? ? ? ? ? ? ?拼裝選擇項(xiàng)

? ? ? ? ? ? ? ?appendItemsToken(result, (ItemsToken) each, count, sqlTokens);

? ? ? ? ? ?}else if (eachinstanceof RowCountToken) {

// ? ? ? ? ? ? ? ?拼裝分頁(yè)長(zhǎng)度項(xiàng)

? ? ? ? ? ? ? ?appendLimitRowCount(result, (RowCountToken) each, count, sqlTokens, isRewriteLimit);

? ? ? ? ? ?}else if (eachinstanceof OffsetToken) {

// ? ? ? ? ? ? ? ?拼裝分頁(yè)偏移量項(xiàng)

? ? ? ? ? ? ? ?appendLimitOffsetToken(result, (OffsetToken) each, count, sqlTokens, isRewriteLimit);

? ? ? ? ? ?}else if (eachinstanceof OrderByToken) {

// ? ? ? ? ? ? ? ?拼裝排序項(xiàng)

? ? ? ? ? ? ? ?appendOrderByToken(result, count, sqlTokens);

? ? ? ? ? ?}

count++;

? ? ? ?}

return result;

? ?}

// ? ? ? ?如果路由結(jié)果集是笛卡爾積結(jié)果集

? ? ? ?if (routingResultinstanceof CartesianRoutingResult) {

// ? ? ? ? ? ?遍歷數(shù)據(jù)源

? ? ? ? ? ?for (CartesianDataSource cartesianDataSource : ((CartesianRoutingResult) routingResult).getRoutingDataSources()) {

// ? ? ? ? ? ? ? 遍歷笛卡爾積表路由組

? ? ? ? ? ? ? ?for (CartesianTableReference cartesianTableReference : cartesianDataSource.getRoutingTableReferences()) {

// ? ? ? ? ? ? ? ? ? ?拼裝最小執(zhí)行單元瘫辩,并裝載路由結(jié)果集對(duì)象

? ? ? ? ? ? ? ? ? ?result.getExecutionUnits().add(new SQLExecutionUnit(cartesianDataSource.getDataSource(), rewriteEngine.generateSQL(cartesianTableReference, sqlBuilder)));

}else {

// ? ? ? ? ? ?簡(jiǎn)單路由拼裝最小執(zhí)行單元

? ? ? ? ? ?for (TableUnit each : routingResult.getTableUnits().getTableUnits()) {

result.getExecutionUnits().add(new SQLExecutionUnit(each.getDataSourceName(), rewriteEngine.generateSQL(each, sqlBuilder)));

? ? ? ? ? ?}

以上是sql改寫(xiě)的源碼解析

說(shuō)到最后

以上內(nèi)容,僅供參考坛悉。



?

關(guān)注微信公眾號(hào)

加入技術(shù)微信群

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末伐厌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子裸影,更是在濱河造成了極大的恐慌挣轨,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件空民,死亡現(xiàn)場(chǎng)離奇詭異刃唐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)界轩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門画饥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人浊猾,你說(shuō)我怎么就攤上這事抖甘。” “怎么了葫慎?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵衔彻,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我偷办,道長(zhǎng)艰额,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任椒涯,我火速辦了婚禮柄沮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘废岂。我一直安慰自己祖搓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布湖苞。 她就那樣靜靜地躺著拯欧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪财骨。 梳的紋絲不亂的頭發(fā)上镐作,一...
    開(kāi)封第一講書(shū)人閱讀 51,590評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音隆箩,去河邊找鬼滑肉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛摘仅,可吹牛的內(nèi)容都是我干的靶庙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼娃属,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼六荒!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起矾端,我...
    開(kāi)封第一講書(shū)人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤掏击,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后秩铆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體砚亭,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡灯变,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捅膘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片添祸。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖寻仗,靈堂內(nèi)的尸體忽然破棺而出刃泌,到底是詐尸還是另有隱情,我是刑警寧澤署尤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布耙替,位于F島的核電站,受9級(jí)特大地震影響曹体,放射性物質(zhì)發(fā)生泄漏俗扇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一箕别、第九天 我趴在偏房一處隱蔽的房頂上張望狐援。 院中可真熱鬧,春花似錦究孕、人聲如沸啥酱。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)镶殷。三九已至,卻和暖如春微酬,著一層夾襖步出監(jiān)牢的瞬間绘趋,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工颗管, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留陷遮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓垦江,卻偏偏與公主長(zhǎng)得像帽馋,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子比吭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 說(shuō)在前面 sql路由這里的內(nèi)容比較多绽族,包含單表路由或者綁定表路由、多庫(kù)多表路由衩藤、笛卡爾積路由吧慢,分三部分來(lái)介紹,今天...
    天河2018閱讀 1,897評(píng)論 0 0
  • 今天匈仗,我去了楊國(guó)福那里點(diǎn)餐,這是我第一次去那里吃逢慌,是楊國(guó)福來(lái)這里的第一次悠轩。 對(duì)于大學(xué)我最糾結(jié)的事情就是,今天去一飯...
    杰克是機(jī)長(zhǎng)閱讀 480評(píng)論 1 2
  • 1涕癣、熟記快捷鍵: cmd+c, cmd+v前标,cmd+a坠韩,這幾個(gè)大家都知道,不過(guò)盡量別用在代碼拷貝上炼列。 cmd+de...
    零一_fb4d閱讀 1,323評(píng)論 0 0
  • 學(xué)校文化是一種無(wú)形的力量只搁,文化一旦被積淀和充溢出來(lái),就會(huì)發(fā)揮出規(guī)范和影響俭尖、浸潤(rùn)和激勵(lì)全體師生的重要作用氢惋。當(dāng)文化融入...
    儲(chǔ)建明閱讀 1,063評(píng)論 0 2
  • 通過(guò)翻閱大量古醫(yī)書(shū)發(fā)現(xiàn),過(guò)去古代中醫(yī)家們對(duì)“神”的理解比現(xiàn)代人更先進(jìn)科學(xué)稽犁。對(duì)他們來(lái)說(shuō)“神”指的是精神焰望,意志,知覺(jué)已亥,...
    青蓮居士LM閱讀 177評(píng)論 0 0