diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/ShadowRouteContextDecorator.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/ShadowRouteContextDecorator.java new file mode 100644 index 0000000000000..85b06be7d698a --- /dev/null +++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/ShadowRouteContextDecorator.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.shadow.route.engine; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.apache.shardingsphere.infra.route.context.RouteContext; +import org.apache.shardingsphere.infra.route.context.RouteMapper; +import org.apache.shardingsphere.infra.route.context.RouteUnit; +import org.apache.shardingsphere.shadow.rule.ShadowRule; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.Map; +import java.util.Optional; + +/** + * Shadow route context decorator. + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class ShadowRouteContextDecorator { + + /** + * Decorate route context. + * + * @param routeContext route context to be decorated + * @param rule shadow rule + * @param shadowDataSourceMappings shadow data source mappings + */ + public static void decorate(final RouteContext routeContext, final ShadowRule rule, final Map shadowDataSourceMappings) { + Collection toBeRemovedRouteUnit = new LinkedList<>(); + Collection toBeAddedRouteUnit = new LinkedList<>(); + for (RouteUnit each : routeContext.getRouteUnits()) { + String logicName = each.getDataSourceMapper().getLogicName(); + String actualName = each.getDataSourceMapper().getActualName(); + Optional sourceDataSourceName = rule.getSourceDataSourceName(actualName); + if (sourceDataSourceName.isPresent()) { + String shadowDataSourceName = shadowDataSourceMappings.get(sourceDataSourceName.get()); + toBeRemovedRouteUnit.add(each); + toBeAddedRouteUnit.add(null == shadowDataSourceName + ? new RouteUnit(new RouteMapper(logicName, sourceDataSourceName.get()), each.getTableMappers()) + : new RouteUnit(new RouteMapper(logicName, shadowDataSourceName), each.getTableMappers())); + } + } + routeContext.getRouteUnits().removeAll(toBeRemovedRouteUnit); + routeContext.getRouteUnits().addAll(toBeAddedRouteUnit); + } +} diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/ShadowRouteEngine.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/ShadowRouteEngine.java index 6e32191d80e6a..c81a83124c70c 100644 --- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/ShadowRouteEngine.java +++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/ShadowRouteEngine.java @@ -18,15 +18,8 @@ package org.apache.shardingsphere.shadow.route.engine; import org.apache.shardingsphere.infra.route.context.RouteContext; -import org.apache.shardingsphere.infra.route.context.RouteMapper; -import org.apache.shardingsphere.infra.route.context.RouteUnit; import org.apache.shardingsphere.shadow.rule.ShadowRule; -import java.util.Collection; -import java.util.LinkedList; -import java.util.Map; -import java.util.Optional; - /** * Shadow route engine. */ @@ -39,30 +32,4 @@ public interface ShadowRouteEngine { * @param rule shadow rule */ void route(RouteContext routeContext, ShadowRule rule); - - /** - * Decorate route context. - * - * @param routeContext route context to be decorated - * @param rule shadow rule - * @param shadowDataSourceMappings shadow data source mappings - */ - default void decorateRouteContext(final RouteContext routeContext, final ShadowRule rule, final Map shadowDataSourceMappings) { - Collection toBeRemovedRouteUnit = new LinkedList<>(); - Collection toBeAddedRouteUnit = new LinkedList<>(); - for (RouteUnit each : routeContext.getRouteUnits()) { - String logicName = each.getDataSourceMapper().getLogicName(); - String actualName = each.getDataSourceMapper().getActualName(); - Optional sourceDataSourceName = rule.getSourceDataSourceName(actualName); - if (sourceDataSourceName.isPresent()) { - String shadowDataSourceName = shadowDataSourceMappings.get(sourceDataSourceName.get()); - toBeRemovedRouteUnit.add(each); - toBeAddedRouteUnit.add(null == shadowDataSourceName - ? new RouteUnit(new RouteMapper(logicName, sourceDataSourceName.get()), each.getTableMappers()) - : new RouteUnit(new RouteMapper(logicName, shadowDataSourceName), each.getTableMappers())); - } - } - routeContext.getRouteUnits().removeAll(toBeRemovedRouteUnit); - routeContext.getRouteUnits().addAll(toBeAddedRouteUnit); - } } diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/AbstractShadowDMLStatementRouteEngine.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/AbstractShadowDMLStatementRouteEngine.java index a7c92037a8d70..e7d80712218e9 100644 --- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/AbstractShadowDMLStatementRouteEngine.java +++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/AbstractShadowDMLStatementRouteEngine.java @@ -17,15 +17,15 @@ package org.apache.shardingsphere.shadow.route.engine.dml; -import lombok.AccessLevel; import lombok.Getter; -import lombok.RequiredArgsConstructor; +import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation; import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext; import org.apache.shardingsphere.infra.binder.context.type.TableAvailable; import org.apache.shardingsphere.infra.hint.HintValueContext; import org.apache.shardingsphere.infra.route.context.RouteContext; import org.apache.shardingsphere.shadow.condition.ShadowColumnCondition; import org.apache.shardingsphere.shadow.condition.ShadowDetermineCondition; +import org.apache.shardingsphere.shadow.route.engine.ShadowRouteContextDecorator; import org.apache.shardingsphere.shadow.route.engine.ShadowRouteEngine; import org.apache.shardingsphere.shadow.route.engine.determiner.ColumnShadowAlgorithmDeterminer; import org.apache.shardingsphere.shadow.route.engine.determiner.HintShadowAlgorithmDeterminer; @@ -45,25 +45,23 @@ /** * Abstract shadow DML statement route engine. */ -@RequiredArgsConstructor(access = AccessLevel.PROTECTED) -@Getter +@HighFrequencyInvocation public abstract class AbstractShadowDMLStatementRouteEngine implements ShadowRouteEngine { - private final SQLStatementContext sqlStatementContext; - - private final HintValueContext hintValueContext; - private final ShadowOperationType operationType; - private final Map tableAliasNameMappings = new LinkedHashMap<>(); + private final boolean isShadow; - @Override - public final void route(final RouteContext routeContext, final ShadowRule rule) { - tableAliasNameMappings.putAll(getTableAliasNameMappings(((TableAvailable) sqlStatementContext).getTablesContext().getSimpleTables())); - decorateRouteContext(routeContext, rule, findShadowDataSourceMappings(rule)); + @Getter + private final Map tableAliasAndNameMappings; + + protected AbstractShadowDMLStatementRouteEngine(final SQLStatementContext sqlStatementContext, final HintValueContext hintValueContext, final ShadowOperationType operationType) { + this.operationType = operationType; + isShadow = hintValueContext.isShadow(); + tableAliasAndNameMappings = getTableAliasAndNameMappings(((TableAvailable) sqlStatementContext).getTablesContext().getSimpleTables()); } - private Map getTableAliasNameMappings(final Collection tableSegments) { + private Map getTableAliasAndNameMappings(final Collection tableSegments) { Map result = new LinkedHashMap<>(tableSegments.size(), 1F); for (SimpleTableSegment each : tableSegments) { String tableName = each.getTableName().getIdentifier().getValue(); @@ -73,12 +71,17 @@ private Map getTableAliasNameMappings(final Collection findShadowDataSourceMappings(final ShadowRule rule) { - Collection relatedShadowTables = rule.getRelatedShadowTables(tableAliasNameMappings.values()); + Collection relatedShadowTables = rule.getRelatedShadowTables(tableAliasAndNameMappings.values()); if (relatedShadowTables.isEmpty() && isMatchDefaultAlgorithm(rule)) { return rule.getAllShadowDataSourceMappings(); } - Map result = findBySQLComments(rule, relatedShadowTables); + Map result = findBySQLHints(rule, relatedShadowTables); return result.isEmpty() ? findByShadowColumn(rule, relatedShadowTables) : result; } @@ -87,15 +90,15 @@ private boolean isMatchDefaultAlgorithm(final ShadowRule rule) { Optional defaultAlgorithm = rule.getDefaultShadowAlgorithm(); if (defaultAlgorithm.isPresent() && defaultAlgorithm.get() instanceof HintShadowAlgorithm) { ShadowDetermineCondition determineCondition = new ShadowDetermineCondition("", ShadowOperationType.HINT_MATCH); - return HintShadowAlgorithmDeterminer.isShadow((HintShadowAlgorithm>) defaultAlgorithm.get(), determineCondition, rule, hintValueContext.isShadow()); + return HintShadowAlgorithmDeterminer.isShadow((HintShadowAlgorithm>) defaultAlgorithm.get(), determineCondition, rule, isShadow); } return false; } - private Map findBySQLComments(final ShadowRule rule, final Collection relatedShadowTables) { + private Map findBySQLHints(final ShadowRule rule, final Collection relatedShadowTables) { Map result = new LinkedHashMap<>(); for (String each : relatedShadowTables) { - if (isContainsShadowInSQLComments(rule, each, new ShadowDetermineCondition(each, operationType))) { + if (isContainsShadowInSQLHints(rule, each, new ShadowDetermineCondition(each, operationType))) { result.putAll(rule.getRelatedShadowDataSourceMappings(each)); return result; } @@ -103,9 +106,9 @@ private Map findBySQLComments(final ShadowRule rule, final Colle return result; } - private boolean isContainsShadowInSQLComments(final ShadowRule rule, final String tableName, final ShadowDetermineCondition shadowCondition) { + private boolean isContainsShadowInSQLHints(final ShadowRule rule, final String tableName, final ShadowDetermineCondition shadowCondition) { for (HintShadowAlgorithm> each : rule.getRelatedHintShadowAlgorithms(tableName)) { - if (HintShadowAlgorithmDeterminer.isShadow(each, shadowCondition, rule, hintValueContext.isShadow())) { + if (HintShadowAlgorithmDeterminer.isShadow(each, shadowCondition, rule, isShadow)) { return true; } } @@ -156,6 +159,6 @@ private boolean isMatchColumnShadowAlgorithm(final String shadowTable, final Col protected abstract Collection getShadowColumnConditions(String shadowColumnName); protected final String getSingleTableName() { - return tableAliasNameMappings.entrySet().iterator().next().getValue(); + return tableAliasAndNameMappings.entrySet().iterator().next().getValue(); } } diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowSelectStatementRouteEngine.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowSelectStatementRouteEngine.java index 49ef8e7cfbf83..9b2fb561749d9 100644 --- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowSelectStatementRouteEngine.java +++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowSelectStatementRouteEngine.java @@ -75,6 +75,6 @@ private Collection getWhereSegment() { private String extractOwnerName(final ColumnSegment columnSegment) { Optional owner = columnSegment.getOwner(); - return owner.isPresent() ? getTableAliasNameMappings().get(owner.get().getIdentifier().getValue()) : getTableAliasNameMappings().keySet().iterator().next(); + return owner.isPresent() ? getTableAliasAndNameMappings().get(owner.get().getIdentifier().getValue()) : getTableAliasAndNameMappings().keySet().iterator().next(); } } diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/impl/ShadowNonDMLStatementRouteEngine.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/impl/ShadowNonDMLStatementRouteEngine.java index dfaa4700c400f..716097a2814c9 100644 --- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/impl/ShadowNonDMLStatementRouteEngine.java +++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/impl/ShadowNonDMLStatementRouteEngine.java @@ -21,6 +21,7 @@ import org.apache.shardingsphere.infra.hint.HintValueContext; import org.apache.shardingsphere.infra.route.context.RouteContext; import org.apache.shardingsphere.shadow.condition.ShadowDetermineCondition; +import org.apache.shardingsphere.shadow.route.engine.ShadowRouteContextDecorator; import org.apache.shardingsphere.shadow.route.engine.ShadowRouteEngine; import org.apache.shardingsphere.shadow.route.engine.determiner.HintShadowAlgorithmDeterminer; import org.apache.shardingsphere.shadow.rule.ShadowRule; @@ -40,7 +41,7 @@ public final class ShadowNonDMLStatementRouteEngine implements ShadowRouteEngine @Override public void route(final RouteContext routeContext, final ShadowRule rule) { - decorateRouteContext(routeContext, rule, findShadowDataSourceMappings(rule)); + ShadowRouteContextDecorator.decorate(routeContext, rule, findShadowDataSourceMappings(rule)); } private Map findShadowDataSourceMappings(final ShadowRule rule) {