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

[shardingsphere] branch master updated: Refactor feature node converter (#26551)

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

zhaojinchao 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 cf0c4dba7b1 Refactor feature node converter (#26551)
cf0c4dba7b1 is described below

commit cf0c4dba7b12b9719f595e8d26856f01cfc64db3
Author: ChenJiaHao <Pa...@163.com>
AuthorDate: Sun Jun 25 21:51:11 2023 +0800

    Refactor feature node converter (#26551)
    
    * Refactor feature node converter
    
    * Support compatible encrypt rule configuration
    
    * Resolve conflicts
---
 .../metadata/converter/BroadcastNodeConverter.java |  17 +-
 .../coverter/BroadcastNodeConverterTest.java       |  10 +-
 ...atibleEncryptRuleConfigurationEventBuilder.java |  73 ++++++
 .../encryptor/AlterCompatibleEncryptorEvent.java}  |  35 +--
 .../encryptor/DeleteCompatibleEncryptorEvent.java} |  35 +--
 .../table/AddCompatibleEncryptTableEvent.java}     |  33 +--
 .../table/AlterCompatibleEncryptTableEvent.java}   |  35 +--
 .../table/DeleteCompatibleEncryptTableEvent.java}  |  35 +--
 .../converter/CompatibleEncryptNodeConverter.java  | 119 ++--------
 .../CompatibleEncryptTableSubscriber.java          | 115 +++++++++
 .../compatible/CompatibleEncryptorSubscriber.java  |  85 +++++++
 ...lCompatibleEncryptRuleConfigurationSwapper.java |  13 +-
 ...shardingsphere.infra.rule.RuleChangedSubscriber |   2 +
 ...ngsphere.mode.spi.RuleConfigurationEventBuilder |   1 +
 .../mask/metadata/converter/MaskNodeConverter.java |   6 +-
 .../converter/ReadwriteSplittingNodeConverter.java |   8 +-
 .../metadata/converter/ShadowNodeConverter.java    |   8 +-
 .../metadata/converter/ShardingNodeConverter.java  |  26 +-
 .../metadata/converter/RuleItemNodeConverter.java  |   2 +-
 .../metadata/converter/RuleRootNodeConverter.java  |   2 +-
 .../metadata/converter/SingleNodeConverter.java    |   4 +-
 .../src/main/resources/conf/config-sharding.yaml   | 262 ++++++++++++++-------
 .../bootstrap/src/main/resources/conf/server.yaml  |  40 ++--
 23 files changed, 626 insertions(+), 340 deletions(-)

diff --git a/features/broadcast/core/src/main/java/org/apache/shardingsphere/broadcast/metadata/converter/BroadcastNodeConverter.java b/features/broadcast/core/src/main/java/org/apache/shardingsphere/broadcast/metadata/converter/BroadcastNodeConverter.java
index bfe53b51817..cdd1d9aedfc 100644
--- a/features/broadcast/core/src/main/java/org/apache/shardingsphere/broadcast/metadata/converter/BroadcastNodeConverter.java
+++ b/features/broadcast/core/src/main/java/org/apache/shardingsphere/broadcast/metadata/converter/BroadcastNodeConverter.java
@@ -20,7 +20,6 @@ package org.apache.shardingsphere.broadcast.metadata.converter;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 
-import java.util.Optional;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -36,8 +35,6 @@ public final class BroadcastNodeConverter {
     
     private static final String RULES_NODE_PREFIX = "/([\\w\\-]+)/([\\w\\-]+)/rules/";
     
-    private static final String VERSION_PATH = "/([\\w\\-]+)/versions/(\\d+)";
-    
     private static final String RULE_ACTIVE_VERSION = "/active_version$";
     
     /**
@@ -56,7 +53,7 @@ public final class BroadcastNodeConverter {
      * @return true or false
      */
     public static boolean isBroadcastPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -72,16 +69,4 @@ public final class BroadcastNodeConverter {
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
-    
-    /**
-     * Get tables version.
-     *
-     * @param rulePath rule path
-     * @return tables version
-     */
-    public static Optional<String> getTablesVersion(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + TABLES_NODE + VERSION_PATH, Pattern.CASE_INSENSITIVE);
-        Matcher matcher = pattern.matcher(rulePath);
-        return matcher.find() ? Optional.of(matcher.group(4)) : Optional.empty();
-    }
 }
diff --git a/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java b/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
index be2fdf16e7a..4bc7b8fd766 100644
--- a/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
+++ b/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
@@ -20,18 +20,12 @@ package org.apache.shardingsphere.broadcast.metadata.coverter;
 import org.apache.shardingsphere.broadcast.metadata.converter.BroadcastNodeConverter;
 import org.junit.jupiter.api.Test;
 
-import java.util.Optional;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class BroadcastNodeConverterTest {
     
     @Test
-    void assertGetTablesVersion() {
-        Optional<String> actual = BroadcastNodeConverter.getTablesVersion("/metadata/foo_db/rules/broadcast/tables/foo/versions/1");
-        assertTrue(actual.isPresent());
-        assertThat(actual.get(), is("1"));
+    void assertIsTablesActiveVersionPath() {
+        assertTrue(BroadcastNodeConverter.isTablesActiveVersionPath("/metadata/foo_db/rules/broadcast/tables/active_version"));
     }
 }
diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/CompatibleEncryptRuleConfigurationEventBuilder.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/CompatibleEncryptRuleConfigurationEventBuilder.java
new file mode 100644
index 00000000000..98f2c4c4198
--- /dev/null
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/CompatibleEncryptRuleConfigurationEventBuilder.java
@@ -0,0 +1,73 @@
+/*
+ * 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.encrypt.event;
+
+import com.google.common.base.Strings;
+import org.apache.shardingsphere.encrypt.event.compatible.encryptor.AlterCompatibleEncryptorEvent;
+import org.apache.shardingsphere.encrypt.event.compatible.encryptor.DeleteCompatibleEncryptorEvent;
+import org.apache.shardingsphere.encrypt.event.compatible.table.AddCompatibleEncryptTableEvent;
+import org.apache.shardingsphere.encrypt.event.compatible.table.AlterCompatibleEncryptTableEvent;
+import org.apache.shardingsphere.encrypt.event.compatible.table.DeleteCompatibleEncryptTableEvent;
+import org.apache.shardingsphere.encrypt.metadata.converter.CompatibleEncryptNodeConverter;
+import org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
+import org.apache.shardingsphere.mode.event.DataChangedEvent;
+import org.apache.shardingsphere.mode.event.DataChangedEvent.Type;
+import org.apache.shardingsphere.mode.spi.RuleConfigurationEventBuilder;
+
+import java.util.Optional;
+
+/**
+ * Compatible encrypt rule configuration event builder.
+ * @deprecated compatible support will remove in next version.
+ */
+@Deprecated
+public final class CompatibleEncryptRuleConfigurationEventBuilder implements RuleConfigurationEventBuilder {
+    
+    @Override
+    public Optional<GovernanceEvent> build(final String databaseName, final DataChangedEvent event) {
+        if (!CompatibleEncryptNodeConverter.getRuleRootNodeConverter().isRulePath(event.getKey()) || Strings.isNullOrEmpty(event.getValue())) {
+            return Optional.empty();
+        }
+        Optional<String> tableName = CompatibleEncryptNodeConverter.getTableNodeConvertor().getNameByActiveVersionPath(event.getKey());
+        if (tableName.isPresent() && !Strings.isNullOrEmpty(event.getValue())) {
+            return createEncryptConfigEvent(databaseName, tableName.get(), event);
+        }
+        Optional<String> encryptorName = CompatibleEncryptNodeConverter.getEncryptorNodeConvertor().getNameByActiveVersionPath(event.getKey());
+        if (encryptorName.isPresent() && !Strings.isNullOrEmpty(event.getValue())) {
+            return createEncryptorEvent(databaseName, encryptorName.get(), event);
+        }
+        return Optional.empty();
+    }
+    
+    private Optional<GovernanceEvent> createEncryptConfigEvent(final String databaseName, final String groupName, final DataChangedEvent event) {
+        if (Type.ADDED == event.getType()) {
+            return Optional.of(new AddCompatibleEncryptTableEvent(databaseName, event.getKey(), event.getValue()));
+        }
+        if (Type.UPDATED == event.getType()) {
+            return Optional.of(new AlterCompatibleEncryptTableEvent(databaseName, groupName, event.getKey(), event.getValue()));
+        }
+        return Optional.of(new DeleteCompatibleEncryptTableEvent(databaseName, groupName, event.getKey(), event.getValue()));
+    }
+    
+    private Optional<GovernanceEvent> createEncryptorEvent(final String databaseName, final String encryptorName, final DataChangedEvent event) {
+        if (Type.ADDED == event.getType() || Type.UPDATED == event.getType()) {
+            return Optional.of(new AlterCompatibleEncryptorEvent(databaseName, encryptorName, event.getKey(), event.getValue()));
+        }
+        return Optional.of(new DeleteCompatibleEncryptorEvent(databaseName, encryptorName, event.getKey(), event.getValue()));
+    }
+}
diff --git a/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/encryptor/AlterCompatibleEncryptorEvent.java
similarity index 54%
copy from features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
copy to features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/encryptor/AlterCompatibleEncryptorEvent.java
index be2fdf16e7a..c030368d348 100644
--- a/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/encryptor/AlterCompatibleEncryptorEvent.java
@@ -15,23 +15,26 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.broadcast.metadata.coverter;
+package org.apache.shardingsphere.encrypt.event.compatible.encryptor;
 
-import org.apache.shardingsphere.broadcast.metadata.converter.BroadcastNodeConverter;
-import org.junit.jupiter.api.Test;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
 
-import java.util.Optional;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-class BroadcastNodeConverterTest {
+/**
+ * Alter compatible encryptor event.
+ * @deprecated compatible support will remove in next version.
+ */
+@Deprecated
+@RequiredArgsConstructor
+@Getter
+public final class AlterCompatibleEncryptorEvent implements GovernanceEvent {
+    
+    private final String databaseName;
+    
+    private final String encryptorName;
+    
+    private final String activeVersionKey;
     
-    @Test
-    void assertGetTablesVersion() {
-        Optional<String> actual = BroadcastNodeConverter.getTablesVersion("/metadata/foo_db/rules/broadcast/tables/foo/versions/1");
-        assertTrue(actual.isPresent());
-        assertThat(actual.get(), is("1"));
-    }
+    private final String activeVersion;
 }
diff --git a/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/encryptor/DeleteCompatibleEncryptorEvent.java
similarity index 54%
copy from features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
copy to features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/encryptor/DeleteCompatibleEncryptorEvent.java
index be2fdf16e7a..025c0d098af 100644
--- a/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/encryptor/DeleteCompatibleEncryptorEvent.java
@@ -15,23 +15,26 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.broadcast.metadata.coverter;
+package org.apache.shardingsphere.encrypt.event.compatible.encryptor;
 
-import org.apache.shardingsphere.broadcast.metadata.converter.BroadcastNodeConverter;
-import org.junit.jupiter.api.Test;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
 
-import java.util.Optional;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-class BroadcastNodeConverterTest {
+/**
+ * Delete compatible encryptor event.
+ * @deprecated compatible support will remove in next version.
+ */
+@Deprecated
+@RequiredArgsConstructor
+@Getter
+public final class DeleteCompatibleEncryptorEvent implements GovernanceEvent {
+    
+    private final String databaseName;
+    
+    private final String encryptorName;
+    
+    private final String activeVersionKey;
     
-    @Test
-    void assertGetTablesVersion() {
-        Optional<String> actual = BroadcastNodeConverter.getTablesVersion("/metadata/foo_db/rules/broadcast/tables/foo/versions/1");
-        assertTrue(actual.isPresent());
-        assertThat(actual.get(), is("1"));
-    }
+    private final String activeVersion;
 }
diff --git a/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/table/AddCompatibleEncryptTableEvent.java
similarity index 54%
copy from features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
copy to features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/table/AddCompatibleEncryptTableEvent.java
index be2fdf16e7a..e07079a9d2e 100644
--- a/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/table/AddCompatibleEncryptTableEvent.java
@@ -15,23 +15,24 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.broadcast.metadata.coverter;
+package org.apache.shardingsphere.encrypt.event.compatible.table;
 
-import org.apache.shardingsphere.broadcast.metadata.converter.BroadcastNodeConverter;
-import org.junit.jupiter.api.Test;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
 
-import java.util.Optional;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-class BroadcastNodeConverterTest {
+/**
+ * Add compatible encrypt table event.
+ * @deprecated compatible support will remove in next version.
+ */
+@Deprecated
+@RequiredArgsConstructor
+@Getter
+public final class AddCompatibleEncryptTableEvent implements GovernanceEvent {
+    
+    private final String databaseName;
+    
+    private final String activeVersionKey;
     
-    @Test
-    void assertGetTablesVersion() {
-        Optional<String> actual = BroadcastNodeConverter.getTablesVersion("/metadata/foo_db/rules/broadcast/tables/foo/versions/1");
-        assertTrue(actual.isPresent());
-        assertThat(actual.get(), is("1"));
-    }
+    private final String activeVersion;
 }
diff --git a/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/table/AlterCompatibleEncryptTableEvent.java
similarity index 54%
copy from features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
copy to features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/table/AlterCompatibleEncryptTableEvent.java
index be2fdf16e7a..c248920bf65 100644
--- a/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/table/AlterCompatibleEncryptTableEvent.java
@@ -15,23 +15,26 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.broadcast.metadata.coverter;
+package org.apache.shardingsphere.encrypt.event.compatible.table;
 
-import org.apache.shardingsphere.broadcast.metadata.converter.BroadcastNodeConverter;
-import org.junit.jupiter.api.Test;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
 
-import java.util.Optional;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-class BroadcastNodeConverterTest {
+/**
+ * Alter compatible encrypt table event.
+ * @deprecated compatible support will remove in next version.
+ */
+@Deprecated
+@RequiredArgsConstructor
+@Getter
+public final class AlterCompatibleEncryptTableEvent implements GovernanceEvent {
+    
+    private final String databaseName;
+    
+    private final String tableName;
+    
+    private final String activeVersionKey;
     
-    @Test
-    void assertGetTablesVersion() {
-        Optional<String> actual = BroadcastNodeConverter.getTablesVersion("/metadata/foo_db/rules/broadcast/tables/foo/versions/1");
-        assertTrue(actual.isPresent());
-        assertThat(actual.get(), is("1"));
-    }
+    private final String activeVersion;
 }
diff --git a/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/table/DeleteCompatibleEncryptTableEvent.java
similarity index 54%
copy from features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
copy to features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/table/DeleteCompatibleEncryptTableEvent.java
index be2fdf16e7a..adbb4f0b157 100644
--- a/features/broadcast/core/src/test/java/org/apache/shardingsphere/broadcast/metadata/coverter/BroadcastNodeConverterTest.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/event/compatible/table/DeleteCompatibleEncryptTableEvent.java
@@ -15,23 +15,26 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.broadcast.metadata.coverter;
+package org.apache.shardingsphere.encrypt.event.compatible.table;
 
-import org.apache.shardingsphere.broadcast.metadata.converter.BroadcastNodeConverter;
-import org.junit.jupiter.api.Test;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.rule.event.GovernanceEvent;
 
-import java.util.Optional;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-class BroadcastNodeConverterTest {
+/**
+ * Delete compatible encrypt table event.
+ * @deprecated compatible support will remove in next version.
+ */
+@Deprecated
+@RequiredArgsConstructor
+@Getter
+public final class DeleteCompatibleEncryptTableEvent implements GovernanceEvent {
+    
+    private final String databaseName;
+    
+    private final String tableName;
+    
+    private final String activeVersionKey;
     
-    @Test
-    void assertGetTablesVersion() {
-        Optional<String> actual = BroadcastNodeConverter.getTablesVersion("/metadata/foo_db/rules/broadcast/tables/foo/versions/1");
-        assertTrue(actual.isPresent());
-        assertThat(actual.get(), is("1"));
-    }
+    private final String activeVersion;
 }
diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/converter/CompatibleEncryptNodeConverter.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/converter/CompatibleEncryptNodeConverter.java
index c1d2ae56a8f..c26591d6c97 100644
--- a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/converter/CompatibleEncryptNodeConverter.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/metadata/converter/CompatibleEncryptNodeConverter.java
@@ -19,10 +19,8 @@ package org.apache.shardingsphere.encrypt.metadata.converter;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-
-import java.util.Optional;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import org.apache.shardingsphere.infra.metadata.converter.RuleItemNodeConverter;
+import org.apache.shardingsphere.infra.metadata.converter.RuleRootNodeConverter;
 
 /**
  * Compatible encrypt node converter.
@@ -32,119 +30,36 @@ import java.util.regex.Pattern;
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
 public final class CompatibleEncryptNodeConverter {
     
-    private static final String ROOT_NODE = "compatible_encrypt";
-    
-    private static final String TABLES_NODE = "tables";
-    
-    private static final String ENCRYPTORS_NODE = "encryptors";
-    
-    private static final String RULES_NODE_PREFIX = "/([\\w\\-]+)/([\\w\\-]+)/rules/";
-    
-    private static final String RULE_NAME_PATTERN = "/([\\w\\-]+)?";
+    private static final RuleRootNodeConverter ROOT_NODE_CONVERTER = new RuleRootNodeConverter("compatible_encrypt");
     
-    private static final String RULE_VERSION = "/([\\w\\-]+)/versions/([\\w\\-]+)$";
+    private static final RuleItemNodeConverter TABLE_NODE_CONVERTER = new RuleItemNodeConverter(ROOT_NODE_CONVERTER, "tables");
     
-    /**
-     * Get table name path.
-     *
-     * @param tableName table name
-     * @return table name path
-     */
-    public static String getTableNamePath(final String tableName) {
-        return String.join("/", TABLES_NODE, tableName);
-    }
+    private static final RuleItemNodeConverter ENCRYPTOR_NODE_CONVERTER = new RuleItemNodeConverter(ROOT_NODE_CONVERTER, "encryptors");
     
     /**
-     * Get encryptor path.
+     * Get rule root node converter.
      *
-     * @param encryptorName encryptor name
-     * @return encryptor path
+     * @return rule root node converter
      */
-    public static String getEncryptorPath(final String encryptorName) {
-        return String.join("/", ENCRYPTORS_NODE, encryptorName);
+    public static RuleRootNodeConverter getRuleRootNodeConverter() {
+        return ROOT_NODE_CONVERTER;
     }
     
     /**
-     * Is encrypt path.
+     * Get table node convertor.
      *
-     * @param rulePath rule path
-     * @return true or false
-     */
-    public static boolean isEncryptPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
-        Matcher matcher = pattern.matcher(rulePath);
-        return matcher.find();
-    }
-    
-    /**
-     * Is encrypt table path.
-     *
-     * @param rulePath rule path
-     * @return true or false
-     */
-    public static boolean isTablePath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + TABLES_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
-        Matcher matcher = pattern.matcher(rulePath);
-        return matcher.find();
-    }
-    
-    /**
-     * Is encryptor path.
-     *
-     * @param rulePath rule path
-     * @return true or false
-     */
-    public static boolean isEncryptorPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + ENCRYPTORS_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
-        Matcher matcher = pattern.matcher(rulePath);
-        return matcher.find();
-    }
-    
-    /**
-     * Get table name.
-     *
-     * @param rulePath rule path
-     * @return table name
-     */
-    public static Optional<String> getTableName(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + TABLES_NODE + RULE_NAME_PATTERN, Pattern.CASE_INSENSITIVE);
-        Matcher matcher = pattern.matcher(rulePath);
-        return matcher.find() ? Optional.of(matcher.group(3)) : Optional.empty();
-    }
-    
-    /**
-     *  Get encryptor name.
-     *
-     * @param rulePath rule path
-     * @return encryptor name
-     */
-    public static Optional<String> getEncryptorName(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + ENCRYPTORS_NODE + RULE_NAME_PATTERN, Pattern.CASE_INSENSITIVE);
-        Matcher matcher = pattern.matcher(rulePath);
-        return matcher.find() ? Optional.of(matcher.group(3)) : Optional.empty();
-    }
-    
-    /**
-     * Get encrypt table version.
-     * 
-     * @param rulePath rule path
-     * @return encrypt table version
+     * @return table node convertor
      */
-    public static Optional<String> getEncryptTableVersion(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + TABLES_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
-        Matcher matcher = pattern.matcher(rulePath);
-        return matcher.find() ? Optional.of(matcher.group(4)) : Optional.empty();
+    public static RuleItemNodeConverter getTableNodeConvertor() {
+        return TABLE_NODE_CONVERTER;
     }
     
     /**
-     * Get encryptor version.
+     * Get encryptor node convertor.
      *
-     * @param rulePath rule path
-     * @return encryptor version
+     * @return encryptor node convertor
      */
-    public static Optional<String> getEncryptorVersion(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + ENCRYPTORS_NODE + RULE_VERSION, Pattern.CASE_INSENSITIVE);
-        Matcher matcher = pattern.matcher(rulePath);
-        return matcher.find() ? Optional.of(matcher.group(4)) : Optional.empty();
+    public static RuleItemNodeConverter getEncryptorNodeConvertor() {
+        return ENCRYPTOR_NODE_CONVERTER;
     }
 }
diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/subscriber/compatible/CompatibleEncryptTableSubscriber.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/subscriber/compatible/CompatibleEncryptTableSubscriber.java
new file mode 100644
index 00000000000..8fca3ccb9a6
--- /dev/null
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/subscriber/compatible/CompatibleEncryptTableSubscriber.java
@@ -0,0 +1,115 @@
+/*
+ * 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.encrypt.subscriber.compatible;
+
+import com.google.common.eventbus.Subscribe;
+import lombok.Setter;
+import org.apache.shardingsphere.encrypt.api.config.CompatibleEncryptRuleConfiguration;
+import org.apache.shardingsphere.encrypt.api.config.rule.EncryptTableRuleConfiguration;
+import org.apache.shardingsphere.encrypt.event.compatible.table.AddCompatibleEncryptTableEvent;
+import org.apache.shardingsphere.encrypt.event.compatible.table.AlterCompatibleEncryptTableEvent;
+import org.apache.shardingsphere.encrypt.event.compatible.table.DeleteCompatibleEncryptTableEvent;
+import org.apache.shardingsphere.encrypt.rule.EncryptRule;
+import org.apache.shardingsphere.encrypt.yaml.config.rule.YamlEncryptTableRuleConfiguration;
+import org.apache.shardingsphere.encrypt.yaml.swapper.rule.YamlEncryptTableRuleConfigurationSwapper;
+import org.apache.shardingsphere.infra.instance.InstanceContext;
+import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.rule.RuleChangedSubscriber;
+import org.apache.shardingsphere.infra.util.yaml.YamlEngine;
+import org.apache.shardingsphere.mode.event.config.DatabaseRuleConfigurationChangedEvent;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * Compatible encrypt table subscriber.
+ * @deprecated compatible support will remove in next version.
+ */
+@Deprecated
+@SuppressWarnings("UnstableApiUsage")
+@Setter
+public final class CompatibleEncryptTableSubscriber implements RuleChangedSubscriber {
+    
+    private Map<String, ShardingSphereDatabase> databases;
+    
+    private InstanceContext instanceContext;
+    
+    /**
+     * Renew with add encrypt configuration.
+     *
+     * @param event add encrypt configuration event
+     */
+    @Subscribe
+    public synchronized void renew(final AddCompatibleEncryptTableEvent event) {
+        if (!event.getActiveVersion().equals(instanceContext.getModeContextManager().getActiveVersionByKey(event.getActiveVersionKey()))) {
+            return;
+        }
+        ShardingSphereDatabase database = databases.get(event.getDatabaseName());
+        EncryptTableRuleConfiguration needToAddedConfig = swapEncryptTableRuleConfig(
+                instanceContext.getModeContextManager().getVersionPathByActiveVersionKey(event.getActiveVersionKey(), event.getActiveVersion()));
+        Optional<EncryptRule> rule = database.getRuleMetaData().findSingleRule(EncryptRule.class);
+        CompatibleEncryptRuleConfiguration config;
+        if (rule.isPresent()) {
+            config = (CompatibleEncryptRuleConfiguration) rule.get().getConfiguration();
+            config.getTables().add(needToAddedConfig);
+        } else {
+            config = new CompatibleEncryptRuleConfiguration(Collections.singletonList(needToAddedConfig), Collections.emptyMap());
+        }
+        instanceContext.getEventBusContext().post(new DatabaseRuleConfigurationChangedEvent(event.getDatabaseName(), config));
+    }
+    
+    /**
+     * Renew with alter encrypt configuration.
+     *
+     * @param event alter encrypt configuration event
+     */
+    @Subscribe
+    public synchronized void renew(final AlterCompatibleEncryptTableEvent event) {
+        if (!event.getActiveVersion().equals(instanceContext.getModeContextManager().getActiveVersionByKey(event.getActiveVersionKey()))) {
+            return;
+        }
+        ShardingSphereDatabase database = databases.get(event.getDatabaseName());
+        EncryptTableRuleConfiguration needToAlteredConfig = swapEncryptTableRuleConfig(
+                instanceContext.getModeContextManager().getVersionPathByActiveVersionKey(event.getActiveVersionKey(), event.getActiveVersion()));
+        CompatibleEncryptRuleConfiguration config = (CompatibleEncryptRuleConfiguration) database.getRuleMetaData().getSingleRule(EncryptRule.class).getConfiguration();
+        config.getTables().removeIf(each -> each.getName().equals(event.getTableName()));
+        config.getTables().add(needToAlteredConfig);
+        instanceContext.getEventBusContext().post(new DatabaseRuleConfigurationChangedEvent(event.getDatabaseName(), config));
+    }
+    
+    /**
+     * Renew with delete encrypt configuration.
+     *
+     * @param event delete encrypt configuration event
+     */
+    @Subscribe
+    public synchronized void renew(final DeleteCompatibleEncryptTableEvent event) {
+        if (!event.getActiveVersion().equals(instanceContext.getModeContextManager().getActiveVersionByKey(event.getActiveVersionKey()))) {
+            return;
+        }
+        ShardingSphereDatabase database = databases.get(event.getDatabaseName());
+        CompatibleEncryptRuleConfiguration config = (CompatibleEncryptRuleConfiguration) database.getRuleMetaData().getSingleRule(EncryptRule.class).getConfiguration();
+        config.getTables().removeIf(each -> each.getName().equals(event.getTableName()));
+        instanceContext.getEventBusContext().post(new DatabaseRuleConfigurationChangedEvent(event.getDatabaseName(), config));
+    }
+    
+    private EncryptTableRuleConfiguration swapEncryptTableRuleConfig(final String yamlContext) {
+        return new YamlEncryptTableRuleConfigurationSwapper().swapToObject(YamlEngine.unmarshal(yamlContext, YamlEncryptTableRuleConfiguration.class));
+    }
+}
diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/subscriber/compatible/CompatibleEncryptorSubscriber.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/subscriber/compatible/CompatibleEncryptorSubscriber.java
new file mode 100644
index 00000000000..5bf08d9722d
--- /dev/null
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/subscriber/compatible/CompatibleEncryptorSubscriber.java
@@ -0,0 +1,85 @@
+/*
+ * 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.encrypt.subscriber.compatible;
+
+import com.google.common.eventbus.Subscribe;
+import lombok.Setter;
+import org.apache.shardingsphere.encrypt.api.config.CompatibleEncryptRuleConfiguration;
+import org.apache.shardingsphere.encrypt.event.compatible.encryptor.AlterCompatibleEncryptorEvent;
+import org.apache.shardingsphere.encrypt.event.compatible.encryptor.DeleteCompatibleEncryptorEvent;
+import org.apache.shardingsphere.encrypt.rule.EncryptRule;
+import org.apache.shardingsphere.infra.config.algorithm.AlgorithmConfiguration;
+import org.apache.shardingsphere.infra.instance.InstanceContext;
+import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.rule.RuleChangedSubscriber;
+import org.apache.shardingsphere.infra.util.yaml.YamlEngine;
+import org.apache.shardingsphere.infra.yaml.config.pojo.algorithm.YamlAlgorithmConfiguration;
+import org.apache.shardingsphere.infra.yaml.config.swapper.algorithm.YamlAlgorithmConfigurationSwapper;
+import org.apache.shardingsphere.mode.event.config.DatabaseRuleConfigurationChangedEvent;
+
+import java.util.Map;
+
+/**
+ * Compatible encrypt encryptor subscriber.
+ * @deprecated compatible support will remove in next version.
+ */
+@Deprecated
+@SuppressWarnings("UnstableApiUsage")
+@Setter
+public final class CompatibleEncryptorSubscriber implements RuleChangedSubscriber {
+    
+    private Map<String, ShardingSphereDatabase> databases;
+    
+    private InstanceContext instanceContext;
+    
+    /**
+     * Renew with alter encryptor.
+     *
+     * @param event alter encryptor event
+     */
+    @Subscribe
+    public synchronized void renew(final AlterCompatibleEncryptorEvent event) {
+        if (!event.getActiveVersion().equals(instanceContext.getModeContextManager().getActiveVersionByKey(event.getActiveVersionKey()))) {
+            return;
+        }
+        ShardingSphereDatabase database = databases.get(event.getDatabaseName());
+        CompatibleEncryptRuleConfiguration config = (CompatibleEncryptRuleConfiguration) database.getRuleMetaData().getSingleRule(EncryptRule.class).getConfiguration();
+        config.getEncryptors().put(event.getEncryptorName(), swapToAlgorithmConfig(
+                instanceContext.getModeContextManager().getVersionPathByActiveVersionKey(event.getActiveVersionKey(), event.getActiveVersion())));
+    }
+    
+    /**
+     * Renew with delete encryptor.
+     *
+     * @param event delete encryptor event
+     */
+    @Subscribe
+    public synchronized void renew(final DeleteCompatibleEncryptorEvent event) {
+        if (!event.getActiveVersion().equals(instanceContext.getModeContextManager().getActiveVersionByKey(event.getActiveVersionKey()))) {
+            return;
+        }
+        ShardingSphereDatabase database = databases.get(event.getDatabaseName());
+        CompatibleEncryptRuleConfiguration config = (CompatibleEncryptRuleConfiguration) database.getRuleMetaData().getSingleRule(EncryptRule.class).getConfiguration();
+        config.getEncryptors().remove(event.getEncryptorName());
+        instanceContext.getEventBusContext().post(new DatabaseRuleConfigurationChangedEvent(event.getDatabaseName(), config));
+    }
+    
+    private AlgorithmConfiguration swapToAlgorithmConfig(final String yamlContext) {
+        return new YamlAlgorithmConfigurationSwapper().swapToObject(YamlEngine.unmarshal(yamlContext, YamlAlgorithmConfiguration.class));
+    }
+}
diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/yaml/swapper/NewYamlCompatibleEncryptRuleConfigurationSwapper.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/yaml/swapper/NewYamlCompatibleEncryptRuleConfigurationSwapper.java
index 94f121ccff1..67df1f4483c 100644
--- a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/yaml/swapper/NewYamlCompatibleEncryptRuleConfigurationSwapper.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/yaml/swapper/NewYamlCompatibleEncryptRuleConfigurationSwapper.java
@@ -54,10 +54,11 @@ public final class NewYamlCompatibleEncryptRuleConfigurationSwapper implements N
     public Collection<YamlDataNode> swapToDataNodes(final CompatibleEncryptRuleConfiguration data) {
         Collection<YamlDataNode> result = new LinkedHashSet<>();
         for (Entry<String, AlgorithmConfiguration> entry : data.getEncryptors().entrySet()) {
-            result.add(new YamlDataNode(CompatibleEncryptNodeConverter.getEncryptorPath(entry.getKey()), YamlEngine.marshal(algorithmSwapper.swapToYamlConfiguration(entry.getValue()))));
+            result.add(new YamlDataNode(CompatibleEncryptNodeConverter.getEncryptorNodeConvertor().getNamePath(entry.getKey()),
+                    YamlEngine.marshal(algorithmSwapper.swapToYamlConfiguration(entry.getValue()))));
         }
         for (EncryptTableRuleConfiguration each : data.getTables()) {
-            result.add(new YamlDataNode(CompatibleEncryptNodeConverter.getTableNamePath(each.getName()), YamlEngine.marshal(tableSwapper.swapToYamlConfiguration(each))));
+            result.add(new YamlDataNode(CompatibleEncryptNodeConverter.getTableNodeConvertor().getNamePath(each.getName()), YamlEngine.marshal(tableSwapper.swapToYamlConfiguration(each))));
         }
         return result;
     }
@@ -67,11 +68,11 @@ public final class NewYamlCompatibleEncryptRuleConfigurationSwapper implements N
         Collection<EncryptTableRuleConfiguration> tables = new LinkedList<>();
         Map<String, AlgorithmConfiguration> encryptors = new HashMap<>();
         for (YamlDataNode each : dataNodes) {
-            if (CompatibleEncryptNodeConverter.isTablePath(each.getKey())) {
-                CompatibleEncryptNodeConverter.getTableName(each.getKey())
+            if (CompatibleEncryptNodeConverter.getTableNodeConvertor().isPath(each.getKey())) {
+                CompatibleEncryptNodeConverter.getTableNodeConvertor().getName(each.getKey())
                         .ifPresent(tableName -> tables.add(tableSwapper.swapToObject(YamlEngine.unmarshal(each.getValue(), YamlCompatibleEncryptTableRuleConfiguration.class))));
-            } else if (CompatibleEncryptNodeConverter.isEncryptorPath(each.getKey())) {
-                CompatibleEncryptNodeConverter.getEncryptorName(each.getKey())
+            } else if (CompatibleEncryptNodeConverter.getEncryptorNodeConvertor().isPath(each.getKey())) {
+                CompatibleEncryptNodeConverter.getEncryptorNodeConvertor().getName(each.getKey())
                         .ifPresent(encryptorName -> encryptors.put(encryptorName, algorithmSwapper.swapToObject(YamlEngine.unmarshal(each.getValue(), YamlAlgorithmConfiguration.class))));
             }
         }
diff --git a/features/encrypt/core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.rule.RuleChangedSubscriber b/features/encrypt/core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.rule.RuleChangedSubscriber
index 212a192b7c6..d3c51493a97 100644
--- a/features/encrypt/core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.rule.RuleChangedSubscriber
+++ b/features/encrypt/core/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.rule.RuleChangedSubscriber
@@ -17,3 +17,5 @@
 
 org.apache.shardingsphere.encrypt.subscriber.EncryptTableSubscriber
 org.apache.shardingsphere.encrypt.subscriber.EncryptorSubscriber
+org.apache.shardingsphere.encrypt.subscriber.compatible.CompatibleEncryptTableSubscriber
+org.apache.shardingsphere.encrypt.subscriber.compatible.CompatibleEncryptorSubscriber
diff --git a/features/encrypt/core/src/main/resources/META-INF/services/org.apache.shardingsphere.mode.spi.RuleConfigurationEventBuilder b/features/encrypt/core/src/main/resources/META-INF/services/org.apache.shardingsphere.mode.spi.RuleConfigurationEventBuilder
index aefcf6ca88f..c9a02484a9e 100644
--- a/features/encrypt/core/src/main/resources/META-INF/services/org.apache.shardingsphere.mode.spi.RuleConfigurationEventBuilder
+++ b/features/encrypt/core/src/main/resources/META-INF/services/org.apache.shardingsphere.mode.spi.RuleConfigurationEventBuilder
@@ -16,3 +16,4 @@
 #
 
 org.apache.shardingsphere.encrypt.event.EncryptRuleConfigurationEventBuilder
+org.apache.shardingsphere.encrypt.event.CompatibleEncryptRuleConfigurationEventBuilder
diff --git a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/metadata/converter/MaskNodeConverter.java b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/metadata/converter/MaskNodeConverter.java
index fa021809e62..343bf83da51 100644
--- a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/metadata/converter/MaskNodeConverter.java
+++ b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/metadata/converter/MaskNodeConverter.java
@@ -69,7 +69,7 @@ public final class MaskNodeConverter {
      * @return true or false
      */
     public static boolean isMaskPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -81,7 +81,7 @@ public final class MaskNodeConverter {
      * @return true or false
      */
     public static boolean isTablePath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + TABLES_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + TABLES_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -93,7 +93,7 @@ public final class MaskNodeConverter {
      * @return true or false
      */
     public static boolean isAlgorithmPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + ALGORITHMS_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + ALGORITHMS_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
diff --git a/features/readwrite-splitting/core/src/main/java/org/apache/shardingsphere/readwritesplitting/metadata/converter/ReadwriteSplittingNodeConverter.java b/features/readwrite-splitting/core/src/main/java/org/apache/shardingsphere/readwritesplitting/metadata/converter/ReadwriteSplittingNodeConverter.java
index ea79cab81b2..b73a620a6e0 100644
--- a/features/readwrite-splitting/core/src/main/java/org/apache/shardingsphere/readwritesplitting/metadata/converter/ReadwriteSplittingNodeConverter.java
+++ b/features/readwrite-splitting/core/src/main/java/org/apache/shardingsphere/readwritesplitting/metadata/converter/ReadwriteSplittingNodeConverter.java
@@ -38,7 +38,7 @@ public final class ReadwriteSplittingNodeConverter {
     
     private static final String RULES_NODE_PREFIX = "/([\\w\\-]+)/([\\w\\-]+)/rules/";
     
-    private static final String RULE_NAME_PATTERN = "/([\\w\\-]+)/versions?";
+    private static final String RULE_NAME_PATTERN = "/([\\w\\-]+)?";
     
     private static final String RULE_ACTIVE_VERSION = "/([\\w\\-]+)/active_version$";
     
@@ -69,7 +69,7 @@ public final class ReadwriteSplittingNodeConverter {
      * @return true or false
      */
     public static boolean isReadwriteSplittingPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -81,7 +81,7 @@ public final class ReadwriteSplittingNodeConverter {
      * @return true or false
      */
     public static boolean isDataSourcePath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + DATA_SOURCES_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + DATA_SOURCES_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -93,7 +93,7 @@ public final class ReadwriteSplittingNodeConverter {
      * @return true or false
      */
     public static boolean isLoadBalancerPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + LOAD_BALANCER_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + LOAD_BALANCER_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/metadata/converter/ShadowNodeConverter.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/metadata/converter/ShadowNodeConverter.java
index 14f6bf9bf96..7391e65160d 100644
--- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/metadata/converter/ShadowNodeConverter.java
+++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/metadata/converter/ShadowNodeConverter.java
@@ -92,7 +92,7 @@ public final class ShadowNodeConverter {
      * @return true or false
      */
     public static boolean isShadowPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -104,7 +104,7 @@ public final class ShadowNodeConverter {
      * @return true or false
      */
     public static boolean isDataSourcePath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + DATA_SOURCES_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + DATA_SOURCES_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -116,7 +116,7 @@ public final class ShadowNodeConverter {
      * @return true or false
      */
     public static boolean isTablePath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + TABLES_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + TABLES_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -128,7 +128,7 @@ public final class ShadowNodeConverter {
      * @return true or false
      */
     public static boolean isAlgorithmPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + ALGORITHMS_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + ALGORITHMS_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
diff --git a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/metadata/converter/ShardingNodeConverter.java b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/metadata/converter/ShardingNodeConverter.java
index 5e41668ebb9..afa704f1ebe 100644
--- a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/metadata/converter/ShardingNodeConverter.java
+++ b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/metadata/converter/ShardingNodeConverter.java
@@ -187,7 +187,7 @@ public final class ShardingNodeConverter {
      * @return true or false
      */
     public static boolean isShardingPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -199,7 +199,7 @@ public final class ShardingNodeConverter {
      * @return true or false
      */
     public static boolean isTablePath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + TABLES_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + TABLES_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -211,7 +211,7 @@ public final class ShardingNodeConverter {
      * @return true or false
      */
     public static boolean isAutoTablePath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + AUTO_TABLES_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + AUTO_TABLES_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -223,7 +223,7 @@ public final class ShardingNodeConverter {
      * @return true or false
      */
     public static boolean isBindingTablePath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + BINDING_TABLES_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + BINDING_TABLES_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -295,7 +295,7 @@ public final class ShardingNodeConverter {
      * @return true or false
      */
     public static boolean isShardingAlgorithmPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + SHARDING_ALGORITHMS_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + SHARDING_ALGORITHMS_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -307,7 +307,7 @@ public final class ShardingNodeConverter {
      * @return true or false
      */
     public static boolean isKeyGeneratorPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + KEY_GENERATORS_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + KEY_GENERATORS_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -319,7 +319,7 @@ public final class ShardingNodeConverter {
      * @return true or false
      */
     public static boolean isAuditorPath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + AUDITORS_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + AUDITORS_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
@@ -412,7 +412,7 @@ public final class ShardingNodeConverter {
      * Get table name by active version path.
      *
      * @param activeVersionPath active version path
-     * @return table name version
+     * @return table name
      */
     public static Optional<String> getTableNameByActiveVersionPath(final String activeVersionPath) {
         Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + TABLES_NODE + RULE_ACTIVE_VERSION, Pattern.CASE_INSENSITIVE);
@@ -424,7 +424,7 @@ public final class ShardingNodeConverter {
      * Get auto table name by active version path.
      *
      * @param activeVersionPath active version path
-     * @return auto table name version
+     * @return auto table name
      */
     public static Optional<String> getAutoTableNameByActiveVersionPath(final String activeVersionPath) {
         Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + AUTO_TABLES_NODE + RULE_ACTIVE_VERSION, Pattern.CASE_INSENSITIVE);
@@ -436,7 +436,7 @@ public final class ShardingNodeConverter {
      * Get binding table name by active version path.
      *
      * @param activeVersionPath active version path
-     * @return binding table name version
+     * @return binding table name
      */
     public static Optional<String> getBindingTableNameByActiveVersionPath(final String activeVersionPath) {
         Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + BINDING_TABLES_NODE + RULE_ACTIVE_VERSION, Pattern.CASE_INSENSITIVE);
@@ -508,7 +508,7 @@ public final class ShardingNodeConverter {
      * Get sharding algorithm name by active version path.
      *
      * @param activeVersionPath active version path
-     * @return sharding algorithm version
+     * @return sharding algorithm name
      */
     public static Optional<String> getShardingAlgorithmNameByActiveVersionPath(final String activeVersionPath) {
         Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + SHARDING_ALGORITHMS_NODE + RULE_ACTIVE_VERSION, Pattern.CASE_INSENSITIVE);
@@ -520,7 +520,7 @@ public final class ShardingNodeConverter {
      * Get key generator name by active version path.
      *
      * @param activeVersionPath active version path
-     * @return key generator version
+     * @return key generator name
      */
     public static Optional<String> getKeyGeneratorNameByActiveVersionPath(final String activeVersionPath) {
         Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + KEY_GENERATORS_NODE + RULE_ACTIVE_VERSION, Pattern.CASE_INSENSITIVE);
@@ -532,7 +532,7 @@ public final class ShardingNodeConverter {
      * Get auditor name by active version path.
      *
      * @param activeVersionPath active version path
-     * @return auditor version
+     * @return auditor name
      */
     public static Optional<String> getAuditorNameByActiveVersionPath(final String activeVersionPath) {
         Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/" + AUDITORS_NODE + RULE_ACTIVE_VERSION, Pattern.CASE_INSENSITIVE);
diff --git a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/converter/RuleItemNodeConverter.java b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/converter/RuleItemNodeConverter.java
index 2b3ededfed5..5220e5c5d13 100644
--- a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/converter/RuleItemNodeConverter.java
+++ b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/converter/RuleItemNodeConverter.java
@@ -40,7 +40,7 @@ public final class RuleItemNodeConverter {
     
     public RuleItemNodeConverter(final RuleRootNodeConverter ruleRootNodeConverter, final String itemsNode) {
         this.itemsNode = itemsNode;
-        itemsPathPattern = Pattern.compile(ruleRootNodeConverter.getRuleNodePrefix() + "/" + itemsNode + "\\.*", Pattern.CASE_INSENSITIVE);
+        itemsPathPattern = Pattern.compile(ruleRootNodeConverter.getRuleNodePrefix() + "/" + itemsNode + "/.*", Pattern.CASE_INSENSITIVE);
         itemNamePathPattern = Pattern.compile(ruleRootNodeConverter.getRuleNodePrefix() + "/" + itemsNode + RULE_NAME, Pattern.CASE_INSENSITIVE);
         itemVersionPathPattern = Pattern.compile(ruleRootNodeConverter.getRuleNodePrefix() + "/" + itemsNode + RULE_ACTIVE_VERSION, Pattern.CASE_INSENSITIVE);
     }
diff --git a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/converter/RuleRootNodeConverter.java b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/converter/RuleRootNodeConverter.java
index e891378ddba..9cf21f10834 100644
--- a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/converter/RuleRootNodeConverter.java
+++ b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/converter/RuleRootNodeConverter.java
@@ -35,7 +35,7 @@ public final class RuleRootNodeConverter {
     
     public RuleRootNodeConverter(final String ruleType) {
         ruleNodePrefix = RULE_NODE_PREFIX + ruleType;
-        rulePathPattern = Pattern.compile(ruleNodePrefix + "\\.*", Pattern.CASE_INSENSITIVE);
+        rulePathPattern = Pattern.compile(ruleNodePrefix + "/.*", Pattern.CASE_INSENSITIVE);
     }
     
     /**
diff --git a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/metadata/converter/SingleNodeConverter.java b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/metadata/converter/SingleNodeConverter.java
index 32fe7c9d4aa..14de346003d 100644
--- a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/metadata/converter/SingleNodeConverter.java
+++ b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/metadata/converter/SingleNodeConverter.java
@@ -35,8 +35,6 @@ public final class SingleNodeConverter {
     
     private static final String RULES_NODE_PREFIX = "/([\\w\\-]+)/([\\w\\-]+)/rules/";
     
-    private static final String VERSION_PATTERN = "/versions/\\d+";
-    
     private static final String RULE_ACTIVE_VERSION = "/active_version$";
     
     /**
@@ -55,7 +53,7 @@ public final class SingleNodeConverter {
      * @return true or false
      */
     public static boolean isSinglePath(final String rulePath) {
-        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "\\.*", Pattern.CASE_INSENSITIVE);
+        Pattern pattern = Pattern.compile(RULES_NODE_PREFIX + ROOT_NODE + "/.*", Pattern.CASE_INSENSITIVE);
         Matcher matcher = pattern.matcher(rulePath);
         return matcher.find();
     }
diff --git a/proxy/bootstrap/src/main/resources/conf/config-sharding.yaml b/proxy/bootstrap/src/main/resources/conf/config-sharding.yaml
index 8c27e5fa20a..d77bdce1d39 100644
--- a/proxy/bootstrap/src/main/resources/conf/config-sharding.yaml
+++ b/proxy/bootstrap/src/main/resources/conf/config-sharding.yaml
@@ -110,84 +110,188 @@
 #
 ######################################################################################################
 
-#databaseName: sharding_db
-#
-#dataSources:
-#  ds_0:
-#    url: jdbc:mysql://127.0.0.1:3306/demo_ds_0?serverTimezone=UTC&useSSL=false
-#    username: root
-#    password:
-#    connectionTimeoutMilliseconds: 30000
-#    idleTimeoutMilliseconds: 60000
-#    maxLifetimeMilliseconds: 1800000
-#    maxPoolSize: 50
-#    minPoolSize: 1
-#  ds_1:
-#    url: jdbc:mysql://127.0.0.1:3306/demo_ds_1?serverTimezone=UTC&useSSL=false
-#    username: root
-#    password:
-#    connectionTimeoutMilliseconds: 30000
-#    idleTimeoutMilliseconds: 60000
-#    maxLifetimeMilliseconds: 1800000
-#    maxPoolSize: 50
-#    minPoolSize: 1
-#
-#rules:
-#- !SHARDING
+databaseName: sharding_db
+
+dataSources:
+  ds_0:
+    url: jdbc:mysql://127.0.0.1:3306/demo_ds_0?serverTimezone=UTC&useSSL=false
+    username: root
+    password: 123456
+    connectionTimeoutMilliseconds: 30000
+    idleTimeoutMilliseconds: 60000
+    maxLifetimeMilliseconds: 1800000
+    maxPoolSize: 50
+    minPoolSize: 1
+  ds_1:
+    url: jdbc:mysql://127.0.0.1:3306/demo_ds_1?serverTimezone=UTC&useSSL=false
+    username: root
+    password: 123456
+    connectionTimeoutMilliseconds: 30000
+    idleTimeoutMilliseconds: 60000
+    maxLifetimeMilliseconds: 1800000
+    maxPoolSize: 50
+    minPoolSize: 1
+  ds_2:
+    url: jdbc:mysql://127.0.0.1:3306/demo_ds_2?serverTimezone=UTC&useSSL=false
+    username: root
+    password: 123456
+    connectionTimeoutMilliseconds: 30000
+    idleTimeoutMilliseconds: 60000
+    maxLifetimeMilliseconds: 1800000
+    maxPoolSize: 50
+    minPoolSize: 1
+
+rules:
+- !SHARDING
+  tables:
+    t_order:
+      actualDataNodes: ds_${0..1}.t_order_${0..1}
+      tableStrategy:
+        standard:
+          shardingColumn: order_id
+          shardingAlgorithmName: t_order_inline
+      keyGenerateStrategy:
+        column: order_id
+        keyGeneratorName: snowflake
+      auditStrategy:
+        auditorNames:
+          - sharding_key_required_auditor
+        allowHintDisable: true
+    t_order_item:
+      actualDataNodes: ds_${0..1}.t_order_item_${0..1}
+      tableStrategy:
+        standard:
+          shardingColumn: order_id
+          shardingAlgorithmName: t_order_item_inline
+      keyGenerateStrategy:
+        column: order_item_id
+        keyGeneratorName: snowflake
+  defaultDatabaseStrategy:
+    standard:
+      shardingColumn: user_id
+      shardingAlgorithmName: database_inline
+  defaultTableStrategy:
+    none:
+  defaultAuditStrategy:
+    auditorNames:
+      - sharding_key_required_auditor
+    allowHintDisable: true
+
+  shardingAlgorithms:
+    database_inline:
+      type: INLINE
+      props:
+        algorithm-expression: ds_${user_id % 2}
+    t_order_inline:
+      type: INLINE
+      props:
+        algorithm-expression: t_order_${order_id % 2}
+    t_order_item_inline:
+      type: INLINE
+      props:
+        algorithm-expression: t_order_item_${order_id % 2}
+
+  keyGenerators:
+    snowflake:
+      type: SNOWFLAKE
+
+  auditors:
+    sharding_key_required_auditor:
+      type: DML_SHARDING_CONDITIONS
+- !READWRITE_SPLITTING
+  dataSources:
+    readwrite_ds:
+      writeDataSourceName: ds_0
+      readDataSourceNames:
+        - ds_1
+        - ds_2
+      loadBalancerName: random2
+  loadBalancers:
+    random2:
+      type: RANDOM
+    readwrite_ds_random2:
+      type: RANDOM
+- !MASK
+  tables:
+    t_order:
+      columns:
+        password:
+          maskAlgorithm: md5_mask
+        email:
+          maskAlgorithm: mask_before_special_chars_mask
+        telephone:
+          maskAlgorithm: keep_first_n_last_m_mask
+
+  maskAlgorithms:
+    md5_mask:
+      type: MD5
+    mask_before_special_chars_mask:
+      type: MASK_BEFORE_SPECIAL_CHARS
+      props:
+        special-chars: '@'
+        replace-char: '*'
+    keep_first_n_last_m_mask:
+      type: KEEP_FIRST_N_LAST_M
+      props:
+        first-n: 3
+        last-m: 4
+        replace-char: '*'
+- !ENCRYPT
+  tables:
+    t_order:
+      columns:
+        username:
+          cipher:
+            name: username
+            encryptorName: aes_encryptor
+          assistedQuery:
+            name: assisted_query_username
+            encryptorName: assisted_encryptor
+          likeQuery:
+            name: like_query_username
+            encryptorName: like_encryptor
+        pwd:
+          cipher:
+            name: pwd
+            encryptorName: aes_encryptor
+          assistedQuery:
+            name: assisted_query_pwd
+            encryptorName: assisted_encryptor
+  encryptors:
+    aes_encryptor:
+      type: AES
+      props:
+        aes-key-value: 123456abc
+    assisted_encryptor:
+      type: MD5
+    like_encryptor:
+      type: CHAR_DIGEST_LIKE
+#- !COMPATIBLE_ENCRYPT
 #  tables:
-#    t_order:
-#      actualDataNodes: ds_${0..1}.t_order_${0..1}
-#      tableStrategy:
-#        standard:
-#          shardingColumn: order_id
-#          shardingAlgorithmName: t_order_inline
-#      keyGenerateStrategy:
-#        column: order_id
-#        keyGeneratorName: snowflake
-#      auditStrategy:
-#        auditorNames:
-#          - sharding_key_required_auditor
-#        allowHintDisable: true
-#    t_order_item:
-#      actualDataNodes: ds_${0..1}.t_order_item_${0..1}
-#      tableStrategy:
-#        standard:
-#          shardingColumn: order_id
-#          shardingAlgorithmName: t_order_item_inline
-#      keyGenerateStrategy:
-#        column: order_item_id
-#        keyGeneratorName: snowflake
-#  bindingTables:
-#    - t_order,t_order_item
-#  defaultDatabaseStrategy:
-#    standard:
-#      shardingColumn: user_id
-#      shardingAlgorithmName: database_inline
-#  defaultTableStrategy:
-#    none:
-#  defaultAuditStrategy:
-#    auditorNames:
-#      - sharding_key_required_auditor
-#    allowHintDisable: true
-#
-#  shardingAlgorithms:
-#    database_inline:
-#      type: INLINE
-#      props:
-#        algorithm-expression: ds_${user_id % 2}
-#    t_order_inline:
-#      type: INLINE
-#      props:
-#        algorithm-expression: t_order_${order_id % 2}
-#    t_order_item_inline:
-#      type: INLINE
+#    t_order_compatible:
+#      columns:
+#        username:
+#          cipherColumn: username
+#          encryptorName: aes_encryptor
+#          assistedQueryColumn: assisted_query_username
+#          assistedQueryEncryptorName: assisted_encryptor
+#          likeQueryColumn: like_query_username
+#          likeQueryEncryptorName: like_encryptor
+#        pwd:
+#          cipherColumn: pwd
+#          encryptorName: aes_encryptor
+#          assistedQueryColumn: assisted_query_pwd
+#          assistedQueryEncryptorName: assisted_encryptor
+#  encryptors:
+#    aes_encryptor:
+#      type: AES
 #      props:
-#        algorithm-expression: t_order_item_${order_id % 2}
-#
-#  keyGenerators:
-#    snowflake:
-#      type: SNOWFLAKE
-#
-#  auditors:
-#    sharding_key_required_auditor:
-#      type: DML_SHARDING_CONDITIONS
+#        aes-key-value: 123456abc
+#    assisted_encryptor:
+#      type: MD5
+#    like_encryptor:
+#      type: CHAR_DIGEST_LIKE
+- !BROADCAST
+  tables:
+    - t_order
+    - t_order_item
diff --git a/proxy/bootstrap/src/main/resources/conf/server.yaml b/proxy/bootstrap/src/main/resources/conf/server.yaml
index 9b0c5cd34f3..05ff5c6c186 100644
--- a/proxy/bootstrap/src/main/resources/conf/server.yaml
+++ b/proxy/bootstrap/src/main/resources/conf/server.yaml
@@ -21,26 +21,26 @@
 # 
 ######################################################################################################
 
-#mode:
-#  type: Cluster
-#  repository:
-#    type: ZooKeeper
-#    props:
-#      namespace: governance_ds
-#      server-lists: localhost:2181
-#      retryIntervalMilliseconds: 500
-#      timeToLiveSeconds: 60
-#      maxRetries: 3
-#      operationTimeoutMilliseconds: 500
-#
-#authority:
-#  users:
-#    - user: root@%
-#      password: root
-#    - user: sharding
-#      password: sharding
-#  privilege:
-#    type: ALL_PERMITTED
+mode:
+  type: New_Cluster
+  repository:
+    type: ZooKeeper
+    props:
+      namespace: governance_ds_new11
+      server-lists: localhost:2181
+      retryIntervalMilliseconds: 500
+      timeToLiveSeconds: 60
+      maxRetries: 3
+      operationTimeoutMilliseconds: 500
+
+authority:
+  users:
+    - user: root@%
+      password: root
+    - user: sharding
+      password: sharding
+  privilege:
+    type: ALL_PERMITTED
 #
 #transaction:
 #  defaultType: XA