From 68a0ace306f1c9ca4cb294014267945b38170640 Mon Sep 17 00:00:00 2001 From: Zhengqiang Duan Date: Tue, 26 Nov 2024 17:55:49 +0800 Subject: [PATCH] Move PartialSQLRouteExecutor logic to TablelessRouteEngine to handle tableless sql route (#33820) * Move PartialSQLRouteExecutor logic to TablelessRouteEngine to handle tableless sql route * Remove useless spi file --- .../resource-config.json | 3 - .../infra/route/engine/SQLRouteEngine.java | 94 +++++++++--- .../route/engine/SQLRouteExecutorDecider.java | 36 ----- .../dialect/MySQLSQLRouteExecutorDecider.java | 34 ----- .../TablelessRouteEngine.java} | 10 +- .../TablelessRouteEngineFactory.java | 50 +++++++ .../tableless/router/TablelessSQLRouter.java | 47 ++++++ .../DataSourceBroadcastRouteEngine.java} | 11 +- .../type/ignore/IgnoreRouteEngine.java} | 17 ++- .../engine/type/PartialSQLRouteExecutor.java | 119 --------------- ...infra.route.engine.SQLRouteExecutorDecider | 18 --- .../route/engine/SQLRouteEngineTest.java | 123 ++++++++++------ .../MySQLSQLRouteExecutorDeciderTest.java | 38 ----- .../engine/type/AllSQLRouteExecutorTest.java | 56 ------- .../type/PartialSQLRouteExecutorTest.java | 137 ------------------ .../decider/RouteAllSQLStatementFixture.java | 23 --- ...infra.route.engine.SQLRouteExecutorDecider | 18 --- 17 files changed, 275 insertions(+), 559 deletions(-) delete mode 100644 infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/SQLRouteExecutorDecider.java delete mode 100644 infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/dialect/MySQLSQLRouteExecutorDecider.java rename infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/{SQLRouteExecutor.java => tableless/TablelessRouteEngine.java} (77%) create mode 100644 infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/TablelessRouteEngineFactory.java create mode 100644 infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/router/TablelessSQLRouter.java rename infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/{type/AllSQLRouteExecutor.java => tableless/type/broadcast/DataSourceBroadcastRouteEngine.java} (77%) rename infra/route/src/{test/java/org/apache/shardingsphere/infra/route/fixture/decider/SQLRouteExecutorDeciderFixture.java => main/java/org/apache/shardingsphere/infra/route/engine/tableless/type/ignore/IgnoreRouteEngine.java} (56%) delete mode 100644 infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/type/PartialSQLRouteExecutor.java delete mode 100644 infra/route/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.route.engine.SQLRouteExecutorDecider delete mode 100644 infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/dialect/MySQLSQLRouteExecutorDeciderTest.java delete mode 100644 infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/type/AllSQLRouteExecutorTest.java delete mode 100644 infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/type/PartialSQLRouteExecutorTest.java delete mode 100644 infra/route/src/test/java/org/apache/shardingsphere/infra/route/fixture/decider/RouteAllSQLStatementFixture.java delete mode 100644 infra/route/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.route.engine.SQLRouteExecutorDecider diff --git a/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere/generated-reachability-metadata/resource-config.json b/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere/generated-reachability-metadata/resource-config.json index 2c4176936c6ca..941a363ba7a0e 100644 --- a/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere/generated-reachability-metadata/resource-config.json +++ b/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere/generated-reachability-metadata/resource-config.json @@ -261,9 +261,6 @@ }, { "condition":{"typeReachable":"org.apache.shardingsphere.infra.route.engine.type.PartialSQLRouteExecutor"}, "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.infra.route.SQLRouter\\E" - }, { - "condition":{"typeReachable":"org.apache.shardingsphere.infra.route.engine.SQLRouteEngine"}, - "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.infra.route.engine.SQLRouteExecutorDecider\\E" }, { "condition":{"typeReachable":"org.apache.shardingsphere.proxy.frontend.mysql.command.query.text.query.MySQLComQueryPacketExecutor"}, "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.infra.rule.builder.database.DatabaseRuleBuilder\\E" diff --git a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/SQLRouteEngine.java b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/SQLRouteEngine.java index 476934dc43bae..fa951c44162c2 100644 --- a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/SQLRouteEngine.java +++ b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/SQLRouteEngine.java @@ -17,51 +17,111 @@ package org.apache.shardingsphere.infra.route.engine; -import lombok.RequiredArgsConstructor; import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation; import org.apache.shardingsphere.infra.config.props.ConfigurationProperties; +import org.apache.shardingsphere.infra.exception.kernel.syntax.hint.DataSourceHintNotExistsException; +import org.apache.shardingsphere.infra.hint.HintManager; +import org.apache.shardingsphere.infra.hint.HintValueContext; import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; +import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit; import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData; +import org.apache.shardingsphere.infra.route.SQLRouter; import org.apache.shardingsphere.infra.route.context.RouteContext; -import org.apache.shardingsphere.infra.route.engine.type.AllSQLRouteExecutor; -import org.apache.shardingsphere.infra.route.engine.type.PartialSQLRouteExecutor; +import org.apache.shardingsphere.infra.route.context.RouteMapper; +import org.apache.shardingsphere.infra.route.context.RouteUnit; +import org.apache.shardingsphere.infra.route.engine.tableless.router.TablelessSQLRouter; +import org.apache.shardingsphere.infra.route.type.DataSourceSQLRouter; +import org.apache.shardingsphere.infra.route.type.DecorateSQLRouter; +import org.apache.shardingsphere.infra.route.type.EntranceSQLRouter; +import org.apache.shardingsphere.infra.route.type.TableSQLRouter; import org.apache.shardingsphere.infra.rule.ShardingSphereRule; import org.apache.shardingsphere.infra.session.query.QueryContext; -import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader; -import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement; +import org.apache.shardingsphere.infra.spi.type.ordered.OrderedSPILoader; import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; /** * SQL route engine. */ @HighFrequencyInvocation -@RequiredArgsConstructor public final class SQLRouteEngine { - private final Collection rules; - private final ConfigurationProperties props; + @SuppressWarnings("rawtypes") + private final Map tableRouters; + + @SuppressWarnings("rawtypes") + private final Map dataSourceRouters; + + @SuppressWarnings("rawtypes") + public SQLRouteEngine(final Collection rules, final ConfigurationProperties props) { + this.props = props; + Map routers = OrderedSPILoader.getServices(SQLRouter.class, rules); + tableRouters = filterRouters(routers, TableSQLRouter.class); + dataSourceRouters = filterRouters(routers, DataSourceSQLRouter.class); + } + + @SuppressWarnings("rawtypes") + private Map filterRouters(final Map routers, final Class targetClass) { + Map result = new LinkedHashMap<>(); + for (Entry entry : routers.entrySet()) { + if (targetClass.isAssignableFrom(entry.getValue().getClass())) { + result.put(entry.getKey(), entry.getValue()); + } + } + return result; + } + /** - * Route SQL. + * Route. * * @param queryContext query context * @param globalRuleMetaData global rule meta data - * @param database database + * @param database sharding sphere database * @return route context */ public RouteContext route(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database) { - SQLRouteExecutor executor = isNeedRouteAll(queryContext.getSqlStatementContext().getSqlStatement()) ? new AllSQLRouteExecutor() : new PartialSQLRouteExecutor(rules, props); - return executor.route(queryContext, globalRuleMetaData, database); + RouteContext result = new RouteContext(); + Optional dataSourceName = findDataSourceByHint(queryContext.getHintValueContext(), database.getResourceMetaData().getStorageUnits()); + if (dataSourceName.isPresent()) { + result.getRouteUnits().add(new RouteUnit(new RouteMapper(dataSourceName.get(), dataSourceName.get()), Collections.emptyList())); + return result; + } + result = route(queryContext, globalRuleMetaData, database, tableRouters, result); + result = new TablelessSQLRouter().route(queryContext, globalRuleMetaData, database, result); + result = route(queryContext, globalRuleMetaData, database, dataSourceRouters, result); + if (result.getRouteUnits().isEmpty() && 1 == database.getResourceMetaData().getStorageUnits().size()) { + String singleDataSourceName = database.getResourceMetaData().getStorageUnits().keySet().iterator().next(); + result.getRouteUnits().add(new RouteUnit(new RouteMapper(singleDataSourceName, singleDataSourceName), Collections.emptyList())); + } + return result; } - private boolean isNeedRouteAll(final SQLStatement sqlStatement) { - for (SQLRouteExecutorDecider each : ShardingSphereServiceLoader.getServiceInstances(SQLRouteExecutorDecider.class)) { - if (each.isNeedRouteAll(sqlStatement)) { - return true; + @SuppressWarnings({"unchecked", "rawtypes"}) + private RouteContext route(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database, final Map routers, + final RouteContext routeContext) { + RouteContext result = routeContext; + for (Entry entry : routers.entrySet()) { + if (result.getRouteUnits().isEmpty() && entry.getValue() instanceof EntranceSQLRouter) { + result = ((EntranceSQLRouter) entry.getValue()).createRouteContext(queryContext, globalRuleMetaData, database, entry.getKey(), props); + } else if (entry.getValue() instanceof DecorateSQLRouter) { + ((DecorateSQLRouter) entry.getValue()).decorateRouteContext(result, queryContext, database, entry.getKey(), props); } } - return false; + return result; + } + + private Optional findDataSourceByHint(final HintValueContext hintValueContext, final Map storageUnits) { + Optional result = HintManager.isInstantiated() && HintManager.getDataSourceName().isPresent() ? HintManager.getDataSourceName() : hintValueContext.findHintDataSourceName(); + if (result.isPresent() && !storageUnits.containsKey(result.get())) { + throw new DataSourceHintNotExistsException(result.get()); + } + return result; } } diff --git a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/SQLRouteExecutorDecider.java b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/SQLRouteExecutorDecider.java deleted file mode 100644 index a51cdc5380259..0000000000000 --- a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/SQLRouteExecutorDecider.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.infra.route.engine; - -import org.apache.shardingsphere.infra.spi.annotation.SingletonSPI; -import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement; - -/** - * SQL route executor decider. - */ -@SingletonSPI -public interface SQLRouteExecutorDecider { - - /** - * Judge is need route all resources. - * - * @param sqlStatement SQL statement - * @return is need route all resources or not - */ - boolean isNeedRouteAll(SQLStatement sqlStatement); -} diff --git a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/dialect/MySQLSQLRouteExecutorDecider.java b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/dialect/MySQLSQLRouteExecutorDecider.java deleted file mode 100644 index 58733c763ff1d..0000000000000 --- a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/dialect/MySQLSQLRouteExecutorDecider.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.infra.route.engine.dialect; - -import org.apache.shardingsphere.infra.route.engine.SQLRouteExecutorDecider; -import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement; -import org.apache.shardingsphere.sql.parser.statement.mysql.dal.MySQLShowTableStatusStatement; -import org.apache.shardingsphere.sql.parser.statement.mysql.dal.MySQLShowTablesStatement; - -/** - * SQL route executor decider for MySQL. - */ -public final class MySQLSQLRouteExecutorDecider implements SQLRouteExecutorDecider { - - @Override - public boolean isNeedRouteAll(final SQLStatement sqlStatement) { - return sqlStatement instanceof MySQLShowTablesStatement || sqlStatement instanceof MySQLShowTableStatusStatement; - } -} diff --git a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/SQLRouteExecutor.java b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/TablelessRouteEngine.java similarity index 77% rename from infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/SQLRouteExecutor.java rename to infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/TablelessRouteEngine.java index f5d91e2b5e421..07873b74a052c 100644 --- a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/SQLRouteExecutor.java +++ b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/TablelessRouteEngine.java @@ -15,25 +15,23 @@ * limitations under the License. */ -package org.apache.shardingsphere.infra.route.engine; +package org.apache.shardingsphere.infra.route.engine.tableless; import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData; import org.apache.shardingsphere.infra.route.context.RouteContext; -import org.apache.shardingsphere.infra.session.query.QueryContext; /** - * SQL route executor. + * Tableless route engine. */ -public interface SQLRouteExecutor { +public interface TablelessRouteEngine { /** * Route. * - * @param queryContext query context * @param globalRuleMetaData global rule meta data * @param database database * @return route context */ - RouteContext route(QueryContext queryContext, RuleMetaData globalRuleMetaData, ShardingSphereDatabase database); + RouteContext route(RuleMetaData globalRuleMetaData, ShardingSphereDatabase database); } diff --git a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/TablelessRouteEngineFactory.java b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/TablelessRouteEngineFactory.java new file mode 100644 index 0000000000000..498788e644211 --- /dev/null +++ b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/TablelessRouteEngineFactory.java @@ -0,0 +1,50 @@ +/* + * 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.infra.route.engine.tableless; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext; +import org.apache.shardingsphere.infra.route.engine.tableless.type.broadcast.DataSourceBroadcastRouteEngine; +import org.apache.shardingsphere.infra.route.engine.tableless.type.ignore.IgnoreRouteEngine; +import org.apache.shardingsphere.infra.session.query.QueryContext; +import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement; +import org.apache.shardingsphere.sql.parser.statement.core.statement.dal.ShowTableStatusStatement; +import org.apache.shardingsphere.sql.parser.statement.core.statement.dal.ShowTablesStatement; + +/** + * Tableless route engine factory. + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class TablelessRouteEngineFactory { + + /** + * Create new instance of route engine. + * + * @param queryContext query context + * @return created instance + */ + public static TablelessRouteEngine newInstance(final QueryContext queryContext) { + SQLStatementContext sqlStatementContext = queryContext.getSqlStatementContext(); + SQLStatement sqlStatement = sqlStatementContext.getSqlStatement(); + if (sqlStatement instanceof ShowTablesStatement || sqlStatement instanceof ShowTableStatusStatement) { + return new DataSourceBroadcastRouteEngine(); + } + return new IgnoreRouteEngine(); + } +} diff --git a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/router/TablelessSQLRouter.java b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/router/TablelessSQLRouter.java new file mode 100644 index 0000000000000..1d7cde9ae7659 --- /dev/null +++ b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/router/TablelessSQLRouter.java @@ -0,0 +1,47 @@ +/* + * 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.infra.route.engine.tableless.router; + +import org.apache.shardingsphere.infra.binder.context.extractor.SQLStatementContextExtractor; +import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; +import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData; +import org.apache.shardingsphere.infra.route.context.RouteContext; +import org.apache.shardingsphere.infra.route.engine.tableless.TablelessRouteEngineFactory; +import org.apache.shardingsphere.infra.session.query.QueryContext; + +/** + * Tableless sql router. + */ +public final class TablelessSQLRouter { + + /** + * Route. + * + * @param queryContext query context + * @param globalRuleMetaData global rule meta data + * @param database sharding sphere database + * @param routeContext route context + * @return route context + */ + public RouteContext route(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database, final RouteContext routeContext) { + if (routeContext.getRouteUnits().isEmpty() && SQLStatementContextExtractor.getTableNames(database, queryContext.getSqlStatementContext()).isEmpty()) { + return TablelessRouteEngineFactory.newInstance(queryContext).route(globalRuleMetaData, database); + } + return routeContext; + } +} diff --git a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/type/AllSQLRouteExecutor.java b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/type/broadcast/DataSourceBroadcastRouteEngine.java similarity index 77% rename from infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/type/AllSQLRouteExecutor.java rename to infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/type/broadcast/DataSourceBroadcastRouteEngine.java index 3733f14b1b76c..95e8afde12daf 100644 --- a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/type/AllSQLRouteExecutor.java +++ b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/type/broadcast/DataSourceBroadcastRouteEngine.java @@ -15,25 +15,24 @@ * limitations under the License. */ -package org.apache.shardingsphere.infra.route.engine.type; +package org.apache.shardingsphere.infra.route.engine.tableless.type.broadcast; import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData; 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.infra.route.engine.SQLRouteExecutor; -import org.apache.shardingsphere.infra.session.query.QueryContext; +import org.apache.shardingsphere.infra.route.engine.tableless.TablelessRouteEngine; import java.util.Collections; /** - * All SQL route executor. + * Datasource broadcast route engine. */ -public final class AllSQLRouteExecutor implements SQLRouteExecutor { +public final class DataSourceBroadcastRouteEngine implements TablelessRouteEngine { @Override - public RouteContext route(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database) { + public RouteContext route(final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database) { RouteContext result = new RouteContext(); for (String each : database.getResourceMetaData().getStorageUnits().keySet()) { result.getRouteUnits().add(new RouteUnit(new RouteMapper(each, each), Collections.emptyList())); diff --git a/infra/route/src/test/java/org/apache/shardingsphere/infra/route/fixture/decider/SQLRouteExecutorDeciderFixture.java b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/type/ignore/IgnoreRouteEngine.java similarity index 56% rename from infra/route/src/test/java/org/apache/shardingsphere/infra/route/fixture/decider/SQLRouteExecutorDeciderFixture.java rename to infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/type/ignore/IgnoreRouteEngine.java index 049e808045fe1..054910c48f59c 100644 --- a/infra/route/src/test/java/org/apache/shardingsphere/infra/route/fixture/decider/SQLRouteExecutorDeciderFixture.java +++ b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/tableless/type/ignore/IgnoreRouteEngine.java @@ -15,15 +15,20 @@ * limitations under the License. */ -package org.apache.shardingsphere.infra.route.fixture.decider; +package org.apache.shardingsphere.infra.route.engine.tableless.type.ignore; -import org.apache.shardingsphere.infra.route.engine.SQLRouteExecutorDecider; -import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement; +import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; +import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData; +import org.apache.shardingsphere.infra.route.context.RouteContext; +import org.apache.shardingsphere.infra.route.engine.tableless.TablelessRouteEngine; -public final class SQLRouteExecutorDeciderFixture implements SQLRouteExecutorDecider { +/** + * Ignore route engine. + */ +public final class IgnoreRouteEngine implements TablelessRouteEngine { @Override - public boolean isNeedRouteAll(final SQLStatement sqlStatement) { - return sqlStatement instanceof RouteAllSQLStatementFixture; + public RouteContext route(final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database) { + return new RouteContext(); } } diff --git a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/type/PartialSQLRouteExecutor.java b/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/type/PartialSQLRouteExecutor.java deleted file mode 100644 index 9b08097270e3b..0000000000000 --- a/infra/route/src/main/java/org/apache/shardingsphere/infra/route/engine/type/PartialSQLRouteExecutor.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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.infra.route.engine.type; - -import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation; -import org.apache.shardingsphere.infra.config.props.ConfigurationProperties; -import org.apache.shardingsphere.infra.exception.kernel.syntax.hint.DataSourceHintNotExistsException; -import org.apache.shardingsphere.infra.hint.HintManager; -import org.apache.shardingsphere.infra.hint.HintValueContext; -import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; -import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit; -import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData; -import org.apache.shardingsphere.infra.route.SQLRouter; -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.infra.route.engine.SQLRouteExecutor; -import org.apache.shardingsphere.infra.route.type.DataSourceSQLRouter; -import org.apache.shardingsphere.infra.route.type.DecorateSQLRouter; -import org.apache.shardingsphere.infra.route.type.EntranceSQLRouter; -import org.apache.shardingsphere.infra.route.type.TableSQLRouter; -import org.apache.shardingsphere.infra.rule.ShardingSphereRule; -import org.apache.shardingsphere.infra.session.query.QueryContext; -import org.apache.shardingsphere.infra.spi.type.ordered.OrderedSPILoader; - -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; - -/** - * Partial SQL route executor. - */ -@HighFrequencyInvocation -public final class PartialSQLRouteExecutor implements SQLRouteExecutor { - - private final ConfigurationProperties props; - - @SuppressWarnings("rawtypes") - private final Map tableRouters; - - @SuppressWarnings("rawtypes") - private final Map dataSourceRouters; - - @SuppressWarnings("rawtypes") - public PartialSQLRouteExecutor(final Collection rules, final ConfigurationProperties props) { - this.props = props; - Map routers = OrderedSPILoader.getServices(SQLRouter.class, rules); - tableRouters = filterRouters(routers, TableSQLRouter.class); - dataSourceRouters = filterRouters(routers, DataSourceSQLRouter.class); - } - - @SuppressWarnings("rawtypes") - private Map filterRouters(final Map routers, final Class targetClass) { - Map result = new LinkedHashMap<>(); - for (Entry entry : routers.entrySet()) { - if (targetClass.isAssignableFrom(entry.getValue().getClass())) { - result.put(entry.getKey(), entry.getValue()); - } - } - return result; - } - - @Override - public RouteContext route(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database) { - RouteContext result = new RouteContext(); - Optional dataSourceName = findDataSourceByHint(queryContext.getHintValueContext(), database.getResourceMetaData().getStorageUnits()); - if (dataSourceName.isPresent()) { - result.getRouteUnits().add(new RouteUnit(new RouteMapper(dataSourceName.get(), dataSourceName.get()), Collections.emptyList())); - return result; - } - result = route(queryContext, globalRuleMetaData, database, tableRouters, result); - result = route(queryContext, globalRuleMetaData, database, dataSourceRouters, result); - if (result.getRouteUnits().isEmpty() && 1 == database.getResourceMetaData().getStorageUnits().size()) { - String singleDataSourceName = database.getResourceMetaData().getStorageUnits().keySet().iterator().next(); - result.getRouteUnits().add(new RouteUnit(new RouteMapper(singleDataSourceName, singleDataSourceName), Collections.emptyList())); - } - return result; - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private RouteContext route(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database, final Map routers, - final RouteContext routeContext) { - RouteContext result = routeContext; - for (Entry entry : routers.entrySet()) { - if (result.getRouteUnits().isEmpty() && entry.getValue() instanceof EntranceSQLRouter) { - result = ((EntranceSQLRouter) entry.getValue()).createRouteContext(queryContext, globalRuleMetaData, database, entry.getKey(), props); - } else if (entry.getValue() instanceof DecorateSQLRouter) { - ((DecorateSQLRouter) entry.getValue()).decorateRouteContext(result, queryContext, database, entry.getKey(), props); - } - } - return result; - } - - private Optional findDataSourceByHint(final HintValueContext hintValueContext, final Map storageUnits) { - Optional result = HintManager.isInstantiated() && HintManager.getDataSourceName().isPresent() ? HintManager.getDataSourceName() : hintValueContext.findHintDataSourceName(); - if (result.isPresent() && !storageUnits.containsKey(result.get())) { - throw new DataSourceHintNotExistsException(result.get()); - } - return result; - } -} diff --git a/infra/route/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.route.engine.SQLRouteExecutorDecider b/infra/route/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.route.engine.SQLRouteExecutorDecider deleted file mode 100644 index fd8bcd3c97be4..0000000000000 --- a/infra/route/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.route.engine.SQLRouteExecutorDecider +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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. -# - -org.apache.shardingsphere.infra.route.engine.dialect.MySQLSQLRouteExecutorDecider diff --git a/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/SQLRouteEngineTest.java b/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/SQLRouteEngineTest.java index ec6cd2ee585c9..9a075e370364a 100644 --- a/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/SQLRouteEngineTest.java +++ b/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/SQLRouteEngineTest.java @@ -18,81 +18,120 @@ package org.apache.shardingsphere.infra.route.engine; import org.apache.shardingsphere.infra.binder.context.statement.CommonSQLStatementContext; -import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext; import org.apache.shardingsphere.infra.config.props.ConfigurationProperties; -import org.apache.shardingsphere.infra.database.core.type.DatabaseType; +import org.apache.shardingsphere.infra.database.core.DefaultDatabase; +import org.apache.shardingsphere.infra.exception.kernel.syntax.hint.DataSourceHintNotExistsException; +import org.apache.shardingsphere.infra.hint.HintManager; import org.apache.shardingsphere.infra.hint.HintValueContext; import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; -import org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData; +import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit; import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData; import org.apache.shardingsphere.infra.route.context.RouteContext; -import org.apache.shardingsphere.infra.route.context.RouteUnit; -import org.apache.shardingsphere.infra.route.fixture.decider.RouteAllSQLStatementFixture; -import org.apache.shardingsphere.infra.route.fixture.rule.RouteFailureRuleFixture; +import org.apache.shardingsphere.infra.route.fixture.rule.DataSourceRouteRuleFixture; import org.apache.shardingsphere.infra.route.fixture.rule.TableRouteRuleFixture; import org.apache.shardingsphere.infra.session.connection.ConnectionContext; import org.apache.shardingsphere.infra.session.query.QueryContext; -import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.Properties; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +@ExtendWith(MockitoExtension.class) class SQLRouteEngineTest { + private final SQLRouteEngine sqlRouteEngine = + new SQLRouteEngine(Arrays.asList(new TableRouteRuleFixture(), new DataSourceRouteRuleFixture()), new ConfigurationProperties(new Properties())); + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private ShardingSphereDatabase database; + + @Mock + private ShardingSphereMetaData metaData; + + @Mock + private CommonSQLStatementContext sqlStatementContext; + + @Mock + private HintValueContext hintValueContext; + + private final ConnectionContext connectionContext = new ConnectionContext(Collections::emptySet); + + @BeforeEach + void setup() { + Map storageUnits = new HashMap<>(2, 1F); + storageUnits.put("ds_0", mock(StorageUnit.class)); + storageUnits.put("ds_1", mock(StorageUnit.class)); + when(database.getResourceMetaData().getStorageUnits()).thenReturn(storageUnits); + connectionContext.setCurrentDatabaseName(DefaultDatabase.LOGIC_NAME); + } + + @Test + void assertRouteBySQLCommentHint() { + when(hintValueContext.findHintDataSourceName()).thenReturn(Optional.of("ds_1")); + QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), hintValueContext, connectionContext, metaData); + RouteContext routeContext = sqlRouteEngine.route(queryContext, mock(RuleMetaData.class), database); + assertThat(routeContext.getRouteUnits().size(), is(1)); + assertThat(routeContext.getRouteUnits().iterator().next().getDataSourceMapper().getActualName(), is("ds_1")); + } + @Test - void assertRouteToPartial() { - ShardingSphereDatabase database = createDatabase(); - QueryContext queryContext = mockQueryContext(database, mock(SQLStatement.class)); - RouteContext actual = - new SQLRouteEngine(Collections.singleton(new TableRouteRuleFixture()), new ConfigurationProperties(new Properties())).route(queryContext, mock(RuleMetaData.class), database); - assertThat(actual.getRouteUnits().size(), is(1)); - RouteUnit routeUnit = actual.getRouteUnits().iterator().next(); - assertThat(routeUnit.getDataSourceMapper().getLogicName(), is("ds")); - assertThat(routeUnit.getDataSourceMapper().getActualName(), is("ds_0")); - assertTrue(routeUnit.getTableMappers().isEmpty()); + void assertRouteByHintManagerHint() { + try (HintManager hintManager = HintManager.getInstance()) { + hintManager.setDataSourceName("ds_1"); + QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext(), connectionContext, metaData); + RouteContext routeContext = sqlRouteEngine.route(queryContext, mock(RuleMetaData.class), database); + assertThat(routeContext.getRouteUnits().size(), is(1)); + assertThat(routeContext.getRouteUnits().iterator().next().getDataSourceMapper().getActualName(), is("ds_1")); + } } @Test - void assertRouteToAll() { - ShardingSphereDatabase database = createDatabase(); - QueryContext queryContext = mockQueryContext(database, new RouteAllSQLStatementFixture()); - RouteContext actual = - new SQLRouteEngine(Collections.singleton(new TableRouteRuleFixture()), new ConfigurationProperties(new Properties())).route(queryContext, mock(RuleMetaData.class), database); - assertTrue(actual.getRouteUnits().isEmpty()); + void assertRouteBySQLCommentHintWithException() { + when(hintValueContext.findHintDataSourceName()).thenReturn(Optional.of("ds_3")); + QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), hintValueContext, connectionContext, metaData); + assertThrows(DataSourceHintNotExistsException.class, () -> sqlRouteEngine.route(queryContext, mock(RuleMetaData.class), database)); } @Test - void assertRouteFailed() { - ShardingSphereDatabase database = createDatabase(); - QueryContext queryContext = mockQueryContext(database, mock(SQLStatement.class)); - assertThrows(UnsupportedOperationException.class, () -> new SQLRouteEngine( - Collections.singleton(new RouteFailureRuleFixture()), new ConfigurationProperties(new Properties())).route(queryContext, mock(RuleMetaData.class), database)); + void assertRouteByHintManagerHintWithException() { + try (HintManager hintManager = HintManager.getInstance()) { + hintManager.setDataSourceName("ds_3"); + QueryContext logicSQL = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext(), connectionContext, metaData); + assertThrows(DataSourceHintNotExistsException.class, () -> sqlRouteEngine.route(logicSQL, mock(RuleMetaData.class), database)); + } } - private ShardingSphereDatabase createDatabase() { - RuleMetaData ruleMetaData = new RuleMetaData(Collections.singleton(new TableRouteRuleFixture())); - return new ShardingSphereDatabase("logic_schema", mock(DatabaseType.class), mock(ResourceMetaData.class, RETURNS_DEEP_STUBS), ruleMetaData, Collections.emptyMap()); + @Test + void assertRouteWithShardingSphereRule() { + QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext(), connectionContext, metaData); + RouteContext routeContext = sqlRouteEngine.route(queryContext, mock(RuleMetaData.class), database); + assertThat(routeContext.getRouteUnits().size(), is(1)); + assertThat(routeContext.getRouteUnits().iterator().next().getDataSourceMapper().getActualName(), is("ds_0")); } - private QueryContext mockQueryContext(final ShardingSphereDatabase database, final SQLStatement sqlStatement) { - ConnectionContext connectionContext = mock(ConnectionContext.class); - when(connectionContext.getCurrentDatabaseName()).thenReturn(Optional.of("logic_schema")); - ShardingSphereMetaData metaData = mock(ShardingSphereMetaData.class); - when(metaData.getDatabase("logic_schema")).thenReturn(database); - when(metaData.containsDatabase("logic_schema")).thenReturn(true); - SQLStatementContext sqlStatementContext = mock(CommonSQLStatementContext.class); - when(sqlStatementContext.getSqlStatement()).thenReturn(sqlStatement); - return new QueryContext(sqlStatementContext, "SELECT 1", Collections.emptyList(), new HintValueContext(), connectionContext, metaData); + @Test + void assertRouteWithEmptyRouteContext() { + SQLRouteEngine sqlRouteEngine = new SQLRouteEngine(Collections.emptyList(), new ConfigurationProperties(new Properties())); + QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext(), connectionContext, metaData); + when(database.getResourceMetaData().getStorageUnits()).thenReturn(Collections.singletonMap("ds_0", mock(StorageUnit.class))); + RouteContext routeContext = sqlRouteEngine.route(queryContext, mock(RuleMetaData.class), database); + assertThat(routeContext.getRouteUnits().size(), is(1)); + assertThat(routeContext.getRouteUnits().iterator().next().getDataSourceMapper().getActualName(), is("ds_0")); } } diff --git a/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/dialect/MySQLSQLRouteExecutorDeciderTest.java b/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/dialect/MySQLSQLRouteExecutorDeciderTest.java deleted file mode 100644 index 573a7311a6f62..0000000000000 --- a/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/dialect/MySQLSQLRouteExecutorDeciderTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.infra.route.engine.dialect; - -import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement; -import org.apache.shardingsphere.sql.parser.statement.mysql.dal.MySQLShowTableStatusStatement; -import org.apache.shardingsphere.sql.parser.statement.mysql.dal.MySQLShowTablesStatement; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; - -class MySQLSQLRouteExecutorDeciderTest { - - @Test - void assertIsNeedRouteAll() { - MySQLSQLRouteExecutorDecider decider = new MySQLSQLRouteExecutorDecider(); - assertTrue(decider.isNeedRouteAll(new MySQLShowTablesStatement())); - assertTrue(decider.isNeedRouteAll(new MySQLShowTableStatusStatement())); - assertFalse(decider.isNeedRouteAll(mock(SQLStatement.class))); - } -} diff --git a/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/type/AllSQLRouteExecutorTest.java b/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/type/AllSQLRouteExecutorTest.java deleted file mode 100644 index edc93dd408222..0000000000000 --- a/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/type/AllSQLRouteExecutorTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.infra.route.engine.type; - -import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; -import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData; -import org.apache.shardingsphere.infra.route.context.RouteContext; -import org.apache.shardingsphere.infra.route.context.RouteUnit; -import org.apache.shardingsphere.infra.session.connection.ConnectionContext; -import org.apache.shardingsphere.infra.session.query.QueryContext; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.RETURNS_DEEP_STUBS; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class AllSQLRouteExecutorTest { - - @Test - void assertRouteSuccess() { - String name = "test"; - ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS); - when(database.getResourceMetaData().getStorageUnits().keySet()).thenReturn(Stream.of(name).collect(Collectors.toSet())); - AllSQLRouteExecutor allSQLRouteExecutor = new AllSQLRouteExecutor(); - QueryContext queryContext = mock(QueryContext.class); - when(queryContext.getConnectionContext()).thenReturn(new ConnectionContext(Collections::emptySet)); - RouteContext actual = allSQLRouteExecutor.route(queryContext, mock(RuleMetaData.class), database); - assertThat(actual.getRouteUnits().size(), is(1)); - RouteUnit routeUnit = actual.getRouteUnits().iterator().next(); - assertThat(routeUnit.getDataSourceMapper().getLogicName(), is(name)); - assertThat(routeUnit.getDataSourceMapper().getActualName(), is(name)); - assertTrue(routeUnit.getTableMappers().isEmpty()); - } -} diff --git a/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/type/PartialSQLRouteExecutorTest.java b/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/type/PartialSQLRouteExecutorTest.java deleted file mode 100644 index 2c30dfa2dcb06..0000000000000 --- a/infra/route/src/test/java/org/apache/shardingsphere/infra/route/engine/type/PartialSQLRouteExecutorTest.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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.infra.route.engine.type; - -import org.apache.shardingsphere.infra.binder.context.statement.CommonSQLStatementContext; -import org.apache.shardingsphere.infra.config.props.ConfigurationProperties; -import org.apache.shardingsphere.infra.database.core.DefaultDatabase; -import org.apache.shardingsphere.infra.exception.kernel.syntax.hint.DataSourceHintNotExistsException; -import org.apache.shardingsphere.infra.hint.HintManager; -import org.apache.shardingsphere.infra.hint.HintValueContext; -import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; -import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; -import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit; -import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData; -import org.apache.shardingsphere.infra.route.context.RouteContext; -import org.apache.shardingsphere.infra.route.fixture.rule.DataSourceRouteRuleFixture; -import org.apache.shardingsphere.infra.route.fixture.rule.TableRouteRuleFixture; -import org.apache.shardingsphere.infra.session.connection.ConnectionContext; -import org.apache.shardingsphere.infra.session.query.QueryContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.Properties; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class PartialSQLRouteExecutorTest { - - private final PartialSQLRouteExecutor sqlRouteExecutor = - new PartialSQLRouteExecutor(Arrays.asList(new TableRouteRuleFixture(), new DataSourceRouteRuleFixture()), new ConfigurationProperties(new Properties())); - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private ShardingSphereDatabase database; - - @Mock - private ShardingSphereMetaData metaData; - - @Mock - private CommonSQLStatementContext sqlStatementContext; - - @Mock - private HintValueContext hintValueContext; - - private final ConnectionContext connectionContext = new ConnectionContext(Collections::emptySet); - - @BeforeEach - void setup() { - Map storageUnits = new HashMap<>(2, 1F); - storageUnits.put("ds_0", mock(StorageUnit.class)); - storageUnits.put("ds_1", mock(StorageUnit.class)); - when(database.getResourceMetaData().getStorageUnits()).thenReturn(storageUnits); - connectionContext.setCurrentDatabaseName(DefaultDatabase.LOGIC_NAME); - } - - @Test - void assertRouteBySQLCommentHint() { - when(hintValueContext.findHintDataSourceName()).thenReturn(Optional.of("ds_1")); - QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), hintValueContext, connectionContext, metaData); - RouteContext routeContext = sqlRouteExecutor.route(queryContext, mock(RuleMetaData.class), database); - assertThat(routeContext.getRouteUnits().size(), is(1)); - assertThat(routeContext.getRouteUnits().iterator().next().getDataSourceMapper().getActualName(), is("ds_1")); - } - - @Test - void assertRouteByHintManagerHint() { - try (HintManager hintManager = HintManager.getInstance()) { - hintManager.setDataSourceName("ds_1"); - QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext(), connectionContext, metaData); - RouteContext routeContext = sqlRouteExecutor.route(queryContext, mock(RuleMetaData.class), database); - assertThat(routeContext.getRouteUnits().size(), is(1)); - assertThat(routeContext.getRouteUnits().iterator().next().getDataSourceMapper().getActualName(), is("ds_1")); - } - } - - @Test - void assertRouteBySQLCommentHintWithException() { - when(hintValueContext.findHintDataSourceName()).thenReturn(Optional.of("ds_3")); - QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), hintValueContext, connectionContext, metaData); - assertThrows(DataSourceHintNotExistsException.class, () -> sqlRouteExecutor.route(queryContext, mock(RuleMetaData.class), database)); - } - - @Test - void assertRouteByHintManagerHintWithException() { - try (HintManager hintManager = HintManager.getInstance()) { - hintManager.setDataSourceName("ds_3"); - QueryContext logicSQL = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext(), connectionContext, metaData); - assertThrows(DataSourceHintNotExistsException.class, () -> sqlRouteExecutor.route(logicSQL, mock(RuleMetaData.class), database)); - } - } - - @Test - void assertRouteWithShardingSphereRule() { - QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext(), connectionContext, metaData); - RouteContext routeContext = sqlRouteExecutor.route(queryContext, mock(RuleMetaData.class), database); - assertThat(routeContext.getRouteUnits().size(), is(1)); - assertThat(routeContext.getRouteUnits().iterator().next().getDataSourceMapper().getActualName(), is("ds_0")); - } - - @Test - void assertRouteWithEmptyRouteContext() { - PartialSQLRouteExecutor sqlRouteExecutor = new PartialSQLRouteExecutor(Collections.emptyList(), new ConfigurationProperties(new Properties())); - QueryContext queryContext = new QueryContext(sqlStatementContext, "", Collections.emptyList(), new HintValueContext(), connectionContext, metaData); - when(database.getResourceMetaData().getStorageUnits()).thenReturn(Collections.singletonMap("ds_0", mock(StorageUnit.class))); - RouteContext routeContext = sqlRouteExecutor.route(queryContext, mock(RuleMetaData.class), database); - assertThat(routeContext.getRouteUnits().size(), is(1)); - assertThat(routeContext.getRouteUnits().iterator().next().getDataSourceMapper().getActualName(), is("ds_0")); - } -} diff --git a/infra/route/src/test/java/org/apache/shardingsphere/infra/route/fixture/decider/RouteAllSQLStatementFixture.java b/infra/route/src/test/java/org/apache/shardingsphere/infra/route/fixture/decider/RouteAllSQLStatementFixture.java deleted file mode 100644 index a8cf0185ae7ec..0000000000000 --- a/infra/route/src/test/java/org/apache/shardingsphere/infra/route/fixture/decider/RouteAllSQLStatementFixture.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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.infra.route.fixture.decider; - -import org.apache.shardingsphere.sql.parser.statement.core.statement.AbstractSQLStatement; - -public final class RouteAllSQLStatementFixture extends AbstractSQLStatement { -} diff --git a/infra/route/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.route.engine.SQLRouteExecutorDecider b/infra/route/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.route.engine.SQLRouteExecutorDecider deleted file mode 100644 index 2e169b8c81cf8..0000000000000 --- a/infra/route/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.route.engine.SQLRouteExecutorDecider +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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. -# - -org.apache.shardingsphere.infra.route.fixture.decider.SQLRouteExecutorDeciderFixture