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ù)微信群