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),