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 c87252791f8 Move encrypt table name uniqueness checks to Bean
Validation (#40054)
c87252791f8 is described below
commit c87252791f88992aabe04ab0bfe76876629219cb
Author: Liang Zhang <[email protected]>
AuthorDate: Sun Oct 4 22:55:58 2026 +0800
Move encrypt table name uniqueness checks to Bean Validation (#40054)
* Align DistSQL executor tests with production SPIs
* Move encrypt table name uniqueness checks to Bean Validation
---
.../user-manual/error-code/sql-error-code.cn.md | 1 -
.../user-manual/error-code/sql-error-code.en.md | 1 -
.../encrypt/config/EncryptRuleConfiguration.java | 2 +
.../config/EncryptRuleConfigurationTest.java | 15 +++
.../config/EncryptRuleConfigurationChecker.java | 47 ---------
.../MissingRequiredEncryptColumnException.java | 34 -------
...g.rule.checker.DatabaseRuleConfigurationChecker | 18 ----
.../EncryptRuleConfigurationCheckerTest.java | 51 ----------
.../constraint/unique/UniqueTableNames.java | 59 +++++++++++
.../unique/UniqueTableNamesValidator.java | 53 ++++++++++
.../unique/UniqueTableNamesValidatorTest.java | 108 +++++++++++++++++++++
.../spi}/fixture/FixtureRule.java | 2 +-
.../fixture/FixtureDistSQLQueryExecutor.java | 2 +-
.../fixture/FixtureDistSQLQueryStatement.java | 2 +-
.../fixture/FixtureDistSQLUpdateExecutor.java | 2 +-
.../fixture/FixtureDistSQLUpdateStatement.java | 2 +-
.../FixtureDatabaseRuleDefinitionExecutor.java | 2 +-
.../FixtureDatabaseRuleDefinitionStatement.java | 2 +-
...handler.executor.spi.query.DistSQLQueryExecutor | 2 +-
...ndler.executor.spi.update.DistSQLUpdateExecutor | 2 +-
...te.rule.database.DatabaseRuleDefinitionExecutor | 2 +-
.../reachability-metadata.json | 36 +++++++
22 files changed, 283 insertions(+), 162 deletions(-)
diff --git a/docs/document/content/user-manual/error-code/sql-error-code.cn.md
b/docs/document/content/user-manual/error-code/sql-error-code.cn.md
index 8957f63747b..aa93f19a1fd 100644
--- a/docs/document/content/user-manual/error-code/sql-error-code.cn.md
+++ b/docs/document/content/user-manual/error-code/sql-error-code.cn.md
@@ -230,7 +230,6 @@ SQL 错误码以标准的 SQL State,Vendor Code 和详细错误信息提供,
| Vendor Code | SQL State | 错误信息
|
|-------------|-----------|----------------------------------------------------------------------------------------------|
-| 21000 | 42S02 | %s column is required in %s.
|
| 21001 | 42S02 | Can not find encrypt table '%s'.
|
| 21002 | 42S02 | Can not find logic encrypt column by '%s'.
|
| 21003 | 42S02 | Can not find encrypt column '%s' from table '%s'.
|
diff --git a/docs/document/content/user-manual/error-code/sql-error-code.en.md
b/docs/document/content/user-manual/error-code/sql-error-code.en.md
index 7fbf94c6617..e8d16b584da 100644
--- a/docs/document/content/user-manual/error-code/sql-error-code.en.md
+++ b/docs/document/content/user-manual/error-code/sql-error-code.en.md
@@ -230,7 +230,6 @@ SQL error codes provide by standard `SQL State`, `Vendor
Code` and `Reason`, whi
| Vendor Code | SQL State | Reason
|
|-------------|-----------|----------------------------------------------------------------------------------------------|
-| 21000 | 42S02 | %s column is required in %s.
|
| 21001 | 42S02 | Can not find encrypt table '%s'.
|
| 21002 | 42S02 | Can not find logic encrypt column by '%s'.
|
| 21003 | 42S02 | Can not find encrypt column '%s' from table '%s'.
|
diff --git
a/features/encrypt/api/src/main/java/org/apache/shardingsphere/encrypt/config/EncryptRuleConfiguration.java
b/features/encrypt/api/src/main/java/org/apache/shardingsphere/encrypt/config/EncryptRuleConfiguration.java
index f25aaabdac8..af880959b8e 100644
---
a/features/encrypt/api/src/main/java/org/apache/shardingsphere/encrypt/config/EncryptRuleConfiguration.java
+++
b/features/encrypt/api/src/main/java/org/apache/shardingsphere/encrypt/config/EncryptRuleConfiguration.java
@@ -26,6 +26,7 @@ import
org.apache.shardingsphere.infra.config.rule.function.EnhancedRuleConfigur
import
org.apache.shardingsphere.infra.config.rule.scope.DatabaseRuleConfiguration;
import
org.apache.shardingsphere.infra.config.rule.validator.constraint.reference.ConfigurationReferenceExists;
import
org.apache.shardingsphere.infra.config.rule.validator.constraint.spi.SPITypeExists;
+import
org.apache.shardingsphere.infra.config.rule.validator.constraint.unique.UniqueTableNames;
import
org.apache.shardingsphere.infra.config.rule.validator.group.RuleConfigurationTypeValidationGroup;
import javax.validation.Valid;
@@ -46,6 +47,7 @@ public final class EncryptRuleConfiguration implements
DatabaseRuleConfiguration
@NotNull
@Valid
+ @UniqueTableNames(groups = RuleConfigurationTypeValidationGroup.class)
private final Collection<@NotNull EncryptTableRuleConfiguration> tables;
@NotNull
diff --git
a/features/encrypt/api/src/test/java/org/apache/shardingsphere/encrypt/config/EncryptRuleConfigurationTest.java
b/features/encrypt/api/src/test/java/org/apache/shardingsphere/encrypt/config/EncryptRuleConfigurationTest.java
index ae8a651dc51..e295c92d717 100644
---
a/features/encrypt/api/src/test/java/org/apache/shardingsphere/encrypt/config/EncryptRuleConfigurationTest.java
+++
b/features/encrypt/api/src/test/java/org/apache/shardingsphere/encrypt/config/EncryptRuleConfigurationTest.java
@@ -28,6 +28,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
+import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -65,6 +66,8 @@ class EncryptRuleConfigurationTest {
Arguments.of("Empty configuration", new
EncryptRuleConfiguration(Collections.emptyList(), Collections.emptyMap())),
Arguments.of("Table without columns", new
EncryptRuleConfiguration(
Collections.singleton(new
EncryptTableRuleConfiguration("foo_tbl", Collections.emptyList())),
Collections.emptyMap())),
+ Arguments.of("Table names remain case sensitive", new
EncryptRuleConfiguration(Arrays.asList(
+ new EncryptTableRuleConfiguration("foo_tbl",
Collections.emptyList()), new EncryptTableRuleConfiguration("FOO_TBL",
Collections.emptyList())), Collections.emptyMap())),
Arguments.of("Complete configuration",
createValidRuleConfiguration()),
Arguments.of("Multiple columns without derived column
conflicts", createValidMultipleColumnRuleConfiguration()));
}
@@ -101,6 +104,18 @@ class EncryptRuleConfigurationTest {
assertThat(actual.getMessage(), is("Invalid 'EncryptRuleConfiguration'
rule, error message is: Property `tables` references unconfigured encryptors
`bar_encryptor`."));
}
+ @Test
+ void assertDuplicateTableNamesViolation() {
+ EncryptRuleConfiguration ruleConfig = new
EncryptRuleConfiguration(Arrays.asList(new
EncryptTableRuleConfiguration("foo_tbl", Collections.emptyList()),
+ new EncryptTableRuleConfiguration("bar_tbl",
Collections.emptyList()), new EncryptTableRuleConfiguration("foo_tbl",
Collections.emptyList())), Collections.emptyMap());
+ InvalidRuleConfigurationException actual =
assertThrows(InvalidRuleConfigurationException.class, () ->
RuleConfigurationValidator.validate(ruleConfig));
+ assertThat(actual.getMessage(), is("Invalid 'EncryptRuleConfiguration'
rule, error message is: Property `tables` must not contain duplicate table
names `foo_tbl`."));
+ SQLException actualSQLException = actual.toSQLException();
+ assertThat(actualSQLException.getMessage(), is(actual.getMessage()));
+ assertThat(actualSQLException.getSQLState(), is("44000"));
+ assertThat(actualSQLException.getErrorCode(), is(10200));
+ }
+
private static Stream<Arguments> invalidRuleConfigurationArguments() {
EncryptColumnRuleConfiguration invalidAssistedQueryName =
createValidColumnConfiguration();
invalidAssistedQueryName.setAssistedQuery(new
EncryptColumnItemRuleConfiguration("", "foo_encryptor"));
diff --git
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/config/EncryptRuleConfigurationChecker.java
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/config/EncryptRuleConfigurationChecker.java
deleted file mode 100644
index 429796130be..00000000000
---
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/config/EncryptRuleConfigurationChecker.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.encrypt.checker.config;
-
-import org.apache.shardingsphere.encrypt.config.EncryptRuleConfiguration;
-import
org.apache.shardingsphere.encrypt.config.rule.EncryptTableRuleConfiguration;
-import org.apache.shardingsphere.encrypt.constant.EncryptOrder;
-import
org.apache.shardingsphere.infra.config.rule.checker.DatabaseRuleConfigurationChecker;
-
-import java.util.Collection;
-import java.util.stream.Collectors;
-
-/**
- * Encrypt rule configuration checker.
- */
-public final class EncryptRuleConfigurationChecker implements
DatabaseRuleConfigurationChecker<EncryptRuleConfiguration> {
-
- @Override
- public Collection<String> getTableNames(final EncryptRuleConfiguration
ruleConfig) {
- return
ruleConfig.getTables().stream().map(EncryptTableRuleConfiguration::getName).collect(Collectors.toList());
- }
-
- @Override
- public int getOrder() {
- return EncryptOrder.ORDER;
- }
-
- @Override
- public Class<EncryptRuleConfiguration> getTypeClass() {
- return EncryptRuleConfiguration.class;
- }
-}
diff --git
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/exception/metadata/MissingRequiredEncryptColumnException.java
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/exception/metadata/MissingRequiredEncryptColumnException.java
deleted file mode 100644
index ddc65468d4f..00000000000
---
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/exception/metadata/MissingRequiredEncryptColumnException.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.encrypt.exception.metadata;
-
-import org.apache.shardingsphere.encrypt.exception.EncryptSQLException;
-import
org.apache.shardingsphere.infra.exception.external.sql.identifier.SQLExceptionIdentifier;
-import
org.apache.shardingsphere.infra.exception.external.sql.sqlstate.XOpenSQLState;
-
-/**
- * Missing required encrypt column Exception.
- */
-public final class MissingRequiredEncryptColumnException extends
EncryptSQLException {
-
- private static final long serialVersionUID = -6765795304282762539L;
-
- public MissingRequiredEncryptColumnException(final String columnType,
final SQLExceptionIdentifier sqlExceptionIdentifier) {
- super(XOpenSQLState.NOT_FOUND, 0, "%s column is required in %s.",
columnType, sqlExceptionIdentifier);
- }
-}
diff --git
a/features/encrypt/core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.config.rule.checker.DatabaseRuleConfigurationChecker
b/features/encrypt/core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.config.rule.checker.DatabaseRuleConfigurationChecker
deleted file mode 100644
index c02e5b307d8..00000000000
---
a/features/encrypt/core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.config.rule.checker.DatabaseRuleConfigurationChecker
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-org.apache.shardingsphere.encrypt.checker.config.EncryptRuleConfigurationChecker
diff --git
a/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/checker/config/EncryptRuleConfigurationCheckerTest.java
b/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/checker/config/EncryptRuleConfigurationCheckerTest.java
deleted file mode 100644
index 879e1b47401..00000000000
---
a/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/checker/config/EncryptRuleConfigurationCheckerTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.encrypt.checker.config;
-
-import org.apache.shardingsphere.encrypt.config.EncryptRuleConfiguration;
-import
org.apache.shardingsphere.encrypt.config.rule.EncryptTableRuleConfiguration;
-import
org.apache.shardingsphere.infra.config.rule.checker.DatabaseRuleConfigurationChecker;
-import org.apache.shardingsphere.infra.spi.type.ordered.OrderedSPILoader;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.util.Collections;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-
-class EncryptRuleConfigurationCheckerTest {
-
- @SuppressWarnings("rawtypes")
- private DatabaseRuleConfigurationChecker checker;
-
- @BeforeEach
- void setUp() {
- checker =
OrderedSPILoader.getServicesByClass(DatabaseRuleConfigurationChecker.class,
Collections.singleton(EncryptRuleConfiguration.class)).get(EncryptRuleConfiguration.class);
- }
-
- @SuppressWarnings("unchecked")
- @Test
- void assertGetTableNames() {
- assertThat(checker.getTableNames(createValidRuleConfiguration()),
is(Collections.singletonList("t_encrypt")));
- }
-
- private EncryptRuleConfiguration createValidRuleConfiguration() {
- return new EncryptRuleConfiguration(Collections.singleton(new
EncryptTableRuleConfiguration("t_encrypt", Collections.emptyList())),
Collections.emptyMap());
- }
-}
diff --git
a/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNames.java
b/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNames.java
new file mode 100644
index 00000000000..140ab1356bc
--- /dev/null
+++
b/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNames.java
@@ -0,0 +1,59 @@
+/*
+ * 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.config.rule.validator.constraint.unique;
+
+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;
+
+/**
+ * Unique table names constraint.
+ * Collection elements must expose a public {@code String getName()} method.
+ * Apply after null collection and element constraints have passed.
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = UniqueTableNamesValidator.class)
+@Documented
+public @interface UniqueTableNames {
+
+ /**
+ * Get message.
+ *
+ * @return message
+ */
+ String message() default "must not contain duplicate table names";
+
+ /**
+ * Get groups.
+ *
+ * @return groups
+ */
+ Class<?>[] groups() default {};
+
+ /**
+ * Get payload.
+ *
+ * @return payload
+ */
+ Class<? extends Payload>[] payload() default {};
+}
diff --git
a/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidator.java
b/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidator.java
new file mode 100644
index 00000000000..283b1ff39d5
--- /dev/null
+++
b/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidator.java
@@ -0,0 +1,53 @@
+/*
+ * 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.config.rule.validator.constraint.unique;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.ValidationException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Unique table names validator.
+ */
+public final class UniqueTableNamesValidator implements
ConstraintValidator<UniqueTableNames, Collection<?>> {
+
+ @Override
+ public boolean isValid(final Collection<?> value, final
ConstraintValidatorContext context) {
+ Set<String> tableNames = new HashSet<>(value.size(), 1F);
+ Set<String> duplicatedTableNames =
value.stream().map(this::getTableName).filter(tableName ->
!tableNames.add(tableName)).collect(Collectors.toCollection(LinkedHashSet::new));
+ if (duplicatedTableNames.isEmpty()) {
+ return true;
+ }
+ context.disableDefaultConstraintViolation();
+ context.buildConstraintViolationWithTemplate(String.format("must not
contain duplicate table names `%s`", String.join(", ",
duplicatedTableNames))).addConstraintViolation();
+ return false;
+ }
+
+ private String getTableName(final Object tableConfig) {
+ try {
+ return (String)
tableConfig.getClass().getMethod("getName").invoke(tableConfig);
+ } catch (final ReflectiveOperationException ex) {
+ throw new ValidationException(String.format("Can not read property
`name` from `%s`.", tableConfig.getClass().getName()), ex);
+ }
+ }
+}
diff --git
a/infra/common/src/test/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidatorTest.java
b/infra/common/src/test/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidatorTest.java
new file mode 100644
index 00000000000..09fdbf63435
--- /dev/null
+++
b/infra/common/src/test/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidatorTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.config.rule.validator.constraint.unique;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+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.validation.ConstraintValidatorContext;
+import javax.validation.ConstraintValidatorContext.ConstraintViolationBuilder;
+import javax.validation.ValidationException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+class UniqueTableNamesValidatorTest {
+
+ private final UniqueTableNamesValidator validator = new
UniqueTableNamesValidator();
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("validTablesArguments")
+ void assertIsValidWithoutDuplicatedNames(final String name, final
Collection<?> tables) {
+ ConstraintValidatorContext context =
mock(ConstraintValidatorContext.class);
+ assertTrue(validator.isValid(tables, context));
+ verifyNoInteractions(context);
+ }
+
+ private static Stream<Arguments> validTablesArguments() {
+ return Stream.of(
+ Arguments.of("Empty tables", Collections.emptyList()),
+ Arguments.of("Single table", createTables("foo_tbl")),
+ Arguments.of("Distinct table names", createTables("foo_tbl",
"bar_tbl")),
+ Arguments.of("Table names remain case sensitive",
createTables("foo_tbl", "FOO_TBL")));
+ }
+
+ private static Collection<Table> createTables(final String... tableNames) {
+ return
Arrays.stream(tableNames).map(Table::new).collect(Collectors.toList());
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("duplicatedTablesArguments")
+ void assertIsValidWithDuplicatedNames(final String name, final
Collection<?> tables, final String expectedMessage) {
+ ConstraintValidatorContext context =
mock(ConstraintValidatorContext.class);
+ ConstraintViolationBuilder builder =
mock(ConstraintViolationBuilder.class);
+
when(context.buildConstraintViolationWithTemplate(expectedMessage)).thenReturn(builder);
+ assertFalse(validator.isValid(tables, context));
+ verify(context).disableDefaultConstraintViolation();
+ verify(builder).addConstraintViolation();
+ }
+
+ private static Stream<Arguments> duplicatedTablesArguments() {
+ return Stream.of(
+ Arguments.of("Nonadjacent duplicated name",
createTables("foo_tbl", "bar_tbl", "foo_tbl"), "must not contain duplicate
table names `foo_tbl`"),
+ Arguments.of("All duplicated names retain encounter order",
createTables("z_tbl", "a_tbl", "z_tbl", "a_tbl", "z_tbl"),
+ "must not contain duplicate table names `z_tbl,
a_tbl`"),
+ Arguments.of("Names read across different table types",
Arrays.asList(new Table("foo_tbl"), new OtherTable("foo_tbl")), "must not
contain duplicate table names `foo_tbl`"));
+ }
+
+ @Test
+ void assertIsValidWithMissingNameProperty() {
+ ValidationException actual = assertThrows(ValidationException.class,
() -> validator.isValid(Collections.singleton(new Object()),
mock(ConstraintValidatorContext.class)));
+ assertThat(actual.getMessage(), is("Can not read property `name` from
`java.lang.Object`."));
+ }
+
+ @RequiredArgsConstructor
+ @Getter
+ public static final class Table {
+
+ private final String name;
+ }
+
+ @RequiredArgsConstructor
+ @Getter
+ public static final class OtherTable {
+
+ private final String name;
+ }
+}
diff --git
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureRule.java
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/fixture/FixtureRule.java
similarity index 94%
rename from
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureRule.java
rename to
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/fixture/FixtureRule.java
index 5a7a8dc5818..14aac497e45 100644
---
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureRule.java
+++
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/fixture/FixtureRule.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.distsql.handler.engine.concurrent.fixture;
+package org.apache.shardingsphere.distsql.handler.executor.spi.fixture;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
diff --git
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDistSQLQueryExecutor.java
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/query/fixture/FixtureDistSQLQueryExecutor.java
similarity index 97%
rename from
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDistSQLQueryExecutor.java
rename to
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/query/fixture/FixtureDistSQLQueryExecutor.java
index f2cddad4efd..5e26b380e55 100644
---
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDistSQLQueryExecutor.java
+++
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/query/fixture/FixtureDistSQLQueryExecutor.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.distsql.handler.engine.concurrent.fixture;
+package org.apache.shardingsphere.distsql.handler.executor.spi.query.fixture;
import
org.apache.shardingsphere.distsql.handler.executor.aware.DistSQLExecutorRuleAware;
import
org.apache.shardingsphere.distsql.handler.executor.spi.query.DistSQLQueryExecutor;
diff --git
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDistSQLQueryStatement.java
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/query/fixture/FixtureDistSQLQueryStatement.java
similarity index 93%
rename from
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDistSQLQueryStatement.java
rename to
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/query/fixture/FixtureDistSQLQueryStatement.java
index bdf9825d462..db3ac2f9df6 100644
---
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDistSQLQueryStatement.java
+++
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/query/fixture/FixtureDistSQLQueryStatement.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.distsql.handler.engine.concurrent.fixture;
+package org.apache.shardingsphere.distsql.handler.executor.spi.query.fixture;
import lombok.AllArgsConstructor;
import lombok.Getter;
diff --git
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDistSQLUpdateExecutor.java
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/update/fixture/FixtureDistSQLUpdateExecutor.java
similarity index 96%
rename from
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDistSQLUpdateExecutor.java
rename to
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/update/fixture/FixtureDistSQLUpdateExecutor.java
index f1c58859811..25031bf0656 100644
---
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDistSQLUpdateExecutor.java
+++
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/update/fixture/FixtureDistSQLUpdateExecutor.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.distsql.handler.engine.concurrent.fixture;
+package org.apache.shardingsphere.distsql.handler.executor.spi.update.fixture;
import
org.apache.shardingsphere.distsql.handler.executor.aware.DistSQLExecutorRuleAware;
import
org.apache.shardingsphere.distsql.handler.executor.spi.update.DistSQLUpdateExecutor;
diff --git
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDistSQLUpdateStatement.java
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/update/fixture/FixtureDistSQLUpdateStatement.java
similarity index 93%
rename from
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDistSQLUpdateStatement.java
rename to
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/update/fixture/FixtureDistSQLUpdateStatement.java
index edb69a65e9a..ed8e4f6440e 100644
---
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDistSQLUpdateStatement.java
+++
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/update/fixture/FixtureDistSQLUpdateStatement.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.distsql.handler.engine.concurrent.fixture;
+package org.apache.shardingsphere.distsql.handler.executor.spi.update.fixture;
import lombok.AllArgsConstructor;
import lombok.Getter;
diff --git
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDatabaseRuleDefinitionExecutor.java
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/update/rule/database/fixture/FixtureDatabaseRuleDefinitionExecutor.java
similarity index 95%
rename from
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDatabaseRuleDefinitionExecutor.java
rename to
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/update/rule/database/fixture/FixtureDatabaseRuleDefinitionExecutor.java
index 6695db18be9..aa17866d2d0 100644
---
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDatabaseRuleDefinitionExecutor.java
+++
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/update/rule/database/fixture/FixtureDatabaseRuleDefinitionExecutor.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.distsql.handler.engine.concurrent.fixture;
+package
org.apache.shardingsphere.distsql.handler.executor.spi.update.rule.database.fixture;
import
org.apache.shardingsphere.distsql.handler.executor.spi.update.rule.database.DatabaseRuleDefinitionExecutor;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
diff --git
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDatabaseRuleDefinitionStatement.java
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/update/rule/database/fixture/FixtureDatabaseRuleDefinitionStatement.java
similarity index 93%
rename from
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDatabaseRuleDefinitionStatement.java
rename to
infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/update/rule/database/fixture/FixtureDatabaseRuleDefinitionStatement.java
index f251a1896d5..8eae6405b6e 100644
---
a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/engine/concurrent/fixture/FixtureDatabaseRuleDefinitionStatement.java
+++
b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/spi/update/rule/database/fixture/FixtureDatabaseRuleDefinitionStatement.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.distsql.handler.engine.concurrent.fixture;
+package
org.apache.shardingsphere.distsql.handler.executor.spi.update.rule.database.fixture;
import lombok.Getter;
import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
diff --git
a/infra/distsql-handler/src/test/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.spi.query.DistSQLQueryExecutor
b/infra/distsql-handler/src/test/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.spi.query.DistSQLQueryExecutor
index 00e99159f18..a37bcf3ca6c 100644
---
a/infra/distsql-handler/src/test/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.spi.query.DistSQLQueryExecutor
+++
b/infra/distsql-handler/src/test/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.spi.query.DistSQLQueryExecutor
@@ -15,4 +15,4 @@
# limitations under the License.
#
-org.apache.shardingsphere.distsql.handler.engine.concurrent.fixture.FixtureDistSQLQueryExecutor
+org.apache.shardingsphere.distsql.handler.executor.spi.query.fixture.FixtureDistSQLQueryExecutor
diff --git
a/infra/distsql-handler/src/test/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.spi.update.DistSQLUpdateExecutor
b/infra/distsql-handler/src/test/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.spi.update.DistSQLUpdateExecutor
index eb012944bf2..1fc8633dbe3 100644
---
a/infra/distsql-handler/src/test/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.spi.update.DistSQLUpdateExecutor
+++
b/infra/distsql-handler/src/test/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.spi.update.DistSQLUpdateExecutor
@@ -15,4 +15,4 @@
# limitations under the License.
#
-org.apache.shardingsphere.distsql.handler.engine.concurrent.fixture.FixtureDistSQLUpdateExecutor
+org.apache.shardingsphere.distsql.handler.executor.spi.update.fixture.FixtureDistSQLUpdateExecutor
diff --git
a/infra/distsql-handler/src/test/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.spi.update.rule.database.DatabaseRuleDefinitionExecutor
b/infra/distsql-handler/src/test/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.spi.update.rule.database.DatabaseRuleDefinitionExecutor
index bc91e04442b..fc203c14ea7 100644
---
a/infra/distsql-handler/src/test/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.spi.update.rule.database.DatabaseRuleDefinitionExecutor
+++
b/infra/distsql-handler/src/test/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.executor.spi.update.rule.database.DatabaseRuleDefinitionExecutor
@@ -15,4 +15,4 @@
# limitations under the License.
#
-org.apache.shardingsphere.distsql.handler.engine.concurrent.fixture.FixtureDatabaseRuleDefinitionExecutor
+org.apache.shardingsphere.distsql.handler.executor.spi.update.rule.database.fixture.FixtureDatabaseRuleDefinitionExecutor
diff --git
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere/infra-reachability-metadata/reachability-metadata.json
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere/infra-reachability-metadata/reachability-metadata.json
index 316602b95ab..cbc131c4a6e 100644
---
a/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere/infra-reachability-metadata/reachability-metadata.json
+++
b/infra/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere/infra-reachability-metadata/reachability-metadata.json
@@ -337,6 +337,38 @@
}
]
},
+ {
+ "condition": {
+ "typeReached":
"org.apache.shardingsphere.infra.config.rule.validator.RuleConfigurationValidator"
+ },
+ "type":
"org.apache.shardingsphere.infra.config.rule.validator.constraint.unique.UniqueTableNamesValidator",
+ "methods": [
+ {
+ "name": "<init>",
+ "parameterTypes": []
+ }
+ ]
+ },
+ {
+ "condition": {
+ "typeReached":
"org.apache.shardingsphere.infra.config.rule.validator.RuleConfigurationValidator"
+ },
+ "type":
"org.apache.shardingsphere.infra.config.rule.validator.constraint.unique.UniqueTableNames",
+ "methods": [
+ {
+ "name": "groups",
+ "parameterTypes": []
+ },
+ {
+ "name": "message",
+ "parameterTypes": []
+ },
+ {
+ "name": "payload",
+ "parameterTypes": []
+ }
+ ]
+ },
{
"condition": {
"typeReached":
"org.apache.shardingsphere.infra.config.rule.validator.RuleConfigurationValidator"
@@ -444,6 +476,10 @@
{
"name": "getColumns",
"parameterTypes": []
+ },
+ {
+ "name": "getName",
+ "parameterTypes": []
}
]
},