You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ch...@apache.org on 2023/06/15 15:39:07 UTC

[shardingsphere] branch master updated: Add NewViewMetaDataPersistService and NewTableMetaDataPersistService (#26376)

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

chengzhang 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 1bfc00f0100 Add NewViewMetaDataPersistService and NewTableMetaDataPersistService (#26376)
1bfc00f0100 is described below

commit 1bfc00f01005e59f66268165def72cf08080c2e9
Author: zhaojinchao <zh...@apache.org>
AuthorDate: Thu Jun 15 23:39:01 2023 +0800

    Add NewViewMetaDataPersistService and NewTableMetaDataPersistService (#26376)
    
    * Add NewViewMetaDataPersistService and NewTableMetaDataPersistService
    
    * Add unit test
    
    * Fix ci
---
 .../update/AlterMaskRuleStatementUpdater.java      |   2 +-
 .../update/DropMaskRuleStatementUpdater.java       |   2 +-
 .../persist/node/NewDatabaseMetaDataNode.java      | 178 ++++++++++++++++-----
 .../metadata/persist/node/NewGlobalNode.java       |  14 +-
 .../config/global/NewGlobalRulePersistService.java |   7 +-
 .../schema/NewTableMetaDataPersistService.java     |  84 ++++++++++
 .../schema/NewViewMetaDataPersistService.java      |  84 ++++++++++
 .../persist/node/NewDatabaseMetaDataNodeTest.java  |  53 +++++-
 .../metadata/persist/node/NewGlobalNodeTest.java   |   6 +-
 .../watcher/NewMetaDataChangedWatcher.java         |   4 +-
 10 files changed, 383 insertions(+), 51 deletions(-)

diff --git a/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/AlterMaskRuleStatementUpdater.java b/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/AlterMaskRuleStatementUpdater.java
index 5022fdd6da2..de63d2ceae5 100644
--- a/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/AlterMaskRuleStatementUpdater.java
+++ b/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/AlterMaskRuleStatementUpdater.java
@@ -65,7 +65,7 @@ public final class AlterMaskRuleStatementUpdater implements RuleDefinitionAlterU
     public MaskRuleConfiguration buildToBeAlteredRuleConfiguration(final AlterMaskRuleStatement sqlStatement) {
         return MaskRuleStatementConverter.convert(sqlStatement.getRules());
     }
-
+    
     @Override
     public MaskRuleConfiguration buildToBeDroppedRuleConfiguration(final MaskRuleConfiguration currentRuleConfig, final MaskRuleConfiguration toBeAlteredRuleConfig) {
         Collection<String> toBeAlteredTableNames = toBeAlteredRuleConfig.getTables().stream().map(MaskTableRuleConfiguration::getName).collect(Collectors.toList());
diff --git a/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/DropMaskRuleStatementUpdater.java b/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/DropMaskRuleStatementUpdater.java
index 851a581d495..bf51369c941 100644
--- a/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/DropMaskRuleStatementUpdater.java
+++ b/features/mask/distsql/handler/src/main/java/org/apache/shardingsphere/mask/distsql/handler/update/DropMaskRuleStatementUpdater.java
@@ -60,7 +60,7 @@ public final class DropMaskRuleStatementUpdater implements RuleDefinitionDropUpd
         return null != currentRuleConfig
                 && !getIdenticalData(currentRuleConfig.getTables().stream().map(MaskTableRuleConfiguration::getName).collect(Collectors.toSet()), sqlStatement.getTables()).isEmpty();
     }
-
+    
     @Override
     public MaskRuleConfiguration buildToBeDroppedRuleConfiguration(final MaskRuleConfiguration currentRuleConfig, final DropMaskRuleStatement sqlStatement) {
         Collection<MaskTableRuleConfiguration> toBeDroppedTables = new LinkedList<>();
diff --git a/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/node/NewDatabaseMetaDataNode.java b/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/node/NewDatabaseMetaDataNode.java
index 9d52699a780..0bc06538d89 100644
--- a/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/node/NewDatabaseMetaDataNode.java
+++ b/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/node/NewDatabaseMetaDataNode.java
@@ -37,45 +37,15 @@ public final class NewDatabaseMetaDataNode {
     
     private static final String RULE_NODE = "rules";
     
-    private static final String ACTIVE_VERSION = "active_version";
+    private static final String SCHEMAS_NODE = "schemas";
     
-    private static final String VERSIONS = "versions";
+    private static final String TABLES_NODE = "tables";
     
-    /**
-     * Is data sources node.
-     *
-     * @param path path
-     * @return true or false
-     */
-    public static boolean isDataSourcesNode(final String path) {
-        Pattern pattern = Pattern.compile(getMetaDataNodeNode() + "/([\\w\\-]+)/" + DATA_SOURCES_NODE + "/?", Pattern.CASE_INSENSITIVE);
-        Matcher matcher = pattern.matcher(path);
-        return matcher.find();
-    }
+    private static final String VIEWS_NODE = "views";
     
-    /**
-     * Get data source name by data source node.
-     *
-     * @param path path
-     * @return data source name
-     */
-    public static Optional<String> getDataSourceNameByDataSourceNode(final String path) {
-        Pattern pattern = Pattern.compile(getMetaDataNodeNode() + "/([\\w\\-]+)/" + DATA_SOURCES_NODE + "/([\\w\\-]+)?", Pattern.CASE_INSENSITIVE);
-        Matcher matcher = pattern.matcher(path);
-        return matcher.find() ? Optional.of(matcher.group(2)) : Optional.empty();
-    }
+    private static final String ACTIVE_VERSION = "active_version";
     
-    /**
-     * Get version by data source node.
-     *
-     * @param path path
-     * @return data source version
-     */
-    public static Optional<String> getVersionByDataSourceNode(final String path) {
-        Pattern pattern = Pattern.compile(getMetaDataNodeNode() + "/([\\w\\-]+)/" + DATA_SOURCES_NODE + "/([\\w\\-]+)/versions/([\\w\\-]+)$", Pattern.CASE_INSENSITIVE);
-        Matcher matcher = pattern.matcher(path);
-        return matcher.find() ? Optional.of(matcher.group(3)) : Optional.empty();
-    }
+    private static final String VERSIONS = "versions";
     
     /**
      * Get data Sources node.
@@ -184,6 +154,140 @@ public final class NewDatabaseMetaDataNode {
         return String.join("/", getMetaDataNodeNode(), databaseName, RULE_NODE);
     }
     
+    /**
+     * Get table active version node.
+     *
+     * @param databaseName database name
+     * @param schemaName schema name
+     * @param tableName table name
+     * @return tables active version node
+     */
+    public static String getTableActiveVersionNode(final String databaseName, final String schemaName, final String tableName) {
+        return String.join("/", getTableNode(databaseName, schemaName, tableName), ACTIVE_VERSION);
+    }
+    
+    /**
+     * Get table versions node.
+     *
+     * @param databaseName database name
+     * @param schemaName schema name
+     * @param tableName table name
+     * @return tables versions node
+     */
+    public static String getTableVersionsNode(final String databaseName, final String schemaName, final String tableName) {
+        return String.join("/", getTableNode(databaseName, schemaName, tableName), VERSIONS);
+    }
+    
+    /**
+     * Get table version node.
+     *
+     * @param databaseName database name
+     * @param schemaName schema name
+     * @param tableName table name
+     * @param version version
+     * @return table version node
+     */
+    public static String getTableVersionNode(final String databaseName, final String schemaName, final String tableName, final String version) {
+        return String.join("/", getTableVersionsNode(databaseName, schemaName, tableName), version);
+    }
+    
+    /**
+     * Get table node.
+     *
+     * @param databaseName database name
+     * @param schemaName schema name
+     * @param tableName table name
+     * @return table node
+     */
+    public static String getTableNode(final String databaseName, final String schemaName, final String tableName) {
+        return String.join("/", getMetaDataNodeNode(), databaseName, SCHEMAS_NODE, schemaName, TABLES_NODE, tableName);
+    }
+    
+    /**
+     * Get view name active version node.
+     *
+     * @param databaseName database name
+     * @param schemaName schema name
+     * @param viewName view name
+     * @return view active version node
+     */
+    public static String getViewActiveVersionNode(final String databaseName, final String schemaName, final String viewName) {
+        return String.join("/", getViewNode(databaseName, schemaName, viewName), ACTIVE_VERSION);
+    }
+    
+    /**
+     * Get view versions node.
+     *
+     * @param databaseName database name
+     * @param schemaName schema name
+     * @param viewName view name
+     * @return view versions node
+     */
+    public static String getViewVersionsNode(final String databaseName, final String schemaName, final String viewName) {
+        return String.join("/", getViewNode(databaseName, schemaName, viewName), VERSIONS);
+    }
+    
+    /**
+     * Get view version node.
+     *
+     * @param databaseName database name
+     * @param schemaName schema name
+     * @param viewName view name
+     * @param version version
+     * @return view version node
+     */
+    public static String getViewVersionNode(final String databaseName, final String schemaName, final String viewName, final String version) {
+        return String.join("/", getViewVersionsNode(databaseName, schemaName, viewName), version);
+    }
+    
+    /**
+     * Get view node.
+     *
+     * @param databaseName database name
+     * @param schemaName schema name
+     * @param viewName view name
+     * @return tables path
+     */
+    public static String getViewNode(final String databaseName, final String schemaName, final String viewName) {
+        return String.join("/", getMetaDataNodeNode(), databaseName, SCHEMAS_NODE, schemaName, VIEWS_NODE, viewName);
+    }
+    
+    /**
+     * Is data sources node.
+     *
+     * @param path path
+     * @return true or false
+     */
+    public static boolean isDataSourcesNode(final String path) {
+        Pattern pattern = Pattern.compile(getMetaDataNodeNode() + "/([\\w\\-]+)/" + DATA_SOURCES_NODE + "/?", Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(path);
+        return matcher.find();
+    }
+    
+    /**
+     * Get data source name by data source node.
+     *
+     * @param path path
+     * @return data source name
+     */
+    public static Optional<String> getDataSourceNameByDataSourceNode(final String path) {
+        Pattern pattern = Pattern.compile(getMetaDataNodeNode() + "/([\\w\\-]+)/" + DATA_SOURCES_NODE + "/([\\w\\-]+)?", Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(path);
+        return matcher.find() ? Optional.of(matcher.group(2)) : Optional.empty();
+    }
+    
+    /**
+     * Get version by data source node.
+     *
+     * @param path path
+     * @return data source version
+     */
+    public static Optional<String> getVersionByDataSourceNode(final String path) {
+        Pattern pattern = Pattern.compile(getMetaDataNodeNode() + "/([\\w\\-]+)/" + DATA_SOURCES_NODE + "/([\\w\\-]+)/versions/([\\w\\-]+)$", Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(path);
+        return matcher.find() ? Optional.of(matcher.group(3)) : Optional.empty();
+    }
+    
     /**
      * Get database name.
      *
@@ -202,7 +306,7 @@ public final class NewDatabaseMetaDataNode {
      * @param schemaPath database path
      * @return database name
      */
-    public static Optional<String> getDatabaseNameBySchemaPath(final String schemaPath) {
+    public static Optional<String> getDatabaseNameBySchemaNode(final String schemaPath) {
         Pattern pattern = Pattern.compile(getMetaDataNodeNode() + "/([\\w\\-]+)?", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(schemaPath);
         return matcher.find() ? Optional.of(matcher.group(1)) : Optional.empty();
@@ -226,7 +330,7 @@ public final class NewDatabaseMetaDataNode {
      * @param tablePath table path
      * @return schema name
      */
-    public static Optional<String> getSchemaNameByTablePath(final String tablePath) {
+    public static Optional<String> getSchemaNameByTableNode(final String tablePath) {
         Pattern pattern = Pattern.compile(getMetaDataNodeNode() + "/([\\w\\-]+)/schemas/([\\w\\-]+)?", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(tablePath);
         return matcher.find() ? Optional.of(matcher.group(2)) : Optional.empty();
diff --git a/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/node/NewGlobalNode.java b/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/node/NewGlobalNode.java
index 321e07d7b66..7cd837e29f9 100644
--- a/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/node/NewGlobalNode.java
+++ b/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/node/NewGlobalNode.java
@@ -42,7 +42,17 @@ public final class NewGlobalNode {
      * @return global rule active version node
      */
     public static String getGlobalRuleActiveVersionNode(final String rulePath) {
-        return String.join("/", rulePath, ACTIVE_VERSION);
+        return String.join("/", getGlobalRuleRootNode(), rulePath, ACTIVE_VERSION);
+    }
+    
+    /**
+     * Get global rule versions node.
+     *
+     * @param ruleName rule name
+     * @return global rule versions node
+     */
+    public static String getGlobalRuleVersionsNode(final String ruleName) {
+        return String.join("/", getGlobalRuleRootNode(), ruleName, VERSIONS);
     }
     
     /**
@@ -53,7 +63,7 @@ public final class NewGlobalNode {
      * @return global rule version node
      */
     public static String getGlobalRuleVersionNode(final String ruleName, final String version) {
-        return String.join("/", getGlobalRuleRootNode(), ruleName, VERSIONS, version);
+        return String.join("/", getGlobalRuleVersionsNode(ruleName), version);
     }
     
     /**
diff --git a/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/service/config/global/NewGlobalRulePersistService.java b/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/service/config/global/NewGlobalRulePersistService.java
index 074fd9b040c..7ab55c8afa3 100644
--- a/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/service/config/global/NewGlobalRulePersistService.java
+++ b/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/service/config/global/NewGlobalRulePersistService.java
@@ -32,6 +32,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Optional;
 import java.util.Map;
+import java.util.List;
 import java.util.Map.Entry;
 
 /**
@@ -67,7 +68,10 @@ public final class NewGlobalRulePersistService extends AbstractPersistService im
             if (Strings.isNullOrEmpty(NewGlobalNode.getGlobalRuleActiveVersionNode(each.getKey()))) {
                 repository.persist(NewGlobalNode.getGlobalRuleActiveVersionNode(each.getKey()), DEFAULT_VERSION);
             }
-            repository.persist(NewGlobalNode.getGlobalRuleVersionNode(each.getKey(), DEFAULT_VERSION), each.getValue());
+            List<String> versions = repository.getChildrenKeys(NewGlobalNode.getGlobalRuleVersionsNode(each.getKey()));
+            repository.persist(NewGlobalNode.getGlobalRuleVersionNode(each.getKey(), versions.isEmpty()
+                    ? DEFAULT_VERSION
+                    : String.valueOf(Integer.parseInt(versions.get(0)) + 1)), each.getValue());
         }
     }
     
@@ -79,6 +83,7 @@ public final class NewGlobalRulePersistService extends AbstractPersistService im
     }
     
     /**
+     * TODO Avoid load all keys.
      * Load all users.
      * 
      * @return collection of user
diff --git a/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/service/schema/NewTableMetaDataPersistService.java b/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/service/schema/NewTableMetaDataPersistService.java
new file mode 100644
index 00000000000..5d0ed10ee40
--- /dev/null
+++ b/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/service/schema/NewTableMetaDataPersistService.java
@@ -0,0 +1,84 @@
+/*
+ * 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.metadata.persist.service.schema;
+
+import com.google.common.base.Strings;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
+import org.apache.shardingsphere.infra.util.yaml.YamlEngine;
+import org.apache.shardingsphere.infra.yaml.schema.pojo.YamlShardingSphereTable;
+import org.apache.shardingsphere.infra.yaml.schema.swapper.YamlTableSwapper;
+import org.apache.shardingsphere.metadata.persist.node.DatabaseMetaDataNode;
+import org.apache.shardingsphere.metadata.persist.node.NewDatabaseMetaDataNode;
+import org.apache.shardingsphere.mode.spi.PersistRepository;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.Map.Entry;
+
+/**
+ * TODO Rename TableMetaDataPersistService when metadata structure adjustment completed. #25485
+ * Table meta data persist service.
+ */
+@RequiredArgsConstructor
+public final class NewTableMetaDataPersistService implements SchemaMetaDataPersistService<Map<String, ShardingSphereTable>> {
+    
+    private static final String DEFAULT_VERSION = "0";
+    
+    private final PersistRepository repository;
+    
+    @Override
+    public void persist(final String databaseName, final String schemaName, final Map<String, ShardingSphereTable> tables) {
+        for (Entry<String, ShardingSphereTable> entry : tables.entrySet()) {
+            String tableName = entry.getKey().toLowerCase();
+            if (Strings.isNullOrEmpty(repository.getDirectly(NewDatabaseMetaDataNode.getTableActiveVersionNode(databaseName, schemaName, tableName)))) {
+                repository.persist(NewDatabaseMetaDataNode.getTableActiveVersionNode(databaseName, schemaName, tableName), DEFAULT_VERSION);
+            }
+            List<String> versions = repository.getChildrenKeys(NewDatabaseMetaDataNode.getTableVersionsNode(databaseName, schemaName, tableName));
+            repository.persist(NewDatabaseMetaDataNode.getTableVersionNode(databaseName, schemaName, tableName, versions.isEmpty()
+                    ? DEFAULT_VERSION
+                    : String.valueOf(Integer.parseInt(versions.get(0)) + 1)), YamlEngine.marshal(new YamlTableSwapper().swapToYamlConfiguration(entry.getValue())));
+        }
+    }
+    
+    @Override
+    public Map<String, ShardingSphereTable> load(final String databaseName, final String schemaName) {
+        Collection<String> tableNames = repository.getChildrenKeys(DatabaseMetaDataNode.getMetaDataTablesPath(databaseName, schemaName));
+        return tableNames.isEmpty() ? Collections.emptyMap() : getTableMetaDataByTableNames(databaseName, schemaName, tableNames);
+    }
+    
+    private Map<String, ShardingSphereTable> getTableMetaDataByTableNames(final String databaseName, final String schemaName, final Collection<String> tableNames) {
+        Map<String, ShardingSphereTable> result = new LinkedHashMap<>(tableNames.size(), 1F);
+        tableNames.forEach(each -> {
+            String table = repository.getDirectly(NewDatabaseMetaDataNode.getTableVersionNode(databaseName, schemaName, each,
+                    repository.getDirectly(NewDatabaseMetaDataNode.getTableActiveVersionNode(databaseName, schemaName, each))));
+            if (!Strings.isNullOrEmpty(table)) {
+                result.put(each.toLowerCase(), new YamlTableSwapper().swapToObject(YamlEngine.unmarshal(table, YamlShardingSphereTable.class)));
+            }
+        });
+        return result;
+    }
+    
+    @Override
+    public void delete(final String databaseName, final String schemaName, final String tableName) {
+        repository.delete(NewDatabaseMetaDataNode.getTableNode(databaseName, schemaName, tableName.toLowerCase()));
+    }
+}
diff --git a/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/service/schema/NewViewMetaDataPersistService.java b/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/service/schema/NewViewMetaDataPersistService.java
new file mode 100644
index 00000000000..b8e5536e3a2
--- /dev/null
+++ b/kernel/metadata/core/src/main/java/org/apache/shardingsphere/metadata/persist/service/schema/NewViewMetaDataPersistService.java
@@ -0,0 +1,84 @@
+/*
+ * 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.metadata.persist.service.schema;
+
+import com.google.common.base.Strings;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereView;
+import org.apache.shardingsphere.infra.util.yaml.YamlEngine;
+import org.apache.shardingsphere.infra.yaml.schema.pojo.YamlShardingSphereView;
+import org.apache.shardingsphere.infra.yaml.schema.swapper.YamlViewSwapper;
+import org.apache.shardingsphere.metadata.persist.node.DatabaseMetaDataNode;
+import org.apache.shardingsphere.metadata.persist.node.NewDatabaseMetaDataNode;
+import org.apache.shardingsphere.mode.spi.PersistRepository;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.Map.Entry;
+
+/**
+ * TODO Rename ViewMetaDataPersistService when metadata structure adjustment completed. #25485
+ * View meta data persist service.
+ */
+@RequiredArgsConstructor
+public final class NewViewMetaDataPersistService implements SchemaMetaDataPersistService<Map<String, ShardingSphereView>> {
+    
+    private static final String DEFAULT_VERSION = "0";
+    
+    private final PersistRepository repository;
+    
+    @Override
+    public void persist(final String databaseName, final String schemaName, final Map<String, ShardingSphereView> views) {
+        for (Entry<String, ShardingSphereView> entry : views.entrySet()) {
+            String viewName = entry.getKey().toLowerCase();
+            if (Strings.isNullOrEmpty(repository.getDirectly(NewDatabaseMetaDataNode.getViewActiveVersionNode(databaseName, schemaName, viewName)))) {
+                repository.persist(NewDatabaseMetaDataNode.getViewActiveVersionNode(databaseName, schemaName, viewName), DEFAULT_VERSION);
+            }
+            List<String> versions = repository.getChildrenKeys(NewDatabaseMetaDataNode.getViewVersionsNode(databaseName, schemaName, viewName));
+            repository.persist(NewDatabaseMetaDataNode.getViewVersionNode(databaseName, schemaName, viewName, versions.isEmpty()
+                    ? DEFAULT_VERSION
+                    : String.valueOf(Integer.parseInt(versions.get(0)) + 1)), YamlEngine.marshal(new YamlViewSwapper().swapToYamlConfiguration(entry.getValue())));
+        }
+    }
+    
+    @Override
+    public Map<String, ShardingSphereView> load(final String databaseName, final String schemaName) {
+        Collection<String> viewNames = repository.getChildrenKeys(DatabaseMetaDataNode.getMetaDataViewsPath(databaseName, schemaName));
+        return viewNames.isEmpty() ? Collections.emptyMap() : getViewMetaDataByViewNames(databaseName, schemaName, viewNames);
+    }
+    
+    private Map<String, ShardingSphereView> getViewMetaDataByViewNames(final String databaseName, final String schemaName, final Collection<String> viewNames) {
+        Map<String, ShardingSphereView> result = new LinkedHashMap<>(viewNames.size(), 1F);
+        viewNames.forEach(each -> {
+            String view = repository.getDirectly(NewDatabaseMetaDataNode.getViewVersionNode(databaseName, schemaName, each,
+                    repository.getDirectly(NewDatabaseMetaDataNode.getViewActiveVersionNode(databaseName, schemaName, each))));
+            if (!Strings.isNullOrEmpty(view)) {
+                result.put(each.toLowerCase(), new YamlViewSwapper().swapToObject(YamlEngine.unmarshal(view, YamlShardingSphereView.class)));
+            }
+        });
+        return result;
+    }
+    
+    @Override
+    public void delete(final String databaseName, final String schemaName, final String viewName) {
+        repository.delete(NewDatabaseMetaDataNode.getViewNode(databaseName, schemaName, viewName.toLowerCase()));
+    }
+}
diff --git a/kernel/metadata/core/src/test/java/org/apache/shardingsphere/metadata/persist/node/NewDatabaseMetaDataNodeTest.java b/kernel/metadata/core/src/test/java/org/apache/shardingsphere/metadata/persist/node/NewDatabaseMetaDataNodeTest.java
index 3083a532809..33a0352c6ba 100644
--- a/kernel/metadata/core/src/test/java/org/apache/shardingsphere/metadata/persist/node/NewDatabaseMetaDataNodeTest.java
+++ b/kernel/metadata/core/src/test/java/org/apache/shardingsphere/metadata/persist/node/NewDatabaseMetaDataNodeTest.java
@@ -47,6 +47,11 @@ class NewDatabaseMetaDataNodeTest {
         assertThat(actual.get(), is("0"));
     }
     
+    @Test
+    void asserGetTableNode() {
+        assertThat(NewDatabaseMetaDataNode.getTableNode("foo_db", "foo_schema", "foo_table"), is("/metadata/foo_db/schemas/foo_schema/tables/foo_table"));
+    }
+    
     @Test
     void assertGetDatabaseName() {
         Optional<String> actual = NewDatabaseMetaDataNode.getDatabaseName("/metadata/foo_db");
@@ -55,8 +60,8 @@ class NewDatabaseMetaDataNodeTest {
     }
     
     @Test
-    void assertGetDatabaseNameBySchemaPath() {
-        Optional<String> actual = NewDatabaseMetaDataNode.getDatabaseNameBySchemaPath("/metadata/foo_db/schemas/foo_schema");
+    void assertGetDatabaseNameBySchemaNode() {
+        Optional<String> actual = NewDatabaseMetaDataNode.getDatabaseNameBySchemaNode("/metadata/foo_db/schemas/foo_schema");
         assertTrue(actual.isPresent());
         assertThat(actual.get(), is("foo_db"));
     }
@@ -69,8 +74,8 @@ class NewDatabaseMetaDataNodeTest {
     }
     
     @Test
-    void assertGetSchemaNameByTablePath() {
-        Optional<String> actual = NewDatabaseMetaDataNode.getSchemaNameByTablePath("/metadata/foo_db/schemas/foo_schema/tables");
+    void assertGetSchemaNameByTableNode() {
+        Optional<String> actual = NewDatabaseMetaDataNode.getSchemaNameByTableNode("/metadata/foo_db/schemas/foo_schema/tables");
         assertTrue(actual.isPresent());
         assertThat(actual.get(), is("foo_schema"));
     }
@@ -123,4 +128,44 @@ class NewDatabaseMetaDataNodeTest {
     void assertGetDatabaseRuleVersionNode() {
         assertThat(NewDatabaseMetaDataNode.getDatabaseRuleVersionNode("foo_db", "foo_rule", "foo_tables", "1"), is("/metadata/foo_db/rules/foo_rule/foo_tables/versions/1"));
     }
+    
+    @Test
+    void assertGetTableActiveVersionNode() {
+        assertThat(NewDatabaseMetaDataNode.getTableActiveVersionNode("foo_db", "foo_schema", "foo_table"), is("/metadata/foo_db/schemas/foo_schema/tables/foo_table/active_version"));
+    }
+    
+    @Test
+    void assertGetTableVersionsNode() {
+        assertThat(NewDatabaseMetaDataNode.getTableVersionsNode("foo_db", "foo_schema", "foo_table"), is("/metadata/foo_db/schemas/foo_schema/tables/foo_table/versions"));
+    }
+    
+    @Test
+    void assertGetTableVersionNode() {
+        assertThat(NewDatabaseMetaDataNode.getTableVersionNode("foo_db", "foo_schema", "foo_table", "0"), is("/metadata/foo_db/schemas/foo_schema/tables/foo_table/versions/0"));
+    }
+    
+    @Test
+    void assertGetTableNode() {
+        assertThat(NewDatabaseMetaDataNode.getTableNode("foo_db", "foo_schema", "foo_table"), is("/metadata/foo_db/schemas/foo_schema/tables/foo_table"));
+    }
+    
+    @Test
+    void assertGetViewActiveVersionNode() {
+        assertThat(NewDatabaseMetaDataNode.getViewActiveVersionNode("foo_db", "foo_schema", "foo_view"), is("/metadata/foo_db/schemas/foo_schema/views/foo_view/active_version"));
+    }
+    
+    @Test
+    void assertGetViewVersionsNode() {
+        assertThat(NewDatabaseMetaDataNode.getViewVersionsNode("foo_db", "foo_schema", "foo_view"), is("/metadata/foo_db/schemas/foo_schema/views/foo_view/versions"));
+    }
+    
+    @Test
+    void assertGetViewVersionNode() {
+        assertThat(NewDatabaseMetaDataNode.getViewVersionNode("foo_db", "foo_schema", "foo_view", "0"), is("/metadata/foo_db/schemas/foo_schema/views/foo_view/versions/0"));
+    }
+    
+    @Test
+    void assertGetViewNode() {
+        assertThat(NewDatabaseMetaDataNode.getViewNode("foo_db", "foo_schema", "foo_view"), is("/metadata/foo_db/schemas/foo_schema/views/foo_view"));
+    }
 }
diff --git a/kernel/metadata/core/src/test/java/org/apache/shardingsphere/metadata/persist/node/NewGlobalNodeTest.java b/kernel/metadata/core/src/test/java/org/apache/shardingsphere/metadata/persist/node/NewGlobalNodeTest.java
index 107c4ff36e5..c34837d5b70 100644
--- a/kernel/metadata/core/src/test/java/org/apache/shardingsphere/metadata/persist/node/NewGlobalNodeTest.java
+++ b/kernel/metadata/core/src/test/java/org/apache/shardingsphere/metadata/persist/node/NewGlobalNodeTest.java
@@ -42,11 +42,11 @@ class NewGlobalNodeTest {
     
     @Test
     void assertGetGlobalRuleActiveVersionNode() {
-        assertThat(NewGlobalNode.getGlobalRuleActiveVersionNode("transaction"), is("transaction/active_version"));
+        assertThat(NewGlobalNode.getGlobalRuleActiveVersionNode("transaction"), is("/rules/transaction/active_version"));
     }
     
     @Test
-    void assertGetGlobalRuleVersionNode() {
-        assertThat(NewGlobalNode.getGlobalRuleVersionNode("transaction", "0"), is("/rules/transaction/versions/0"));
+    void assertGetGlobalRuleVersionsNode() {
+        assertThat(NewGlobalNode.getGlobalRuleVersionsNode("transaction"), is("/rules/transaction/versions"));
     }
 }
diff --git a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/registry/metadata/watcher/NewMetaDataChangedWatcher.java b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/registry/metadata/watcher/NewMetaDataChangedWatcher.java
index 2c75e0c09f2..b8f363939ff 100644
--- a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/registry/metadata/watcher/NewMetaDataChangedWatcher.java
+++ b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/coordinator/registry/metadata/watcher/NewMetaDataChangedWatcher.java
@@ -75,12 +75,12 @@ public final class NewMetaDataChangedWatcher implements NewGovernanceWatcher<Gov
         if (databaseName.isPresent()) {
             return createDatabaseChangedEvent(databaseName.get(), event);
         }
-        databaseName = NewDatabaseMetaDataNode.getDatabaseNameBySchemaPath(key);
+        databaseName = NewDatabaseMetaDataNode.getDatabaseNameBySchemaNode(key);
         Optional<String> schemaName = NewDatabaseMetaDataNode.getSchemaName(key);
         if (databaseName.isPresent() && schemaName.isPresent()) {
             return createSchemaChangedEvent(databaseName.get(), schemaName.get(), event);
         }
-        schemaName = NewDatabaseMetaDataNode.getSchemaNameByTablePath(key);
+        schemaName = NewDatabaseMetaDataNode.getSchemaNameByTableNode(key);
         Optional<String> tableName = NewDatabaseMetaDataNode.getTableName(key);
         if (databaseName.isPresent() && schemaName.isPresent() && tableName.isPresent()) {
             return createTableChangedEvent(databaseName.get(), schemaName.get(), tableName.get(), event);