You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by me...@apache.org on 2026/03/20 03:06:09 UTC

(shardingsphere) branch master updated: Use protocol rule to search for schema scope (#38522)

This is an automated email from the ASF dual-hosted git repository.

menghaoran 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 d9989c79e69 Use  protocol rule to search for schema scope (#38522)
d9989c79e69 is described below

commit d9989c79e6952bfd582be9c29ed8251743f5fb80
Author: Haoran Meng <me...@gmail.com>
AuthorDate: Fri Mar 20 11:06:02 2026 +0800

    Use  protocol rule to search for schema scope (#38522)
---
 .../metadata/identifier/IdentifierCaseRuleSet.java | 14 +++-
 .../identifier/IdentifierCaseRuleSetTest.java      | 14 ++++
 .../DatabaseIdentifierContextFactory.java          | 18 ++++-
 .../ShardingSphereDatabaseIdentifierTest.java      | 78 ++++++++++++++++++++++
 .../DatabaseIdentifierContextFactoryTest.java      | 21 ++++++
 5 files changed, 142 insertions(+), 3 deletions(-)

diff --git a/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/identifier/IdentifierCaseRuleSet.java b/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/identifier/IdentifierCaseRuleSet.java
index 704568e6216..8a29563e56b 100644
--- a/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/identifier/IdentifierCaseRuleSet.java
+++ b/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/identifier/IdentifierCaseRuleSet.java
@@ -17,6 +17,9 @@
 
 package org.apache.shardingsphere.database.connector.core.metadata.identifier;
 
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -26,8 +29,17 @@ public final class IdentifierCaseRuleSet {
     
     private final IdentifierCaseRule defaultRule;
     
+    private final Map<IdentifierScope, IdentifierCaseRule> scopedRules;
+    
     public IdentifierCaseRuleSet(final IdentifierCaseRule defaultRule) {
+        this(defaultRule, Collections.emptyMap());
+    }
+    
+    public IdentifierCaseRuleSet(final IdentifierCaseRule defaultRule, final Map<IdentifierScope, IdentifierCaseRule> scopedRules) {
         this.defaultRule = Objects.requireNonNull(defaultRule, "defaultRule cannot be null.");
+        Map<IdentifierScope, IdentifierCaseRule> actualScopedRules = new EnumMap<>(IdentifierScope.class);
+        actualScopedRules.putAll(Objects.requireNonNull(scopedRules, "scopedRules cannot be null."));
+        this.scopedRules = Collections.unmodifiableMap(actualScopedRules);
     }
     
     /**
@@ -38,6 +50,6 @@ public final class IdentifierCaseRuleSet {
      */
     public IdentifierCaseRule getRule(final IdentifierScope identifierScope) {
         Objects.requireNonNull(identifierScope, "identifierScope cannot be null.");
-        return defaultRule;
+        return scopedRules.getOrDefault(identifierScope, defaultRule);
     }
 }
diff --git a/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/identifier/IdentifierCaseRuleSetTest.java b/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/identifier/IdentifierCaseRuleSetTest.java
index f8f01a380e9..08e7fadbdaa 100644
--- a/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/identifier/IdentifierCaseRuleSetTest.java
+++ b/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/identifier/IdentifierCaseRuleSetTest.java
@@ -19,7 +19,9 @@ package org.apache.shardingsphere.database.connector.core.metadata.identifier;
 
 import org.junit.jupiter.api.Test;
 
+import java.util.EnumMap;
 import java.util.Locale;
+import java.util.Map;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
@@ -33,4 +35,16 @@ class IdentifierCaseRuleSetTest {
         IdentifierCaseRule actualRule = new IdentifierCaseRuleSet(expectedRule).getRule(IdentifierScope.TABLE);
         assertThat(actualRule, is(expectedRule));
     }
+    
+    @Test
+    void assertGetRuleWithScopeOverride() {
+        IdentifierCaseRule defaultRule = new StandardIdentifierCaseRule(LookupMode.EXACT, LookupMode.NORMALIZED,
+                each -> each.toLowerCase(Locale.ENGLISH), each -> true);
+        IdentifierCaseRule schemaRule = new StandardIdentifierCaseRule(LookupMode.EXACT, LookupMode.EXACT, each -> each, each -> true);
+        Map<IdentifierScope, IdentifierCaseRule> scopedRules = new EnumMap<>(IdentifierScope.class);
+        scopedRules.put(IdentifierScope.SCHEMA, schemaRule);
+        IdentifierCaseRuleSet actualRuleSet = new IdentifierCaseRuleSet(defaultRule, scopedRules);
+        assertThat(actualRuleSet.getRule(IdentifierScope.SCHEMA), is(schemaRule));
+        assertThat(actualRuleSet.getRule(IdentifierScope.TABLE), is(defaultRule));
+    }
 }
diff --git a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/identifier/DatabaseIdentifierContextFactory.java b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/identifier/DatabaseIdentifierContextFactory.java
index bc6715eff83..f3c93680be9 100644
--- a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/identifier/DatabaseIdentifierContextFactory.java
+++ b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/identifier/DatabaseIdentifierContextFactory.java
@@ -19,16 +19,20 @@ package org.apache.shardingsphere.infra.metadata.identifier;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCaseRule;
 import org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCaseRuleSet;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCaseRuleSets;
+import org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
 import org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
 import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit;
 
 import javax.sql.DataSource;
 import java.util.Collection;
+import java.util.EnumMap;
 import java.util.LinkedHashSet;
+import java.util.Map;
 import java.util.Optional;
 import java.util.Properties;
 
@@ -109,11 +113,21 @@ public final class DatabaseIdentifierContextFactory {
     }
     
     private static IdentifierCaseRuleSet createRuleSet(final DatabaseType protocolType, final ResourceMetaData resourceMetaData, final ConfigurationProperties props) {
+        IdentifierCaseRuleResolver resolver = new IdentifierCaseRuleResolver();
         if (hasMixedIdentifierRuleDatabaseTypes(resourceMetaData)) {
-            return IdentifierCaseRuleSets.newInsensitiveRuleSet();
+            IdentifierCaseRuleSet insensitiveRuleSet = IdentifierCaseRuleSets.newInsensitiveRuleSet();
+            return createScopeAwareRuleSet(resolver.resolve(protocolType, props, null), insensitiveRuleSet);
         }
         DatabaseType resolvedDatabaseType = getIdentifierRuleDatabaseType(resourceMetaData).orElse(protocolType);
-        return new IdentifierCaseRuleResolver().resolve(resolvedDatabaseType, props, getFirstDataSource(resourceMetaData));
+        return createScopeAwareRuleSet(resolver.resolve(protocolType, props, null), resolver.resolve(resolvedDatabaseType, props, getFirstDataSource(resourceMetaData)));
+    }
+    
+    private static IdentifierCaseRuleSet createScopeAwareRuleSet(final IdentifierCaseRuleSet protocolRuleSet, final IdentifierCaseRuleSet storageRuleSet) {
+        Map<IdentifierScope, IdentifierCaseRule> scopedRules = new EnumMap<>(IdentifierScope.class);
+        for (IdentifierScope each : IdentifierScope.values()) {
+            scopedRules.put(each, IdentifierScope.SCHEMA == each ? protocolRuleSet.getRule(each) : storageRuleSet.getRule(each));
+        }
+        return new IdentifierCaseRuleSet(storageRuleSet.getRule(IdentifierScope.TABLE), scopedRules);
     }
     
     private static Optional<DatabaseType> getIdentifierRuleDatabaseType(final ResourceMetaData resourceMetaData) {
diff --git a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/database/ShardingSphereDatabaseIdentifierTest.java b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/database/ShardingSphereDatabaseIdentifierTest.java
index 49c19021da7..825ac0ae4ff 100644
--- a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/database/ShardingSphereDatabaseIdentifierTest.java
+++ b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/database/ShardingSphereDatabaseIdentifierTest.java
@@ -21,7 +21,10 @@ import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
 import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
 import org.apache.shardingsphere.infra.config.props.MetadataIdentifierCaseSensitivity;
+import org.apache.shardingsphere.infra.datasource.pool.props.domain.DataSourcePoolProperties;
 import org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
+import org.apache.shardingsphere.infra.metadata.database.resource.node.StorageNode;
+import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit;
 import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereColumn;
 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
@@ -29,8 +32,16 @@ import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSp
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.Test;
 
+import javax.sql.DataSource;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
 import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.Properties;
+import java.util.logging.Logger;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
@@ -43,6 +54,8 @@ class ShardingSphereDatabaseIdentifierTest {
     
     private final DatabaseType oracleDatabaseType = TypedSPILoader.getService(DatabaseType.class, "Oracle");
     
+    private final DatabaseType mySQLDatabaseType = TypedSPILoader.getService(DatabaseType.class, "MySQL");
+    
     @Test
     void assertContainsSchemaByString() {
         assertTrue(createDatabase(postgreSQLDatabaseType, "foo_schema").containsSchema("FOO_SCHEMA"));
@@ -74,6 +87,16 @@ class ShardingSphereDatabaseIdentifierTest {
         assertTrue(createDatabase(oracleDatabaseType, "FOO_SCHEMA").containsSchema("foo_schema"));
     }
     
+    @Test
+    void assertContainsProtocolDefaultSchemaWithOracleStorageRule() {
+        ShardingSphereSchema schema = new ShardingSphereSchema("test_db", mySQLDatabaseType,
+                Collections.singleton(new ShardingSphereTable("T_ORDER", Collections.emptyList(), Collections.emptyList(), Collections.emptyList())), Collections.emptyList());
+        ShardingSphereDatabase database = new ShardingSphereDatabase("test_db", mySQLDatabaseType, createOracleResourceMetaData(),
+                new RuleMetaData(Collections.emptyList()), Collections.singleton(schema), new ConfigurationProperties(new Properties()));
+        assertTrue(database.containsSchema("TEST_DB"));
+        assertTrue(database.getSchema("test_db").containsTable("t_order"));
+    }
+    
     @Test
     void assertAttachIdentifierContextToSchema() {
         ShardingSphereSchema schema = new ShardingSphereSchema("foo_schema", postgreSQLDatabaseType,
@@ -136,4 +159,59 @@ class ShardingSphereDatabaseIdentifierTest {
     private ResourceMetaData createResourceMetaData() {
         return new ResourceMetaData(Collections.emptyMap(), Collections.emptyMap());
     }
+    
+    private ResourceMetaData createOracleResourceMetaData() {
+        Map<String, Object> props = new LinkedHashMap<>(2, 1F);
+        props.put("url", "jdbc:oracle:thin:@localhost:1521:xe");
+        props.put("username", "root");
+        Map<String, StorageUnit> storageUnits = new LinkedHashMap<>(1, 1F);
+        storageUnits.put("ds_0", new StorageUnit(new StorageNode("ds_0"), new DataSourcePoolProperties("com.zaxxer.hikari.HikariDataSource", props), new FixtureDataSource()));
+        return new ResourceMetaData(Collections.emptyMap(), storageUnits);
+    }
+    
+    private static final class FixtureDataSource implements DataSource {
+        
+        @Override
+        public Connection getConnection() throws SQLException {
+            throw new SQLFeatureNotSupportedException("Not supported in fixture.");
+        }
+        
+        @Override
+        public Connection getConnection(final String username, final String password) throws SQLException {
+            throw new SQLFeatureNotSupportedException("Not supported in fixture.");
+        }
+        
+        @Override
+        public PrintWriter getLogWriter() {
+            return null;
+        }
+        
+        @Override
+        public void setLogWriter(final PrintWriter out) {
+        }
+        
+        @Override
+        public void setLoginTimeout(final int seconds) {
+        }
+        
+        @Override
+        public int getLoginTimeout() {
+            return 0;
+        }
+        
+        @Override
+        public Logger getParentLogger() {
+            return Logger.getGlobal();
+        }
+        
+        @Override
+        public <T> T unwrap(final Class<T> iface) throws SQLException {
+            throw new SQLFeatureNotSupportedException("Not supported in fixture.");
+        }
+        
+        @Override
+        public boolean isWrapperFor(final Class<?> iface) {
+            return false;
+        }
+    }
 }
diff --git a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/identifier/DatabaseIdentifierContextFactoryTest.java b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/identifier/DatabaseIdentifierContextFactoryTest.java
index 35c19e8efc8..8f08017dc45 100644
--- a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/identifier/DatabaseIdentifierContextFactoryTest.java
+++ b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/identifier/DatabaseIdentifierContextFactoryTest.java
@@ -111,6 +111,27 @@ class DatabaseIdentifierContextFactoryTest {
         assertThat(actualRule.matches(actualIdentifier, logicIdentifier, QuoteCharacter.NONE), is(expectedMatched));
     }
     
+    @Test
+    void assertCreateUsesProtocolRuleForSchemaAndStorageRuleForTable() {
+        DatabaseIdentifierContext actual = DatabaseIdentifierContextFactory.create(MYSQL_DATABASE_TYPE,
+                createResourceMetaDataWithStorageUrls("jdbc:oracle:thin:@localhost:1521:xe"), new ConfigurationProperties(new Properties()));
+        IdentifierCaseRule actualSchemaRule = actual.getRule(IdentifierScope.SCHEMA);
+        IdentifierCaseRule actualTableRule = actual.getRule(IdentifierScope.TABLE);
+        assertTrue(actualSchemaRule.matches("test_db", "TEST_DB", QuoteCharacter.NONE));
+        assertTrue(actualTableRule.matches("T_ORDER", "t_order", QuoteCharacter.NONE));
+    }
+    
+    @Test
+    void assertRefreshUsesProtocolRuleForSchemaAndStorageRuleForTable() {
+        DatabaseIdentifierContext actual = DatabaseIdentifierContextFactory.createDefault();
+        DatabaseIdentifierContextFactory.refresh(actual, MYSQL_DATABASE_TYPE, createResourceMetaDataWithStorageUrls("jdbc:oracle:thin:@localhost:1521:xe"),
+                new ConfigurationProperties(new Properties()));
+        IdentifierCaseRule actualSchemaRule = actual.getRule(IdentifierScope.SCHEMA);
+        IdentifierCaseRule actualTableRule = actual.getRule(IdentifierScope.TABLE);
+        assertTrue(actualSchemaRule.matches("test_db", "TEST_DB", QuoteCharacter.NONE));
+        assertTrue(actualTableRule.matches("T_ORDER", "t_order", QuoteCharacter.NONE));
+    }
+    
     private static Stream<Arguments> createWithProtocolTypeAndPropsArguments() {
         return Stream.of(
                 Arguments.of("null protocol type and null props use insensitive rules", null, null, LookupMode.NORMALIZED, "Foo", "foo", true),