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

zhangliang 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 d4c59bb1fcb Add SystemSchemaBuilderTest (#37087)
d4c59bb1fcb is described below

commit d4c59bb1fcb3d64917c1f99fe6d4989b2f194076
Author: Liang Zhang <[email protected]>
AuthorDate: Thu Nov 13 17:29:40 2025 +0800

    Add SystemSchemaBuilderTest (#37087)
---
 AGENTS.md                                          |  6 +-
 .../core/metadata/database/system/SystemTable.java | 49 +++++++++++++++
 .../database/system/SystemDatabaseTest.java        | 71 ++++++++++++++++++++++
 .../metadata/database/system/SystemTableTest.java  | 67 ++++++++++++++++++++
 .../schema/builder/SystemSchemaBuilder.java        | 15 +----
 .../schema/builder/SystemSchemaBuilderTest.java    | 32 +++++++++-
 6 files changed, 224 insertions(+), 16 deletions(-)

diff --git a/AGENTS.md b/AGENTS.md
index 53fe48d496c..5cb50e0028e 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -37,8 +37,9 @@ Reference this flow when reasoning about new features or 
debugging regressions.
 Mention which topology you target, the registry used, and any compatibility 
constraints (e.g., MySQL 5.7 vs 8.0) when proposing changes.
 
 ## Design Playbook
+- **Styles to favor:** elegant, minimal solutions—express intent with the 
smallest construct that works, keep methods/tests lean, and avoid incidental 
complexity.
 - **Patterns to lean on:** builder/factory helpers in `infra`, SPI-based 
extension points, immutable DTOs for plan descriptions, explicit strategy enums 
for behavior toggles.
-- **Anti-patterns:** duplicating SQL parsing logic, bypassing metadata caches, 
silent fallbacks when configuration is invalid, adding static singletons in 
shared modules.
+- **Anti-patterns:** duplicating SQL parsing logic, bypassing metadata caches, 
silent fallbacks when configuration is invalid, adding static singletons in 
shared modules, over-engineering simple flows.
 - **Known pitfalls:** routing regressions when skipping shadow rules, timezone 
drift when mocking time poorly, forgetting to validate both standalone and 
cluster (`mode`) settings, missing ASF headers in new files.
 - **Success recipe:** describe why a change is needed, point to affected data 
flow step, keep public APIs backwards compatible, and document defaults in 
`docs`.
 - **Case in point:** a prior shadow-rule regression was fixed by (1) 
reproducing via `proxy` + sample config, (2) adding a `kernel` unit test 
covering the skipped branch, (3) updating docs with the exact YAML flag—mirror 
that discipline for new features.
@@ -69,6 +70,9 @@ Mention which topology you target, the registry used, and any 
compatibility cons
 - Mock databases, time, and network boundaries; build POJOs directly.
 - When Jacoco fails, open `{module}/target/site/jacoco/index.html`, note 
uncovered branches, and explain how new tests address them.
 - Need a quick coverage view? Run `./mvnw -pl {module} -am -Djacoco.skip=false 
test jacoco:report` and open `{module}/target/site/jacoco/index.html`.
+- Jacoco is disabled by default (the top-level POM sets `jacoco.skip=true`), 
so explicitly pass `-Djacoco.skip=false` when you need coverage data, then run 
`jacoco:report` for the same module scope.
+- Aggregator modules do not produce `jacoco.exec`; run tests under the 
concrete module (`-pl {module} -am ... test`) before invoking `./mvnw -pl 
{module} jacoco:report -Djacoco.skip=false`, otherwise the report step will be 
skipped.
+- When static mocking is required, prefer 
`@ExtendWith(AutoMockExtension.class)` plus `@StaticMockSettings` to manage 
Mockito static mocks; avoid manual `mockStatic` blocks unless absolutely 
necessary.
 
 ### Unit Test Style Recap
 - Mirror production package paths, keep tests named `ClassNameTest`, and 
express assertions through `assertXxxCondition` methods.
diff --git 
a/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/system/SystemTable.java
 
b/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/system/SystemTable.java
new file mode 100644
index 00000000000..5c59706161d
--- /dev/null
+++ 
b/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/system/SystemTable.java
@@ -0,0 +1,49 @@
+/*
+ * 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.database.connector.core.metadata.database.system;
+
+import lombok.RequiredArgsConstructor;
+import 
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+
+import java.util.Collections;
+import java.util.Optional;
+
+/**
+ * System table.
+ */
+@RequiredArgsConstructor
+public final class SystemTable {
+    
+    private final DatabaseType databaseType;
+    
+    /**
+     * Judge whether supported system table.
+     *
+     * @param schemaName schema name
+     * @param tableName table name
+     * @return is supported system table or not
+     */
+    public boolean isSupportedSystemTable(final String schemaName, final 
String tableName) {
+        if ("shardingsphere".equals(schemaName) && 
"cluster_information".equals(tableName)) {
+            return true;
+        }
+        Optional<DialectKernelSupportedSystemTable> kernelSupportedSystemTable 
= DatabaseTypedSPILoader.findService(DialectKernelSupportedSystemTable.class, 
databaseType);
+        return kernelSupportedSystemTable.map(optional -> 
optional.getSchemaAndTablesMap().getOrDefault(schemaName, 
Collections.emptySet()).contains(tableName)).orElse(false);
+    }
+}
diff --git 
a/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/database/system/SystemDatabaseTest.java
 
b/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/database/system/SystemDatabaseTest.java
new file mode 100644
index 00000000000..d220789f620
--- /dev/null
+++ 
b/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/database/system/SystemDatabaseTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.database.connector.core.metadata.database.system;
+
+import 
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Optional;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(DatabaseTypedSPILoader.class)
+class SystemDatabaseTest {
+    
+    @Test
+    void assertGetSystemDatabases() {
+        DatabaseType databaseType = mock(DatabaseType.class);
+        DialectSystemDatabase dialectSystemDatabase = 
mock(DialectSystemDatabase.class);
+        Collection<String> expected = Arrays.asList("sys_db", "meta_db");
+        when(dialectSystemDatabase.getSystemDatabases()).thenReturn(expected);
+        when(DatabaseTypedSPILoader.findService(DialectSystemDatabase.class, 
databaseType)).thenReturn(Optional.of(dialectSystemDatabase));
+        SystemDatabase systemDatabase = new SystemDatabase(databaseType);
+        assertThat(systemDatabase.getSystemDatabases(), is(expected));
+    }
+    
+    @Test
+    void assertGetSystemSchemasWithDatabaseName() {
+        DatabaseType databaseType = mock(DatabaseType.class);
+        DialectSystemDatabase dialectSystemDatabase = 
mock(DialectSystemDatabase.class);
+        Collection<String> expected = 
Collections.singletonList("information_schema");
+        
when(dialectSystemDatabase.getSystemSchemas("postgres")).thenReturn(expected);
+        when(DatabaseTypedSPILoader.findService(DialectSystemDatabase.class, 
databaseType)).thenReturn(Optional.of(dialectSystemDatabase));
+        SystemDatabase systemDatabase = new SystemDatabase(databaseType);
+        assertThat(systemDatabase.getSystemSchemas("postgres"), is(expected));
+    }
+    
+    @Test
+    void assertGetSystemSchemasWhenSpiAbsent() {
+        DatabaseType databaseType = mock(DatabaseType.class);
+        when(DatabaseTypedSPILoader.findService(DialectSystemDatabase.class, 
databaseType)).thenReturn(Optional.empty());
+        SystemDatabase systemDatabase = new SystemDatabase(databaseType);
+        assertTrue(systemDatabase.getSystemSchemas().isEmpty());
+    }
+}
diff --git 
a/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/database/system/SystemTableTest.java
 
b/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/database/system/SystemTableTest.java
new file mode 100644
index 00000000000..92931c5ae86
--- /dev/null
+++ 
b/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/database/system/SystemTableTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.database.connector.core.metadata.database.system;
+
+import 
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.Collections;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(DatabaseTypedSPILoader.class)
+class SystemTableTest {
+    
+    private final DatabaseType databaseType = mock(DatabaseType.class);
+    
+    @Test
+    void assertIsSupportedSystemTableForClusterInformation() {
+        assertTrue(new 
SystemTable(databaseType).isSupportedSystemTable("shardingsphere", 
"cluster_information"));
+    }
+    
+    @Test
+    void assertIsSupportedSystemTableWhenKernelSupported() {
+        DialectKernelSupportedSystemTable kernelSupportedSystemTable = 
mock(DialectKernelSupportedSystemTable.class);
+        
when(kernelSupportedSystemTable.getSchemaAndTablesMap()).thenReturn(Collections.singletonMap("information_schema",
 Collections.singleton("columns")));
+        
when(DatabaseTypedSPILoader.findService(DialectKernelSupportedSystemTable.class,
 databaseType)).thenReturn(Optional.of(kernelSupportedSystemTable));
+        assertTrue(new 
SystemTable(databaseType).isSupportedSystemTable("information_schema", 
"columns"));
+    }
+    
+    @Test
+    void assertIsNotSupportedSystemTableWhenKernelUnsupported() {
+        DialectKernelSupportedSystemTable kernelSupportedSystemTable = 
mock(DialectKernelSupportedSystemTable.class);
+        
when(kernelSupportedSystemTable.getSchemaAndTablesMap()).thenReturn(Collections.singletonMap("information_schema",
 Collections.singleton("tables")));
+        
when(DatabaseTypedSPILoader.findService(DialectKernelSupportedSystemTable.class,
 databaseType)).thenReturn(Optional.of(kernelSupportedSystemTable));
+        assertFalse(new 
SystemTable(databaseType).isSupportedSystemTable("information_schema", 
"columns"));
+    }
+    
+    @Test
+    void 
assertIsNotSupportedSystemTableWhenDialectKernelSupportedSystemTableAbsent() {
+        
when(DatabaseTypedSPILoader.findService(DialectKernelSupportedSystemTable.class,
 databaseType)).thenReturn(Optional.empty());
+        assertFalse(new 
SystemTable(databaseType).isSupportedSystemTable("shardingsphere", 
"unknown_table"));
+    }
+}
diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/SystemSchemaBuilder.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/SystemSchemaBuilder.java
index c075043f8fd..1d493f3d6b1 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/SystemSchemaBuilder.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/SystemSchemaBuilder.java
@@ -20,9 +20,8 @@ package 
org.apache.shardingsphere.infra.metadata.database.schema.builder;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.DialectDatabaseMetaData;
-import 
org.apache.shardingsphere.database.connector.core.metadata.database.system.DialectKernelSupportedSystemTable;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.system.SystemDatabase;
-import 
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.system.SystemTable;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import 
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeRegistry;
 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
@@ -40,7 +39,6 @@ import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.Map;
-import java.util.Optional;
 import java.util.Properties;
 import java.util.stream.Collectors;
 
@@ -79,20 +77,13 @@ public final class SystemSchemaBuilder {
     
     private static ShardingSphereSchema createSchema(final String schemaName, 
final DatabaseType databaseType, final boolean isSystemSchemaMetadataEnabled) {
         Collection<ShardingSphereTable> tables = new LinkedList<>();
+        SystemTable systemTable = new SystemTable(databaseType);
         for (InputStream each : 
SystemSchemaManager.getAllInputStreams(databaseType.getType(), schemaName)) {
             YamlShardingSphereTable metaData = new Yaml().loadAs(each, 
YamlShardingSphereTable.class);
-            if (isSystemSchemaMetadataEnabled || 
isSupportedSystemTable(databaseType, schemaName, metaData.getName())) {
+            if (isSystemSchemaMetadataEnabled || 
systemTable.isSupportedSystemTable(schemaName, metaData.getName())) {
                 tables.add(TABLE_SWAPPER.swapToObject(metaData));
             }
         }
         return new ShardingSphereSchema(schemaName, tables, 
Collections.emptyList());
     }
-    
-    private static boolean isSupportedSystemTable(final DatabaseType 
databaseType, final String schemaName, final String tableName) {
-        if ("shardingsphere".equals(schemaName) && 
"cluster_information".equals(tableName)) {
-            return true;
-        }
-        Optional<DialectKernelSupportedSystemTable> kernelSupportedSystemTable 
= DatabaseTypedSPILoader.findService(DialectKernelSupportedSystemTable.class, 
databaseType);
-        return kernelSupportedSystemTable.map(optional -> 
optional.getSchemaAndTablesMap().getOrDefault(schemaName, 
Collections.emptySet()).contains(tableName)).orElse(false);
-    }
 }
diff --git 
a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/SystemSchemaBuilderTest.java
 
b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/SystemSchemaBuilderTest.java
index fb803d7e34b..9f11590c541 100644
--- 
a/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/SystemSchemaBuilderTest.java
+++ 
b/infra/common/src/test/java/org/apache/shardingsphere/infra/metadata/database/schema/builder/SystemSchemaBuilderTest.java
@@ -19,8 +19,11 @@ package 
org.apache.shardingsphere.infra.metadata.database.schema.builder;
 
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import 
org.apache.shardingsphere.infra.config.props.temporary.TemporaryConfigurationPropertyKey;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.infra.util.props.PropertiesBuilder;
+import org.apache.shardingsphere.infra.util.props.PropertiesBuilder.Property;
 import org.junit.jupiter.api.Test;
 
 import java.util.Map;
@@ -28,6 +31,7 @@ import java.util.Properties;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class SystemSchemaBuilderTest {
@@ -35,7 +39,7 @@ class SystemSchemaBuilderTest {
     @Test
     void assertBuildForMySQL() {
         DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "MySQL");
-        ConfigurationProperties configProps = new ConfigurationProperties(new 
Properties());
+        ConfigurationProperties configProps = new 
ConfigurationProperties(PropertiesBuilder.build());
         Map<String, ShardingSphereSchema> actualInformationSchema = 
SystemSchemaBuilder.build("information_schema", databaseType, configProps);
         assertThat(actualInformationSchema.size(), is(1));
         assertTrue(actualInformationSchema.containsKey("information_schema"));
@@ -57,7 +61,7 @@ class SystemSchemaBuilderTest {
     @Test
     void assertBuildForPostgreSQL() {
         DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "PostgreSQL");
-        Map<String, ShardingSphereSchema> actual = 
SystemSchemaBuilder.build("sharding_db", databaseType, new 
ConfigurationProperties(new Properties()));
+        Map<String, ShardingSphereSchema> actual = 
SystemSchemaBuilder.build("sharding_db", databaseType, new 
ConfigurationProperties(PropertiesBuilder.build()));
         assertThat(actual.size(), is(3));
         assertTrue(actual.containsKey("information_schema"));
         assertTrue(actual.containsKey("pg_catalog"));
@@ -70,7 +74,7 @@ class SystemSchemaBuilderTest {
     @Test
     void assertBuildForOpenGaussSQL() {
         DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "openGauss");
-        Map<String, ShardingSphereSchema> actual = 
SystemSchemaBuilder.build("sharding_db", databaseType, new 
ConfigurationProperties(new Properties()));
+        Map<String, ShardingSphereSchema> actual = 
SystemSchemaBuilder.build("sharding_db", databaseType, new 
ConfigurationProperties(PropertiesBuilder.build()));
         assertThat(actual.size(), is(16));
         assertTrue(actual.containsKey("pg_catalog"));
         assertTrue(actual.containsKey("shardingsphere"));
@@ -78,4 +82,26 @@ class SystemSchemaBuilderTest {
         assertThat(actual.get("pg_catalog").getAllTables().size(), is(240));
         assertThat(actual.get("shardingsphere").getAllTables().size(), is(1));
     }
+    
+    @Test
+    void assertBuildForPostgreSQLWhenSystemSchemaMetadataDisabled() {
+        DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "PostgreSQL");
+        Properties props = PropertiesBuilder.build(new 
Property(TemporaryConfigurationPropertyKey.SYSTEM_SCHEMA_METADATA_ASSEMBLY_ENABLED.getKey(),
 Boolean.FALSE.toString()));
+        Map<String, ShardingSphereSchema> actual = 
SystemSchemaBuilder.build("sharding_db", databaseType, new 
ConfigurationProperties(props));
+        assertThat(actual.size(), is(3));
+        ShardingSphereSchema informationSchema = 
actual.get("information_schema");
+        assertThat(informationSchema.getAllTables().size(), is(3));
+        assertTrue(informationSchema.containsTable("columns"));
+        assertTrue(informationSchema.containsTable("tables"));
+        assertTrue(informationSchema.containsTable("views"));
+        assertFalse(informationSchema.containsTable("attributes"));
+        ShardingSphereSchema pgCatalog = actual.get("pg_catalog");
+        assertThat(pgCatalog.getAllTables().size(), is(9));
+        assertTrue(pgCatalog.containsTable("pg_class"));
+        assertTrue(pgCatalog.containsTable("pg_tables"));
+        assertFalse(pgCatalog.containsTable("pg_indexes"));
+        ShardingSphereSchema shardingsphereSchema = 
actual.get("shardingsphere");
+        assertThat(shardingsphereSchema.getAllTables().size(), is(1));
+        assertTrue(shardingsphereSchema.containsTable("cluster_information"));
+    }
 }

Reply via email to