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 e80d9dc0822 Check missed single tables by single rule and repository 
tables (#37348)
e80d9dc0822 is described below

commit e80d9dc082276514081c8e10fe86ee0167577033
Author: Haoran Meng <[email protected]>
AuthorDate: Thu Dec 11 19:45:53 2025 +0800

    Check missed single tables by single rule and repository tables (#37348)
    
    * Refactor DataNode to support parse schema name
    
    * Check missed single tables by single rule and repository tables
    
    * Fix checkstyle
---
 .../shardingsphere/infra/datanode/DataNode.java    |  8 +--
 .../database/ShardingSphereDatabaseFactory.java    | 20 +++++++
 .../infra/datanode/DataNodeTest.java               | 13 +++--
 .../RegisterCenterMetaDataContextsInitFactory.java | 66 ++++++++++++++++++++--
 4 files changed, 92 insertions(+), 15 deletions(-)

diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/datanode/DataNode.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/datanode/DataNode.java
index 1bf06121b0d..d3dfe6c1866 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/datanode/DataNode.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/datanode/DataNode.java
@@ -57,10 +57,10 @@ public final class DataNode {
     public DataNode(final String dataNode) {
         validateDataNodeFormat(dataNode);
         List<String> segments = Splitter.on(DELIMITER).splitToList(dataNode);
-        boolean isIncludeInstance = 3 == segments.size();
-        dataSourceName = isIncludeInstance ? segments.get(0) + DELIMITER + 
segments.get(1) : segments.get(0);
-        schemaName = null;
-        tableName = segments.get(isIncludeInstance ? 2 : 1);
+        boolean isIncludeSchema = 3 == segments.size();
+        dataSourceName = segments.get(0);
+        schemaName = isIncludeSchema ? segments.get(1) : null;
+        tableName = segments.get(isIncludeSchema ? 2 : 1);
     }
     
     /**
diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/ShardingSphereDatabaseFactory.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/ShardingSphereDatabaseFactory.java
index 4ca1be299d1..43be5e088d1 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/ShardingSphereDatabaseFactory.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/database/ShardingSphereDatabaseFactory.java
@@ -103,4 +103,24 @@ public final class ShardingSphereDatabaseFactory {
         Collection<ShardingSphereRule> rules = 
DatabaseRulesBuilder.build(name, protocolType, databaseConfig, 
computeNodeInstanceContext, resourceMetaData);
         return new ShardingSphereDatabase(name, protocolType, 
resourceMetaData, new RuleMetaData(rules), schemas);
     }
+    
+    /**
+     * Create database without system schema.
+     *
+     * @param name database name
+     * @param protocolType database protocol type
+     * @param databaseConfig database configuration
+     * @param props configuration properties
+     * @param computeNodeInstanceContext compute node instance context
+     * @return created database
+     * @throws SQLException SQL exception
+     */
+    public static ShardingSphereDatabase createWithoutSystemSchema(final 
String name, final DatabaseType protocolType, final DatabaseConfiguration 
databaseConfig,
+                                                                   final 
ConfigurationProperties props, final ComputeNodeInstanceContext 
computeNodeInstanceContext) throws SQLException {
+        ResourceMetaData resourceMetaData = new 
ResourceMetaData(databaseConfig.getDataSources(), 
databaseConfig.getStorageUnits());
+        Collection<ShardingSphereRule> databaseRules = 
DatabaseRulesBuilder.build(name, protocolType, databaseConfig, 
computeNodeInstanceContext, resourceMetaData);
+        Map<String, ShardingSphereSchema> schemas = new 
ConcurrentHashMap<>(GenericSchemaBuilder.build(protocolType,
+                new 
GenericSchemaBuilderMaterial(resourceMetaData.getStorageUnits(), databaseRules, 
props, new DatabaseTypeRegistry(protocolType).getDefaultSchemaName(name))));
+        return new ShardingSphereDatabase(name, protocolType, 
resourceMetaData, new RuleMetaData(databaseRules), schemas.values());
+    }
 }
diff --git 
a/infra/common/src/test/java/org/apache/shardingsphere/infra/datanode/DataNodeTest.java
 
b/infra/common/src/test/java/org/apache/shardingsphere/infra/datanode/DataNodeTest.java
index 71f614de1b6..3805054ff4c 100644
--- 
a/infra/common/src/test/java/org/apache/shardingsphere/infra/datanode/DataNodeTest.java
+++ 
b/infra/common/src/test/java/org/apache/shardingsphere/infra/datanode/DataNodeTest.java
@@ -95,7 +95,7 @@ class DataNodeTest {
     void assertToString() {
         assertThat(new DataNode("ds_0.tbl_0").toString(), 
is("DataNode(dataSourceName=ds_0, schemaName=null, tableName=tbl_0)"));
         assertThat(new DataNode("ds", "schema", "tbl").toString(), 
is("DataNode(dataSourceName=ds, schemaName=schema, tableName=tbl)"));
-        assertThat(new DataNode("ds_0.db_0.tbl_0").toString(), 
is("DataNode(dataSourceName=ds_0.db_0, schemaName=null, tableName=tbl_0)"));
+        assertThat(new DataNode("ds_0.schema_0.tbl_0").toString(), 
is("DataNode(dataSourceName=ds_0, schemaName=schema_0, tableName=tbl_0)"));
     }
     
     @Test
@@ -110,9 +110,10 @@ class DataNodeTest {
     
     @Test
     void assertNewValidDataNodeIncludeInstance() {
-        DataNode dataNode = new DataNode("ds_0.db_0.tbl_0");
-        assertThat(dataNode.getDataSourceName(), is("ds_0.db_0"));
+        DataNode dataNode = new DataNode("ds_0.schema_0.tbl_0");
+        assertThat(dataNode.getDataSourceName(), is("ds_0"));
         assertThat(dataNode.getTableName(), is("tbl_0"));
+        assertThat(dataNode.getSchemaName(), is("schema_0"));
     }
     
     @Test
@@ -174,7 +175,7 @@ class DataNodeTest {
     @Test
     void assertNewDataNodeWithMixedFormat() {
         DataNode dataNode = new DataNode("prod-db-01.schema_01.users");
-        assertThat(dataNode.getDataSourceName(), is("prod-db-01.schema_01"));
+        assertThat(dataNode.getDataSourceName(), is("prod-db-01"));
         assertThat(dataNode.getTableName(), is("users"));
     }
     
@@ -197,14 +198,14 @@ class DataNodeTest {
     @Test
     void assertNewDataNodeWithInstanceFormat() {
         DataNode dataNode = new DataNode("instance1.database1.table1");
-        assertThat(dataNode.getDataSourceName(), is("instance1.database1"));
+        assertThat(dataNode.getDataSourceName(), is("instance1"));
         assertThat(dataNode.getTableName(), is("table1"));
     }
     
     @Test
     void assertNewDataNodeWithComplexInstanceFormat() {
         DataNode dataNode = new DataNode("prod-cluster-01.mysql-master.users");
-        assertThat(dataNode.getDataSourceName(), 
is("prod-cluster-01.mysql-master"));
+        assertThat(dataNode.getDataSourceName(), is("prod-cluster-01"));
         assertThat(dataNode.getTableName(), is("users"));
     }
     
diff --git 
a/mode/core/src/main/java/org/apache/shardingsphere/mode/metadata/factory/init/type/RegisterCenterMetaDataContextsInitFactory.java
 
b/mode/core/src/main/java/org/apache/shardingsphere/mode/metadata/factory/init/type/RegisterCenterMetaDataContextsInitFactory.java
index 5915cb5f7d7..8ec8df4a60b 100644
--- 
a/mode/core/src/main/java/org/apache/shardingsphere/mode/metadata/factory/init/type/RegisterCenterMetaDataContextsInitFactory.java
+++ 
b/mode/core/src/main/java/org/apache/shardingsphere/mode/metadata/factory/init/type/RegisterCenterMetaDataContextsInitFactory.java
@@ -17,16 +17,22 @@
 
 package org.apache.shardingsphere.mode.metadata.factory.init.type;
 
+import lombok.extern.slf4j.Slf4j;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.system.SystemDatabase;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import org.apache.shardingsphere.infra.config.database.DatabaseConfiguration;
 import 
org.apache.shardingsphere.infra.config.database.impl.DataSourceGeneratedDatabaseConfiguration;
 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
 import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
 import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
+import org.apache.shardingsphere.infra.database.DatabaseTypeEngine;
+import org.apache.shardingsphere.infra.datanode.DataNode;
 import 
org.apache.shardingsphere.infra.datasource.pool.config.DataSourceConfiguration;
 import 
org.apache.shardingsphere.infra.datasource.pool.destroyer.DataSourcePoolDestroyer;
 import org.apache.shardingsphere.infra.instance.ComputeNodeInstanceContext;
 import 
org.apache.shardingsphere.infra.instance.metadata.jdbc.JDBCInstanceMetaData;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabaseFactory;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabasesFactory;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 import 
org.apache.shardingsphere.mode.manager.builder.ContextManagerBuilderParameter;
@@ -36,17 +42,22 @@ import 
org.apache.shardingsphere.mode.metadata.persist.MetaDataPersistFacade;
 import 
org.apache.shardingsphere.mode.metadata.persist.config.global.PropertiesPersistService;
 import 
org.apache.shardingsphere.mode.metadata.persist.version.VersionPersistService;
 import org.apache.shardingsphere.mode.spi.repository.PersistRepository;
+import org.apache.shardingsphere.single.config.SingleRuleConfiguration;
 
 import javax.sql.DataSource;
 import java.sql.SQLException;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 /**
  * Register center meta data contexts init factory.
  */
+@Slf4j
 public final class RegisterCenterMetaDataContextsInitFactory extends 
MetaDataContextsInitFactory {
     
     private final MetaDataPersistFacade persistFacade;
@@ -68,7 +79,8 @@ public final class RegisterCenterMetaDataContextsInitFactory 
extends MetaDataCon
         // TODO load global data sources from persist service
         Map<String, DataSource> globalDataSources = 
param.getGlobalDataSources();
         ConfigurationProperties props = new 
ConfigurationProperties(persistFacade.getPropsService().load());
-        Map<String, Collection<ShardingSphereSchema>> schemas = 
loadSchemas(effectiveDatabaseConfigs.keySet());
+        DatabaseType protocolType = 
DatabaseTypeEngine.getProtocolType(effectiveDatabaseConfigs, props);
+        Map<String, Collection<ShardingSphereSchema>> schemas = 
loadSchemas(effectiveDatabaseConfigs, protocolType, props);
         Collection<ShardingSphereDatabase> databases;
         if (persistSchemasEnabled) {
             // TODO merge schemas with local
@@ -109,14 +121,58 @@ public final class 
RegisterCenterMetaDataContextsInitFactory extends MetaDataCon
         }
     }
     
-    private Map<String, Collection<ShardingSphereSchema>> loadSchemas(final 
Collection<String> databaseNames) {
+    private Map<String, Collection<ShardingSphereSchema>> loadSchemas(final 
Map<String, DatabaseConfiguration> effectiveDatabaseConfigs,
+                                                                      final 
DatabaseType protocolType, final ConfigurationProperties props) {
+        Collection<String> sysDatabaseNames = new 
SystemDatabase(protocolType).getSystemDatabases();
+        Collection<String> databaseNames = effectiveDatabaseConfigs.keySet();
         Map<String, Collection<ShardingSphereSchema>> result = new 
HashMap<>(databaseNames.size());
-        for (String dbName : databaseNames) {
+        for (Map.Entry<String, DatabaseConfiguration> entry : 
effectiveDatabaseConfigs.entrySet()) {
+            String dbName = entry.getKey();
             Collection<ShardingSphereSchema> schemas = 
persistFacade.getDatabaseMetaDataFacade().getSchema().load(dbName);
-            if (null != schemas) {
-                result.put(dbName, schemas);
+            if (sysDatabaseNames.contains(dbName)) {
+                if (null != schemas) {
+                    result.put(dbName, schemas);
+                }
+            } else {
+                Collection<String> missedSingleTables = 
getMissedSingleTables(entry.getValue(), schemas, dbName);
+                if (missedSingleTables.isEmpty()) {
+                    result.put(dbName, schemas);
+                } else {
+                    log.info("Repository missed single tables: {} of database: 
{}, start to reload", missedSingleTables, dbName);
+                    DataSourceGeneratedDatabaseConfiguration databaseConfig = 
new 
DataSourceGeneratedDatabaseConfiguration(persistFacade.loadDataSourceConfigurations(dbName),
+                            Collections.singleton(new 
SingleRuleConfiguration(missedSingleTables, null)));
+                    try {
+                        ShardingSphereDatabase database = 
ShardingSphereDatabaseFactory.createWithoutSystemSchema(dbName, protocolType, 
databaseConfig, props, instanceContext);
+                        database.getAllSchemas().forEach(schema -> 
persistFacade.getDatabaseMetaDataFacade().getTable().persist(dbName, 
schema.getName(), schema.getAllTables()));
+                        result.put(dbName, 
persistFacade.getDatabaseMetaDataFacade().getSchema().load(dbName));
+                    } catch (final SQLException ex) {
+                        result.put(dbName, schemas);
+                        log.info("Reload reposotiry missed single tables: {} 
of database : {} failed", missedSingleTables, dbName, ex);
+                    }
+                }
             }
         }
         return result;
     }
+    
+    private Collection<String> getMissedSingleTables(final 
DatabaseConfiguration databaseConfiguration, final 
Collection<ShardingSphereSchema> schemas,
+                                                     final String dbName) {
+        Collection<String> result = new LinkedList<>();
+        Optional<SingleRuleConfiguration> singleRuleConfig = 
databaseConfiguration.getRuleConfigurations().stream().filter(each -> each 
instanceof SingleRuleConfiguration)
+                .map(each -> (SingleRuleConfiguration) each).findAny();
+        singleRuleConfig.ifPresent(singleRuleConfiguration -> 
singleRuleConfiguration.getTables().forEach(table -> {
+            DataNode dataNode = new DataNode(table);
+            String logicTableName = new DataNode(table).getTableName();
+            String schemaName = null != dataNode.getSchemaName() ? 
dataNode.getSchemaName() : dbName;
+            Optional<ShardingSphereSchema> schema = findSchema(schemas, 
schemaName);
+            if (!schema.isPresent() || 
!schema.get().containsTable(logicTableName)) {
+                result.add(table);
+            }
+        }));
+        return result;
+    }
+    
+    private Optional<ShardingSphereSchema> findSchema(final 
Collection<ShardingSphereSchema> schemas, final String schemaName) {
+        return schemas.stream().filter(each -> 
each.getName().equals(schemaName)).findFirst();
+    }
 }

Reply via email to