This is an automated email from the ASF dual-hosted git repository.
panjuan 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 5b43f742442 Add SQLFederationDecider to decide whether to use sql
federation engine (#19941)
5b43f742442 is described below
commit 5b43f7424428f5d084fc184f8ff273d7eaaddc3e
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Sun Aug 7 15:48:16 2022 +0800
Add SQLFederationDecider to decide whether to use sql federation engine
(#19941)
---
.../decider/ShardingSQLFederationDecider.java | 83 ++++++++++++++++
...phere.infra.binder.decider.SQLFederationDecider | 18 ++++
.../infra/binder/decider/SQLFederationDecider.java | 44 +++++++++
.../decider/SQLFederationDeciderFactory.java | 49 +++++++++
.../context/SQLFederationDeciderContext.java | 37 +++++++
.../decider/engine/SQLFederationDeciderEngine.java | 70 +++++++++++++
.../engine/SQLFederationDeciderEngineTest.java | 110 +++++++++++++++++++++
.../decider/SQLFederationDeciderMatchFixture.java | 44 +++++++++
.../SQLFederationDeciderNotMatchFixture.java | 43 ++++++++
.../rule/SQLFederationDeciderRuleMatchFixture.java | 36 +++++++
.../SQLFederationDeciderRuleNotMatchFixture.java | 36 +++++++
...phere.infra.binder.decider.SQLFederationDecider | 19 ++++
.../advanced/AdvancedFederationExecutor.java | 4 +-
.../route/engine/impl/PartialSQLRouteExecutor.java | 1 -
.../decider/SingleTableSQLFederationDecider.java | 107 ++++++++++++++++++++
...phere.infra.binder.decider.SQLFederationDecider | 18 ++++
16 files changed, 717 insertions(+), 2 deletions(-)
diff --git
a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/decider/ShardingSQLFederationDecider.java
b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/decider/ShardingSQLFederationDecider.java
new file mode 100644
index 00000000000..805e08e0285
--- /dev/null
+++
b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/java/org/apache/shardingsphere/sharding/decider/ShardingSQLFederationDecider.java
@@ -0,0 +1,83 @@
+/*
+ * 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.sharding.decider;
+
+import org.apache.shardingsphere.infra.binder.LogicSQL;
+import org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider;
+import
org.apache.shardingsphere.infra.binder.decider.context.SQLFederationDeciderContext;
+import
org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
+import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.sharding.constant.ShardingOrder;
+import
org.apache.shardingsphere.sharding.route.engine.condition.ShardingCondition;
+import
org.apache.shardingsphere.sharding.route.engine.condition.ShardingConditions;
+import
org.apache.shardingsphere.sharding.route.engine.condition.engine.ShardingConditionEngine;
+import
org.apache.shardingsphere.sharding.route.engine.condition.engine.ShardingConditionEngineFactory;
+import org.apache.shardingsphere.sharding.rule.ShardingRule;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Sharding SQL federation decider.
+ */
+public final class ShardingSQLFederationDecider implements
SQLFederationDecider<ShardingRule> {
+
+ @Override
+ public void decide(final SQLFederationDeciderContext deciderContext, final
LogicSQL logicSQL, final ShardingSphereDatabase database, final ShardingRule
rule, final ConfigurationProperties props) {
+ SelectStatementContext select = (SelectStatementContext)
logicSQL.getSqlStatementContext();
+ Collection<String> tableNames =
rule.getShardingLogicTableNames(select.getTablesContext().getTableNames());
+ addTableDataNodes(deciderContext, rule, tableNames);
+ ShardingConditions shardingConditions =
createShardingConditions(logicSQL, database, rule);
+ if (select.getPaginationContext().isHasPagination() ||
(shardingConditions.isNeedMerge() &&
shardingConditions.isSameShardingCondition())) {
+ return;
+ }
+ if (select.isContainsSubquery() || select.isContainsHaving() ||
select.isContainsCombine() || select.isContainsPartialDistinctAggregation()) {
+ deciderContext.setUseSQLFederation(true);
+ return;
+ }
+ if (!select.isContainsJoinQuery() ||
rule.isAllTablesInSameDataSource(tableNames)) {
+ return;
+ }
+ boolean allBindingTables = tableNames.size() > 1 &&
rule.isAllBindingTables(database, select, tableNames);
+ deciderContext.setUseSQLFederation(tableNames.size() > 1 &&
!allBindingTables);
+ }
+
+ private static void addTableDataNodes(final SQLFederationDeciderContext
deciderContext, final ShardingRule rule, final Collection<String> tableNames) {
+ for (String each : tableNames) {
+ rule.findTableRule(each).ifPresent(optional ->
deciderContext.getDataNodes().addAll(optional.getActualDataNodes()));
+ }
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ private static ShardingConditions createShardingConditions(final LogicSQL
logicSQL, final ShardingSphereDatabase database, final ShardingRule rule) {
+ ShardingConditionEngine shardingConditionEngine =
ShardingConditionEngineFactory.createShardingConditionEngine(logicSQL,
database, rule);
+ List<ShardingCondition> shardingConditions =
shardingConditionEngine.createShardingConditions(logicSQL.getSqlStatementContext(),
logicSQL.getParameters());
+ return new ShardingConditions(shardingConditions,
logicSQL.getSqlStatementContext(), rule);
+ }
+
+ @Override
+ public int getOrder() {
+ return ShardingOrder.ORDER;
+ }
+
+ @Override
+ public Class<ShardingRule> getTypeClass() {
+ return ShardingRule.class;
+ }
+}
diff --git
a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider
b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider
new file mode 100644
index 00000000000..f96bc312aec
--- /dev/null
+++
b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider
@@ -0,0 +1,18 @@
+#
+# 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.sharding.decider.ShardingSQLFederationDecider
diff --git
a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/decider/SQLFederationDecider.java
b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/decider/SQLFederationDecider.java
new file mode 100644
index 00000000000..a7b2dd97cf9
--- /dev/null
+++
b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/decider/SQLFederationDecider.java
@@ -0,0 +1,44 @@
+/*
+ * 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.binder.decider;
+
+import org.apache.shardingsphere.infra.binder.LogicSQL;
+import
org.apache.shardingsphere.infra.binder.decider.context.SQLFederationDeciderContext;
+import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+import org.apache.shardingsphere.spi.type.ordered.OrderedSPI;
+
+/**
+ * SQL federation decider.
+ *
+ * @param <T> type of rule
+ */
+public interface SQLFederationDecider<T extends ShardingSphereRule> extends
OrderedSPI<T> {
+
+ /**
+ * Judge whether to use sql federation engine.
+ *
+ * @param deciderContext decider context
+ * @param logicSQL logic SQL
+ * @param database database metadata
+ * @param rule rule
+ * @param props props
+ */
+ void decide(SQLFederationDeciderContext deciderContext, LogicSQL logicSQL,
ShardingSphereDatabase database, T rule, ConfigurationProperties props);
+}
diff --git
a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/decider/SQLFederationDeciderFactory.java
b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/decider/SQLFederationDeciderFactory.java
new file mode 100644
index 00000000000..d6da040b4b0
--- /dev/null
+++
b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/decider/SQLFederationDeciderFactory.java
@@ -0,0 +1,49 @@
+/*
+ * 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.binder.decider;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+import org.apache.shardingsphere.spi.ShardingSphereServiceLoader;
+import org.apache.shardingsphere.spi.type.ordered.OrderedSPIRegistry;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * SQL federation decider factory.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class SQLFederationDeciderFactory {
+
+ static {
+ ShardingSphereServiceLoader.register(SQLFederationDecider.class);
+ }
+
+ /**
+ * Get instances of SQL federation decider.
+ *
+ * @param rules rules
+ * @return got instances
+ */
+ @SuppressWarnings("rawtypes")
+ public static Map<ShardingSphereRule, SQLFederationDecider>
getInstances(final Collection<ShardingSphereRule> rules) {
+ return
OrderedSPIRegistry.getRegisteredServices(SQLFederationDecider.class, rules);
+ }
+}
diff --git
a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/decider/context/SQLFederationDeciderContext.java
b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/decider/context/SQLFederationDeciderContext.java
new file mode 100644
index 00000000000..e350f02559a
--- /dev/null
+++
b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/decider/context/SQLFederationDeciderContext.java
@@ -0,0 +1,37 @@
+/*
+ * 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.binder.decider.context;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.infra.datanode.DataNode;
+
+import java.util.Collection;
+import java.util.LinkedHashSet;
+
+/**
+ * Route context.
+ */
+@Getter
+public final class SQLFederationDeciderContext {
+
+ private final Collection<DataNode> dataNodes = new LinkedHashSet<>();
+
+ @Setter
+ private boolean useSQLFederation;
+}
diff --git
a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/decider/engine/SQLFederationDeciderEngine.java
b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/decider/engine/SQLFederationDeciderEngine.java
new file mode 100644
index 00000000000..09b7fe40e1f
--- /dev/null
+++
b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/decider/engine/SQLFederationDeciderEngine.java
@@ -0,0 +1,70 @@
+/*
+ * 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.binder.decider.engine;
+
+import org.apache.shardingsphere.infra.binder.LogicSQL;
+import org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider;
+import
org.apache.shardingsphere.infra.binder.decider.SQLFederationDeciderFactory;
+import
org.apache.shardingsphere.infra.binder.decider.context.SQLFederationDeciderContext;
+import
org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
+import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * SQL federation decider engine.
+ */
+public final class SQLFederationDeciderEngine {
+
+ private final ConfigurationProperties props;
+
+ @SuppressWarnings("rawtypes")
+ private final Map<ShardingSphereRule, SQLFederationDecider> deciders;
+
+ public SQLFederationDeciderEngine(final Collection<ShardingSphereRule>
rules, final ConfigurationProperties props) {
+ this.props = props;
+ deciders = SQLFederationDeciderFactory.getInstances(rules);
+ }
+
+ /**
+ * Decide.
+ *
+ * @param logicSQL logic SQL
+ * @param database ShardingSphere database
+ * @return SQL federation decider context
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public SQLFederationDeciderContext decide(final LogicSQL logicSQL, final
ShardingSphereDatabase database) {
+ SQLFederationDeciderContext result = new SQLFederationDeciderContext();
+ boolean sqlFederationEnabled =
props.getValue(ConfigurationPropertyKey.SQL_FEDERATION_ENABLED);
+ if (!sqlFederationEnabled || !(logicSQL.getSqlStatementContext()
instanceof SelectStatementContext)) {
+ return result;
+ }
+ for (Entry<ShardingSphereRule, SQLFederationDecider> entry :
deciders.entrySet()) {
+ if (!result.isUseSQLFederation()) {
+ entry.getValue().decide(result, logicSQL, database,
entry.getKey(), props);
+ }
+ }
+ return result;
+ }
+}
diff --git
a/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/engine/SQLFederationDeciderEngineTest.java
b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/engine/SQLFederationDeciderEngineTest.java
new file mode 100644
index 00000000000..112ac915164
--- /dev/null
+++
b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/engine/SQLFederationDeciderEngineTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.binder.decider.engine;
+
+import org.apache.shardingsphere.infra.binder.LogicSQL;
+import
org.apache.shardingsphere.infra.binder.decider.context.SQLFederationDeciderContext;
+import
org.apache.shardingsphere.infra.binder.decider.fixture.rule.SQLFederationDeciderRuleMatchFixture;
+import
org.apache.shardingsphere.infra.binder.decider.fixture.rule.SQLFederationDeciderRuleNotMatchFixture;
+import
org.apache.shardingsphere.infra.binder.statement.CommonSQLStatementContext;
+import
org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
+import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
+import org.apache.shardingsphere.infra.database.DefaultDatabase;
+import org.apache.shardingsphere.infra.database.type.DatabaseType;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import
org.apache.shardingsphere.infra.metadata.database.resource.ShardingSphereResource;
+import
org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Properties;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+
+public final class SQLFederationDeciderEngineTest {
+
+ @Test
+ public void assertDecideWhenNotConfigSqlFederationEnabled() {
+ Collection<ShardingSphereRule> rules = Collections.singletonList(new
SQLFederationDeciderRuleMatchFixture());
+ SQLFederationDeciderEngine deciderEngine = new
SQLFederationDeciderEngine(rules, new ConfigurationProperties(new
Properties()));
+ LogicSQL logicSQL = new
LogicSQL(mock(CommonSQLStatementContext.class), "", Collections.emptyList());
+ ShardingSphereDatabase database = new
ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
+ mock(DatabaseType.class), mock(ShardingSphereResource.class,
RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(rules),
Collections.emptyMap());
+ SQLFederationDeciderContext actual = deciderEngine.decide(logicSQL,
database);
+ assertFalse(actual.isUseSQLFederation());
+ }
+
+ @Test
+ public void assertDecideWhenExecuteNotSelectStatement() {
+ Collection<ShardingSphereRule> rules = Collections.singletonList(new
SQLFederationDeciderRuleMatchFixture());
+ Properties props = new Properties();
+ props.put(ConfigurationPropertyKey.SQL_FEDERATION_ENABLED.getKey(),
true);
+ SQLFederationDeciderEngine deciderEngine = new
SQLFederationDeciderEngine(rules, new ConfigurationProperties(props));
+ LogicSQL logicSQL = new
LogicSQL(mock(CommonSQLStatementContext.class), "", Collections.emptyList());
+ ShardingSphereDatabase database = new
ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
+ mock(DatabaseType.class), mock(ShardingSphereResource.class,
RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(rules),
Collections.emptyMap());
+ SQLFederationDeciderContext actual = deciderEngine.decide(logicSQL,
database);
+ assertFalse(actual.isUseSQLFederation());
+ }
+
+ @Test
+ public void assertDecideWhenConfigSingleMatchedRule() {
+ Collection<ShardingSphereRule> rules = Collections.singletonList(new
SQLFederationDeciderRuleMatchFixture());
+ Properties props = new Properties();
+ props.put(ConfigurationPropertyKey.SQL_FEDERATION_ENABLED.getKey(),
true);
+ SQLFederationDeciderEngine deciderEngine = new
SQLFederationDeciderEngine(rules, new ConfigurationProperties(props));
+ LogicSQL logicSQL = new LogicSQL(mock(SelectStatementContext.class),
"", Collections.emptyList());
+ ShardingSphereDatabase database = new
ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
+ mock(DatabaseType.class), mock(ShardingSphereResource.class,
RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(rules),
Collections.emptyMap());
+ SQLFederationDeciderContext actual = deciderEngine.decide(logicSQL,
database);
+ assertTrue(actual.isUseSQLFederation());
+ }
+
+ @Test
+ public void assertDecideWhenConfigSingleNotMatchedRule() {
+ Collection<ShardingSphereRule> rules = Collections.singletonList(new
SQLFederationDeciderRuleNotMatchFixture());
+ Properties props = new Properties();
+ props.put(ConfigurationPropertyKey.SQL_FEDERATION_ENABLED.getKey(),
true);
+ SQLFederationDeciderEngine deciderEngine = new
SQLFederationDeciderEngine(rules, new ConfigurationProperties(props));
+ LogicSQL logicSQL = new LogicSQL(mock(SelectStatementContext.class),
"", Collections.emptyList());
+ ShardingSphereDatabase database = new
ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
+ mock(DatabaseType.class), mock(ShardingSphereResource.class,
RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(rules),
Collections.emptyMap());
+ SQLFederationDeciderContext actual = deciderEngine.decide(logicSQL,
database);
+ assertFalse(actual.isUseSQLFederation());
+ }
+
+ @Test
+ public void assertDecideWhenConfigMultiRule() {
+ Collection<ShardingSphereRule> rules = Arrays.asList(new
SQLFederationDeciderRuleNotMatchFixture(), new
SQLFederationDeciderRuleMatchFixture());
+ Properties props = new Properties();
+ props.put(ConfigurationPropertyKey.SQL_FEDERATION_ENABLED.getKey(),
true);
+ SQLFederationDeciderEngine deciderEngine = new
SQLFederationDeciderEngine(rules, new ConfigurationProperties(props));
+ LogicSQL logicSQL = new LogicSQL(mock(SelectStatementContext.class),
"", Collections.emptyList());
+ ShardingSphereDatabase database = new
ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
+ mock(DatabaseType.class), mock(ShardingSphereResource.class,
RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(rules),
Collections.emptyMap());
+ SQLFederationDeciderContext actual = deciderEngine.decide(logicSQL,
database);
+ assertTrue(actual.isUseSQLFederation());
+ }
+}
diff --git
a/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/fixture/decider/SQLFederationDeciderMatchFixture.java
b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/fixture/decider/SQLFederationDeciderMatchFixture.java
new file mode 100644
index 00000000000..95ad736c8d8
--- /dev/null
+++
b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/fixture/decider/SQLFederationDeciderMatchFixture.java
@@ -0,0 +1,44 @@
+/*
+ * 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.binder.decider.fixture.decider;
+
+import org.apache.shardingsphere.infra.binder.LogicSQL;
+import org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider;
+import
org.apache.shardingsphere.infra.binder.decider.context.SQLFederationDeciderContext;
+import
org.apache.shardingsphere.infra.binder.decider.fixture.rule.SQLFederationDeciderRuleMatchFixture;
+import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+
+public final class SQLFederationDeciderMatchFixture implements
SQLFederationDecider<SQLFederationDeciderRuleMatchFixture> {
+
+ @Override
+ public void decide(final SQLFederationDeciderContext deciderContext, final
LogicSQL logicSQL, final ShardingSphereDatabase database, final
SQLFederationDeciderRuleMatchFixture rule,
+ final ConfigurationProperties props) {
+ deciderContext.setUseSQLFederation(true);
+ }
+
+ @Override
+ public int getOrder() {
+ return 0;
+ }
+
+ @Override
+ public Class<SQLFederationDeciderRuleMatchFixture> getTypeClass() {
+ return SQLFederationDeciderRuleMatchFixture.class;
+ }
+}
diff --git
a/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/fixture/decider/SQLFederationDeciderNotMatchFixture.java
b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/fixture/decider/SQLFederationDeciderNotMatchFixture.java
new file mode 100644
index 00000000000..bb74ca1010d
--- /dev/null
+++
b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/fixture/decider/SQLFederationDeciderNotMatchFixture.java
@@ -0,0 +1,43 @@
+/*
+ * 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.binder.decider.fixture.decider;
+
+import org.apache.shardingsphere.infra.binder.LogicSQL;
+import org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider;
+import
org.apache.shardingsphere.infra.binder.decider.context.SQLFederationDeciderContext;
+import
org.apache.shardingsphere.infra.binder.decider.fixture.rule.SQLFederationDeciderRuleNotMatchFixture;
+import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+
+public final class SQLFederationDeciderNotMatchFixture implements
SQLFederationDecider<SQLFederationDeciderRuleNotMatchFixture> {
+
+ @Override
+ public void decide(final SQLFederationDeciderContext deciderContext, final
LogicSQL logicSQL, final ShardingSphereDatabase database, final
SQLFederationDeciderRuleNotMatchFixture rule,
+ final ConfigurationProperties props) {
+ }
+
+ @Override
+ public int getOrder() {
+ return 10;
+ }
+
+ @Override
+ public Class<SQLFederationDeciderRuleNotMatchFixture> getTypeClass() {
+ return SQLFederationDeciderRuleNotMatchFixture.class;
+ }
+}
diff --git
a/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/fixture/rule/SQLFederationDeciderRuleMatchFixture.java
b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/fixture/rule/SQLFederationDeciderRuleMatchFixture.java
new file mode 100644
index 00000000000..27eac751172
--- /dev/null
+++
b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/fixture/rule/SQLFederationDeciderRuleMatchFixture.java
@@ -0,0 +1,36 @@
+/*
+ * 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.binder.decider.fixture.rule;
+
+import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+
+import static org.mockito.Mockito.mock;
+
+public final class SQLFederationDeciderRuleMatchFixture implements
ShardingSphereRule {
+
+ @Override
+ public RuleConfiguration getConfiguration() {
+ return mock(RuleConfiguration.class);
+ }
+
+ @Override
+ public String getType() {
+ return SQLFederationDeciderRuleMatchFixture.class.getSimpleName();
+ }
+}
diff --git
a/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/fixture/rule/SQLFederationDeciderRuleNotMatchFixture.java
b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/fixture/rule/SQLFederationDeciderRuleNotMatchFixture.java
new file mode 100644
index 00000000000..be17ce14773
--- /dev/null
+++
b/shardingsphere-infra/shardingsphere-infra-binder/src/test/java/org/apache/shardingsphere/infra/binder/decider/fixture/rule/SQLFederationDeciderRuleNotMatchFixture.java
@@ -0,0 +1,36 @@
+/*
+ * 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.binder.decider.fixture.rule;
+
+import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+
+import static org.mockito.Mockito.mock;
+
+public final class SQLFederationDeciderRuleNotMatchFixture implements
ShardingSphereRule {
+
+ @Override
+ public RuleConfiguration getConfiguration() {
+ return mock(RuleConfiguration.class);
+ }
+
+ @Override
+ public String getType() {
+ return SQLFederationDeciderRuleNotMatchFixture.class.getSimpleName();
+ }
+}
diff --git
a/shardingsphere-infra/shardingsphere-infra-binder/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider
b/shardingsphere-infra/shardingsphere-infra-binder/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider
new file mode 100644
index 00000000000..d7cfe99f77a
--- /dev/null
+++
b/shardingsphere-infra/shardingsphere-infra-binder/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider
@@ -0,0 +1,19 @@
+#
+# 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.binder.decider.fixture.decider.SQLFederationDeciderMatchFixture
+org.apache.shardingsphere.infra.binder.decider.fixture.decider.SQLFederationDeciderNotMatchFixture
diff --git
a/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-executor/src/main/java/org/apache/shardingsphere/infra/federation/executor/advanced/AdvancedFederationExecutor.java
b/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-executor/src/main/java/org/apache/shardingsphere/infra/federation/executor/advanced/AdvancedFederationExecutor.java
index c5a0fa70a16..cdb671630a5 100644
---
a/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-executor/src/main/java/org/apache/shardingsphere/infra/federation/executor/advanced/AdvancedFederationExecutor.java
+++
b/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-executor/src/main/java/org/apache/shardingsphere/infra/federation/executor/advanced/AdvancedFederationExecutor.java
@@ -131,6 +131,8 @@ public final class AdvancedFederationExecutor implements
FederationExecutor {
@Override
public void close() throws SQLException {
- resultSet.close();
+ if (null != resultSet) {
+ resultSet.close();
+ }
}
}
diff --git
a/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/engine/impl/PartialSQLRouteExecutor.java
b/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/engine/impl/PartialSQLRouteExecutor.java
index 7d762d65352..e3bb6eaafc0 100644
---
a/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/engine/impl/PartialSQLRouteExecutor.java
+++
b/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/engine/impl/PartialSQLRouteExecutor.java
@@ -65,5 +65,4 @@ public final class PartialSQLRouteExecutor implements
SQLRouteExecutor {
}
return result;
}
-
}
diff --git
a/shardingsphere-kernel/shardingsphere-single-table/shardingsphere-single-table-core/src/main/java/org/apache/shardingsphere/singletable/decider/SingleTableSQLFederationDecider.java
b/shardingsphere-kernel/shardingsphere-single-table/shardingsphere-single-table-core/src/main/java/org/apache/shardingsphere/singletable/decider/SingleTableSQLFederationDecider.java
new file mode 100644
index 00000000000..f32c42b98dd
--- /dev/null
+++
b/shardingsphere-kernel/shardingsphere-single-table/shardingsphere-single-table-core/src/main/java/org/apache/shardingsphere/singletable/decider/SingleTableSQLFederationDecider.java
@@ -0,0 +1,107 @@
+/*
+ * 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.singletable.decider;
+
+import org.apache.shardingsphere.infra.binder.LogicSQL;
+import org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider;
+import
org.apache.shardingsphere.infra.binder.decider.context.SQLFederationDeciderContext;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
+import
org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
+import org.apache.shardingsphere.infra.binder.type.IndexAvailable;
+import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import org.apache.shardingsphere.infra.database.type.DatabaseType;
+import org.apache.shardingsphere.infra.database.type.DatabaseTypeEngine;
+import org.apache.shardingsphere.infra.datanode.DataNode;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.metadata.database.schema.QualifiedTable;
+import
org.apache.shardingsphere.infra.metadata.database.schema.util.IndexMetaDataUtil;
+import org.apache.shardingsphere.singletable.constant.SingleTableOrder;
+import org.apache.shardingsphere.singletable.rule.SingleTableRule;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Optional;
+
+/**
+ * Single table SQL federation decider.
+ */
+public final class SingleTableSQLFederationDecider implements
SQLFederationDecider<SingleTableRule> {
+
+ @Override
+ public void decide(final SQLFederationDeciderContext deciderContext, final
LogicSQL logicSQL,
+ final ShardingSphereDatabase database, final
SingleTableRule rule, final ConfigurationProperties props) {
+ SelectStatementContext select = (SelectStatementContext)
logicSQL.getSqlStatementContext();
+ Collection<QualifiedTable> singleTableNames =
getSingleTableNames(select, database, rule);
+ addTableDataNodes(deciderContext, rule, singleTableNames);
+
deciderContext.setUseSQLFederation(!isAllTablesInSameDataSource(deciderContext,
rule, singleTableNames));
+ }
+
+ private static void addTableDataNodes(final SQLFederationDeciderContext
deciderContext, final SingleTableRule rule, final Collection<QualifiedTable>
singleTableNames) {
+ for (QualifiedTable each : singleTableNames) {
+ rule.findSingleTableDataNode(each.getSchemaName(),
each.getTableName()).ifPresent(optional ->
deciderContext.getDataNodes().add(optional));
+ }
+ }
+
+ private static boolean isAllTablesInSameDataSource(final
SQLFederationDeciderContext deciderContext, final SingleTableRule rule, final
Collection<QualifiedTable> singleTableNames) {
+ if (!rule.isSingleTablesInSameDataSource(singleTableNames)) {
+ return false;
+ }
+ QualifiedTable sampleTable = singleTableNames.iterator().next();
+ Optional<DataNode> dataNode =
rule.findSingleTableDataNode(sampleTable.getSchemaName(),
sampleTable.getTableName());
+ if (!dataNode.isPresent()) {
+ return true;
+ }
+ for (DataNode each : deciderContext.getDataNodes()) {
+ if
(!each.getDataSourceName().equalsIgnoreCase(dataNode.get().getDataSourceName()))
{
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static Collection<QualifiedTable> getSingleTableNames(final
SQLStatementContext<?> sqlStatementContext,
+ final
ShardingSphereDatabase database, final SingleTableRule rule) {
+ DatabaseType databaseType = sqlStatementContext.getDatabaseType();
+ Collection<QualifiedTable> result = getQualifiedTables(database,
databaseType, sqlStatementContext.getTablesContext().getTables());
+ if (result.isEmpty() && sqlStatementContext instanceof IndexAvailable)
{
+ result = IndexMetaDataUtil.getTableNames(database, databaseType,
((IndexAvailable) sqlStatementContext).getIndexes());
+ }
+ return rule.getSingleTableNames(result);
+ }
+
+ private static Collection<QualifiedTable> getQualifiedTables(final
ShardingSphereDatabase database, final DatabaseType databaseType, final
Collection<SimpleTableSegment> tableSegments) {
+ Collection<QualifiedTable> result = new LinkedList<>();
+ String schemaName =
DatabaseTypeEngine.getDefaultSchemaName(databaseType, database.getName());
+ for (SimpleTableSegment each : tableSegments) {
+ String actualSchemaName = each.getOwner().map(optional ->
optional.getIdentifier().getValue()).orElse(schemaName);
+ result.add(new QualifiedTable(actualSchemaName,
each.getTableName().getIdentifier().getValue()));
+ }
+ return result;
+ }
+
+ @Override
+ public int getOrder() {
+ return SingleTableOrder.ORDER;
+ }
+
+ @Override
+ public Class<SingleTableRule> getTypeClass() {
+ return SingleTableRule.class;
+ }
+}
diff --git
a/shardingsphere-kernel/shardingsphere-single-table/shardingsphere-single-table-core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider
b/shardingsphere-kernel/shardingsphere-single-table/shardingsphere-single-table-core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider
new file mode 100644
index 00000000000..93721f0c2e2
--- /dev/null
+++
b/shardingsphere-kernel/shardingsphere-single-table/shardingsphere-single-table-core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.binder.decider.SQLFederationDecider
@@ -0,0 +1,18 @@
+#
+# 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.singletable.decider.SingleTableSQLFederationDecider