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

menghaoranss 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 1b79954a990 Preserve physical schemas for compatible database types 
(#39275)
1b79954a990 is described below

commit 1b79954a990ba9a2e3c0675c0800a2e8140c0584
Author: Haoran Meng <[email protected]>
AuthorDate: Thu Jul 30 15:08:05 2026 +0800

    Preserve physical schemas for compatible database types (#39275)
---
 .../schema/builder/GenericSchemaBuilder.java       | 15 +++-
 .../schema/builder/GenericSchemaBuilderTest.java   | 95 ++++++++++++++++------
 2 files changed, 83 insertions(+), 27 deletions(-)

diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/GenericSchemaBuilder.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/GenericSchemaBuilder.java
index 55558c99a81..2466ee0f009 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/GenericSchemaBuilder.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/GenericSchemaBuilder.java
@@ -23,6 +23,8 @@ import 
org.apache.shardingsphere.database.connector.core.metadata.data.loader.Me
 import 
org.apache.shardingsphere.database.connector.core.metadata.data.loader.MetaDataLoaderMaterial;
 import 
org.apache.shardingsphere.database.connector.core.metadata.data.model.SchemaMetaData;
 import 
org.apache.shardingsphere.database.connector.core.metadata.data.model.TableMetaData;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.DialectDatabaseMetaData;
+import 
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import 
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeRegistry;
 import 
org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit;
@@ -69,9 +71,8 @@ public final class GenericSchemaBuilder {
      * @throws SQLException SQL exception
      */
     public static Map<String, ShardingSphereSchema> build(final 
Collection<String> tableNames, final DatabaseType protocolType, final 
GenericSchemaBuilderMaterial material) throws SQLException {
-        boolean isSameProtocolAndStorageTypes = 
isSameProtocolAndStorageTypes(protocolType, material.getStorageUnits());
         Map<String, SchemaMetaData> result = loadSchemas(tableNames, material);
-        if (!isSameProtocolAndStorageTypes) {
+        if (!isSchemaCompatible(protocolType, material.getStorageUnits())) {
             result = translate(result, protocolType, material);
         }
         return revise(result, material, protocolType);
@@ -90,10 +91,20 @@ public final class GenericSchemaBuilder {
         return materials.isEmpty() ? Collections.emptyMap() : 
MetaDataLoader.load(materials);
     }
     
+    private static boolean isSchemaCompatible(final DatabaseType protocolType, 
final Map<String, StorageUnit> storageUnits) {
+        return isSameProtocolAndStorageTypes(protocolType, storageUnits) || 
isSchemaAvailable(protocolType)
+                && 
storageUnits.values().stream().map(StorageUnit::getStorageType).allMatch(GenericSchemaBuilder::isSchemaAvailable);
+    }
+    
     private static boolean isSameProtocolAndStorageTypes(final DatabaseType 
protocolType, final Map<String, StorageUnit> storageUnits) {
         return 
storageUnits.values().stream().map(StorageUnit::getStorageType).allMatch(protocolType::equals);
     }
     
+    private static boolean isSchemaAvailable(final DatabaseType databaseType) {
+        return 
DatabaseTypedSPILoader.findService(DialectDatabaseMetaData.class, databaseType)
+                .map(each -> 
each.getSchemaOption().isSchemaAvailable()).orElse(false);
+    }
+    
     private static Map<String, SchemaMetaData> translate(final Map<String, 
SchemaMetaData> schemaMetaDataMap, final DatabaseType protocolType, final 
GenericSchemaBuilderMaterial material) {
         Collection<TableMetaData> tableMetaDataList = new LinkedList<>();
         for (StorageUnit each : material.getStorageUnits().values()) {
diff --git 
a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/GenericSchemaBuilderTest.java
 
b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/GenericSchemaBuilderTest.java
index 6da1075f3ef..786859530d9 100644
--- 
a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/GenericSchemaBuilderTest.java
+++ 
b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/GenericSchemaBuilderTest.java
@@ -35,6 +35,9 @@ import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockS
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.mockito.junit.jupiter.MockitoSettings;
 import org.mockito.quality.Strictness;
 
@@ -42,14 +45,15 @@ import java.sql.SQLException;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Properties;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
-import static org.hamcrest.Matchers.is;
 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.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
@@ -60,19 +64,21 @@ import static org.mockito.Mockito.when;
 @StaticMockSettings(MetaDataLoader.class)
 class GenericSchemaBuilderTest {
     
+    private static final DatabaseType MYSQL_DATABASE_TYPE = 
TypedSPILoader.getService(DatabaseType.class, "MySQL");
+    
+    private static final DatabaseType POSTGRESQL_DATABASE_TYPE = 
TypedSPILoader.getService(DatabaseType.class, "PostgreSQL");
+    
+    private static final DatabaseType OPEN_GAUSS_DATABASE_TYPE = 
TypedSPILoader.getService(DatabaseType.class, "openGauss");
+    
+    private static final DatabaseType ORACLE_DATABASE_TYPE = 
TypedSPILoader.getService(DatabaseType.class, "Oracle");
+    
     private final DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "FIXTURE");
     
     private GenericSchemaBuilderMaterial material;
     
     @BeforeEach
     void setUp() {
-        ShardingSphereRule rule = mock(ShardingSphereRule.class);
-        when(rule.getAttributes()).thenReturn(new 
RuleAttributes(mock(TableMapperRuleAttribute.class)));
-        StorageUnit storageUnit = mock(StorageUnit.class);
-        when(storageUnit.getStorageType()).thenReturn(databaseType);
-        when(storageUnit.getDataSource()).thenReturn(new MockedDataSource());
-        material = new 
GenericSchemaBuilderMaterial(Collections.singletonMap("foo_schema", 
storageUnit), Collections.singleton(rule), new ConfigurationProperties(new 
Properties()), "foo_schema",
-                DatabaseIdentifierContextFactory.createDefault());
+        material = createMaterial(databaseType, "foo_schema");
     }
     
     @Test
@@ -121,25 +127,64 @@ class GenericSchemaBuilderTest {
         assertTables(new ShardingSphereSchema("foo_schema", databaseType, 
actual.values().iterator().next().getAllTables(), Collections.emptyList()));
     }
     
-    @Test
-    void assertBuildWithDifferentProtocolAndStorageTypes() throws SQLException 
{
-        DatabaseType differentDatabaseType = 
TypedSPILoader.getService(DatabaseType.class, "PostgreSQL");
-        Collection<String> tableNames = Collections.singleton("foo_tbl");
-        Map<String, SchemaMetaData> schemaMetaDataMap = 
createSchemaMetaDataMap(tableNames, material);
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("schemaAvailableDatabaseTypes")
+    void 
assertBuildKeepsPhysicalSchemasWithDifferentSchemaAvailableDatabaseTypes(final 
String name, final DatabaseType protocolType,
+                                                                               
   final DatabaseType storageType) throws SQLException {
+        Map<String, SchemaMetaData> schemaMetaDataMap = new LinkedHashMap<>(2, 
1F);
+        schemaMetaDataMap.put("public", createSchemaMetaData("public", 
"foo_tbl"));
+        schemaMetaDataMap.put("foo_schema", createSchemaMetaData("foo_schema", 
"bar_tbl"));
         when(MetaDataLoader.load(any())).thenReturn(schemaMetaDataMap);
-        StorageUnit storageUnit = mock(StorageUnit.class);
-        when(storageUnit.getStorageType()).thenReturn(differentDatabaseType);
-        Map<String, StorageUnit> storageUnits = 
Collections.singletonMap("foo_schema", storageUnit);
+        Map<String, ShardingSphereSchema> actual = 
GenericSchemaBuilder.build(Arrays.asList("foo_tbl", "bar_tbl"), protocolType, 
createMaterial(storageType, "public"));
+        assertThat(actual.size(), is(2));
+        assertSchemaTable(actual, "public", "foo_tbl");
+        assertSchemaTable(actual, "foo_schema", "bar_tbl");
+    }
+    
+    @Test
+    void assertBuildTranslatesSchemaWhenProtocolSchemaUnavailable() throws 
SQLException {
+        
when(MetaDataLoader.load(any())).thenReturn(Collections.singletonMap("public", 
createSchemaMetaData("public", "foo_tbl")));
+        Map<String, ShardingSphereSchema> actual =
+                GenericSchemaBuilder.build(Collections.singleton("foo_tbl"), 
MYSQL_DATABASE_TYPE, createMaterial(POSTGRESQL_DATABASE_TYPE, "foo_db"));
+        assertThat(actual.size(), is(1));
+        assertSchemaTable(actual, "foo_db", "foo_tbl");
+    }
+    
+    @Test
+    void assertBuildTranslatesSchemaWhenStorageSchemaUnavailable() throws 
SQLException {
+        
when(MetaDataLoader.load(any())).thenReturn(Collections.singletonMap("PUBLIC", 
createSchemaMetaData("PUBLIC", "foo_tbl")));
+        Map<String, ShardingSphereSchema> actual =
+                GenericSchemaBuilder.build(Collections.singleton("foo_tbl"), 
POSTGRESQL_DATABASE_TYPE, createMaterial(ORACLE_DATABASE_TYPE, "public"));
+        assertThat(actual.size(), is(1));
+        assertSchemaTable(actual, "public", "foo_tbl");
+    }
+    
+    private static Stream<Arguments> schemaAvailableDatabaseTypes() {
+        return Stream.of(
+                Arguments.of("PostgreSQL protocol with openGauss storage", 
POSTGRESQL_DATABASE_TYPE, OPEN_GAUSS_DATABASE_TYPE),
+                Arguments.of("openGauss protocol with PostgreSQL storage", 
OPEN_GAUSS_DATABASE_TYPE, POSTGRESQL_DATABASE_TYPE));
+    }
+    
+    private GenericSchemaBuilderMaterial createMaterial(final DatabaseType 
storageType, final String defaultSchemaName) {
         ShardingSphereRule rule = mock(ShardingSphereRule.class);
         when(rule.getAttributes()).thenReturn(new 
RuleAttributes(mock(TableMapperRuleAttribute.class)));
-        GenericSchemaBuilderMaterial newMaterial = new 
GenericSchemaBuilderMaterial(storageUnits, Collections.singleton(rule), new 
ConfigurationProperties(new Properties()), "foo_schema",
-                DatabaseIdentifierContextFactory.createDefault());
-        Map<String, ShardingSphereSchema> actual = 
GenericSchemaBuilder.build(tableNames, databaseType, newMaterial);
-        assertThat(actual.size(), is(1));
-        ShardingSphereSchema actualSchema = actual.values().iterator().next();
-        assertTrue(actualSchema.getAllTables().isEmpty());
-        assertNull(actualSchema.getTable("foo_tbl"));
-        assertThat(actualSchema.getName(), is("foo_schema"));
+        StorageUnit storageUnit = mock(StorageUnit.class);
+        when(storageUnit.getStorageType()).thenReturn(storageType);
+        when(storageUnit.getDataSource()).thenReturn(new MockedDataSource());
+        return new 
GenericSchemaBuilderMaterial(Collections.singletonMap("foo_schema", 
storageUnit), Collections.singleton(rule), new ConfigurationProperties(new 
Properties()),
+                defaultSchemaName, 
DatabaseIdentifierContextFactory.createDefault());
+    }
+    
+    private SchemaMetaData createSchemaMetaData(final String schemaName, final 
String tableName) {
+        TableMetaData tableMetaData = new TableMetaData(tableName, 
Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
+        return new SchemaMetaData(schemaName, 
Collections.singleton(tableMetaData));
+    }
+    
+    private void assertSchemaTable(final Map<String, ShardingSphereSchema> 
actual, final String expectedSchemaName, final String expectedTableName) {
+        ShardingSphereSchema actualSchema = actual.get(expectedSchemaName);
+        assertThat(actualSchema.getName(), is(expectedSchemaName));
+        assertThat(actualSchema.getAllTables().size(), is(1));
+        assertThat(actualSchema.getAllTables().iterator().next().getName(), 
is(expectedTableName));
     }
     
     private Map<String, SchemaMetaData> createSchemaMetaDataMap(final 
Collection<String> tableNames, final GenericSchemaBuilderMaterial material) {

Reply via email to