You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ji...@apache.org on 2023/04/18 10:06:59 UTC

[shardingsphere] branch master updated: Improve EXPORT METADATA add snapshot data (#25173)

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

jianglongtao 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 a002ddebbc6 Improve EXPORT METADATA add snapshot data (#25173)
a002ddebbc6 is described below

commit a002ddebbc6a450027f2d1358739fa7836340190
Author: ChenJiaHao <Pa...@163.com>
AuthorDate: Tue Apr 18 18:06:52 2023 +0800

    Improve EXPORT METADATA add snapshot data (#25173)
    
    * Improve EXPORT METADATA add snapshot data
    
    * Fix UT
    
    * Fix UT
    
    * Add javadoc
    
    * Fix code style and UT
    
    * Refactor exception
---
 .../DataSourceDefinitionViolationException.java    | 22 ++++----
 .../MissingRequiredDataSourcesException.java       | 21 +++-----
 .../globalclock/core/rule/GlobalClockRule.java     | 22 +++++---
 proxy/backend/core/pom.xml                         |  5 ++
 .../distsql/export/ExportedSnapshotInfo.java       |  2 +
 .../ral/queryable/ExportMetaDataExecutor.java      | 18 +++++++
 .../proxy/backend/util/JsonUtils.java              |  2 +
 .../YamlDatabaseConfigurationImportExecutor.java   | 11 ++--
 .../ral/queryable/ExportMetaDataExecutorTest.java  | 61 +++++++++++++++++++---
 .../ImportDatabaseConfigurationUpdaterTest.java    |  8 +--
 .../ral/updatable/ImportMetaDataUpdaterTest.java   | 20 +++----
 .../expected/export-metadata-configuration.json    |  2 +-
 12 files changed, 136 insertions(+), 58 deletions(-)

diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/distsql/export/ExportedSnapshotInfo.java b/distsql/handler/src/main/java/org/apache/shardingsphere/distsql/handler/exception/datasource/DataSourceDefinitionViolationException.java
similarity index 55%
copy from proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/distsql/export/ExportedSnapshotInfo.java
copy to distsql/handler/src/main/java/org/apache/shardingsphere/distsql/handler/exception/datasource/DataSourceDefinitionViolationException.java
index 2c258da4495..e25f961429a 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/distsql/export/ExportedSnapshotInfo.java
+++ b/distsql/handler/src/main/java/org/apache/shardingsphere/distsql/handler/exception/datasource/DataSourceDefinitionViolationException.java
@@ -15,23 +15,19 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.proxy.backend.distsql.export;
+package org.apache.shardingsphere.distsql.handler.exception.datasource;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.Getter;
-import lombok.Setter;
-
-import java.time.LocalDateTime;
+import org.apache.shardingsphere.distsql.handler.exception.DistSQLException;
+import org.apache.shardingsphere.infra.util.exception.external.sql.sqlstate.SQLState;
 
 /**
- * Exported snapshot info.
+ * Data source definition violation exception.
  */
-@Getter
-@Setter
-public class ExportedSnapshotInfo {
+public abstract class DataSourceDefinitionViolationException extends DistSQLException {
     
-    private String csn;
+    private static final long serialVersionUID = -3318829232811230364L;
     
-    @JsonProperty("create_time")
-    private LocalDateTime createTime;
+    public DataSourceDefinitionViolationException(final SQLState sqlState, final int errorCode, final String reason, final Object... messageArgs) {
+        super(sqlState, errorCode, reason, messageArgs);
+    }
 }
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/distsql/export/ExportedSnapshotInfo.java b/distsql/handler/src/main/java/org/apache/shardingsphere/distsql/handler/exception/datasource/MissingRequiredDataSourcesException.java
similarity index 61%
copy from proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/distsql/export/ExportedSnapshotInfo.java
copy to distsql/handler/src/main/java/org/apache/shardingsphere/distsql/handler/exception/datasource/MissingRequiredDataSourcesException.java
index 2c258da4495..567a3b4eea1 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/distsql/export/ExportedSnapshotInfo.java
+++ b/distsql/handler/src/main/java/org/apache/shardingsphere/distsql/handler/exception/datasource/MissingRequiredDataSourcesException.java
@@ -15,23 +15,18 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.proxy.backend.distsql.export;
+package org.apache.shardingsphere.distsql.handler.exception.datasource;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.Getter;
-import lombok.Setter;
-
-import java.time.LocalDateTime;
+import org.apache.shardingsphere.infra.util.exception.external.sql.sqlstate.XOpenSQLState;
 
 /**
- * Exported snapshot info.
+ * Missing required data sources exception.
  */
-@Getter
-@Setter
-public class ExportedSnapshotInfo {
+public final class MissingRequiredDataSourcesException extends DataSourceDefinitionViolationException {
     
-    private String csn;
+    private static final long serialVersionUID = -7846645449809082667L;
     
-    @JsonProperty("create_time")
-    private LocalDateTime createTime;
+    public MissingRequiredDataSourcesException(final String message) {
+        super(XOpenSQLState.CHECK_OPTION_VIOLATION, 201, message);
+    }
 }
diff --git a/kernel/global-clock/core/src/main/java/org/apache/shardingsphere/globalclock/core/rule/GlobalClockRule.java b/kernel/global-clock/core/src/main/java/org/apache/shardingsphere/globalclock/core/rule/GlobalClockRule.java
index de7d29a6e8a..868d3514779 100644
--- a/kernel/global-clock/core/src/main/java/org/apache/shardingsphere/globalclock/core/rule/GlobalClockRule.java
+++ b/kernel/global-clock/core/src/main/java/org/apache/shardingsphere/globalclock/core/rule/GlobalClockRule.java
@@ -43,18 +43,17 @@ public final class GlobalClockRule implements GlobalRule {
     public GlobalClockRule(final GlobalClockRuleConfiguration ruleConfig, final Map<String, ShardingSphereDatabase> databases) {
         configuration = ruleConfig;
         if (ruleConfig.isEnabled()) {
-            TypedSPILoader.getService(GlobalClockProvider.class, String.join(".", ruleConfig.getType(), ruleConfig.getProvider()),
-                    null == ruleConfig.getProps() ? new Properties() : ruleConfig.getProps());
+            TypedSPILoader.getService(GlobalClockProvider.class, getGlobalClockProviderType(), configuration.getProps());
         }
-        TypedSPILoader.getService(TransactionHook.class, "GLOBAL_CLOCK", getProps(ruleConfig, databases));
+        TypedSPILoader.getService(TransactionHook.class, "GLOBAL_CLOCK", getProps(databases));
     }
     
-    private Properties getProps(final GlobalClockRuleConfiguration ruleConfig, final Map<String, ShardingSphereDatabase> databases) {
+    private Properties getProps(final Map<String, ShardingSphereDatabase> databases) {
         Properties result = new Properties();
         result.setProperty("trunkType", DatabaseTypeEngine.getTrunkDatabaseTypeName(DatabaseTypeEngine.getStorageType(getDataSources(databases))));
-        result.setProperty("enabled", String.valueOf(ruleConfig.isEnabled()));
-        result.setProperty("type", ruleConfig.getType());
-        result.setProperty("provider", ruleConfig.getProvider());
+        result.setProperty("enabled", String.valueOf(configuration.isEnabled()));
+        result.setProperty("type", configuration.getType());
+        result.setProperty("provider", configuration.getProvider());
         return result;
     }
     
@@ -63,6 +62,15 @@ public final class GlobalClockRule implements GlobalRule {
                 .flatMap(each -> each.getResourceMetaData().getDataSources().values().stream()).collect(Collectors.toList());
     }
     
+    /**
+     * Get global clock provider type.
+     * 
+     * @return global clock provider type
+     */
+    public String getGlobalClockProviderType() {
+        return String.join(".", configuration.getType(), configuration.getProvider());
+    }
+    
     @Override
     public String getType() {
         return GlobalClockRule.class.getSimpleName();
diff --git a/proxy/backend/core/pom.xml b/proxy/backend/core/pom.xml
index 98ea3988c2f..1688ffe53e2 100644
--- a/proxy/backend/core/pom.xml
+++ b/proxy/backend/core/pom.xml
@@ -208,6 +208,11 @@
             <artifactId>logback-classic</artifactId>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+            <version>${jackson.version}</version>
+        </dependency>
         
         <dependency>
             <groupId>org.apache.shardingsphere</groupId>
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/distsql/export/ExportedSnapshotInfo.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/distsql/export/ExportedSnapshotInfo.java
index 2c258da4495..b8788b9423c 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/distsql/export/ExportedSnapshotInfo.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/distsql/export/ExportedSnapshotInfo.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.proxy.backend.distsql.export;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import lombok.Getter;
 import lombok.Setter;
@@ -32,6 +33,7 @@ public class ExportedSnapshotInfo {
     
     private String csn;
     
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @JsonProperty("create_time")
     private LocalDateTime createTime;
 }
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ExportMetaDataExecutor.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ExportMetaDataExecutor.java
index 049fd4fc69a..36e4fad3b59 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ExportMetaDataExecutor.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ExportMetaDataExecutor.java
@@ -19,16 +19,20 @@ package org.apache.shardingsphere.proxy.backend.handler.distsql.ral.queryable;
 
 import org.apache.shardingsphere.distsql.handler.ral.query.MetaDataRequiredQueryableRALExecutor;
 import org.apache.shardingsphere.distsql.parser.statement.ral.queryable.ExportMetaDataStatement;
+import org.apache.shardingsphere.globalclock.core.provider.GlobalClockProvider;
+import org.apache.shardingsphere.globalclock.core.rule.GlobalClockRule;
 import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
 import org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.util.spi.type.ordered.OrderedSPILoader;
+import org.apache.shardingsphere.infra.util.spi.type.typed.TypedSPILoader;
 import org.apache.shardingsphere.infra.util.yaml.YamlEngine;
 import org.apache.shardingsphere.infra.yaml.config.swapper.rule.YamlRuleConfigurationSwapper;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.proxy.backend.distsql.export.ExportedClusterInfo;
 import org.apache.shardingsphere.proxy.backend.distsql.export.ExportedMetaData;
+import org.apache.shardingsphere.proxy.backend.distsql.export.ExportedSnapshotInfo;
 import org.apache.shardingsphere.proxy.backend.util.ExportUtils;
 import org.apache.shardingsphere.proxy.backend.util.JsonUtils;
 
@@ -72,6 +76,7 @@ public final class ExportMetaDataExecutor implements MetaDataRequiredQueryableRA
         exportedMetaData.setRules(generateRulesData(metaData.getGlobalRuleMetaData().getConfigurations()));
         ExportedClusterInfo exportedClusterInfo = new ExportedClusterInfo();
         exportedClusterInfo.setMetaData(exportedMetaData);
+        generateSnapshotInfo(metaData, exportedClusterInfo);
         return JsonUtils.toJsonString(exportedClusterInfo);
     }
     
@@ -110,6 +115,19 @@ public final class ExportMetaDataExecutor implements MetaDataRequiredQueryableRA
         return result.toString();
     }
     
+    private void generateSnapshotInfo(final ShardingSphereMetaData metaData, final ExportedClusterInfo exportedClusterInfo) {
+        GlobalClockRule globalClockRule = metaData.getGlobalRuleMetaData().getSingleRule(GlobalClockRule.class);
+        if (globalClockRule.getConfiguration().isEnabled()) {
+            GlobalClockProvider globalClockProvider = TypedSPILoader.getService(GlobalClockProvider.class,
+                    globalClockRule.getGlobalClockProviderType(), globalClockRule.getConfiguration().getProps());
+            long csn = globalClockProvider.getCurrentTimestamp();
+            ExportedSnapshotInfo snapshotInfo = new ExportedSnapshotInfo();
+            snapshotInfo.setCsn(String.valueOf(csn));
+            snapshotInfo.setCreateTime(LocalDateTime.now());
+            exportedClusterInfo.setSnapshotInfo(snapshotInfo);
+        }
+    }
+    
     @Override
     public String getType() {
         return ExportMetaDataStatement.class.getName();
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/util/JsonUtils.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/util/JsonUtils.java
index af5c8f19c81..c75c9f0707e 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/util/JsonUtils.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/util/JsonUtils.java
@@ -22,6 +22,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import lombok.SneakyThrows;
@@ -40,6 +41,7 @@ public final class JsonUtils {
     
     private static ObjectMapper initDefaultMapper() {
         ObjectMapper result = new ObjectMapper();
+        result.registerModule(new JavaTimeModule());
         result.findAndRegisterModules();
         result.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
         result.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/util/YamlDatabaseConfigurationImportExecutor.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/util/YamlDatabaseConfigurationImportExecutor.java
index 297864c0b56..9b2fb7529e5 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/util/YamlDatabaseConfigurationImportExecutor.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/util/YamlDatabaseConfigurationImportExecutor.java
@@ -17,9 +17,9 @@
 
 package org.apache.shardingsphere.proxy.backend.util;
 
-import com.google.common.base.Preconditions;
 import com.zaxxer.hikari.HikariDataSource;
 import org.apache.shardingsphere.distsql.handler.exception.DistSQLException;
+import org.apache.shardingsphere.distsql.handler.exception.datasource.MissingRequiredDataSourcesException;
 import org.apache.shardingsphere.distsql.handler.exception.storageunit.InvalidStorageUnitsException;
 import org.apache.shardingsphere.distsql.handler.validate.DataSourcePropertiesValidateHandler;
 import org.apache.shardingsphere.encrypt.api.config.EncryptRuleConfiguration;
@@ -35,6 +35,8 @@ import org.apache.shardingsphere.infra.datasource.props.DataSourcePropertiesCrea
 import org.apache.shardingsphere.infra.instance.InstanceContext;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+import org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
+import org.apache.shardingsphere.infra.util.exception.external.sql.type.generic.UnsupportedSQLOperationException;
 import org.apache.shardingsphere.infra.yaml.config.pojo.rule.YamlRuleConfiguration;
 import org.apache.shardingsphere.mask.api.config.MaskRuleConfiguration;
 import org.apache.shardingsphere.mask.rule.MaskRule;
@@ -115,14 +117,15 @@ public final class YamlDatabaseConfigurationImportExecutor {
     }
     
     private void checkDatabase(final String databaseName) {
-        Preconditions.checkNotNull(databaseName, "Property `databaseName` in imported config is required");
+        ShardingSpherePreconditions.checkNotNull(databaseName, () -> new UnsupportedSQLOperationException("Property `databaseName` in imported config is required"));
         if (ProxyContext.getInstance().databaseExists(databaseName)) {
-            Preconditions.checkState(ProxyContext.getInstance().getDatabase(databaseName).getResourceMetaData().getDataSources().isEmpty(), "Database `%s` exists and is not empty", databaseName);
+            ShardingSpherePreconditions.checkState(ProxyContext.getInstance().getDatabase(databaseName).getResourceMetaData().getDataSources().isEmpty(),
+                    () -> new UnsupportedSQLOperationException(String.format("Database `%s` exists and is not empty,overwrite is not supported", databaseName)));
         }
     }
     
     private void checkDataSource(final Map<String, YamlProxyDataSourceConfiguration> dataSources) {
-        Preconditions.checkState(!dataSources.isEmpty(), "Data source configurations in imported config is required");
+        ShardingSpherePreconditions.checkState(!dataSources.isEmpty(), () -> new MissingRequiredDataSourcesException("Data source configurations in imported config is required"));
     }
     
     private void addDatabase(final String databaseName) {
diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ExportMetaDataExecutorTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ExportMetaDataExecutorTest.java
index 8fddda6aa6c..ed814bcd308 100644
--- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ExportMetaDataExecutorTest.java
+++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ExportMetaDataExecutorTest.java
@@ -21,16 +21,27 @@ import lombok.SneakyThrows;
 import org.apache.shardingsphere.authority.rule.AuthorityRule;
 import org.apache.shardingsphere.authority.rule.builder.DefaultAuthorityRuleConfigurationBuilder;
 import org.apache.shardingsphere.distsql.parser.statement.ral.queryable.ExportMetaDataStatement;
+import org.apache.shardingsphere.globalclock.core.rule.GlobalClockRule;
+import org.apache.shardingsphere.globalclock.core.rule.builder.DefaultGlobalClockRuleConfigurationBuilder;
+import org.apache.shardingsphere.infra.config.mode.ModeConfiguration;
 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
 import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
+import org.apache.shardingsphere.infra.instance.ComputeNodeInstance;
+import org.apache.shardingsphere.infra.instance.InstanceContext;
+import org.apache.shardingsphere.infra.instance.metadata.InstanceMetaData;
+import org.apache.shardingsphere.infra.instance.mode.ModeContextManager;
+import org.apache.shardingsphere.infra.lock.LockContext;
 import org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
+import org.apache.shardingsphere.infra.util.eventbus.EventBusContext;
+import org.apache.shardingsphere.metadata.persist.MetaDataPersistService;
 import org.apache.shardingsphere.mode.manager.ContextManager;
+import org.apache.shardingsphere.mode.manager.standalone.workerid.generator.StandaloneWorkerIdGenerator;
 import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
-import org.apache.shardingsphere.metadata.persist.MetaDataPersistService;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import org.apache.shardingsphere.test.fixture.jdbc.MockedDataSource;
 import org.apache.shardingsphere.test.mock.AutoMockExtension;
 import org.apache.shardingsphere.test.mock.StaticMockSettings;
 import org.apache.shardingsphere.test.util.PropertiesBuilder;
@@ -38,14 +49,17 @@ import org.apache.shardingsphere.test.util.PropertiesBuilder.Property;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 
+import javax.sql.DataSource;
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.IOException;
-import java.sql.SQLException;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Properties;
 
@@ -84,35 +98,66 @@ class ExportMetaDataExecutorTest {
         Collection<LocalDataQueryResultRow> actual = new ExportMetaDataExecutor().getRows(contextManager.getMetaDataContexts().getMetaData(), sqlStatement);
         assertThat(actual.size(), is(1));
         LocalDataQueryResultRow row = actual.iterator().next();
-        assertThat(row.getCell(3), is("{\"meta_data\":{\"databases\":{\"empty_metadata\":\"databaseName: null\\ndataSources:\\nrules:\\n\"},\"props\":\"\",\"rules\":\"\"}}"));
+        assertThat(row.getCell(3), 
+                is("{\"meta_data\":{\"databases\":{\"empty_metadata\":\"databaseName: null\\ndataSources:\\nrules:\\n\"},"
+                        + "\"props\":\"\",\"rules\":\"rules:\\n- !GLOBAL_CLOCK\\n  enabled: false\\n  provider: local\\n  type: TSO\\n\"}}"));
     }
     
     private ContextManager mockEmptyContextManager() {
         ContextManager result = mock(ContextManager.class, RETURNS_DEEP_STUBS);
         MetaDataContexts metaDataContexts = new MetaDataContexts(mock(MetaDataPersistService.class), new ShardingSphereMetaData(new HashMap<>(),
-                new ShardingSphereRuleMetaData(Collections.emptyList()),
+                new ShardingSphereRuleMetaData(Collections.singletonList(
+                        new GlobalClockRule(new DefaultGlobalClockRuleConfigurationBuilder().build(), Collections.emptyMap()))),
                 new ConfigurationProperties(new Properties())));
         when(result.getMetaDataContexts()).thenReturn(metaDataContexts);
         return result;
     }
     
     @Test
-    void assertExecute() throws SQLException {
+    void assertExecute() {
         when(database.getName()).thenReturn("normal_db");
+        when(database.getResourceMetaData().getAllInstanceDataSourceNames()).thenReturn(Collections.singleton("empty_metadata"));
+        Map<String, DataSource> dataSourceMap = createDataSourceMap();
+        when(database.getResourceMetaData().getDataSources()).thenReturn(dataSourceMap);
+        when(database.getRuleMetaData().getConfigurations()).thenReturn(Collections.emptyList());
         ContextManager contextManager = mockContextManager();
         when(ProxyContext.getInstance().getContextManager()).thenReturn(contextManager);
+        when(ProxyContext.getInstance().getAllDatabaseNames()).thenReturn(Collections.singleton("normal_db"));
+        when(ProxyContext.getInstance().getDatabase("normal_db")).thenReturn(database);
         Collection<LocalDataQueryResultRow> actual = new ExportMetaDataExecutor().getRows(contextManager.getMetaDataContexts().getMetaData(), new ExportMetaDataStatement(null));
         assertThat(actual.size(), is(1));
         LocalDataQueryResultRow row = actual.iterator().next();
-        assertThat(row.getCell(3), is(loadExpectedRow()));
+        assertThat(row.getCell(3).toString(), is(loadExpectedRow()));
     }
     
     private ContextManager mockContextManager() {
-        ContextManager result = mock(ContextManager.class, RETURNS_DEEP_STUBS);
         MetaDataContexts metaDataContexts = new MetaDataContexts(mock(MetaDataPersistService.class), new ShardingSphereMetaData(Collections.singletonMap(database.getName(), database),
-                new ShardingSphereRuleMetaData(Collections.singleton(new AuthorityRule(new DefaultAuthorityRuleConfigurationBuilder().build(), Collections.emptyMap()))),
+                new ShardingSphereRuleMetaData(Arrays.asList(new AuthorityRule(new DefaultAuthorityRuleConfigurationBuilder().build(), Collections.emptyMap()),
+                        new GlobalClockRule(new DefaultGlobalClockRuleConfigurationBuilder().build(), Collections.singletonMap(database.getName(), database)))),
                 new ConfigurationProperties(PropertiesBuilder.build(new Property(ConfigurationPropertyKey.SQL_SHOW.getKey(), "true")))));
+        InstanceContext instanceContext = new InstanceContext(
+                new ComputeNodeInstance(mock(InstanceMetaData.class)), new StandaloneWorkerIdGenerator(), new ModeConfiguration("Standalone", null),
+                mock(ModeContextManager.class), mock(LockContext.class), new EventBusContext());
+        ContextManager result = mock(ContextManager.class, RETURNS_DEEP_STUBS);
         when(result.getMetaDataContexts()).thenReturn(metaDataContexts);
+        when(result.getInstanceContext()).thenReturn(instanceContext);
+        return result;
+    }
+    
+    private Map<String, DataSource> createDataSourceMap() {
+        Map<String, DataSource> result = new LinkedHashMap<>(2, 1);
+        result.put("ds_0", createDataSource("demo_ds_0"));
+        result.put("ds_1", createDataSource("demo_ds_1"));
+        return result;
+    }
+    
+    private DataSource createDataSource(final String name) {
+        MockedDataSource result = new MockedDataSource();
+        result.setUrl(String.format("jdbc:opengauss://127.0.0.1:5432/%s", name));
+        result.setUsername("root");
+        result.setPassword("");
+        result.setMaxPoolSize(50);
+        result.setMinPoolSize(1);
         return result;
     }
     
diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportDatabaseConfigurationUpdaterTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportDatabaseConfigurationUpdaterTest.java
index 1983d4b0fd2..0df6a7309f5 100644
--- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportDatabaseConfigurationUpdaterTest.java
+++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportDatabaseConfigurationUpdaterTest.java
@@ -18,6 +18,7 @@
 package org.apache.shardingsphere.proxy.backend.handler.distsql.ral.updatable;
 
 import lombok.SneakyThrows;
+import org.apache.shardingsphere.distsql.handler.exception.datasource.MissingRequiredDataSourcesException;
 import org.apache.shardingsphere.distsql.handler.exception.rule.DuplicateRuleException;
 import org.apache.shardingsphere.distsql.handler.validate.DataSourcePropertiesValidateHandler;
 import org.apache.shardingsphere.distsql.parser.statement.ral.updatable.ImportDatabaseConfigurationStatement;
@@ -28,6 +29,7 @@ import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.resource.ShardingSphereResourceMetaData;
 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 import org.apache.shardingsphere.infra.rule.identifier.type.DataSourceContainedRule;
+import org.apache.shardingsphere.infra.util.exception.external.sql.type.generic.UnsupportedSQLOperationException;
 import org.apache.shardingsphere.infra.util.spi.exception.ServiceProviderNotFoundServerException;
 import org.apache.shardingsphere.mode.manager.ContextManager;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
@@ -83,17 +85,17 @@ class ImportDatabaseConfigurationUpdaterTest {
     void assertImportExistedDatabase() {
         String databaseName = "sharding_db";
         when(ProxyContext.getInstance().databaseExists(databaseName)).thenReturn(true);
-        assertThrows(IllegalStateException.class, () -> assertExecute(databaseName, "/conf/import/config-sharding.yaml"));
+        assertThrows(UnsupportedSQLOperationException.class, () -> assertExecute(databaseName, "/conf/import/config-sharding.yaml"));
     }
     
     @Test
     void assertImportEmptyDatabaseName() {
-        assertThrows(NullPointerException.class, () -> assertExecute("sharding_db", "/conf/import/config-empty-database-name.yaml"));
+        assertThrows(UnsupportedSQLOperationException.class, () -> assertExecute("sharding_db", "/conf/import/config-empty-database-name.yaml"));
     }
     
     @Test
     void assertImportEmptyDataSource() {
-        assertThrows(IllegalStateException.class, () -> assertExecute("sharding_db", "/conf/import/config-empty-data-source.yaml"));
+        assertThrows(MissingRequiredDataSourcesException.class, () -> assertExecute("sharding_db", "/conf/import/config-empty-data-source.yaml"));
     }
     
     @Test
diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportMetaDataUpdaterTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportMetaDataUpdaterTest.java
index 1d42b740f0b..b86c4a5d79e 100644
--- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportMetaDataUpdaterTest.java
+++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/ImportMetaDataUpdaterTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.proxy.backend.handler.distsql.ral.updatable;
 
+import org.apache.shardingsphere.distsql.handler.exception.datasource.MissingRequiredDataSourcesException;
 import org.apache.shardingsphere.distsql.parser.statement.ral.updatable.ImportMetaDataStatement;
 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
 import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
@@ -26,6 +27,7 @@ import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSp
 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereIndex;
 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
+import org.apache.shardingsphere.infra.util.exception.external.sql.type.generic.UnsupportedSQLOperationException;
 import org.apache.shardingsphere.mode.manager.ContextManager;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.test.fixture.jdbc.MockedDataSource;
@@ -61,7 +63,7 @@ class ImportMetaDataUpdaterTest {
             + "\"props\":\"props:\\n  system-log-level: INFO\\n  sql-show: false\\n\","
             + "\"rules\":\"rules:\\n- !AUTHORITY\\n  privilege:\\n    type: ALL_PERMITTED\\n  users:\\n  - authenticationMethodName: ''\\n    password: root\\n    user: root@%\\n\"}}";
     
-    private final String empty = "empty_metadata";
+    private static final String EMPTY = "empty_metadata";
     
     private ImportMetaDataUpdater importMetaDataUpdater;
     
@@ -69,27 +71,27 @@ class ImportMetaDataUpdaterTest {
     
     @BeforeEach
     void setup() {
-        featureMap.put(empty, "/conf/import/empty-metadata.json");
+        featureMap.put(EMPTY, "/conf/import/empty-metadata.json");
     }
     
     @Test
     void assertCheckImportEmptyMetaData() {
         init(null);
-        assertThrows(IllegalStateException.class, () -> importMetaDataUpdater.executeUpdate(
-                empty, new ImportMetaDataStatement(null, Objects.requireNonNull(ImportMetaDataUpdaterTest.class.getResource(featureMap.get(empty))).getPath())));
+        assertThrows(MissingRequiredDataSourcesException.class, () -> importMetaDataUpdater.executeUpdate(
+                EMPTY, new ImportMetaDataStatement(null, Objects.requireNonNull(ImportMetaDataUpdaterTest.class.getResource(featureMap.get(EMPTY))).getPath())));
     }
     
     @Test
     void assertImportMetaDataFromJsonValue() {
-        init(empty);
-        assertThrows(NullPointerException.class, () -> importMetaDataUpdater.executeUpdate(empty, new ImportMetaDataStatement(METADATA_VALUE, null)));
+        init(EMPTY);
+        assertThrows(NullPointerException.class, () -> importMetaDataUpdater.executeUpdate(EMPTY, new ImportMetaDataStatement(METADATA_VALUE, null)));
     }
     
     @Test
     void assertImportExistedMetaDataFromFile() {
-        init(empty);
-        assertThrows(IllegalStateException.class, () -> importMetaDataUpdater.executeUpdate(
-                empty, new ImportMetaDataStatement(null, Objects.requireNonNull(ImportMetaDataUpdaterTest.class.getResource(featureMap.get(empty))).getPath())));
+        init(EMPTY);
+        assertThrows(UnsupportedSQLOperationException.class, () -> importMetaDataUpdater.executeUpdate(
+                EMPTY, new ImportMetaDataStatement(null, Objects.requireNonNull(ImportMetaDataUpdaterTest.class.getResource(featureMap.get(EMPTY))).getPath())));
     }
     
     private void init(final String feature) {
diff --git a/proxy/backend/core/src/test/resources/expected/export-metadata-configuration.json b/proxy/backend/core/src/test/resources/expected/export-metadata-configuration.json
index e2f0bc96e35..3233fe24af6 100644
--- a/proxy/backend/core/src/test/resources/expected/export-metadata-configuration.json
+++ b/proxy/backend/core/src/test/resources/expected/export-metadata-configuration.json
@@ -1 +1 @@
-{"meta_data":{"databases":{},"props":"props:\n  sql-show: true\n","rules":"rules:\n- !AUTHORITY\n  privilege:\n    type: ALL_PERMITTED\n  users:\n  - authenticationMethodName: ''\n    password: root\n    user: root@%\n"}}
+{"meta_data":{"databases":{"normal_db":"databaseName: normal_db\ndataSources:\n  ds_0:\n    password: \n    url: jdbc:opengauss://127.0.0.1:5432/demo_ds_0\n    username: root\n    minPoolSize: 1\n    maxPoolSize: 50\n  ds_1:\n    password: \n    url: jdbc:opengauss://127.0.0.1:5432/demo_ds_1\n    username: root\n    minPoolSize: 1\n    maxPoolSize: 50\n"},"props":"props:\n  sql-show: true\n","rules":"rules:\n- !AUTHORITY\n  privilege:\n    type: ALL_PERMITTED\n  users:\n  - authenticatio [...]