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 4f69cf38146 Match mask table names case-insensitively in DistSQL 
executors (#39361)
4f69cf38146 is described below

commit 4f69cf38146cd4c5a9da259c0afb4a0d4c3a6f2e
Author: Eunbin Son <[email protected]>
AuthorDate: Tue Sep 8 18:52:38 2026 +0900

    Match mask table names case-insensitively in DistSQL executors (#39361)
    
    * Match mask table names case-insensitively in DistSQL executors
    
    * Remove original case-variant mask table item on ALTER
    
    buildToBeDroppedRuleConfiguration returned an empty table collection, so
    altering an existing t_order as T_ORDER persisted a second item while
    MaskTableChangedProcessor replaces tables by exact name. The durable
    configuration kept both case variants and a stale algorithm reference.
    
    Return the current table items whose names match case-insensitively but
    differ in spelling, so the original item is deleted after the altered one
    is persisted. Items with identical spelling stay out of the dropped
    configuration to avoid removing the newly persisted item.
    
    Add a regression test that runs the executor output through
    MaskTableChangedProcessor and asserts one remaining table with the new
    algorithm.
    
    * Reject case-colliding mask table names within one ALTER
    
    The grammar accepts multiple definitions per statement and existence
    validation compares case-insensitively, so ALTER MASK RULE t_order,
    T_ORDER passed while cleanup excluded both because both exact spellings
    occur in the altered set. Persistence then emitted two case variants of
    one logical table, and MaskRule keys its tables case-insensitively, so
    runtime behavior depended on load order.
    
    Reject targets that collide case-insensitively within one statement
    before consulting the current rule.
    
    * Skip existing mask tables case-insensitively on CREATE IF NOT EXISTS
    
    IF NOT EXISTS bypasses duplicate detection and the build method converted
    every supplied rule, so creating T_ORDER for an existing t_order added a
    second case variant instead of being a no-op.
    
    Filter segments whose table name already exists case-insensitively before
    conversion, which also drops the algorithms generated for them.
---
 RELEASE-NOTES.md                                   |  1 +
 .../handler/update/AlterMaskRuleExecutor.java      | 28 +++++++--
 .../handler/update/CreateMaskRuleExecutor.java     | 25 ++++++--
 .../handler/update/AlterMaskRuleExecutorTest.java  | 66 +++++++++++++++++++---
 .../handler/update/CreateMaskRuleExecutorTest.java | 35 ++++++++++--
 5 files changed, 134 insertions(+), 21 deletions(-)

diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index d954facd5ec..9d27775493f 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -42,6 +42,7 @@
 1. Metadata: Fix wrong logic table metadata when config same actual table name 
in different storage unit - 
[#39157](https://github.com/apache/shardingsphere/pull/39157)
 1. DistSQL: Fix case-sensitive storage unit matching in `SHOW RULES USED 
STORAGE UNIT` - [#38848](https://github.com/apache/shardingsphere/pull/38848)
 1. DistSQL: Use case-insensitive table name matching in broadcast create and 
drop executors - [#39200](https://github.com/apache/shardingsphere/pull/39200)
+1. DistSQL: Match mask table names case-insensitively in create and alter 
executors - [#39361](https://github.com/apache/shardingsphere/pull/39361)
 1. JDBC: Fix stale generated values leaking into prepared statement 
executeBatch calls without pending batches - 
[#38160](https://github.com/apache/shardingsphere/pull/38160)
 1. JDBC: Fix MySQL-compatible typed string conversion for 
`ResultSet#getObject(index, Class<T>)` - 
[#38444](https://github.com/apache/shardingsphere/pull/38444)
 1. JDBC: Fix statement close invalidating live result sets of other statements 
on the same connection - 
[#39503](https://github.com/apache/shardingsphere/pull/39503)
diff --git 
a/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/AlterMaskRuleExecutor.java
 
b/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/AlterMaskRuleExecutor.java
index 99f97a4b979..de485c3fb0f 100644
--- 
a/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/AlterMaskRuleExecutor.java
+++ 
b/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/AlterMaskRuleExecutor.java
@@ -17,11 +17,13 @@
 
 package org.apache.shardingsphere.mask.distsql.handler.update;
 
+import com.cedarsoftware.util.CaseInsensitiveSet;
 import lombok.Setter;
 import 
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.type.DatabaseRuleAlterExecutor;
 import 
org.apache.shardingsphere.distsql.handler.required.DistSQLExecutorCurrentRuleRequired;
 import 
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
 import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
+import 
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.DuplicateRuleException;
 import 
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.MissingRequiredRuleException;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.mask.config.MaskRuleConfiguration;
@@ -33,8 +35,8 @@ import 
org.apache.shardingsphere.mask.distsql.statement.AlterMaskRuleStatement;
 import org.apache.shardingsphere.mask.rule.MaskRule;
 
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.Map;
 import java.util.stream.Collectors;
 
@@ -51,11 +53,23 @@ public final class AlterMaskRuleExecutor implements 
DatabaseRuleAlterExecutor<Al
     
     @Override
     public void checkBeforeUpdate(final AlterMaskRuleStatement sqlStatement) {
+        checkDuplicatedRuleNames(sqlStatement);
         checkToBeAlteredRules(sqlStatement);
     }
     
+    private void checkDuplicatedRuleNames(final AlterMaskRuleStatement 
sqlStatement) {
+        Collection<String> uniqueTableNames = new CaseInsensitiveSet<>();
+        Collection<String> duplicatedTableNames = new LinkedList<>();
+        for (String each : getToBeAlteredMaskTableNames(sqlStatement)) {
+            if (!uniqueTableNames.add(each)) {
+                duplicatedTableNames.add(each);
+            }
+        }
+        ShardingSpherePreconditions.checkMustEmpty(duplicatedTableNames, () -> 
new DuplicateRuleException("mask", database.getName(), duplicatedTableNames));
+    }
+    
     private void checkToBeAlteredRules(final AlterMaskRuleStatement 
sqlStatement) {
-        Collection<String> currentMaskTableNames = 
rule.getConfiguration().getTables().stream().map(MaskTableRuleConfiguration::getName).collect(Collectors.toList());
+        Collection<String> currentMaskTableNames = 
rule.getConfiguration().getTables().stream().map(MaskTableRuleConfiguration::getName).collect(Collectors.toCollection(CaseInsensitiveSet::new));
         Collection<String> notExistedMaskTableNames = 
getToBeAlteredMaskTableNames(sqlStatement).stream().filter(each -> 
!currentMaskTableNames.contains(each)).collect(Collectors.toList());
         ShardingSpherePreconditions.checkMustEmpty(notExistedMaskTableNames, 
() -> new MissingRequiredRuleException("Mask", database.getName(), 
notExistedMaskTableNames));
     }
@@ -71,7 +85,7 @@ public final class AlterMaskRuleExecutor implements 
DatabaseRuleAlterExecutor<Al
     
     @Override
     public MaskRuleConfiguration buildToBeDroppedRuleConfiguration(final 
MaskRuleConfiguration toBeAlteredRuleConfig) {
-        Collection<String> toBeAlteredTableNames = 
toBeAlteredRuleConfig.getTables().stream().map(MaskTableRuleConfiguration::getName).collect(Collectors.toList());
+        Collection<String> toBeAlteredTableNames = 
toBeAlteredRuleConfig.getTables().stream().map(MaskTableRuleConfiguration::getName).collect(Collectors.toCollection(CaseInsensitiveSet::new));
         Collection<MaskColumnRuleConfiguration> columns = 
rule.getConfiguration().getTables().stream().filter(each -> 
!toBeAlteredTableNames.contains(each.getName()))
                 .flatMap(each -> 
each.getColumns().stream()).collect(Collectors.toList());
         columns.addAll(toBeAlteredRuleConfig.getTables().stream().flatMap(each 
-> each.getColumns().stream()).collect(Collectors.toList()));
@@ -82,7 +96,13 @@ public final class AlterMaskRuleExecutor implements 
DatabaseRuleAlterExecutor<Al
                 toBeDroppedAlgorithms.put(each, 
rule.getConfiguration().getMaskAlgorithms().get(each));
             }
         }
-        return new MaskRuleConfiguration(Collections.emptyList(), 
toBeDroppedAlgorithms);
+        return new 
MaskRuleConfiguration(getToBeDroppedTables(toBeAlteredRuleConfig, 
toBeAlteredTableNames), toBeDroppedAlgorithms);
+    }
+    
+    private Collection<MaskTableRuleConfiguration> getToBeDroppedTables(final 
MaskRuleConfiguration toBeAlteredRuleConfig, final Collection<String> 
toBeAlteredTableNames) {
+        Collection<String> toBeAlteredCaseSensitiveTableNames = 
toBeAlteredRuleConfig.getTables().stream().map(MaskTableRuleConfiguration::getName).collect(Collectors.toSet());
+        return rule.getConfiguration().getTables().stream()
+                .filter(each -> toBeAlteredTableNames.contains(each.getName()) 
&& 
!toBeAlteredCaseSensitiveTableNames.contains(each.getName())).collect(Collectors.toList());
     }
     
     @Override
diff --git 
a/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/CreateMaskRuleExecutor.java
 
b/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/CreateMaskRuleExecutor.java
index d63e4f73445..7292b799f3a 100644
--- 
a/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/CreateMaskRuleExecutor.java
+++ 
b/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/CreateMaskRuleExecutor.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.mask.distsql.handler.update;
 
+import com.cedarsoftware.util.CaseInsensitiveSet;
 import lombok.Setter;
 import 
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.type.DatabaseRuleCreateExecutor;
 import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
@@ -33,6 +34,7 @@ import org.apache.shardingsphere.mask.rule.MaskRule;
 import org.apache.shardingsphere.mask.spi.MaskAlgorithm;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.stream.Collectors;
 
@@ -58,11 +60,16 @@ public final class CreateMaskRuleExecutor implements 
DatabaseRuleCreateExecutor<
     }
     
     private void checkDuplicatedRuleNames(final CreateMaskRuleStatement 
sqlStatement) {
-        if (null != rule) {
-            Collection<String> currentRuleNames = 
rule.getConfiguration().getTables().stream().map(MaskTableRuleConfiguration::getName).collect(Collectors.toList());
-            Collection<String> duplicatedRuleNames = 
sqlStatement.getRules().stream().map(MaskRuleSegment::getTableName).filter(currentRuleNames::contains).collect(Collectors.toList());
-            ShardingSpherePreconditions.checkMustEmpty(duplicatedRuleNames, () 
-> new DuplicateRuleException("mask", database.getName(), duplicatedRuleNames));
+        Collection<String> duplicatedRuleNames = 
getDuplicatedRuleNames(sqlStatement);
+        ShardingSpherePreconditions.checkMustEmpty(duplicatedRuleNames, () -> 
new DuplicateRuleException("mask", database.getName(), duplicatedRuleNames));
+    }
+    
+    private Collection<String> getDuplicatedRuleNames(final 
CreateMaskRuleStatement sqlStatement) {
+        if (null == rule) {
+            return Collections.emptyList();
         }
+        Collection<String> currentRuleNames = 
rule.getConfiguration().getTables().stream().map(MaskTableRuleConfiguration::getName).collect(Collectors.toCollection(CaseInsensitiveSet::new));
+        return 
sqlStatement.getRules().stream().map(MaskRuleSegment::getTableName).filter(currentRuleNames::contains).collect(Collectors.toList());
     }
     
     private void checkAlgorithms(final CreateMaskRuleStatement sqlStatement) {
@@ -73,7 +80,15 @@ public final class CreateMaskRuleExecutor implements 
DatabaseRuleCreateExecutor<
     
     @Override
     public MaskRuleConfiguration buildToBeCreatedRuleConfiguration(final 
CreateMaskRuleStatement sqlStatement) {
-        return MaskRuleStatementConverter.convert(sqlStatement.getRules());
+        return 
MaskRuleStatementConverter.convert(getToBeCreatedRuleSegments(sqlStatement));
+    }
+    
+    private Collection<MaskRuleSegment> getToBeCreatedRuleSegments(final 
CreateMaskRuleStatement sqlStatement) {
+        if (!ifNotExists) {
+            return sqlStatement.getRules();
+        }
+        Collection<String> duplicatedRuleNames = 
getDuplicatedRuleNames(sqlStatement);
+        return sqlStatement.getRules().stream().filter(each -> 
!duplicatedRuleNames.contains(each.getTableName())).collect(Collectors.toList());
     }
     
     @Override
diff --git 
a/features/mask/distsql/handler/src/test/java/org/apache/shardingsphere/mask/distsql/handler/update/AlterMaskRuleExecutorTest.java
 
b/features/mask/distsql/handler/src/test/java/org/apache/shardingsphere/mask/distsql/handler/update/AlterMaskRuleExecutorTest.java
index 597b2a589a8..e5a96add029 100644
--- 
a/features/mask/distsql/handler/src/test/java/org/apache/shardingsphere/mask/distsql/handler/update/AlterMaskRuleExecutorTest.java
+++ 
b/features/mask/distsql/handler/src/test/java/org/apache/shardingsphere/mask/distsql/handler/update/AlterMaskRuleExecutorTest.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.mask.distsql.handler.update;
 import 
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleDefinitionExecutor;
 import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
 import 
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
+import 
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.DuplicateRuleException;
 import 
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.MissingRequiredRuleException;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
@@ -30,6 +31,8 @@ import 
org.apache.shardingsphere.mask.distsql.segment.MaskColumnSegment;
 import org.apache.shardingsphere.mask.distsql.segment.MaskRuleSegment;
 import org.apache.shardingsphere.mask.distsql.statement.AlterMaskRuleStatement;
 import org.apache.shardingsphere.mask.rule.MaskRule;
+import org.apache.shardingsphere.mode.spi.rule.RuleChangedItemType;
+import 
org.apache.shardingsphere.mode.spi.rule.RuleItemConfigurationChangedProcessor;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -43,6 +46,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.Map;
 import java.util.Properties;
 import java.util.stream.Collectors;
@@ -81,6 +85,15 @@ class AlterMaskRuleExecutorTest {
         assertThrows(expectedException, () -> 
executor.checkBeforeUpdate(sqlStatement));
     }
     
+    @Test
+    void assertCheckBeforeUpdateWithCaseCollidingTablesInOneStatement() {
+        executor.setRule(mock(MaskRule.class));
+        when(database.getName()).thenReturn("foo_db");
+        AlterMaskRuleStatement sqlStatement = new AlterMaskRuleStatement(
+                Arrays.asList(createRuleSegment("t_order", "order_id", "MD5"), 
createRuleSegment("T_ORDER", "user_id", "MD5")));
+        assertThrows(DuplicateRuleException.class, () -> 
executor.checkBeforeUpdate(sqlStatement));
+    }
+    
     @Test
     void assertBuildToBeAlteredRuleConfiguration() {
         AlterMaskRuleStatement sqlStatement = new 
AlterMaskRuleStatement(Collections.singleton(createRuleSegment("t_order", 
"order_id", "MD5")));
@@ -95,13 +108,7 @@ class AlterMaskRuleExecutorTest {
     
     @Test
     void assertBuildToBeDroppedRuleConfiguration() {
-        Map<String, AlgorithmConfiguration> currentAlgorithms = new 
LinkedHashMap<>(3, 1F);
-        currentAlgorithms.put("order_mask", new AlgorithmConfiguration("MD5", 
new Properties()));
-        currentAlgorithms.put("user_mask", new AlgorithmConfiguration("MD5", 
new Properties()));
-        currentAlgorithms.put("unused_mask", new AlgorithmConfiguration("SM3", 
new Properties()));
-        executor.setRule(createRule(new MaskRuleConfiguration(Arrays.asList(
-                new MaskTableRuleConfiguration("t_order", 
Collections.singleton(new MaskColumnRuleConfiguration("order_id", 
"order_mask"))),
-                new MaskTableRuleConfiguration("t_user", 
Collections.singleton(new MaskColumnRuleConfiguration("user_id", 
"user_mask")))), currentAlgorithms)));
+        
executor.setRule(createRule(createCurrentRuleConfigurationWithAlgorithms()));
         MaskTableRuleConfiguration toBeAlteredTable = new 
MaskTableRuleConfiguration("t_order", Collections.singleton(new 
MaskColumnRuleConfiguration("order_id", "order_mask")));
         MaskRuleConfiguration actual = 
executor.buildToBeDroppedRuleConfiguration(new 
MaskRuleConfiguration(Collections.singleton(toBeAlteredTable), 
Collections.emptyMap()));
         assertTrue(actual.getTables().isEmpty());
@@ -109,6 +116,37 @@ class AlterMaskRuleExecutorTest {
         assertTrue(actual.getMaskAlgorithms().containsKey("unused_mask"));
     }
     
+    @Test
+    void assertBuildToBeDroppedRuleConfigurationWithDifferentTableNameCase() {
+        
executor.setRule(createRule(createCurrentRuleConfigurationWithAlgorithms()));
+        MaskTableRuleConfiguration toBeAlteredTable = new 
MaskTableRuleConfiguration("T_ORDER", Collections.singleton(new 
MaskColumnRuleConfiguration("order_id", "t_order_order_id_sm3")));
+        MaskRuleConfiguration actual = 
executor.buildToBeDroppedRuleConfiguration(new 
MaskRuleConfiguration(Collections.singleton(toBeAlteredTable), 
Collections.emptyMap()));
+        assertThat(actual.getTables().size(), is(1));
+        assertThat(actual.getTables().iterator().next().getName(), 
is("t_order"));
+        assertThat(actual.getMaskAlgorithms().size(), is(2));
+        assertTrue(actual.getMaskAlgorithms().containsKey("order_mask"));
+        assertTrue(actual.getMaskAlgorithms().containsKey("unused_mask"));
+    }
+    
+    @SuppressWarnings("unchecked")
+    @Test
+    void assertUpdatePathWithDifferentTableNameCase() {
+        MaskRuleConfiguration currentRuleConfig = 
createCurrentRuleConfigurationWithAlgorithms();
+        executor.setRule(createRule(currentRuleConfig));
+        MaskTableRuleConfiguration toBeAlteredTable = new 
MaskTableRuleConfiguration("T_ORDER", Collections.singleton(new 
MaskColumnRuleConfiguration("order_id", "t_order_order_id_sm3")));
+        MaskRuleConfiguration toBeDroppedRuleConfig = 
executor.buildToBeDroppedRuleConfiguration(new 
MaskRuleConfiguration(Collections.singleton(toBeAlteredTable), 
Collections.emptyMap()));
+        RuleItemConfigurationChangedProcessor<MaskRuleConfiguration, 
MaskTableRuleConfiguration> processor = TypedSPILoader.getService(
+                RuleItemConfigurationChangedProcessor.class, new 
RuleChangedItemType("mask", "tables"));
+        processor.changeRuleItemConfiguration("T_ORDER", currentRuleConfig, 
toBeAlteredTable);
+        for (MaskTableRuleConfiguration each : 
toBeDroppedRuleConfig.getTables()) {
+            processor.dropRuleItemConfiguration(each.getName(), 
currentRuleConfig);
+        }
+        Collection<MaskTableRuleConfiguration> actual = 
currentRuleConfig.getTables().stream().filter(each -> 
"t_order".equalsIgnoreCase(each.getName())).collect(Collectors.toList());
+        assertThat(actual.size(), is(1));
+        assertThat(actual.iterator().next().getName(), is("T_ORDER"));
+        
assertThat(actual.iterator().next().getColumns().iterator().next().getMaskAlgorithm(),
 is("t_order_order_id_sm3"));
+    }
+    
     @Test
     void assertGetRuleClass() {
         assertThat(executor.getRuleClass(), is(MaskRule.class));
@@ -122,7 +160,9 @@ class AlterMaskRuleExecutorTest {
                         
createCurrentRuleConfiguration(Collections.singleton("t_order")), 
MissingRequiredRuleException.class),
                 Arguments.of("one table exists and one missing",
                         new 
AlterMaskRuleStatement(Arrays.asList(createRuleSegment("t_order", "order_id", 
"MD5"), createRuleSegment("t_missing", "user_id", "AES"))),
-                        
createCurrentRuleConfiguration(Collections.singleton("t_order")), 
MissingRequiredRuleException.class));
+                        
createCurrentRuleConfiguration(Collections.singleton("t_order")), 
MissingRequiredRuleException.class),
+                Arguments.of("existing table in different case", new 
AlterMaskRuleStatement(Collections.singleton(createRuleSegment("T_ORDER", 
"order_id", "MD5"))),
+                        
createCurrentRuleConfiguration(Collections.singleton("t_order")), null));
     }
     
     private static MaskRuleSegment createRuleSegment(final String tableName, 
final String columnName, final String algorithmType) {
@@ -134,6 +174,16 @@ class AlterMaskRuleExecutorTest {
         return new MaskRuleConfiguration(tableRuleConfigs, 
Collections.emptyMap());
     }
     
+    private static MaskRuleConfiguration 
createCurrentRuleConfigurationWithAlgorithms() {
+        Map<String, AlgorithmConfiguration> algorithmConfigs = new 
LinkedHashMap<>(3, 1F);
+        algorithmConfigs.put("order_mask", new AlgorithmConfiguration("MD5", 
new Properties()));
+        algorithmConfigs.put("user_mask", new AlgorithmConfiguration("MD5", 
new Properties()));
+        algorithmConfigs.put("unused_mask", new AlgorithmConfiguration("SM3", 
new Properties()));
+        return new MaskRuleConfiguration(new LinkedList<>(Arrays.asList(
+                new MaskTableRuleConfiguration("t_order", 
Collections.singleton(new MaskColumnRuleConfiguration("order_id", 
"order_mask"))),
+                new MaskTableRuleConfiguration("t_user", 
Collections.singleton(new MaskColumnRuleConfiguration("user_id", 
"user_mask"))))), algorithmConfigs);
+    }
+    
     private MaskRule createRule(final MaskRuleConfiguration ruleConfig) {
         MaskRule result = mock(MaskRule.class);
         when(result.getConfiguration()).thenReturn(ruleConfig);
diff --git 
a/features/mask/distsql/handler/src/test/java/org/apache/shardingsphere/mask/distsql/handler/update/CreateMaskRuleExecutorTest.java
 
b/features/mask/distsql/handler/src/test/java/org/apache/shardingsphere/mask/distsql/handler/update/CreateMaskRuleExecutorTest.java
index 2b4ca444c36..19799f14665 100644
--- 
a/features/mask/distsql/handler/src/test/java/org/apache/shardingsphere/mask/distsql/handler/update/CreateMaskRuleExecutorTest.java
+++ 
b/features/mask/distsql/handler/src/test/java/org/apache/shardingsphere/mask/distsql/handler/update/CreateMaskRuleExecutorTest.java
@@ -18,10 +18,12 @@
 package org.apache.shardingsphere.mask.distsql.handler.update;
 
 import 
org.apache.shardingsphere.distsql.handler.engine.update.DistSQLUpdateExecuteEngine;
+import 
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleDefinitionExecutor;
 import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
 import 
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.DuplicateRuleException;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.apache.shardingsphere.mask.config.MaskRuleConfiguration;
 import org.apache.shardingsphere.mask.config.rule.MaskTableRuleConfiguration;
 import org.apache.shardingsphere.mask.distsql.segment.MaskColumnSegment;
@@ -55,7 +57,16 @@ class CreateMaskRuleExecutorTest {
     void assertExecuteUpdateWithDuplicateMaskRule() {
         MaskRule rule = mock(MaskRule.class);
         
when(rule.getConfiguration()).thenReturn(getCurrentRuleConfiguration());
-        assertThrows(DuplicateRuleException.class, () -> new 
DistSQLUpdateExecuteEngine(createDuplicatedSQLStatement(false, "MD5"), 
"foo_db", mockContextManager(rule), null).executeUpdate());
+        assertThrows(DuplicateRuleException.class,
+                () -> new 
DistSQLUpdateExecuteEngine(createDuplicatedSQLStatement(false, "MD5", "t_mask", 
"t_order"), "foo_db", mockContextManager(rule), null).executeUpdate());
+    }
+    
+    @Test
+    void assertExecuteUpdateWithDuplicateMaskRuleInDifferentCase() {
+        MaskRule rule = mock(MaskRule.class);
+        
when(rule.getConfiguration()).thenReturn(getCurrentRuleConfiguration());
+        assertThrows(DuplicateRuleException.class,
+                () -> new 
DistSQLUpdateExecuteEngine(createDuplicatedSQLStatement(false, "MD5", "T_MASK", 
"T_ORDER"), "foo_db", mockContextManager(rule), null).executeUpdate());
     }
     
     @Test
@@ -82,6 +93,22 @@ class CreateMaskRuleExecutorTest {
         assertDoesNotThrow(() -> 
metaDataManagerPersistService.alterRuleConfiguration(any(), 
argThat(this::assertRuleConfiguration)));
     }
     
+    @Test
+    void 
assertBuildToBeCreatedRuleConfigurationWithIfNotExistsWhenTableNameCaseDiffers()
 {
+        CreateMaskRuleExecutor executor = (CreateMaskRuleExecutor) 
TypedSPILoader.getService(DatabaseRuleDefinitionExecutor.class, 
CreateMaskRuleStatement.class);
+        executor.setDatabase(mock(ShardingSphereDatabase.class));
+        MaskRule rule = mock(MaskRule.class);
+        
when(rule.getConfiguration()).thenReturn(getCurrentRuleConfiguration());
+        executor.setRule(rule);
+        CreateMaskRuleStatement sqlStatement = 
createDuplicatedSQLStatement(true, "MD5", "T_ORDER", "t_new");
+        executor.checkBeforeUpdate(sqlStatement);
+        MaskRuleConfiguration actual = 
executor.buildToBeCreatedRuleConfiguration(sqlStatement);
+        assertThat(actual.getTables().size(), is(1));
+        assertThat(actual.getTables().iterator().next().getName(), 
is("t_new"));
+        assertThat(actual.getMaskAlgorithms().size(), is(1));
+        
assertTrue(actual.getMaskAlgorithms().containsKey("t_new_order_id_md5"));
+    }
+    
     private CreateMaskRuleStatement createSQLStatement(final boolean 
ifNotExists, final String algorithmType) {
         MaskColumnSegment tMaskColumnSegment = new 
MaskColumnSegment("user_id", new AlgorithmSegment(algorithmType, new 
Properties()));
         MaskColumnSegment tOrderColumnSegment = new 
MaskColumnSegment("order_id", new AlgorithmSegment(algorithmType, new 
Properties()));
@@ -93,11 +120,11 @@ class CreateMaskRuleExecutorTest {
         return new CreateMaskRuleStatement(ifNotExists, rules);
     }
     
-    private CreateMaskRuleStatement createDuplicatedSQLStatement(final boolean 
ifNotExists, final String algorithmType) {
+    private CreateMaskRuleStatement createDuplicatedSQLStatement(final boolean 
ifNotExists, final String algorithmType, final String maskTableName, final 
String orderTableName) {
         MaskColumnSegment tMaskColumnSegment = new 
MaskColumnSegment("user_id", new AlgorithmSegment(algorithmType, new 
Properties()));
         MaskColumnSegment tOrderColumnSegment = new 
MaskColumnSegment("order_id", new AlgorithmSegment(algorithmType, new 
Properties()));
-        MaskRuleSegment tMaskRuleSegment = new MaskRuleSegment("t_mask", 
Collections.singleton(tMaskColumnSegment));
-        MaskRuleSegment tOrderRuleSegment = new MaskRuleSegment("t_order", 
Collections.singleton(tOrderColumnSegment));
+        MaskRuleSegment tMaskRuleSegment = new MaskRuleSegment(maskTableName, 
Collections.singleton(tMaskColumnSegment));
+        MaskRuleSegment tOrderRuleSegment = new 
MaskRuleSegment(orderTableName, Collections.singleton(tOrderColumnSegment));
         Collection<MaskRuleSegment> rules = new LinkedList<>();
         rules.add(tMaskRuleSegment);
         rules.add(tOrderRuleSegment);

Reply via email to