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/10/04 03:48:26 UTC
(shardingsphere) branch master updated: Move cluster lock strategy SPI to cluster mode core (#40043)
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 8cc96df968a Move cluster lock strategy SPI to cluster mode core (#40043)
8cc96df968a is described below
commit 8cc96df968ae0c3b2efb66facc4be90f23ebc3e1
Author: Liang Zhang <zh...@apache.org>
AuthorDate: Sun Oct 4 11:48:18 2026 +0800
Move cluster lock strategy SPI to cluster mode core (#40043)
* Move cluster lock strategy SPI to cluster mode core
* Validate sharding table schemas with Bean Validation
---
features/sharding/api/pom.xml | 5 ++
.../rule/ShardingTableRuleConfiguration.java | 3 +
.../ShardingTableRuleConfigurationValidator.java | 54 +++++++++++++
.../ValidShardingTableRuleConfiguration.java | 57 ++++++++++++++
.../api/config/ShardingRuleConfigurationTest.java | 70 +++++++++++++++++
...hardingTableRuleConfigurationValidatorTest.java | 91 ++++++++++++++++++++++
.../config/ShardingRuleConfigurationChecker.java | 27 -------
.../ShardingRuleConfigurationCheckerTest.java | 40 ----------
.../builder/database/DatabaseRulesBuilder.java | 5 +-
.../builder/database/DatabaseRulesBuilderTest.java | 30 +++++++
.../ral/updatable/lock/LockClusterExecutor.java | 2 +-
.../cluster}/lock/spi/ClusterLockStrategy.java | 2 +-
.../lock/impl/ClusterReadWriteLockStrategy.java | 2 +-
.../lock/impl/ClusterWriteLockStrategy.java | 2 +-
...e.manager.cluster.lock.spi.ClusterLockStrategy} | 0
.../impl/ClusterReadWriteLockStrategyTest.java | 2 +-
.../lock/impl/ClusterWriteLockStrategyTest.java | 2 +-
17 files changed, 319 insertions(+), 75 deletions(-)
diff --git a/features/sharding/api/pom.xml b/features/sharding/api/pom.xml
index ef383e634de..38ff9148864 100644
--- a/features/sharding/api/pom.xml
+++ b/features/sharding/api/pom.xml
@@ -37,6 +37,11 @@
<artifactId>shardingsphere-infra-binder-core</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-infra-expr-entry</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>jakarta.validation</groupId>
diff --git a/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/rule/ShardingTableRuleConfiguration.java b/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/rule/ShardingTableRuleConfiguration.java
index ce391c705f1..7e55536ee9c 100644
--- a/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/rule/ShardingTableRuleConfiguration.java
+++ b/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/rule/ShardingTableRuleConfiguration.java
@@ -20,8 +20,10 @@ package org.apache.shardingsphere.sharding.api.config.rule;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
+import org.apache.shardingsphere.infra.config.rule.validator.group.RuleConfigurationTypeValidationGroup;
import org.apache.shardingsphere.sharding.api.config.strategy.audit.ShardingAuditStrategyConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.sharding.ShardingStrategyConfiguration;
+import org.apache.shardingsphere.sharding.api.config.validator.ValidShardingTableRuleConfiguration;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
@@ -29,6 +31,7 @@ import javax.validation.constraints.NotBlank;
/**
* Sharding table rule configuration.
*/
+@ValidShardingTableRuleConfiguration(groups = RuleConfigurationTypeValidationGroup.class)
@RequiredArgsConstructor
@Getter
@Setter
diff --git a/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidator.java b/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidator.java
new file mode 100644
index 00000000000..12740d73ab7
--- /dev/null
+++ b/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidator.java
@@ -0,0 +1,54 @@
+/*
+ * 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.api.config.validator;
+
+import org.apache.shardingsphere.infra.datanode.DataNode;
+import org.apache.shardingsphere.infra.expr.entry.InlineExpressionParserFactory;
+import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Sharding table rule configuration validator.
+ */
+public final class ShardingTableRuleConfigurationValidator implements ConstraintValidator<ValidShardingTableRuleConfiguration, ShardingTableRuleConfiguration> {
+
+ @Override
+ public boolean isValid(final ShardingTableRuleConfiguration value, final ConstraintValidatorContext context) {
+ Collection<String> actualDataNodes = InlineExpressionParserFactory.newInstance(value.getActualDataNodes()).splitAndEvaluate();
+ Map<String, String> schemaNamesByDataSource = new HashMap<>(actualDataNodes.size(), 1F);
+ for (String each : actualDataNodes) {
+ DataNode dataNode = new DataNode(each);
+ if (null == dataNode.getSchemaName()) {
+ continue;
+ }
+ String configuredSchemaName = schemaNamesByDataSource.putIfAbsent(dataNode.getDataSourceName(), dataNode.getSchemaName());
+ if (null != configuredSchemaName && !configuredSchemaName.equalsIgnoreCase(dataNode.getSchemaName())) {
+ context.disableDefaultConstraintViolation();
+ context.buildConstraintViolationWithTemplate(String.format("contains multiple schemas for storage unit `%s` in sharding table `%s`",
+ dataNode.getDataSourceName(), value.getLogicTable())).addPropertyNode("actualDataNodes").addConstraintViolation();
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ValidShardingTableRuleConfiguration.java b/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ValidShardingTableRuleConfiguration.java
new file mode 100644
index 00000000000..578e18cf8bd
--- /dev/null
+++ b/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ValidShardingTableRuleConfiguration.java
@@ -0,0 +1,57 @@
+/*
+ * 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.api.config.validator;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Valid sharding table rule configuration constraint.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = ShardingTableRuleConfigurationValidator.class)
+@Documented
+public @interface ValidShardingTableRuleConfiguration {
+
+ /**
+ * Get message.
+ *
+ * @return message
+ */
+ String message() default "contains multiple schemas for a storage unit";
+
+ /**
+ * Get groups.
+ *
+ * @return groups
+ */
+ Class<?>[] groups() default {};
+
+ /**
+ * Get payload.
+ *
+ * @return payload
+ */
+ Class<? extends Payload>[] payload() default {};
+}
diff --git a/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/ShardingRuleConfigurationTest.java b/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/ShardingRuleConfigurationTest.java
index cf3164d64d5..78f144f9b7a 100644
--- a/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/ShardingRuleConfigurationTest.java
+++ b/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/ShardingRuleConfigurationTest.java
@@ -22,7 +22,9 @@ import org.apache.shardingsphere.infra.config.keygen.KeyGenerateStrategiesConfig
import org.apache.shardingsphere.infra.config.keygen.impl.ColumnKeyGenerateStrategiesRuleConfiguration;
import org.apache.shardingsphere.infra.config.keygen.impl.SequenceKeyGenerateStrategiesRuleConfiguration;
import org.apache.shardingsphere.infra.config.rule.validator.RuleConfigurationValidator;
+import org.apache.shardingsphere.infra.exception.kernel.metadata.datanode.InvalidDataNodeFormatException;
import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.InvalidRuleConfigurationException;
+import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.RuleConfigurationValidationException;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingAutoTableRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableReferenceRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
@@ -36,6 +38,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
+import javax.validation.ValidationException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -44,12 +47,79 @@ import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.isA;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
class ShardingRuleConfigurationTest {
+ @Test
+ void assertValidateBlankLogicTableBeforeDataNodes() {
+ ShardingRuleConfiguration ruleConfig = createRuleConfiguration(new ShardingTableRuleConfiguration("", "malformed"));
+ InvalidRuleConfigurationException actual = assertThrows(InvalidRuleConfigurationException.class, () -> RuleConfigurationValidator.validate(ruleConfig));
+ assertThat(actual.getMessage(), is("Invalid 'ShardingRuleConfiguration' rule, error message is: Property `tables[0].logicTable` must not be blank."));
+ }
+
+ @Test
+ void assertValidateRuleItemWithBlankLogicTableBeforeDataNodes() {
+ ShardingTableRuleConfiguration tableConfig = new ShardingTableRuleConfiguration("", "malformed");
+ InvalidRuleConfigurationException actual = assertThrows(InvalidRuleConfigurationException.class,
+ () -> RuleConfigurationValidator.validateRuleItem(new ShardingRuleConfiguration(), tableConfig));
+ assertThat(actual.getMessage(), is("Invalid 'ShardingRuleConfiguration' rule, error message is: Property `logicTable` must not be blank."));
+ }
+
+ @Test
+ void assertValidateMultipleSchemasForSameDataSource() {
+ ShardingRuleConfiguration ruleConfig = createRuleConfiguration(new ShardingTableRuleConfiguration("foo_tbl", "ds_0.foo_schema_${0..1}.foo_tbl_${0..1}"));
+ InvalidRuleConfigurationException actual = assertThrows(InvalidRuleConfigurationException.class, () -> RuleConfigurationValidator.validate(ruleConfig));
+ assertThat(actual.getMessage(), is("Invalid 'ShardingRuleConfiguration' rule, error message is: "
+ + "Property `tables[0].actualDataNodes` contains multiple schemas for storage unit `ds_0` in sharding table `foo_tbl`."));
+ }
+
+ @Test
+ void assertValidateRuleItemWithMultipleSchemasForSameDataSource() {
+ ShardingRuleConfiguration ruleConfig = new ShardingRuleConfiguration();
+ ShardingTableRuleConfiguration tableConfig = new ShardingTableRuleConfiguration("foo_tbl", "ds_0.foo_schema_${0..1}.foo_tbl_${0..1}");
+ InvalidRuleConfigurationException actual = assertThrows(InvalidRuleConfigurationException.class, () -> RuleConfigurationValidator.validateRuleItem(ruleConfig, tableConfig));
+ assertThat(actual.getMessage(), is("Invalid 'ShardingRuleConfiguration' rule, error message is: "
+ + "Property `actualDataNodes` contains multiple schemas for storage unit `ds_0` in sharding table `foo_tbl`."));
+ assertTrue(ruleConfig.getTables().isEmpty());
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("validSchemaDataNodesArguments")
+ void assertValidateValidSchemaDataNodes(final String name, final ShardingTableRuleConfiguration tableConfig) {
+ assertDoesNotThrow(() -> RuleConfigurationValidator.validate(createRuleConfiguration(tableConfig)));
+ assertDoesNotThrow(() -> RuleConfigurationValidator.validateRuleItem(new ShardingRuleConfiguration(), tableConfig));
+ }
+
+ private static Stream<Arguments> validSchemaDataNodesArguments() {
+ return Stream.of(
+ Arguments.of("null data nodes", new ShardingTableRuleConfiguration("foo_tbl", null)),
+ Arguments.of("empty data nodes", new ShardingTableRuleConfiguration("foo_tbl", "")),
+ Arguments.of("inline data nodes with consistent schemas", new ShardingTableRuleConfiguration("foo_tbl", "ds_${0..1}.foo_schema.foo_tbl_${0..1}")));
+ }
+
+ @Test
+ void assertValidateDifferentSchemasForDifferentLogicTables() {
+ ShardingRuleConfiguration ruleConfig = new ShardingRuleConfiguration();
+ ruleConfig.getTables().add(new ShardingTableRuleConfiguration("foo_tbl", "ds_0.foo_schema.foo_tbl_0"));
+ ruleConfig.getTables().add(new ShardingTableRuleConfiguration("bar_tbl", "ds_0.bar_schema.bar_tbl_0"));
+ assertDoesNotThrow(() -> RuleConfigurationValidator.validate(ruleConfig));
+ }
+
+ @Test
+ void assertValidateMalformedDataNodes() {
+ ShardingRuleConfiguration ruleConfig = createRuleConfiguration(new ShardingTableRuleConfiguration("foo_tbl", "malformed"));
+ RuleConfigurationValidationException actual = assertThrows(RuleConfigurationValidationException.class, () -> RuleConfigurationValidator.validate(ruleConfig));
+ assertThat(actual.getMessage(), is("Can not validate 'ShardingRuleConfiguration' rule configuration.\n"
+ + "More details: javax.validation.ValidationException: org.apache.shardingsphere.infra.exception.kernel.metadata.datanode.InvalidDataNodeFormatException: "
+ + "Invalid format for actual data node 'malformed'."));
+ assertThat(actual.getCause(), isA(ValidationException.class));
+ assertThat(actual.getCause().getCause(), isA(InvalidDataNodeFormatException.class));
+ }
+
@Test
void assertGetLogicTableNames() {
ShardingRuleConfiguration ruleConfig = new ShardingRuleConfiguration();
diff --git a/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidatorTest.java b/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidatorTest.java
new file mode 100644
index 00000000000..ecdd2a71668
--- /dev/null
+++ b/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidatorTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.api.config.validator;
+
+import org.apache.shardingsphere.infra.expr.entry.InlineExpressionParserFactory;
+import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
+import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.validation.ConstraintValidatorContext;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class ShardingTableRuleConfigurationValidatorTest {
+
+ private final ShardingTableRuleConfigurationValidator validator = new ShardingTableRuleConfigurationValidator();
+
+ @Mock
+ private InlineExpressionParser parser;
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private ConstraintValidatorContext context;
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("validDataNodesArguments")
+ void assertValidDataNodes(final String name, final List<String> actualDataNodes) {
+ try (MockedStatic<InlineExpressionParserFactory> mockedFactory = mockStatic(InlineExpressionParserFactory.class)) {
+ mockedFactory.when(() -> InlineExpressionParserFactory.newInstance("data_nodes")).thenReturn(parser);
+ when(parser.splitAndEvaluate()).thenReturn(actualDataNodes);
+ assertTrue(validator.isValid(new ShardingTableRuleConfiguration("foo_tbl", "data_nodes"), context));
+ verifyNoInteractions(context);
+ }
+ }
+
+ private static Stream<Arguments> validDataNodesArguments() {
+ return Stream.of(
+ Arguments.of("no data nodes", Collections.emptyList()),
+ Arguments.of("omitted schema", Collections.singletonList("ds_0.foo_tbl_0")),
+ Arguments.of("same schema for same data source", Arrays.asList("ds_0.foo_schema.foo_tbl_0", "ds_0.foo_schema.foo_tbl_1")),
+ Arguments.of("same schema in different cases", Arrays.asList("ds_0.foo_schema.foo_tbl_0", "ds_0.FOO_SCHEMA.foo_tbl_1")),
+ Arguments.of("omitted schema before explicit schema", Arrays.asList("ds_0.foo_tbl_0", "ds_0.foo_schema.foo_tbl_1")),
+ Arguments.of("omitted schema after explicit schema", Arrays.asList("ds_0.foo_schema.foo_tbl_0", "ds_0.foo_tbl_1")),
+ Arguments.of("different schemas for different data sources", Arrays.asList("ds_0.foo_schema.foo_tbl_0", "ds_1.bar_schema.foo_tbl_1")),
+ Arguments.of("data source names remain case sensitive", Arrays.asList("ds_0.foo_schema.foo_tbl_0", "DS_0.bar_schema.foo_tbl_1")));
+ }
+
+ @Test
+ void assertInvalidDataNodes() {
+ try (MockedStatic<InlineExpressionParserFactory> mockedFactory = mockStatic(InlineExpressionParserFactory.class)) {
+ mockedFactory.when(() -> InlineExpressionParserFactory.newInstance("data_nodes")).thenReturn(parser);
+ when(parser.splitAndEvaluate()).thenReturn(Arrays.asList("ds_0.foo_schema.foo_tbl_0", "ds_0.bar_schema.foo_tbl_1"));
+ assertFalse(validator.isValid(new ShardingTableRuleConfiguration("foo_tbl", "data_nodes"), context));
+ verify(context).disableDefaultConstraintViolation();
+ verify(context.buildConstraintViolationWithTemplate("contains multiple schemas for storage unit `ds_0` in sharding table `foo_tbl`")
+ .addPropertyNode("actualDataNodes")).addConstraintViolation();
+ }
+ }
+}
diff --git a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/checker/config/ShardingRuleConfigurationChecker.java b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/checker/config/ShardingRuleConfigurationChecker.java
index bb53d75f9c6..71ce04f15bd 100644
--- a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/checker/config/ShardingRuleConfigurationChecker.java
+++ b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/checker/config/ShardingRuleConfigurationChecker.java
@@ -19,22 +19,15 @@ package org.apache.shardingsphere.sharding.checker.config;
import org.apache.shardingsphere.infra.config.rule.checker.DatabaseRuleConfigurationChecker;
import org.apache.shardingsphere.infra.datanode.DataNode;
-import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
-import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.InvalidRuleConfigurationException;
import org.apache.shardingsphere.infra.expr.entry.InlineExpressionParserFactory;
-import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingAutoTableRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import org.apache.shardingsphere.sharding.constant.ShardingOrder;
-import javax.sql.DataSource;
import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
-import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -42,26 +35,6 @@ import java.util.stream.Collectors;
*/
public final class ShardingRuleConfigurationChecker implements DatabaseRuleConfigurationChecker<ShardingRuleConfiguration> {
- @Override
- public void check(final String databaseName, final ShardingRuleConfiguration ruleConfig, final Map<String, DataSource> dataSourceMap, final Collection<ShardingSphereRule> builtRules) {
- ruleConfig.getTables().forEach(this::checkDataNodeSchemas);
- }
-
- private void checkDataNodeSchemas(final ShardingTableRuleConfiguration tableRuleConfig) {
- Collection<String> actualDataNodes = InlineExpressionParserFactory.newInstance(tableRuleConfig.getActualDataNodes()).splitAndEvaluate();
- Map<String, String> schemaNamesByDataSource = new HashMap<>(actualDataNodes.size(), 1F);
- for (String each : actualDataNodes) {
- DataNode dataNode = new DataNode(each);
- if (null == dataNode.getSchemaName()) {
- continue;
- }
- String configuredSchemaName = schemaNamesByDataSource.putIfAbsent(dataNode.getDataSourceName(), dataNode.getSchemaName());
- ShardingSpherePreconditions.checkState(null == configuredSchemaName || configuredSchemaName.equalsIgnoreCase(dataNode.getSchemaName()),
- () -> new InvalidRuleConfigurationException("sharding table", Collections.singleton(tableRuleConfig.getLogicTable()),
- Collections.singleton(String.format("Multiple schemas are configured for storage unit '%s'.", dataNode.getDataSourceName()))));
- }
- }
-
@Override
public Collection<String> getRequiredDataSourceNames(final ShardingRuleConfiguration ruleConfig) {
Collection<String> result = new LinkedHashSet<>();
diff --git a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/checker/config/ShardingRuleConfigurationCheckerTest.java b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/checker/config/ShardingRuleConfigurationCheckerTest.java
index 5c01f007431..cde76e0929b 100644
--- a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/checker/config/ShardingRuleConfigurationCheckerTest.java
+++ b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/checker/config/ShardingRuleConfigurationCheckerTest.java
@@ -18,27 +18,19 @@
package org.apache.shardingsphere.sharding.checker.config;
import org.apache.shardingsphere.infra.config.rule.checker.DatabaseRuleConfigurationChecker;
-import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.InvalidRuleConfigurationException;
import org.apache.shardingsphere.infra.spi.type.ordered.OrderedSPILoader;
import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingAutoTableRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import org.junit.jupiter.api.BeforeEach;
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 java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
-import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-import static org.junit.jupiter.api.Assertions.assertThrows;
class ShardingRuleConfigurationCheckerTest {
@@ -50,38 +42,6 @@ class ShardingRuleConfigurationCheckerTest {
DatabaseRuleConfigurationChecker.class, Collections.singleton(ShardingRuleConfiguration.class)).get(ShardingRuleConfiguration.class);
}
- @Test
- void assertCheckWithMultipleSchemasForSameDataSource() {
- ShardingRuleConfiguration ruleConfig = createRuleConfiguration();
- ruleConfig.setTables(Collections.singleton(new ShardingTableRuleConfiguration("foo_tbl", "ds_0.foo_schema_${0..1}.foo_tbl_${0..1}")));
- InvalidRuleConfigurationException actual = assertThrows(InvalidRuleConfigurationException.class,
- () -> checker.check("foo_db", ruleConfig, Collections.emptyMap(), Collections.emptyList()));
- assertThat(actual.getMessage(), is("Invalid 'sharding table' rules 'foo_tbl', error messages are: Multiple schemas are configured for storage unit 'ds_0'."));
- }
-
- @ParameterizedTest(name = "{0}")
- @MethodSource("validSchemaDataNodesArguments")
- void assertCheckWithValidSchemaDataNodes(final String name, final Collection<ShardingTableRuleConfiguration> tableRuleConfigs) {
- ShardingRuleConfiguration ruleConfig = createRuleConfiguration();
- ruleConfig.setTables(tableRuleConfigs);
- assertDoesNotThrow(() -> checker.check("foo_db", ruleConfig, Collections.emptyMap(), Collections.emptyList()));
- }
-
- private static Stream<Arguments> validSchemaDataNodesArguments() {
- return Stream.of(
- Arguments.of("same schema for same data source", Collections.singleton(
- new ShardingTableRuleConfiguration("foo_tbl", "ds_0.foo_schema.foo_tbl_0,ds_0.foo_schema.foo_tbl_1"))),
- Arguments.of("same schema in different cases for same data source", Collections.singleton(
- new ShardingTableRuleConfiguration("foo_tbl", "ds_0.foo_schema.foo_tbl_0,ds_0.FOO_SCHEMA.foo_tbl_1"))),
- Arguments.of("omitted schema and explicit schema for same data source", Collections.singleton(
- new ShardingTableRuleConfiguration("foo_tbl", "ds_0.foo_tbl_0,ds_0.foo_schema.foo_tbl_1"))),
- Arguments.of("different schemas for different data sources", Collections.singleton(
- new ShardingTableRuleConfiguration("foo_tbl", "ds_0.foo_schema.foo_tbl_0,ds_1.bar_schema.foo_tbl_1"))),
- Arguments.of("different schemas for different logic tables", Arrays.asList(
- new ShardingTableRuleConfiguration("foo_tbl", "ds_0.foo_schema.foo_tbl_0"),
- new ShardingTableRuleConfiguration("bar_tbl", "ds_0.bar_schema.bar_tbl_0"))));
- }
-
@Test
void assertGetRequiredDataSourceNames() {
ShardingRuleConfiguration ruleConfig = createRuleConfiguration();
diff --git a/infra/common/src/main/java/org/apache/shardingsphere/infra/rule/builder/database/DatabaseRulesBuilder.java b/infra/common/src/main/java/org/apache/shardingsphere/infra/rule/builder/database/DatabaseRulesBuilder.java
index 8c8ff05d30d..e238c6cb99e 100644
--- a/infra/common/src/main/java/org/apache/shardingsphere/infra/rule/builder/database/DatabaseRulesBuilder.java
+++ b/infra/common/src/main/java/org/apache/shardingsphere/infra/rule/builder/database/DatabaseRulesBuilder.java
@@ -67,7 +67,6 @@ public final class DatabaseRulesBuilder {
final ComputeNodeInstanceContext computeNodeInstanceContext, final ResourceMetaData resourceMetaData) {
RuleConfigurationValidator.validate(databaseConfig.getRuleConfigurations());
Map<RuleConfiguration, DatabaseRuleBuilder> ruleBuilderMap = getRuleBuilderMap(databaseConfig);
- RuleConfigurationValidator.validate(ruleBuilderMap.keySet());
Collection<ShardingSphereRule> result = new LinkedList<>();
for (Entry<RuleConfiguration, DatabaseRuleBuilder> entry : ruleBuilderMap.entrySet()) {
DatabaseRuleConfigurationChecker configChecker = OrderedSPILoader.getServicesByClass(
@@ -153,7 +152,9 @@ public final class DatabaseRulesBuilder {
Map<RuleConfiguration, DatabaseRuleBuilder> result = new LinkedHashMap<>(defaultBuilders.size(), 1F);
// TODO consider about order for new put items
for (Entry<DatabaseRuleBuilder, DefaultDatabaseRuleConfigurationBuilder> entry : defaultBuilders.entrySet()) {
- result.put(entry.getValue().build(), entry.getKey());
+ RuleConfiguration ruleConfig = entry.getValue().build();
+ RuleConfigurationValidator.validate(ruleConfig);
+ result.put(ruleConfig, entry.getKey());
}
return result;
}
diff --git a/infra/common/src/test/java/org/apache/shardingsphere/infra/rule/builder/database/DatabaseRulesBuilderTest.java b/infra/common/src/test/java/org/apache/shardingsphere/infra/rule/builder/database/DatabaseRulesBuilderTest.java
index fb6631b4dc4..f2f3c650ee6 100644
--- a/infra/common/src/test/java/org/apache/shardingsphere/infra/rule/builder/database/DatabaseRulesBuilderTest.java
+++ b/infra/common/src/test/java/org/apache/shardingsphere/infra/rule/builder/database/DatabaseRulesBuilderTest.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.infra.rule.builder.database;
import org.apache.shardingsphere.infra.config.database.impl.DataSourceProvidedDatabaseConfiguration;
import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
import org.apache.shardingsphere.infra.config.rule.checker.DatabaseRuleConfigurationChecker;
+import org.apache.shardingsphere.infra.config.rule.validator.RuleConfigurationValidator;
import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.DuplicateRuleException;
import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.InvalidRuleConfigurationException;
import org.apache.shardingsphere.infra.fixture.FixtureRule;
@@ -56,6 +57,7 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
class DatabaseRulesBuilderTest {
@@ -123,6 +125,34 @@ class DatabaseRulesBuilderTest {
new DataSourceProvidedDatabaseConfiguration(Collections.emptyMap(), Collections.singleton(ruleConfig)), null, EMPTY_RESOURCE_META_DATA));
}
+ @Test
+ void assertBuildWithRuleConfigurationValidatedOnce() {
+ ToggleFixtureDatabaseRuleConfiguration ruleConfig = new ToggleFixtureDatabaseRuleConfiguration(false);
+ try (MockedStatic<RuleConfigurationValidator> mockedValidator = mockStatic(RuleConfigurationValidator.class, CALLS_REAL_METHODS)) {
+ Collection<ShardingSphereRule> actual = DatabaseRulesBuilder.build("foo_db", null,
+ new DataSourceProvidedDatabaseConfiguration(Collections.emptyMap(), Collections.singleton(ruleConfig)), null, EMPTY_RESOURCE_META_DATA);
+ assertTrue(actual.stream().anyMatch(ToggleFixtureRule.class::isInstance));
+ mockedValidator.verify(() -> RuleConfigurationValidator.validate(ruleConfig));
+ }
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ void assertBuildWithInvalidDefaultRuleConfiguration() {
+ FixtureDatabaseRuleConfiguration ruleConfig = new FixtureDatabaseRuleConfiguration();
+ ruleConfig.setName("");
+ DatabaseRuleBuilder<FixtureDatabaseRuleConfiguration> ruleBuilder = mock(DatabaseRuleBuilder.class);
+ DefaultDatabaseRuleConfigurationBuilder<FixtureDatabaseRuleConfiguration, ?> defaultBuilder = mock(DefaultDatabaseRuleConfigurationBuilder.class);
+ when(defaultBuilder.build()).thenReturn(ruleConfig);
+ try (MockedStatic<OrderedSPILoader> mockedLoader = mockStatic(OrderedSPILoader.class, CALLS_REAL_METHODS)) {
+ mockedLoader.when(() -> OrderedSPILoader.getServices(eq(DefaultDatabaseRuleConfigurationBuilder.class), anyCollection()))
+ .thenReturn(Collections.singletonMap(ruleBuilder, defaultBuilder));
+ assertThrows(InvalidRuleConfigurationException.class, () -> DatabaseRulesBuilder.build("foo_db", null,
+ new DataSourceProvidedDatabaseConfiguration(Collections.emptyMap(), Collections.emptyList()), null, EMPTY_RESOURCE_META_DATA));
+ verifyNoInteractions(ruleBuilder);
+ }
+ }
+
@Test
void assertBuildSingleRule() {
assertThat(DatabaseRulesBuilder.build("foo_db", null, Collections.emptyList(), new FixtureDatabaseRuleConfiguration(), null, EMPTY_RESOURCE_META_DATA), isA(FixtureRule.class));
diff --git a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/ral/updatable/lock/LockClusterExecutor.java b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/ral/updatable/lock/LockClusterExecutor.java
index 4a24bd2067b..5d0ce9cc893 100644
--- a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/ral/updatable/lock/LockClusterExecutor.java
+++ b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/ral/updatable/lock/LockClusterExecutor.java
@@ -18,7 +18,6 @@
package org.apache.shardingsphere.distsql.handler.executor.ral.updatable.lock;
import org.apache.shardingsphere.distsql.handler.engine.update.spi.DistSQLUpdateExecutor;
-import org.apache.shardingsphere.distsql.handler.executor.lock.spi.ClusterLockStrategy;
import org.apache.shardingsphere.distsql.handler.required.DistSQLExecutorClusterModeRequired;
import org.apache.shardingsphere.distsql.statement.type.ral.updatable.LockClusterStatement;
import org.apache.shardingsphere.infra.algorithm.core.exception.MissingRequiredAlgorithmException;
@@ -27,6 +26,7 @@ import org.apache.shardingsphere.infra.exception.external.sql.identifier.SQLExce
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.mode.manager.ContextManager;
import org.apache.shardingsphere.mode.manager.cluster.lock.exception.LockedClusterException;
+import org.apache.shardingsphere.mode.manager.cluster.lock.spi.ClusterLockStrategy;
import org.apache.shardingsphere.mode.state.ShardingSphereState;
import java.sql.SQLException;
diff --git a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/lock/spi/ClusterLockStrategy.java b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/lock/spi/ClusterLockStrategy.java
similarity index 94%
rename from infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/lock/spi/ClusterLockStrategy.java
rename to mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/lock/spi/ClusterLockStrategy.java
index 30f87fc49e1..9fa4448f58e 100644
--- a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/lock/spi/ClusterLockStrategy.java
+++ b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/lock/spi/ClusterLockStrategy.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.distsql.handler.executor.lock.spi;
+package org.apache.shardingsphere.mode.manager.cluster.lock.spi;
import org.apache.shardingsphere.infra.spi.annotation.SingletonSPI;
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPI;
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterReadWriteLockStrategy.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterReadWriteLockStrategy.java
index 6db5210aff8..487151f3c17 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterReadWriteLockStrategy.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterReadWriteLockStrategy.java
@@ -17,7 +17,7 @@
package org.apache.shardingsphere.proxy.backend.lock.impl;
-import org.apache.shardingsphere.distsql.handler.executor.lock.spi.ClusterLockStrategy;
+import org.apache.shardingsphere.mode.manager.cluster.lock.spi.ClusterLockStrategy;
import org.apache.shardingsphere.mode.state.ShardingSphereState;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterWriteLockStrategy.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterWriteLockStrategy.java
index 5feb9a239ba..24affb5dce7 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterWriteLockStrategy.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterWriteLockStrategy.java
@@ -17,7 +17,7 @@
package org.apache.shardingsphere.proxy.backend.lock.impl;
-import org.apache.shardingsphere.distsql.handler.executor.lock.spi.ClusterLockStrategy;
+import org.apache.shardingsphere.mode.manager.cluster.lock.spi.ClusterLockStrategy;
import org.apache.shardingsphere.mode.state.ShardingSphereState;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
diff --git a/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.lock.spi.ClusterLockStrategy b/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.mode.manager.cluster.lock.spi.ClusterLockStrategy
similarity index 100%
rename from proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.lock.spi.ClusterLockStrategy
rename to proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.mode.manager.cluster.lock.spi.ClusterLockStrategy
diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterReadWriteLockStrategyTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterReadWriteLockStrategyTest.java
index b4c4b1b650c..16be664878c 100644
--- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterReadWriteLockStrategyTest.java
+++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterReadWriteLockStrategyTest.java
@@ -17,8 +17,8 @@
package org.apache.shardingsphere.proxy.backend.lock.impl;
-import org.apache.shardingsphere.distsql.handler.executor.lock.spi.ClusterLockStrategy;
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.mode.manager.cluster.lock.spi.ClusterLockStrategy;
import org.apache.shardingsphere.mode.state.ShardingSphereState;
import org.apache.shardingsphere.mode.state.StatePersistService;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterWriteLockStrategyTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterWriteLockStrategyTest.java
index b17f4dbd923..7995ef19162 100644
--- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterWriteLockStrategyTest.java
+++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/lock/impl/ClusterWriteLockStrategyTest.java
@@ -17,8 +17,8 @@
package org.apache.shardingsphere.proxy.backend.lock.impl;
-import org.apache.shardingsphere.distsql.handler.executor.lock.spi.ClusterLockStrategy;
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.mode.manager.cluster.lock.spi.ClusterLockStrategy;
import org.apache.shardingsphere.mode.state.ShardingSphereState;
import org.apache.shardingsphere.mode.state.StatePersistService;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;