You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2026/08/15 13:46:42 UTC
(shardingsphere) branch master updated: Add SQL router integration tests for subquery scenarios (#39471)
This is an automated email from the ASF dual-hosted git repository.
terrymanu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 2354bee3096 Add SQL router integration tests for subquery scenarios (#39471)
2354bee3096 is described below
commit 2354bee309637080b77a16ba6f156ee5a90440a0
Author: Liang Zhang <zh...@apache.org>
AuthorDate: Sat Aug 15 21:46:36 2026 +0800
Add SQL router integration tests for subquery scenarios (#39471)
* Add SQL router integration tests for subquery scenarios
* Add SQL router integration tests for subquery scenarios
---
.../engine/type/standard/SubqueryRouteTest.java | 38 +---
test/it/pom.xml | 1 +
test/it/router/pom.xml | 67 ++++++
.../test/it/router/ShardingSQLRouterIT.java | 243 +++++++++++++++++++++
4 files changed, 312 insertions(+), 37 deletions(-)
diff --git a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/SubqueryRouteTest.java b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/SubqueryRouteTest.java
index eb2bab0d2fb..d59433ead23 100644
--- a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/SubqueryRouteTest.java
+++ b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/SubqueryRouteTest.java
@@ -17,9 +17,7 @@
package org.apache.shardingsphere.sharding.route.engine.type.standard;
-import org.apache.shardingsphere.infra.hint.HintManager;
import org.apache.shardingsphere.sharding.route.engine.type.standard.assertion.ShardingRouteAssert;
-import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
@@ -28,7 +26,6 @@ import org.junit.jupiter.params.provider.ArgumentsSource;
import org.junit.jupiter.params.support.ParameterDeclarations;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
@@ -41,27 +38,11 @@ class SubqueryRouteTest {
ShardingRouteAssert.assertRoute(sql, params);
}
- @Test
- void assertRouteWithHint() {
- HintManager hintManager = HintManager.getInstance();
- hintManager.addDatabaseShardingValue("t_hint_test", 1);
- hintManager.addTableShardingValue("t_hint_test", 1);
- String sql = "SELECT COUNT(*) FROM t_hint_test WHERE user_id = (SELECT user_id FROM t_hint_test WHERE user_id IN (?,?,?)) ";
- ShardingRouteAssert.assertRoute(sql, Arrays.asList(1, 3, 5));
- hintManager.close();
- }
-
private static final class TestCaseArgumentsProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(final ParameterDeclarations parameters, final ExtensionContext context) {
return Stream.of(
- Arguments.of("oneTableDifferentConditionWithFederation",
- "SELECT (SELECT MAX(id) FROM t_order b WHERE b.user_id =? ) FROM t_order a WHERE user_id = ? ", Arrays.asList(3, 2)),
- Arguments.of("oneTableSameConditionWithFederation",
- "SELECT (SELECT MAX(id) FROM t_order b WHERE b.user_id = ? AND b.user_id = a.user_id) FROM t_order a WHERE user_id = ? ", Arrays.asList(1, 1)),
- Arguments.of("bindingTableWithFederation",
- "SELECT (SELECT MAX(id) FROM t_order_item b WHERE b.user_id = ?) FROM t_order a WHERE user_id = ? ", Arrays.asList(1, 1)),
Arguments.of("notShardingTable",
"SELECT (SELECT MAX(id) FROM t_category b WHERE b.id = ?) FROM t_category a WHERE id = ? ", Arrays.asList(1, 1)),
Arguments.of("bindingTableWithDifferentValueWithFederation",
@@ -69,24 +50,7 @@ class SubqueryRouteTest {
Arguments.of("twoTableWithDifferentOperatorWithFederation",
"SELECT (SELECT MAX(id) FROM t_order_item b WHERE b.user_id in(?,?)) FROM t_order a WHERE user_id = ? ", Arrays.asList(1, 2, 1)),
Arguments.of("twoTableWithInWithFederation",
- "SELECT (SELECT MAX(id) FROM t_order_item b WHERE b.user_id in(?,?)) FROM t_order a WHERE user_id in(?,?) ", Arrays.asList(1, 2, 1, 3)),
- Arguments.of("subqueryInSubqueryError",
- "SELECT (SELECT status FROM t_order b WHERE b.user_id =? AND status = (SELECT status FROM t_order b WHERE b.user_id =?)) as c FROM t_order a "
- + "WHERE status = (SELECT status FROM t_order b WHERE b.user_id =? AND status = (SELECT status FROM t_order b WHERE b.user_id =?))",
- Arrays.asList(11, 2, 1, 1)),
- Arguments.of("subqueryInSubquery",
- "SELECT (SELECT status FROM t_order b WHERE b.user_id =? AND status = (SELECT status FROM t_order b WHERE b.user_id =?)) as c FROM t_order a "
- + "WHERE status = (SELECT status FROM t_order b WHERE b.user_id =? AND status = (SELECT status FROM t_order b WHERE b.user_id =?))",
- Arrays.asList(1, 1, 1, 1)),
- Arguments.of("subqueryInFromError",
- "SELECT b.status FROM t_order b join (SELECT user_id,status FROM t_order b WHERE b.user_id =?) c ON b.user_id = c.user_id WHERE b.user_id =? ", Arrays.asList(11, 1)),
- Arguments.of("subqueryInFrom",
- "SELECT b.status FROM t_order b join (SELECT user_id,status FROM t_order b WHERE b.user_id =?) c ON b.user_id = c.user_id WHERE b.user_id =? ", Arrays.asList(1, 1)),
- Arguments.of("subqueryForAggregation",
- "SELECT count(*) FROM t_order WHERE user_id = (SELECT user_id FROM t_order WHERE user_id =?) ", Collections.singletonList(1)),
- Arguments.of("subqueryForBinding",
- "SELECT count(*) FROM t_order WHERE user_id = (SELECT user_id FROM t_order_item WHERE user_id =?) ", Collections.singletonList(1)),
- Arguments.of("subqueryWithOneInstance", "SELECT COUNT(*) FROM t_order WHERE user_id =?", Collections.singletonList(1)));
+ "SELECT (SELECT MAX(id) FROM t_order_item b WHERE b.user_id in(?,?)) FROM t_order a WHERE user_id in(?,?) ", Arrays.asList(1, 2, 1, 3)));
}
}
}
diff --git a/test/it/pom.xml b/test/it/pom.xml
index 544bca39c86..5fa39fa38b5 100644
--- a/test/it/pom.xml
+++ b/test/it/pom.xml
@@ -33,6 +33,7 @@
<module>distsql</module>
<module>parser</module>
<module>optimizer</module>
+ <module>router</module>
<module>rewriter</module>
<module>pipeline</module>
<module>binder</module>
diff --git a/test/it/router/pom.xml b/test/it/router/pom.xml
new file mode 100644
index 00000000000..bfd06c39bb6
--- /dev/null
+++ b/test/it/router/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-test-it</artifactId>
+ <version>5.5.4-SNAPSHOT</version>
+ </parent>
+ <artifactId>shardingsphere-test-it-router</artifactId>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-test-infra-fixture-database</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-sharding-mysql</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-sql-parser-core</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-parser-sql-engine-mysql</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-infra-binder-mysql</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-infra-route-mysql</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/test/it/router/src/test/java/org/apache/shardingsphere/test/it/router/ShardingSQLRouterIT.java b/test/it/router/src/test/java/org/apache/shardingsphere/test/it/router/ShardingSQLRouterIT.java
new file mode 100644
index 00000000000..839c357df2f
--- /dev/null
+++ b/test/it/router/src/test/java/org/apache/shardingsphere/test/it/router/ShardingSQLRouterIT.java
@@ -0,0 +1,243 @@
+/*
+ * 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.test.it.router;
+
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
+import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.binder.engine.SQLBindEngine;
+import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import org.apache.shardingsphere.infra.datanode.DataNode;
+import org.apache.shardingsphere.infra.hint.HintManager;
+import org.apache.shardingsphere.infra.hint.HintValueContext;
+import org.apache.shardingsphere.infra.instance.ComputeNodeInstanceContext;
+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.rule.RuleMetaData;
+import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereColumn;
+import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
+import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
+import org.apache.shardingsphere.infra.parser.SQLParserEngine;
+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.SQLRouteEngine;
+import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
+import org.apache.shardingsphere.infra.session.query.QueryContext;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.infra.util.props.PropertiesBuilder;
+import org.apache.shardingsphere.infra.util.props.PropertiesBuilder.Property;
+import org.apache.shardingsphere.parser.rule.SQLParserRule;
+import org.apache.shardingsphere.parser.rule.builder.DefaultSQLParserRuleConfigurationBuilder;
+import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
+import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableReferenceRuleConfiguration;
+import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
+import org.apache.shardingsphere.sharding.api.config.strategy.sharding.HintShardingStrategyConfiguration;
+import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration;
+import org.apache.shardingsphere.sharding.rule.ShardingRule;
+import org.apache.shardingsphere.test.infra.fixture.jdbc.MockedDataSource;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import javax.sql.DataSource;
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Stream;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+
+class ShardingSQLRouterIT {
+
+ private static final String DATABASE_NAME = "foo_db";
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("getTestArguments")
+ void assertRoute(final String name, final String sql, final List<Object> params, final Set<String> expectedRouteUnits,
+ final List<Set<String>> expectedOriginalDataNodes) {
+ RouteContext actual = route(sql, params);
+ assertThat(getRouteUnitSignatures(actual), is(expectedRouteUnits));
+ assertThat(getOriginalDataNodeSignatures(actual), is(expectedOriginalDataNodes));
+ }
+
+ private static Stream<Arguments> getTestArguments() {
+ return Stream.of(
+ Arguments.of("oneTableDifferentConditionWithFederation",
+ "SELECT (SELECT MAX(id) FROM t_order b WHERE b.user_id =? ) FROM t_order a WHERE user_id = ? ", Arrays.asList(3, 2),
+ createRouteUnits("ds_0:t_order=t_order_0", "ds_1:t_order=t_order_1"),
+ createOriginalDataNodes("ds_1.t_order_1", "ds_0.t_order_0")),
+ Arguments.of("oneTableSameConditionWithFederation",
+ "SELECT (SELECT MAX(id) FROM t_order b WHERE b.user_id = ? AND b.user_id = a.user_id) FROM t_order a WHERE user_id = ? ", Arrays.asList(1, 1),
+ createRouteUnits("ds_1:t_order=t_order_1"), createOriginalDataNodes("ds_1.t_order_1")),
+ Arguments.of("bindingTableWithFederation",
+ "SELECT (SELECT MAX(id) FROM t_order_item b WHERE b.user_id = ?) FROM t_order a WHERE user_id = ? ", Arrays.asList(1, 1),
+ createRouteUnits("ds_1:t_order_item=t_order_item_1"), createOriginalDataNodes("ds_1.t_order_item_1")),
+ Arguments.of("subqueryInSubqueryError",
+ "SELECT (SELECT status FROM t_order b WHERE b.user_id =? AND status = (SELECT status FROM t_order b WHERE b.user_id =?)) as c FROM t_order a "
+ + "WHERE status = (SELECT status FROM t_order b WHERE b.user_id =? AND status = (SELECT status FROM t_order b WHERE b.user_id =?))",
+ Arrays.asList(11, 2, 1, 1), createRouteUnits("ds_0:t_order=t_order_0", "ds_1:t_order=t_order_1"),
+ createOriginalDataNodes("ds_1.t_order_1", "ds_0.t_order_0", "ds_1.t_order_1")),
+ Arguments.of("subqueryInSubquery",
+ "SELECT (SELECT status FROM t_order b WHERE b.user_id =? AND status = (SELECT status FROM t_order b WHERE b.user_id =?)) as c FROM t_order a "
+ + "WHERE status = (SELECT status FROM t_order b WHERE b.user_id =? AND status = (SELECT status FROM t_order b WHERE b.user_id =?))",
+ Arrays.asList(1, 1, 1, 1), createRouteUnits("ds_1:t_order=t_order_1"), createOriginalDataNodes("ds_1.t_order_1")),
+ Arguments.of("subqueryInFromError",
+ "SELECT b.status FROM t_order b join (SELECT user_id,status FROM t_order b WHERE b.user_id =?) c ON b.user_id = c.user_id WHERE b.user_id =? ",
+ Arrays.asList(11, 1), createRouteUnits("ds_1:t_order=t_order_1"), createOriginalDataNodes("ds_1.t_order_1", "ds_1.t_order_1")),
+ Arguments.of("subqueryInFrom",
+ "SELECT b.status FROM t_order b join (SELECT user_id,status FROM t_order b WHERE b.user_id =?) c ON b.user_id = c.user_id WHERE b.user_id =? ",
+ Arrays.asList(1, 1), createRouteUnits("ds_1:t_order=t_order_1"), createOriginalDataNodes("ds_1.t_order_1")),
+ Arguments.of("subqueryForAggregation",
+ "SELECT count(*) FROM t_order WHERE user_id = (SELECT user_id FROM t_order WHERE user_id =?) ", Collections.singletonList(1),
+ createRouteUnits("ds_1:t_order=t_order_1"), createOriginalDataNodes("ds_1.t_order_1")),
+ Arguments.of("subqueryForBinding",
+ "SELECT count(*) FROM t_order WHERE user_id = (SELECT user_id FROM t_order_item WHERE user_id =?) ", Collections.singletonList(1),
+ createRouteUnits("ds_1:t_order_item=t_order_item_1"), createOriginalDataNodes("ds_1.t_order_item_1")));
+ }
+
+ @Test
+ void assertRouteWithHint() {
+ try (HintManager hintManager = HintManager.getInstance()) {
+ hintManager.addDatabaseShardingValue("t_hint_test", 1);
+ hintManager.addTableShardingValue("t_hint_test", 1);
+ String sql = "SELECT COUNT(*) FROM t_hint_test WHERE user_id = (SELECT user_id FROM t_hint_test WHERE user_id IN (?,?,?)) ";
+ RouteContext actual = route(sql, Arrays.asList(1, 3, 5));
+ assertThat(getRouteUnitSignatures(actual), is(createRouteUnits("ds_1:t_hint_test=t_hint_test_1")));
+ assertThat(getOriginalDataNodeSignatures(actual), is(Collections.emptyList()));
+ }
+ }
+
+ private static RouteContext route(final String sql, final List<Object> params) {
+ DatabaseType databaseType = TypedSPILoader.getService(DatabaseType.class, "MySQL");
+ ShardingRule shardingRule = createShardingRule();
+ ConfigurationProperties props = new ConfigurationProperties(new Properties());
+ ShardingSphereDatabase database = createDatabase(databaseType, shardingRule, props);
+ RuleMetaData globalRuleMetaData = mock(RuleMetaData.class);
+ ShardingSphereMetaData metaData = new ShardingSphereMetaData(Collections.singleton(database), mock(), globalRuleMetaData, props);
+ SQLParserEngine parserEngine = new SQLParserRule(new DefaultSQLParserRuleConfigurationBuilder().build()).getSQLParserEngine(databaseType);
+ SQLStatementContext sqlStatementContext = new SQLBindEngine(metaData, DATABASE_NAME, new HintValueContext()).bind(parserEngine.parse(sql, false));
+ ConnectionContext connectionContext = new ConnectionContext(Collections::emptySet);
+ connectionContext.setCurrentDatabaseName(DATABASE_NAME);
+ QueryContext queryContext = new QueryContext(sqlStatementContext, sql, params, new HintValueContext(), connectionContext, metaData);
+ return new SQLRouteEngine(Collections.singleton(shardingRule), props).route(queryContext, globalRuleMetaData, database);
+ }
+
+ private static ShardingSphereDatabase createDatabase(final DatabaseType databaseType, final ShardingRule shardingRule, final ConfigurationProperties props) {
+ return new ShardingSphereDatabase(DATABASE_NAME, databaseType, mock(ResourceMetaData.class, RETURNS_DEEP_STUBS),
+ new RuleMetaData(Collections.singleton(shardingRule)), buildSchemas(databaseType), props);
+ }
+
+ private static Collection<ShardingSphereSchema> buildSchemas(final DatabaseType databaseType) {
+ Collection<ShardingSphereTable> tables = new LinkedList<>();
+ tables.add(new ShardingSphereTable("t_order", Arrays.asList(
+ new ShardingSphereColumn("id", Types.INTEGER, true, false, false, true, false, false),
+ new ShardingSphereColumn("user_id", Types.INTEGER, false, false, false, true, false, false),
+ new ShardingSphereColumn("status", Types.VARCHAR, false, false, false, true, false, false)), Collections.emptyList(), Collections.emptyList()));
+ tables.add(new ShardingSphereTable("t_order_item", Arrays.asList(
+ new ShardingSphereColumn("id", Types.INTEGER, true, false, false, true, false, false),
+ new ShardingSphereColumn("user_id", Types.INTEGER, false, false, false, true, false, false)), Collections.emptyList(), Collections.emptyList()));
+ tables.add(new ShardingSphereTable("t_hint_test", Collections.singleton(
+ new ShardingSphereColumn("user_id", Types.INTEGER, true, false, false, true, false, false)), Collections.emptyList(), Collections.emptyList()));
+ return Collections.singleton(new ShardingSphereSchema(DATABASE_NAME, databaseType, tables, Collections.emptyList()));
+ }
+
+ private static ShardingRule createShardingRule() {
+ ShardingRuleConfiguration config = new ShardingRuleConfiguration();
+ config.getTables().add(createInlineTableRule("t_order"));
+ config.getTables().add(createInlineTableRule("t_order_item"));
+ config.getTables().add(createHintTableRule());
+ config.getBindingTableGroups().add(new ShardingTableReferenceRuleConfiguration("foo", "t_order,t_order_item"));
+ config.getShardingAlgorithms().put("ds_inline", createAlgorithm("INLINE", "ds_${user_id % 2}"));
+ config.getShardingAlgorithms().put("t_order_inline", createAlgorithm("INLINE", "t_order_${user_id % 2}"));
+ config.getShardingAlgorithms().put("t_order_item_inline", createAlgorithm("INLINE", "t_order_item_${user_id % 2}"));
+ config.getShardingAlgorithms().put("ds_hint_inline", createAlgorithm("HINT_INLINE", "ds_${value % 2}"));
+ config.getShardingAlgorithms().put("t_hint_test_hint_inline", createAlgorithm("HINT_INLINE", "t_hint_test_${value % 2}"));
+ Map<String, DataSource> dataSources = new LinkedHashMap<>();
+ dataSources.put("ds_0", new MockedDataSource());
+ dataSources.put("ds_1", new MockedDataSource());
+ return new ShardingRule(config, dataSources, mock(ComputeNodeInstanceContext.class), Collections.emptyList());
+ }
+
+ private static ShardingTableRuleConfiguration createInlineTableRule(final String tableName) {
+ ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration(tableName, String.format("ds_${0..1}.%s_${0..1}", tableName));
+ result.setDatabaseShardingStrategy(new StandardShardingStrategyConfiguration("user_id", "ds_inline"));
+ result.setTableShardingStrategy(new StandardShardingStrategyConfiguration("user_id", tableName + "_inline"));
+ return result;
+ }
+
+ private static ShardingTableRuleConfiguration createHintTableRule() {
+ ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_hint_test", "ds_${0..1}.t_hint_test_${0..1}");
+ result.setDatabaseShardingStrategy(new HintShardingStrategyConfiguration("ds_hint_inline"));
+ result.setTableShardingStrategy(new HintShardingStrategyConfiguration("t_hint_test_hint_inline"));
+ return result;
+ }
+
+ private static AlgorithmConfiguration createAlgorithm(final String type, final String expression) {
+ return new AlgorithmConfiguration(type, PropertiesBuilder.build(new Property("algorithm-expression", expression)));
+ }
+
+ private static Set<String> getRouteUnitSignatures(final RouteContext routeContext) {
+ Set<String> result = new TreeSet<>();
+ for (RouteUnit each : routeContext.getRouteUnits()) {
+ Collection<String> tableMappers = new TreeSet<>();
+ for (RouteMapper tableMapper : each.getTableMappers()) {
+ tableMappers.add(tableMapper.getLogicName() + "=" + tableMapper.getActualName());
+ }
+ result.add(each.getDataSourceMapper().getActualName() + ":" + String.join(",", tableMappers));
+ }
+ return result;
+ }
+
+ private static List<Set<String>> getOriginalDataNodeSignatures(final RouteContext routeContext) {
+ List<Set<String>> result = new LinkedList<>();
+ for (Collection<DataNode> each : routeContext.getOriginalDataNodes()) {
+ Set<String> dataNodes = new TreeSet<>();
+ for (DataNode dataNode : each) {
+ dataNodes.add(dataNode.getDataSourceName() + "." + dataNode.getTableName());
+ }
+ result.add(dataNodes);
+ }
+ return result;
+ }
+
+ private static List<Set<String>> createOriginalDataNodes(final String... dataNodes) {
+ List<Set<String>> result = new LinkedList<>();
+ for (String each : dataNodes) {
+ result.add(Collections.singleton(each));
+ }
+ return result;
+ }
+
+ private static Set<String> createRouteUnits(final String... routeUnits) {
+ return new TreeSet<>(Arrays.asList(routeUnits));
+ }
+}