You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ji...@apache.org on 2022/11/09 03:10:21 UTC

[shardingsphere] branch master updated: ConvertYamlConfigurationHandler supports mixed rules. (#21994)

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

jianglongtao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new e7ef5ea7457 ConvertYamlConfigurationHandler supports mixed rules. (#21994)
e7ef5ea7457 is described below

commit e7ef5ea74571e649b4cd06e480e2ea1fa93bf9a5
Author: yx9o <ya...@163.com>
AuthorDate: Wed Nov 9 11:10:15 2022 +0800

    ConvertYamlConfigurationHandler supports mixed rules. (#21994)
    
    * ConvertYamlConfigurationHandler supports mixed rules.
    
    * update.
---
 .../common/constant/DistSQLScriptConstants.java    |  14 +-
 .../queryable/ConvertYamlConfigurationHandler.java | 107 +++++++++-----
 .../ConvertYamlConfigurationHandlerTest.java       |  62 ++++----
 .../test/resources/conf/convert/config-mix.yaml    | 158 +++++++++++++++++++++
 ...rt-create-encrypt.yaml => convert-encrypt.yaml} |   0
 .../src/test/resources/expected/convert-mix.yaml   |  92 ++++++++++++
 ...vert-create-shadow.yaml => convert-shadow.yaml} |   0
 ...-create-sharding.yaml => convert-sharding.yaml} |   0
 8 files changed, 357 insertions(+), 76 deletions(-)

diff --git a/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/common/constant/DistSQLScriptConstants.java b/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/common/constant/DistSQLScriptConstants.java
index ae6f21b6dab..3f9c9c1902a 100644
--- a/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/common/constant/DistSQLScriptConstants.java
+++ b/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/common/constant/DistSQLScriptConstants.java
@@ -121,11 +121,21 @@ public final class DistSQLScriptConstants {
     
     public static final String CREATE_READWRITE_SPLITTING_RULE = "CREATE READWRITE_SPLITTING RULE";
     
-    public static final String READWRITE_SPLITTING = " %s ("
+    public static final String READWRITE_SPLITTING_FOR_STATIC = " %s ("
             + System.lineSeparator()
             + "WRITE_STORAGE_UNIT=%s,"
             + System.lineSeparator()
-            + "READ_STORAGE_UNITS(%s)%s)";
+            + "READ_STORAGE_UNITS(%s)%s"
+            + System.lineSeparator()
+            + ")";
+    
+    public static final String READWRITE_SPLITTING_FOR_DYNAMIC = " %s ("
+            + System.lineSeparator()
+            + "AUTO_AWARE_RESOURCE=%s,"
+            + System.lineSeparator()
+            + "WRITE_DATA_SOURCE_QUERY_ENABLED=%s%s"
+            + System.lineSeparator()
+            + ")";
     
     public static final String READ_RESOURCE = "%s";
     
diff --git a/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ConvertYamlConfigurationHandler.java b/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ConvertYamlConfigurationHandler.java
index ad99c663946..59c61a115eb 100644
--- a/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ConvertYamlConfigurationHandler.java
+++ b/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ConvertYamlConfigurationHandler.java
@@ -32,13 +32,13 @@ import org.apache.shardingsphere.encrypt.api.config.rule.EncryptTableRuleConfigu
 import org.apache.shardingsphere.encrypt.yaml.config.YamlEncryptRuleConfiguration;
 import org.apache.shardingsphere.encrypt.yaml.swapper.YamlEncryptRuleConfigurationSwapper;
 import org.apache.shardingsphere.infra.config.algorithm.AlgorithmConfiguration;
+import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
 import org.apache.shardingsphere.infra.datasource.props.DataSourceProperties;
 import org.apache.shardingsphere.infra.datasource.props.DataSourcePropertiesCreator;
 import org.apache.shardingsphere.infra.datasource.props.custom.CustomDataSourceProperties;
 import org.apache.shardingsphere.infra.datasource.props.synonym.PoolPropertySynonyms;
 import org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
 import org.apache.shardingsphere.infra.util.yaml.YamlEngine;
-import org.apache.shardingsphere.infra.yaml.config.pojo.rule.YamlRuleConfiguration;
 import org.apache.shardingsphere.mode.manager.ContextManager;
 import org.apache.shardingsphere.proxy.backend.config.yaml.YamlProxyDataSourceConfiguration;
 import org.apache.shardingsphere.proxy.backend.config.yaml.YamlProxyDatabaseConfiguration;
@@ -48,6 +48,7 @@ import org.apache.shardingsphere.proxy.backend.handler.distsql.ral.QueryableRALB
 import org.apache.shardingsphere.proxy.backend.handler.distsql.ral.common.constant.DistSQLScriptConstants;
 import org.apache.shardingsphere.readwritesplitting.api.ReadwriteSplittingRuleConfiguration;
 import org.apache.shardingsphere.readwritesplitting.api.rule.ReadwriteSplittingDataSourceRuleConfiguration;
+import org.apache.shardingsphere.readwritesplitting.api.strategy.DynamicReadwriteSplittingStrategyConfiguration;
 import org.apache.shardingsphere.readwritesplitting.api.strategy.StaticReadwriteSplittingStrategyConfiguration;
 import org.apache.shardingsphere.readwritesplitting.yaml.config.YamlReadwriteSplittingRuleConfiguration;
 import org.apache.shardingsphere.readwritesplitting.yaml.swapper.YamlReadwriteSplittingRuleConfigurationSwapper;
@@ -69,6 +70,7 @@ import java.io.File;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -104,20 +106,43 @@ public final class ConvertYamlConfigurationHandler extends QueryableRALBackendHa
     private String generateDistSQL(final YamlProxyDatabaseConfiguration yamlConfig) {
         StringBuilder result = new StringBuilder();
         appendResourceDistSQL(yamlConfig, result);
-        for (YamlRuleConfiguration each : yamlConfig.getRules()) {
-            if (each instanceof YamlReadwriteSplittingRuleConfiguration) {
-                appendReadWriteSplittingDistSQL((YamlReadwriteSplittingRuleConfiguration) each, result);
-            } else if (each instanceof YamlShardingRuleConfiguration) {
-                appendShardingDistSQL((YamlShardingRuleConfiguration) each, result);
+        swapToRuleConfigs(yamlConfig).values().forEach(each -> {
+            if (each instanceof ShardingRuleConfiguration) {
+                appendShardingDistSQL((ShardingRuleConfiguration) each, result);
+            } else if (each instanceof ReadwriteSplittingRuleConfiguration) {
+                appendReadWriteSplittingDistSQL((ReadwriteSplittingRuleConfiguration) each, result);
+            } else if (each instanceof DatabaseDiscoveryRuleConfiguration) {
+                appendDatabaseDiscoveryDistSQL((DatabaseDiscoveryRuleConfiguration) each, result);
+            } else if (each instanceof EncryptRuleConfiguration) {
+                appendEncryptDistSQL((EncryptRuleConfiguration) each, result);
+            } else if (each instanceof ShadowRuleConfiguration) {
+                appendShadowDistSQL((ShadowRuleConfiguration) each, result);
+            }
+        });
+        return result.toString();
+    }
+    
+    private Map<Integer, RuleConfiguration> swapToRuleConfigs(final YamlProxyDatabaseConfiguration yamlConfig) {
+        Map<Integer, RuleConfiguration> result = new TreeMap<>(Comparator.reverseOrder());
+        yamlConfig.getRules().forEach(each -> {
+            if (each instanceof YamlShardingRuleConfiguration) {
+                YamlShardingRuleConfigurationSwapper swapper = new YamlShardingRuleConfigurationSwapper();
+                result.put(swapper.getOrder(), swapper.swapToObject((YamlShardingRuleConfiguration) each));
+            } else if (each instanceof YamlReadwriteSplittingRuleConfiguration) {
+                YamlReadwriteSplittingRuleConfigurationSwapper swapper = new YamlReadwriteSplittingRuleConfigurationSwapper();
+                result.put(swapper.getOrder(), swapper.swapToObject((YamlReadwriteSplittingRuleConfiguration) each));
             } else if (each instanceof YamlDatabaseDiscoveryRuleConfiguration) {
-                appendDatabaseDiscoveryDistSQL((YamlDatabaseDiscoveryRuleConfiguration) each, result);
+                YamlDatabaseDiscoveryRuleConfigurationSwapper swapper = new YamlDatabaseDiscoveryRuleConfigurationSwapper();
+                result.put(swapper.getOrder(), swapper.swapToObject((YamlDatabaseDiscoveryRuleConfiguration) each));
             } else if (each instanceof YamlEncryptRuleConfiguration) {
-                appendEncryptDistSQL((YamlEncryptRuleConfiguration) each, result);
+                YamlEncryptRuleConfigurationSwapper swapper = new YamlEncryptRuleConfigurationSwapper();
+                result.put(swapper.getOrder(), swapper.swapToObject((YamlEncryptRuleConfiguration) each));
             } else if (each instanceof YamlShadowRuleConfiguration) {
-                appendShadowDistSQL((YamlShadowRuleConfiguration) each, result);
+                YamlShadowRuleConfigurationSwapper swapper = new YamlShadowRuleConfigurationSwapper();
+                result.put(swapper.getOrder(), swapper.swapToObject((YamlShadowRuleConfiguration) each));
             }
-        }
-        return result.toString();
+        });
+        return result;
     }
     
     private void appendResourceDistSQL(final YamlProxyDatabaseConfiguration yamlConfig, final StringBuilder result) {
@@ -184,8 +209,7 @@ public final class ConvertYamlConfigurationHandler extends QueryableRALBackendHa
         }
     }
     
-    private void appendShardingDistSQL(final YamlShardingRuleConfiguration yamlRuleConfig, final StringBuilder result) {
-        ShardingRuleConfiguration ruleConfig = new YamlShardingRuleConfigurationSwapper().swapToObject(yamlRuleConfig);
+    private void appendShardingDistSQL(final ShardingRuleConfiguration ruleConfig, final StringBuilder result) {
         appendShardingAlgorithms(ruleConfig, result);
         appendKeyGenerators(ruleConfig, result);
         appendShardingTableRules(ruleConfig, result);
@@ -297,39 +321,53 @@ public final class ConvertYamlConfigurationHandler extends QueryableRALBackendHa
             return;
         }
         result.append(String.format(DistSQLScriptConstants.BROADCAST_TABLE_RULE, String.join(",", ruleConfig.getBroadcastTables())));
-        result.append(DistSQLScriptConstants.SEMI).append(System.lineSeparator());
+        result.append(DistSQLScriptConstants.SEMI).append(System.lineSeparator()).append(System.lineSeparator());
     }
     
-    private void appendReadWriteSplittingDistSQL(final YamlReadwriteSplittingRuleConfiguration yamlRuleConfig, final StringBuilder result) {
-        ReadwriteSplittingRuleConfiguration ruleConfig = new YamlReadwriteSplittingRuleConfigurationSwapper().swapToObject(yamlRuleConfig);
+    private void appendReadWriteSplittingDistSQL(final ReadwriteSplittingRuleConfiguration ruleConfig, final StringBuilder result) {
         if (ruleConfig.getDataSources().isEmpty()) {
             return;
         }
         result.append(DistSQLScriptConstants.CREATE_READWRITE_SPLITTING_RULE);
-        appendStaticReadWriteSplittingRule(ruleConfig, result);
-        // TODO Dynamic READ-WRITE-SPLITTING RULES
-    }
-    
-    private void appendStaticReadWriteSplittingRule(final ReadwriteSplittingRuleConfiguration ruleConfig, final StringBuilder result) {
         Iterator<ReadwriteSplittingDataSourceRuleConfiguration> iterator = ruleConfig.getDataSources().iterator();
         while (iterator.hasNext()) {
             ReadwriteSplittingDataSourceRuleConfiguration dataSourceRuleConfig = iterator.next();
-            StaticReadwriteSplittingStrategyConfiguration staticStrategy = dataSourceRuleConfig.getStaticStrategy();
-            String readDataSourceNames = getReadDataSourceNames(staticStrategy.getReadDataSourceNames());
-            String loadBalancerType = getLoadBalancerType(ruleConfig.getLoadBalancers().get(dataSourceRuleConfig.getLoadBalancerName()));
-            result.append(String.format(DistSQLScriptConstants.READWRITE_SPLITTING, dataSourceRuleConfig.getName(), staticStrategy.getWriteDataSourceName(), readDataSourceNames, loadBalancerType));
+            appendStaticReadWriteSplittingRule(dataSourceRuleConfig.getStaticStrategy(), ruleConfig.getLoadBalancers(), dataSourceRuleConfig, result);
+            appendDynamicReadWriteSplittingRule(dataSourceRuleConfig.getDynamicStrategy(), ruleConfig.getLoadBalancers(), dataSourceRuleConfig, result);
             if (iterator.hasNext()) {
                 result.append(DistSQLScriptConstants.COMMA);
             }
         }
-        result.append(DistSQLScriptConstants.SEMI).append(System.lineSeparator());
+        result.append(DistSQLScriptConstants.SEMI).append(System.lineSeparator()).append(System.lineSeparator());
+    }
+    
+    private void appendDynamicReadWriteSplittingRule(final DynamicReadwriteSplittingStrategyConfiguration dynamicConfig, final Map<String, AlgorithmConfiguration> loadBalancers,
+                                                     final ReadwriteSplittingDataSourceRuleConfiguration dataSourceRuleConfig, final StringBuilder result) {
+        if (null == dynamicConfig) {
+            return;
+        }
+        String loadBalancerType = getLoadBalancerType(loadBalancers.get(dataSourceRuleConfig.getLoadBalancerName()));
+        boolean allowWriteDataSourceQuery = Strings.isNullOrEmpty(dynamicConfig.getWriteDataSourceQueryEnabled()) ? Boolean.TRUE : Boolean.parseBoolean(dynamicConfig.getWriteDataSourceQueryEnabled());
+        result.append(String.format(DistSQLScriptConstants.READWRITE_SPLITTING_FOR_DYNAMIC,
+                dataSourceRuleConfig.getName(), dynamicConfig.getAutoAwareDataSourceName(), allowWriteDataSourceQuery, loadBalancerType));
+    }
+    
+    private void appendStaticReadWriteSplittingRule(final StaticReadwriteSplittingStrategyConfiguration staticConfig, final Map<String, AlgorithmConfiguration> loadBalancers,
+                                                    final ReadwriteSplittingDataSourceRuleConfiguration dataSourceRuleConfig, final StringBuilder result) {
+        if (null == staticConfig) {
+            return;
+        }
+        String readDataSourceNames = getReadDataSourceNames(staticConfig.getReadDataSourceNames());
+        String loadBalancerType = getLoadBalancerType(loadBalancers.get(dataSourceRuleConfig.getLoadBalancerName()));
+        result.append(String.format(DistSQLScriptConstants.READWRITE_SPLITTING_FOR_STATIC,
+                dataSourceRuleConfig.getName(), staticConfig.getWriteDataSourceName(), readDataSourceNames, loadBalancerType));
     }
     
     private String getLoadBalancerType(final AlgorithmConfiguration algorithmConfig) {
         StringBuilder result = new StringBuilder();
         String loadBalancerType = getAlgorithmType(algorithmConfig);
         if (!Strings.isNullOrEmpty(loadBalancerType)) {
-            result.append(DistSQLScriptConstants.COMMA).append(System.lineSeparator()).append(loadBalancerType).append(System.lineSeparator());
+            result.append(DistSQLScriptConstants.COMMA).append(System.lineSeparator()).append(loadBalancerType);
         }
         return result.toString();
     }
@@ -346,8 +384,7 @@ public final class ConvertYamlConfigurationHandler extends QueryableRALBackendHa
         return result.toString();
     }
     
-    private void appendDatabaseDiscoveryDistSQL(final YamlDatabaseDiscoveryRuleConfiguration yamlRuleConfig, final StringBuilder result) {
-        DatabaseDiscoveryRuleConfiguration ruleConfig = new YamlDatabaseDiscoveryRuleConfigurationSwapper().swapToObject(yamlRuleConfig);
+    private void appendDatabaseDiscoveryDistSQL(final DatabaseDiscoveryRuleConfiguration ruleConfig, final StringBuilder result) {
         if (ruleConfig.getDataSources().isEmpty()) {
             return;
         }
@@ -364,7 +401,7 @@ public final class ConvertYamlConfigurationHandler extends QueryableRALBackendHa
                 result.append(DistSQLScriptConstants.COMMA);
             }
         }
-        result.append(DistSQLScriptConstants.SEMI).append(System.lineSeparator());
+        result.append(DistSQLScriptConstants.SEMI).append(System.lineSeparator()).append(System.lineSeparator());
     }
     
     private String getDatabaseDiscoveryHeartbeat(final DatabaseDiscoveryHeartBeatConfiguration heartBeatConfig) {
@@ -376,8 +413,7 @@ public final class ConvertYamlConfigurationHandler extends QueryableRALBackendHa
         return result.toString();
     }
     
-    private void appendEncryptDistSQL(final YamlEncryptRuleConfiguration yamlRuleConfig, final StringBuilder result) {
-        EncryptRuleConfiguration ruleConfig = new YamlEncryptRuleConfigurationSwapper().swapToObject(yamlRuleConfig);
+    private void appendEncryptDistSQL(final EncryptRuleConfiguration ruleConfig, final StringBuilder result) {
         if (ruleConfig.getTables().isEmpty()) {
             return;
         }
@@ -393,7 +429,7 @@ public final class ConvertYamlConfigurationHandler extends QueryableRALBackendHa
                 result.append(DistSQLScriptConstants.COMMA).append(System.lineSeparator());
             }
         }
-        result.append(DistSQLScriptConstants.SEMI).append(System.lineSeparator());
+        result.append(DistSQLScriptConstants.SEMI).append(System.lineSeparator()).append(System.lineSeparator());
     }
     
     private String getEncryptColumns(final Collection<EncryptColumnRuleConfiguration> ruleConfigs, final Map<String, AlgorithmConfiguration> encryptors) {
@@ -426,8 +462,7 @@ public final class ConvertYamlConfigurationHandler extends QueryableRALBackendHa
         return result.toString();
     }
     
-    private void appendShadowDistSQL(final YamlShadowRuleConfiguration yamlRuleConfig, final StringBuilder result) {
-        ShadowRuleConfiguration ruleConfig = new YamlShadowRuleConfigurationSwapper().swapToObject(yamlRuleConfig);
+    private void appendShadowDistSQL(final ShadowRuleConfiguration ruleConfig, final StringBuilder result) {
         if (ruleConfig.getDataSources().isEmpty()) {
             return;
         }
@@ -444,7 +479,7 @@ public final class ConvertYamlConfigurationHandler extends QueryableRALBackendHa
                 result.append(DistSQLScriptConstants.COMMA);
             }
         }
-        result.append(DistSQLScriptConstants.SEMI).append(System.lineSeparator());
+        result.append(DistSQLScriptConstants.SEMI).append(System.lineSeparator()).append(System.lineSeparator());
     }
     
     private String getShadowTables(final String shadowRuleName, final Map<String, ShadowTableConfiguration> ruleConfig, final Map<String, AlgorithmConfiguration> algorithmConfigs) {
diff --git a/proxy/backend/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ConvertYamlConfigurationHandlerTest.java b/proxy/backend/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ConvertYamlConfigurationHandlerTest.java
index 33dab4ec1ad..070aea2a67c 100644
--- a/proxy/backend/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ConvertYamlConfigurationHandlerTest.java
+++ b/proxy/backend/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ConvertYamlConfigurationHandlerTest.java
@@ -22,7 +22,6 @@ import org.apache.shardingsphere.distsql.parser.statement.ral.queryable.ConvertY
 import org.apache.shardingsphere.proxy.backend.response.header.query.QueryHeader;
 import org.apache.shardingsphere.proxy.backend.response.header.query.QueryResponseHeader;
 import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
-import org.junit.Before;
 import org.junit.Test;
 
 import java.io.BufferedReader;
@@ -30,8 +29,6 @@ import java.io.FileReader;
 import java.io.IOException;
 import java.sql.SQLException;
 import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.Objects;
 
 import static org.hamcrest.CoreMatchers.is;
@@ -42,75 +39,63 @@ import static org.mockito.Mockito.mock;
 
 public final class ConvertYamlConfigurationHandlerTest {
     
-    private final String shardingFilePath = "/conf/convert/config-sharding.yaml";
+    private final String shardingConfigFilePath = "/conf/convert/config-sharding.yaml";
     
-    private final String readWriteSplittingFilePath = "/conf/convert/config-readwrite-splitting.yaml";
+    private final String readWriteSplittingConfigFilePath = "/conf/convert/config-readwrite-splitting.yaml";
     
-    private final String databaseDiscoveryFilePath = "/conf/convert/config-database-discovery.yaml";
+    private final String databaseDiscoveryConfigFilePath = "/conf/convert/config-database-discovery.yaml";
     
-    private final String encryptFilePath = "/conf/convert/config-encrypt.yaml";
+    private final String encryptConfigFilePath = "/conf/convert/config-encrypt.yaml";
     
-    private final String shadowFilePath = "/conf/convert/config-shadow.yaml";
+    private final String shadowConfigFilePath = "/conf/convert/config-shadow.yaml";
     
-    private final String shardingExpectedFilePath = "/expected/convert-create-sharding.yaml";
+    private final String mixConfigFilePath = "/conf/convert/config-mix.yaml";
+    
+    private final String shardingExpectedFilePath = "/expected/convert-sharding.yaml";
     
     private final String readWriteSplittingExpectedFilePath = "/expected/convert-readwrite-splitting.yaml";
     
     private final String databaseDiscoveryExpectedFilePath = "/expected/convert-database-discovery.yaml";
     
-    private final String encryptExpectedFilePath = "/expected/convert-create-encrypt.yaml";
-    
-    private final String shadowExpectedFilePath = "/expected/convert-create-shadow.yaml";
-    
-    private final String sharding = "sharding";
-    
-    private final String readWriteSplitting = "readWriteSplitting";
-    
-    private final String databaseDiscovery = "databaseDiscovery";
-    
-    private final String encrypt = "encrypt";
+    private final String encryptExpectedFilePath = "/expected/convert-encrypt.yaml";
     
-    private final String shadow = "shadow";
+    private final String shadowExpectedFilePath = "/expected/convert-shadow.yaml";
     
-    private final Map<String, String> featureMap = new HashMap<>(5, 1);
-    
-    @Before
-    public void setup() {
-        featureMap.put(sharding, shardingFilePath);
-        featureMap.put(readWriteSplitting, readWriteSplittingFilePath);
-        featureMap.put(databaseDiscovery, databaseDiscoveryFilePath);
-        featureMap.put(encrypt, encryptFilePath);
-        featureMap.put(shadow, shadowFilePath);
-    }
+    private final String mixExpectedFilePath = "/expected/convert-mix.yaml";
     
     @Test
     public void assertExecuteWithSharding() throws SQLException {
-        assertExecute(sharding, shardingExpectedFilePath);
+        assertExecute(shardingConfigFilePath, shardingExpectedFilePath);
     }
     
     @Test
     public void assertExecuteWithReadWriteSplitting() throws SQLException {
-        assertExecute(readWriteSplitting, readWriteSplittingExpectedFilePath);
+        assertExecute(readWriteSplittingConfigFilePath, readWriteSplittingExpectedFilePath);
     }
     
     @Test
     public void assertExecuteWithDatabaseDiscovery() throws SQLException {
-        assertExecute(databaseDiscovery, databaseDiscoveryExpectedFilePath);
+        assertExecute(databaseDiscoveryConfigFilePath, databaseDiscoveryExpectedFilePath);
     }
     
     @Test
     public void assertExecuteWithEncrypt() throws SQLException {
-        assertExecute(encrypt, encryptExpectedFilePath);
+        assertExecute(encryptConfigFilePath, encryptExpectedFilePath);
     }
     
     @Test
     public void assertExecuteWithShadow() throws SQLException {
-        assertExecute(shadow, shadowExpectedFilePath);
+        assertExecute(shadowConfigFilePath, shadowExpectedFilePath);
+    }
+    
+    @Test
+    public void assertExecuteWithMix() throws SQLException {
+        assertExecute(mixConfigFilePath, mixExpectedFilePath);
     }
     
-    public void assertExecute(final String type, final String expectedFilePath) throws SQLException {
+    public void assertExecute(final String configFilePath, final String expectedFilePath) throws SQLException {
         ConvertYamlConfigurationHandler handler = new ConvertYamlConfigurationHandler();
-        handler.init(new ConvertYamlConfigurationStatement(Objects.requireNonNull(ConvertYamlConfigurationHandlerTest.class.getResource(featureMap.get(type))).getPath()),
+        handler.init(new ConvertYamlConfigurationStatement(Objects.requireNonNull(ConvertYamlConfigurationHandlerTest.class.getResource(configFilePath)).getPath()),
                 mock(ConnectionSession.class));
         assertQueryResponseHeader((QueryResponseHeader) handler.execute());
         assertTrue(handler.next());
@@ -156,6 +141,7 @@ public final class ConvertYamlConfigurationHandlerTest {
                     result.append(line).append(System.lineSeparator());
                 }
             }
+            result.append(System.lineSeparator());
         }
         return result.toString();
     }
diff --git a/proxy/backend/src/test/resources/conf/convert/config-mix.yaml b/proxy/backend/src/test/resources/conf/convert/config-mix.yaml
new file mode 100644
index 00000000000..a3de8567b40
--- /dev/null
+++ b/proxy/backend/src/test/resources/conf/convert/config-mix.yaml
@@ -0,0 +1,158 @@
+#
+# 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.
+#
+
+databaseName: mix_db
+
+dataSources:
+  ds_0:
+    url: jdbc:mysql://127.0.0.1:3306/demo_ds_0?serverTimezone=UTC&useSSL=false
+    username: root
+    password: 12345678
+    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: 12345678
+    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: 12345678
+    connectionTimeoutMilliseconds: 30000
+    idleTimeoutMilliseconds: 60000
+    maxLifetimeMilliseconds: 1800000
+    maxPoolSize: 50
+    minPoolSize: 1
+  ds_3:
+    url: jdbc:mysql://127.0.0.1:3306/demo_ds_3?serverTimezone=UTC&useSSL=false
+    username: root
+    password: 12345678
+    connectionTimeoutMilliseconds: 30000
+    idleTimeoutMilliseconds: 60000
+    maxLifetimeMilliseconds: 1800000
+    maxPoolSize: 50
+    minPoolSize: 1
+  ds_4:
+    url: jdbc:mysql://127.0.0.1:3306/demo_ds_4?serverTimezone=UTC&useSSL=false
+    username: root
+    password: 12345678
+    connectionTimeoutMilliseconds: 30000
+    idleTimeoutMilliseconds: 60000
+    maxLifetimeMilliseconds: 1800000
+    maxPoolSize: 50
+    minPoolSize: 1
+  ds_5:
+    url: jdbc:mysql://127.0.0.1:3306/demo_ds_5?serverTimezone=UTC&useSSL=false
+    username: root
+    password: 12345678
+    connectionTimeoutMilliseconds: 30000
+    idleTimeoutMilliseconds: 60000
+    maxLifetimeMilliseconds: 1800000
+    maxPoolSize: 50
+    minPoolSize: 1
+
+rules:
+  - !SHARDING
+    tables:
+      t_order:
+        actualDataNodes: replica_ds_${0..1}.t_order_${0..1}
+        tableStrategy:
+          standard:
+            shardingColumn: order_id
+            shardingAlgorithmName: t_order_inline
+        keyGenerateStrategy:
+          column: order_id
+          keyGeneratorName: snowflake
+    defaultDatabaseStrategy:
+      standard:
+        shardingColumn: user_id
+        shardingAlgorithmName: database_inline
+    shardingAlgorithms:
+      database_inline:
+        type: INLINE
+        props:
+          algorithm-expression: replica_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
+  - !READWRITE_SPLITTING
+    dataSources:
+      replica_ds_0:
+        dynamicStrategy:
+          autoAwareDataSourceName: readwrite_ds_0
+      replica_ds_1:
+        dynamicStrategy:
+          autoAwareDataSourceName: readwrite_ds_1
+  - !DB_DISCOVERY
+    dataSources:
+      readwrite_ds_0:
+        dataSourceNames:
+          - ds_0
+          - ds_1
+          - ds_2
+        discoveryHeartbeatName: mgr-heartbeat
+        discoveryTypeName: mgr
+      readwrite_ds_1:
+        dataSourceNames:
+          - ds_3
+          - ds_4
+          - ds_5
+        discoveryHeartbeatName: mgr-heartbeat
+        discoveryTypeName: mgr
+    discoveryHeartbeats:
+      mgr-heartbeat:
+        props:
+          keep-alive-cron: '0/5 * * * * ?'
+    discoveryTypes:
+      mgr:
+        type: MySQL.MGR
+        props:
+          group-name: 558edd3c-02ec-11ea-9bb3-080027e39bd2
+  - !ENCRYPT
+    encryptors:
+      aes_encryptor:
+        type: AES
+        props:
+          aes-key-value: 123456abc
+      md5_encryptor:
+        type: MD5
+    tables:
+      t_encrypt:
+        columns:
+          user_id:
+            plainColumn: user_plain
+            cipherColumn: user_cipher
+            encryptorName: aes_encryptor
+          order_id:
+            cipherColumn: order_cipher
+            encryptorName: md5_encryptor
diff --git a/proxy/backend/src/test/resources/expected/convert-create-encrypt.yaml b/proxy/backend/src/test/resources/expected/convert-encrypt.yaml
similarity index 100%
rename from proxy/backend/src/test/resources/expected/convert-create-encrypt.yaml
rename to proxy/backend/src/test/resources/expected/convert-encrypt.yaml
diff --git a/proxy/backend/src/test/resources/expected/convert-mix.yaml b/proxy/backend/src/test/resources/expected/convert-mix.yaml
new file mode 100644
index 00000000000..0bb31859888
--- /dev/null
+++ b/proxy/backend/src/test/resources/expected/convert-mix.yaml
@@ -0,0 +1,92 @@
+#
+# 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.
+#
+CREATE DATABASE mix_db;
+USE mix_db;
+
+REGISTER STORAGE UNIT ds_0 (
+URL='jdbc:mysql://127.0.0.1:3306/demo_ds_0?serverTimezone=UTC&useSSL=false',
+USER='root',
+PASSWORD='12345678',
+PROPERTIES('minPoolSize'='1', 'connectionTimeoutMilliseconds'='30000', 'maxLifetimeMilliseconds'='1800000', 'idleTimeoutMilliseconds'='60000', 'maxPoolSize'='50')
+), ds_1 (
+URL='jdbc:mysql://127.0.0.1:3306/demo_ds_1?serverTimezone=UTC&useSSL=false',
+USER='root',
+PASSWORD='12345678',
+PROPERTIES('minPoolSize'='1', 'connectionTimeoutMilliseconds'='30000', 'maxLifetimeMilliseconds'='1800000', 'idleTimeoutMilliseconds'='60000', 'maxPoolSize'='50')
+), ds_2 (
+URL='jdbc:mysql://127.0.0.1:3306/demo_ds_2?serverTimezone=UTC&useSSL=false',
+USER='root',
+PASSWORD='12345678',
+PROPERTIES('minPoolSize'='1', 'connectionTimeoutMilliseconds'='30000', 'maxLifetimeMilliseconds'='1800000', 'idleTimeoutMilliseconds'='60000', 'maxPoolSize'='50')
+), ds_3 (
+URL='jdbc:mysql://127.0.0.1:3306/demo_ds_3?serverTimezone=UTC&useSSL=false',
+USER='root',
+PASSWORD='12345678',
+PROPERTIES('minPoolSize'='1', 'connectionTimeoutMilliseconds'='30000', 'maxLifetimeMilliseconds'='1800000', 'idleTimeoutMilliseconds'='60000', 'maxPoolSize'='50')
+), ds_4 (
+URL='jdbc:mysql://127.0.0.1:3306/demo_ds_4?serverTimezone=UTC&useSSL=false',
+USER='root',
+PASSWORD='12345678',
+PROPERTIES('minPoolSize'='1', 'connectionTimeoutMilliseconds'='30000', 'maxLifetimeMilliseconds'='1800000', 'idleTimeoutMilliseconds'='60000', 'maxPoolSize'='50')
+), ds_5 (
+URL='jdbc:mysql://127.0.0.1:3306/demo_ds_5?serverTimezone=UTC&useSSL=false',
+USER='root',
+PASSWORD='12345678',
+PROPERTIES('minPoolSize'='1', 'connectionTimeoutMilliseconds'='30000', 'maxLifetimeMilliseconds'='1800000', 'idleTimeoutMilliseconds'='60000', 'maxPoolSize'='50')
+);
+
+CREATE DB_DISCOVERY RULE readwrite_ds_0 (
+STORAGE_UNITS(ds_0,ds_1,ds_2),
+TYPE(NAME='mysql.mgr', PROPERTIES('group-name'='558edd3c-02ec-11ea-9bb3-080027e39bd2')),
+HEARTBEAT(PROPERTIES('keep-alive-cron'='0/5 * * * * ?'))
+), readwrite_ds_1 (
+STORAGE_UNITS(ds_3,ds_4,ds_5),
+TYPE(NAME='mysql.mgr', PROPERTIES('group-name'='558edd3c-02ec-11ea-9bb3-080027e39bd2')),
+HEARTBEAT(PROPERTIES('keep-alive-cron'='0/5 * * * * ?'))
+);
+
+CREATE READWRITE_SPLITTING RULE replica_ds_0 (
+AUTO_AWARE_RESOURCE=readwrite_ds_0,
+WRITE_DATA_SOURCE_QUERY_ENABLED=true
+), replica_ds_1 (
+AUTO_AWARE_RESOURCE=readwrite_ds_1,
+WRITE_DATA_SOURCE_QUERY_ENABLED=true
+);
+
+CREATE ENCRYPT RULE t_encrypt (
+COLUMNS(
+(NAME=user_id, PLAIN=user_plain, CIPHER=user_cipher, TYPE(NAME='aes', PROPERTIES('aes-key-value'='123456abc'))),
+(NAME=order_id, CIPHER=order_cipher, TYPE(NAME='md5'))
+),QUERY_WITH_CIPHER_COLUMN=true);
+
+CREATE SHARDING ALGORITHM database_inline (
+TYPE(NAME='inline', PROPERTIES('algorithm-expression'='replica_ds_${user_id % 2}'))
+), t_order_inline (
+TYPE(NAME='inline', PROPERTIES('algorithm-expression'='t_order_${order_id % 2}'))
+), t_order_item_inline (
+TYPE(NAME='inline', PROPERTIES('algorithm-expression'='t_order_item_${order_id % 2}'))
+);
+
+CREATE SHARDING KEY GENERATOR snowflake (
+TYPE(NAME='snowflake')
+);
+
+CREATE SHARDING TABLE RULE t_order (
+DATANODES('replica_ds_${0..1}.t_order_${0..1}'),
+TABLE_STRATEGY(TYPE='standard', SHARDING_COLUMN=order_id, SHARDING_ALGORITHM=t_order_inline),
+KEY_GENERATE_STRATEGY(COLUMN=order_id, KEY_GENERATOR=snowflake)
+);
diff --git a/proxy/backend/src/test/resources/expected/convert-create-shadow.yaml b/proxy/backend/src/test/resources/expected/convert-shadow.yaml
similarity index 100%
rename from proxy/backend/src/test/resources/expected/convert-create-shadow.yaml
rename to proxy/backend/src/test/resources/expected/convert-shadow.yaml
diff --git a/proxy/backend/src/test/resources/expected/convert-create-sharding.yaml b/proxy/backend/src/test/resources/expected/convert-sharding.yaml
similarity index 100%
rename from proxy/backend/src/test/resources/expected/convert-create-sharding.yaml
rename to proxy/backend/src/test/resources/expected/convert-sharding.yaml