You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by pa...@apache.org on 2021/05/18 09:01:44 UTC

[shardingsphere] branch master updated: Create database discovery rule (#10376)

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

panjuan 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 33cfc3a  Create database discovery rule (#10376)
33cfc3a is described below

commit 33cfc3a3e6a4bfc13c3beed86857953e9b99dc60
Author: Haoran Meng <me...@gmail.com>
AuthorDate: Tue May 18 17:00:53 2021 +0800

    Create database discovery rule (#10376)
    
    * Create database discovery rule
    
    * Create database discovery rule
    
    Co-authored-by: menghaoranss <me...@apache.org>
---
 .../db/protocol/error/CommonErrorCode.java         |   4 +
 .../src/main/antlr4/imports/Keyword.g4             |   4 +
 .../src/main/antlr4/imports/RDLStatement.g4        |  40 ++----
 .../distsql/parser/autogen/DistSQLStatement.g4     |   1 +
 .../distsql/parser/core/DistSQLVisitor.java        |  27 ++++-
 .../api/DistSQLStatementParserEngineTest.java      |  28 +++++
 .../segment/rdl/DatabaseDiscoveryRuleSegment.java} |  54 ++++-----
 .../CreateDatabaseDiscoveryRuleStatement.java}     |  44 +++----
 .../shardingsphere-db-discovery-common/pom.xml     |   6 +-
 .../DatabaseDiscoveryRuleStatementConverter.java   |  70 +++++++++++
 ...atabaseDiscoveryRuleStatementConverterTest.java |  58 +++++++++
 .../DatabaseDiscoveryRuleExistsException.java      |  42 +++----
 .../InvalidDatabaseDiscoveryTypesException.java    |  44 +++----
 .../text/distsql/rdl/RDLBackendHandlerFactory.java |   5 +
 .../CreateDatabaseDiscoveryRuleBackendHandler.java |  90 ++++++++++++++
 .../distsql/fixture/TestDatabaseDiscoveryType.java |  58 +++++++++
 ...ateDatabaseDiscoveryRuleBackendHandlerTest.java | 135 +++++++++++++++++++++
 ...ingsphere.dbdiscovery.spi.DatabaseDiscoveryType |  18 +++
 .../frontend/mysql/err/MySQLErrPacketFactory.java  |   8 ++
 19 files changed, 588 insertions(+), 148 deletions(-)

diff --git a/shardingsphere-db-protocol/shardingsphere-db-protocol-core/src/main/java/org/apache/shardingsphere/db/protocol/error/CommonErrorCode.java b/shardingsphere-db-protocol/shardingsphere-db-protocol-core/src/main/java/org/apache/shardingsphere/db/protocol/error/CommonErrorCode.java
index 59d6124..26a0d8a 100644
--- a/shardingsphere-db-protocol/shardingsphere-db-protocol-core/src/main/java/org/apache/shardingsphere/db/protocol/error/CommonErrorCode.java
+++ b/shardingsphere-db-protocol/shardingsphere-db-protocol-core/src/main/java/org/apache/shardingsphere/db/protocol/error/CommonErrorCode.java
@@ -63,6 +63,10 @@ public enum CommonErrorCode implements SQLErrorCode {
 
     INVALID_LOAD_BALANCERS(1117, "C1117", "Invalid load balancers %s."),
 
+    DATABASE_DISCOVERY_RULE_EXIST(1118, "C1118", "Database discovery rule already exist in schema %s."),
+
+    INVALID_DATABASE_DISCOVERY_TYPES(1119, "C1119", "Invalid database discovery types %s."),
+
     SCALING_JOB_NOT_EXIST(1201, "C1201", "Scaling job %s does not exist."),
     
     SCALING_OPERATE_FAILED(1209, "C1209", "Scaling Operate Failed: [%s]"),
diff --git a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/imports/Keyword.g4 b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/imports/Keyword.g4
index 0b80011..cae0395 100644
--- a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/imports/Keyword.g4
+++ b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/imports/Keyword.g4
@@ -206,3 +206,7 @@ RULES
 BROADCAST
     : B R O A D C A S T
     ;
+
+DB_DISCOVERY
+    : D B UL_ D I S C O V E R Y
+    ;
diff --git a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/imports/RDLStatement.g4 b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/imports/RDLStatement.g4
index b5aa46a..21754aa 100644
--- a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/imports/RDLStatement.g4
+++ b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/imports/RDLStatement.g4
@@ -127,38 +127,10 @@ shardingColumn
     : SHARDING_COLUMN EQ columnName
     ;
 
-alterBindingTables
-    : alterBindingTable (COMMA alterBindingTable)*
-    ;
-
-alterBindingTable
-    : (ADD | DROP) bindingTable
-    ;
-
-bindingTables
-    : bindingTable (COMMA bindingTable)*
-    ;
-
-bindingTable
-    : BINDING_TABLE LP tableNames RP
-    ;
-
-defaultTableStrategy
-    : DEFAULT_TABLE_STRATEGY columnName? functionDefinition
-    ;
-
-broadcastTables
-    : BROADCAST_TABLES LP IDENTIFIER (COMMA IDENTIFIER)* RP
-    ;
-
 keyGenerateStrategy
     : GENERATED_KEY LP COLUMN EQ columnName COMMA functionDefinition RP
     ;
 
-actualDataNodes
-    : STRING (COMMA STRING)*
-    ;
-
 ruleName
     : IDENTIFIER
     ;
@@ -167,10 +139,6 @@ tableName
     : IDENTIFIER
     ;
 
-tableNames
-    : IDENTIFIER+
-    ;
-
 columnName
     : IDENTIFIER
     ;
@@ -218,3 +186,11 @@ algorithmProperties
 algorithmProperty
     : key=(IDENTIFIER | STRING) EQ value=(NUMBER | INT | STRING)
     ;
+
+createDatabaseDiscoveryRule
+    : CREATE DB_DISCOVERY RULE databaseDiscoveryRuleDefinition  (COMMA databaseDiscoveryRuleDefinition)*
+    ;
+
+databaseDiscoveryRuleDefinition
+    : ruleName LP resources COMMA functionDefinition RP
+    ;
diff --git a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4 b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4
index 724288a..417bce3 100644
--- a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4
+++ b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4
@@ -34,6 +34,7 @@ execute
     | dropShardingBroadcastTableRules
     | alterReadwriteSplittingRule
     | dropReadwriteSplittingRule
+    | createDatabaseDiscoveryRule
     | showResources
     | showRule
     | showScalingJobList
diff --git a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/DistSQLVisitor.java b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/DistSQLVisitor.java
index 8cf3f9d..9b3cfe1 100644
--- a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/DistSQLVisitor.java
+++ b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/DistSQLVisitor.java
@@ -47,6 +47,7 @@ import org.apache.shardingsphere.distsql.parser.autogen.DistSQLStatementParser.T
 import org.apache.shardingsphere.distsql.parser.segment.DataSourceSegment;
 import org.apache.shardingsphere.distsql.parser.segment.FunctionSegment;
 import org.apache.shardingsphere.distsql.parser.segment.TableRuleSegment;
+import org.apache.shardingsphere.distsql.parser.segment.rdl.DatabaseDiscoveryRuleSegment;
 import org.apache.shardingsphere.distsql.parser.segment.rdl.ReadwriteSplittingRuleSegment;
 import org.apache.shardingsphere.distsql.parser.segment.rdl.ShardingBindingTableRuleSegment;
 import org.apache.shardingsphere.distsql.parser.statement.ral.impl.CheckScalingJobStatement;
@@ -61,6 +62,7 @@ import org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterShardin
 import org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterShardingBroadcastTableRulesStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterShardingTableRuleStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.AddResourceStatement;
+import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateDatabaseDiscoveryRuleStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateReadwriteSplittingRuleStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateShardingBindingTableRulesStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateShardingBroadcastTableRulesStatement;
@@ -270,7 +272,22 @@ public final class DistSQLVisitor extends DistSQLStatementBaseVisitor<ASTNode> {
         result.setAlgorithmProps(algorithmProps);
         return result;
     }
-    
+
+    @Override
+    public ASTNode visitCreateDatabaseDiscoveryRule(final DistSQLStatementParser.CreateDatabaseDiscoveryRuleContext ctx) {
+        return new CreateDatabaseDiscoveryRuleStatement(ctx.databaseDiscoveryRuleDefinition().stream().map(each -> (DatabaseDiscoveryRuleSegment) visit(each)).collect(Collectors.toList()));
+    }
+
+    @Override
+    public ASTNode visitDatabaseDiscoveryRuleDefinition(final DistSQLStatementParser.DatabaseDiscoveryRuleDefinitionContext ctx) {
+        DatabaseDiscoveryRuleSegment result = new DatabaseDiscoveryRuleSegment();
+        result.setName(ctx.ruleName().getText());
+        result.setDataSources(ctx.resources().IDENTIFIER().stream().map(each -> new IdentifierValue(each.getText()).getValue()).collect(Collectors.toList()));
+        result.setDiscoveryTypeName(ctx.functionDefinition().functionName().getText());
+        result.setProps(buildAlgorithmProperties(ctx.functionDefinition().algorithmProperties()));
+        return result;
+    }
+
     @Override
     public ASTNode visitTableName(final TableNameContext ctx) {
         return new TableNameSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), new IdentifierValue(ctx.getText()));
@@ -340,4 +357,12 @@ public final class DistSQLVisitor extends DistSQLStatementBaseVisitor<ASTNode> {
     public ASTNode visitCheckScalingJob(final CheckScalingJobContext ctx) {
         return new CheckScalingJobStatement(Long.parseLong(ctx.jobId().getText()));
     }
+
+    private Properties buildAlgorithmProperties(final DistSQLStatementParser.AlgorithmPropertiesContext ctx) {
+        Properties result = new Properties();
+        for (AlgorithmPropertyContext each : ctx.algorithmProperty()) {
+            result.setProperty(new IdentifierValue(each.key.getText()).getValue(), new IdentifierValue(each.value.getText()).getValue());
+        }
+        return result;
+    }
 }
diff --git a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/test/java/org/apache/shardingsphere/distsql/parser/api/DistSQLStatementParserEngineTest.java b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/test/java/org/apache/shardingsphere/distsql/parser/api/DistSQLStatementParserEngineTest.java
index 89ae130..073a413 100644
--- a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/test/java/org/apache/shardingsphere/distsql/parser/api/DistSQLStatementParserEngineTest.java
+++ b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/test/java/org/apache/shardingsphere/distsql/parser/api/DistSQLStatementParserEngineTest.java
@@ -19,12 +19,14 @@ package org.apache.shardingsphere.distsql.parser.api;
 
 import org.apache.shardingsphere.distsql.parser.segment.DataSourceSegment;
 import org.apache.shardingsphere.distsql.parser.segment.TableRuleSegment;
+import org.apache.shardingsphere.distsql.parser.segment.rdl.DatabaseDiscoveryRuleSegment;
 import org.apache.shardingsphere.distsql.parser.segment.rdl.ShardingBindingTableRuleSegment;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterReadwriteSplittingRuleStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterShardingBindingTableRulesStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterShardingBroadcastTableRulesStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterShardingTableRuleStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.AddResourceStatement;
+import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateDatabaseDiscoveryRuleStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateReadwriteSplittingRuleStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateShardingBindingTableRulesStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateShardingBroadcastTableRulesStatement;
@@ -107,6 +109,14 @@ public final class DistSQLStatementParserEngineTest {
 
     private static final String RDL_DROP_READWRITE_SPLITTING_RULE = "DROP READWRITE_SPLITTING RULE ms_group_0,ms_group_1";
 
+    private static final String RDL_CREATE_DATABASE_DISCOVERY_RULE = "CREATE DB_DISCOVERY RULE ha_group_0 ("
+            + "RESOURCES(resource0,resource1),"
+            + "TYPE(NAME=mgr,PROPERTIES(groupName='92504d5b-6dec',keepAliveCron=''))),"
+            + "ha_group_1 ("
+            + "RESOURCES(resource2,resource3),"
+            + "TYPE(NAME=mgr2,PROPERTIES(groupName='92504d5b-6dec-2',keepAliveCron=''))"
+            + ")";
+
     private final DistSQLStatementParserEngine engine = new DistSQLStatementParserEngine();
     
     @Test
@@ -280,4 +290,22 @@ public final class DistSQLStatementParserEngineTest {
         assertTrue(sqlStatement instanceof DropReadwriteSplittingRuleStatement);
         assertThat(((DropReadwriteSplittingRuleStatement) sqlStatement).getRuleNames(), is(Arrays.asList("ms_group_0", "ms_group_1")));
     }
+
+    @Test
+    public void assertParseCreateDatabaseDiscoveryRule() {
+        SQLStatement sqlStatement = engine.parse(RDL_CREATE_DATABASE_DISCOVERY_RULE);
+        assertTrue(sqlStatement instanceof CreateDatabaseDiscoveryRuleStatement);
+        CreateDatabaseDiscoveryRuleStatement statement = (CreateDatabaseDiscoveryRuleStatement) sqlStatement;
+        assertThat(statement.getDatabaseDiscoveryRules().size(), is(2));
+        List<DatabaseDiscoveryRuleSegment> databaseDiscoveryRuleSegments
+                = new ArrayList<>(((CreateDatabaseDiscoveryRuleStatement) sqlStatement).getDatabaseDiscoveryRules());
+        assertThat(databaseDiscoveryRuleSegments.get(0).getName(), is("ha_group_0"));
+        assertThat(databaseDiscoveryRuleSegments.get(0).getDiscoveryTypeName(), is("mgr"));
+        assertThat(databaseDiscoveryRuleSegments.get(0).getDataSources(), is(Arrays.asList("resource0", "resource1")));
+        assertThat(databaseDiscoveryRuleSegments.get(0).getProps().get("groupName"), is("92504d5b-6dec"));
+        assertThat(databaseDiscoveryRuleSegments.get(1).getName(), is("ha_group_1"));
+        assertThat(databaseDiscoveryRuleSegments.get(1).getDiscoveryTypeName(), is("mgr2"));
+        assertThat(databaseDiscoveryRuleSegments.get(1).getDataSources(), is(Arrays.asList("resource2", "resource3")));
+        assertThat(databaseDiscoveryRuleSegments.get(1).getProps().get("groupName"), is("92504d5b-6dec-2"));
+    }
 }
diff --git a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4 b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-statement/src/main/java/org/apache/shardingsphere/distsql/parser/segment/rdl/DatabaseDiscoveryRuleSegment.java
similarity index 51%
copy from shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4
copy to shardingsphere-distsql-parser/shardingsphere-distsql-parser-statement/src/main/java/org/apache/shardingsphere/distsql/parser/segment/rdl/DatabaseDiscoveryRuleSegment.java
index 724288a..0c37486 100644
--- a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4
+++ b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-statement/src/main/java/org/apache/shardingsphere/distsql/parser/segment/rdl/DatabaseDiscoveryRuleSegment.java
@@ -15,33 +15,27 @@
  * limitations under the License.
  */
 
-grammar DistSQLStatement;
-
-import Symbol, RDLStatement, RQLStatement, RALStatement;
-
-execute
-    : (addResource
-    | dropResource
-    | createShardingTableRule
-    | createShardingBindingTableRules
-    | createShardingBroadcastTableRules
-    | createReadwriteSplittingRule
-    | alterShardingTableRule
-    | alterShardingBindingTableRules
-    | alterShardingBroadcastTableRules
-    | dropShardingTableRule
-    | dropShardingBindingTableRules
-    | dropShardingBroadcastTableRules
-    | alterReadwriteSplittingRule
-    | dropReadwriteSplittingRule
-    | showResources
-    | showRule
-    | showScalingJobList
-    | showScalingJobStatus
-    | startScalingJob
-    | stopScalingJob
-    | dropScalingJob
-    | resetScalingJob
-    | checkScalingJob
-    ) SEMI?
-    ;
+package org.apache.shardingsphere.distsql.parser.segment.rdl;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.api.visitor.ASTNode;
+
+import java.util.Collection;
+import java.util.Properties;
+
+/**
+ * Database discovery rule segment.
+ */
+@Getter
+@Setter
+public final class DatabaseDiscoveryRuleSegment implements ASTNode {
+
+    private String name;
+
+    private Collection<String> dataSources;
+
+    private String discoveryTypeName;
+
+    private Properties props;
+}
diff --git a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4 b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-statement/src/main/java/org/apache/shardingsphere/distsql/parser/statement/rdl/create/impl/CreateDatabaseDiscoveryRuleStatement.java
similarity index 51%
copy from shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4
copy to shardingsphere-distsql-parser/shardingsphere-distsql-parser-statement/src/main/java/org/apache/shardingsphere/distsql/parser/statement/rdl/create/impl/CreateDatabaseDiscoveryRuleStatement.java
index 724288a..4e35267 100644
--- a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4
+++ b/shardingsphere-distsql-parser/shardingsphere-distsql-parser-statement/src/main/java/org/apache/shardingsphere/distsql/parser/statement/rdl/create/impl/CreateDatabaseDiscoveryRuleStatement.java
@@ -15,33 +15,21 @@
  * limitations under the License.
  */
 
-grammar DistSQLStatement;
+package org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl;
 
-import Symbol, RDLStatement, RQLStatement, RALStatement;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.distsql.parser.segment.rdl.DatabaseDiscoveryRuleSegment;
+import org.apache.shardingsphere.distsql.parser.statement.rdl.create.CreateRDLStatement;
 
-execute
-    : (addResource
-    | dropResource
-    | createShardingTableRule
-    | createShardingBindingTableRules
-    | createShardingBroadcastTableRules
-    | createReadwriteSplittingRule
-    | alterShardingTableRule
-    | alterShardingBindingTableRules
-    | alterShardingBroadcastTableRules
-    | dropShardingTableRule
-    | dropShardingBindingTableRules
-    | dropShardingBroadcastTableRules
-    | alterReadwriteSplittingRule
-    | dropReadwriteSplittingRule
-    | showResources
-    | showRule
-    | showScalingJobList
-    | showScalingJobStatus
-    | startScalingJob
-    | stopScalingJob
-    | dropScalingJob
-    | resetScalingJob
-    | checkScalingJob
-    ) SEMI?
-    ;
+import java.util.Collection;
+
+/**
+ * Create database discovery rule statement.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class CreateDatabaseDiscoveryRuleStatement extends CreateRDLStatement {
+    
+    private final Collection<DatabaseDiscoveryRuleSegment> databaseDiscoveryRules;
+}
diff --git a/shardingsphere-features/shardingsphere-db-discovery/shardingsphere-db-discovery-common/pom.xml b/shardingsphere-features/shardingsphere-db-discovery/shardingsphere-db-discovery-common/pom.xml
index 864b51a..94e5804 100644
--- a/shardingsphere-features/shardingsphere-db-discovery/shardingsphere-db-discovery-common/pom.xml
+++ b/shardingsphere-features/shardingsphere-db-discovery/shardingsphere-db-discovery-common/pom.xml
@@ -39,7 +39,11 @@
             <artifactId>shardingsphere-db-discovery-mgr</artifactId>
             <version>${project.version}</version>
         </dependency>
-        
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-distsql-parser-statement</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>com.h2database</groupId>
             <artifactId>h2</artifactId>
diff --git a/shardingsphere-features/shardingsphere-db-discovery/shardingsphere-db-discovery-common/src/main/java/org/apache/shardingsphere/dbdiscovery/common/yaml/converter/DatabaseDiscoveryRuleStatementConverter.java b/shardingsphere-features/shardingsphere-db-discovery/shardingsphere-db-discovery-common/src/main/java/org/apache/shardingsphere/dbdiscovery/common/yaml/converter/DatabaseDiscoveryRuleStatementConverter.java
new file mode 100644
index 0000000..8ecb178
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-db-discovery/shardingsphere-db-discovery-common/src/main/java/org/apache/shardingsphere/dbdiscovery/common/yaml/converter/DatabaseDiscoveryRuleStatementConverter.java
@@ -0,0 +1,70 @@
+/*
+ * 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.dbdiscovery.common.yaml.converter;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.dbdiscovery.common.yaml.config.YamlDatabaseDiscoveryRuleConfiguration;
+import org.apache.shardingsphere.dbdiscovery.common.yaml.config.rule.YamlDatabaseDiscoveryDataSourceRuleConfiguration;
+import org.apache.shardingsphere.distsql.parser.segment.rdl.DatabaseDiscoveryRuleSegment;
+import org.apache.shardingsphere.infra.yaml.config.algorithm.YamlShardingSphereAlgorithmConfiguration;
+
+import java.util.Collection;
+
+/**
+ * Database discovery rule statement converter.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class DatabaseDiscoveryRuleStatementConverter {
+    
+    /**
+     * Convert database discovery rule segment to YAML database discovery rule configuration.
+     *
+     * @param databaseDiscoveryRuleSegments collection of database discovery rule segments
+     * @return YAML database discovery rule configuration
+     */
+    public static YamlDatabaseDiscoveryRuleConfiguration convert(final Collection<DatabaseDiscoveryRuleSegment> databaseDiscoveryRuleSegments) {
+        YamlDatabaseDiscoveryRuleConfiguration result = new YamlDatabaseDiscoveryRuleConfiguration();
+        for (DatabaseDiscoveryRuleSegment each : databaseDiscoveryRuleSegments) {
+            String databaseDiscoveryType = getDatabaseDiscoveryType(each.getName(), each.getDiscoveryTypeName());
+            result.getDataSources().put(each.getName(), buildDataSourceRuleConfiguration(databaseDiscoveryType, each));
+            result.getDiscoveryTypes().put(databaseDiscoveryType, buildDiscoveryType(each));
+        }
+        return result;
+    }
+
+    private static YamlDatabaseDiscoveryDataSourceRuleConfiguration buildDataSourceRuleConfiguration(final String databaseDiscoveryType,
+                                                                                                     final DatabaseDiscoveryRuleSegment databaseDiscoveryRuleSegment) {
+        YamlDatabaseDiscoveryDataSourceRuleConfiguration result = new YamlDatabaseDiscoveryDataSourceRuleConfiguration();
+        result.getDataSourceNames().addAll(databaseDiscoveryRuleSegment.getDataSources());
+        result.setDiscoveryTypeName(databaseDiscoveryType);
+        result.setProps(databaseDiscoveryRuleSegment.getProps());
+        return result;
+    }
+
+    private static YamlShardingSphereAlgorithmConfiguration buildDiscoveryType(final DatabaseDiscoveryRuleSegment databaseDiscoveryRuleSegment) {
+        YamlShardingSphereAlgorithmConfiguration result = new YamlShardingSphereAlgorithmConfiguration();
+        result.setType(databaseDiscoveryRuleSegment.getDiscoveryTypeName());
+        result.setProps(databaseDiscoveryRuleSegment.getProps());
+        return result;
+    }
+
+    private static String getDatabaseDiscoveryType(final String ruleName, final String databaseDiscoveryType) {
+        return String.format("%s_%s", ruleName, databaseDiscoveryType);
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-db-discovery/shardingsphere-db-discovery-common/src/test/java/org/apache/shardingsphere/dbdiscovery/common/yaml/converter/DatabaseDiscoveryRuleStatementConverterTest.java b/shardingsphere-features/shardingsphere-db-discovery/shardingsphere-db-discovery-common/src/test/java/org/apache/shardingsphere/dbdiscovery/common/yaml/converter/DatabaseDiscoveryRuleStatementConverterTest.java
new file mode 100644
index 0000000..1245699
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-db-discovery/shardingsphere-db-discovery-common/src/test/java/org/apache/shardingsphere/dbdiscovery/common/yaml/converter/DatabaseDiscoveryRuleStatementConverterTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.dbdiscovery.common.yaml.converter;
+
+import org.apache.shardingsphere.dbdiscovery.common.yaml.config.YamlDatabaseDiscoveryRuleConfiguration;
+import org.apache.shardingsphere.distsql.parser.segment.rdl.DatabaseDiscoveryRuleSegment;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Properties;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.hamcrest.CoreMatchers.is;
+
+public final class DatabaseDiscoveryRuleStatementConverterTest {
+
+    @Test
+    public void assertConvert() {
+        YamlDatabaseDiscoveryRuleConfiguration yamlDatabaseDiscoveryRuleConfiguration
+                = DatabaseDiscoveryRuleStatementConverter.convert(buildDatabaseDiscoveryRuleSegments());
+        assertNotNull(yamlDatabaseDiscoveryRuleConfiguration);
+        assertThat(yamlDatabaseDiscoveryRuleConfiguration.getDataSources().keySet(), is(Collections.singleton("pr_ds")));
+        assertThat(yamlDatabaseDiscoveryRuleConfiguration.getDataSources().get("pr_ds").getDataSourceNames(), is(Arrays.asList("resource0", "resource1")));
+        assertThat(yamlDatabaseDiscoveryRuleConfiguration.getDataSources().get("pr_ds").getDiscoveryTypeName(), is("pr_ds_MGR"));
+        assertThat(yamlDatabaseDiscoveryRuleConfiguration.getDiscoveryTypes().keySet(), is(Collections.singleton("pr_ds_MGR")));
+        assertThat(yamlDatabaseDiscoveryRuleConfiguration.getDiscoveryTypes().get("pr_ds_MGR").getType(), is("MGR"));
+        assertThat(yamlDatabaseDiscoveryRuleConfiguration.getDiscoveryTypes().get("pr_ds_MGR").getProps().get("test"), is("value"));
+    }
+
+    private Collection<DatabaseDiscoveryRuleSegment> buildDatabaseDiscoveryRuleSegments() {
+        DatabaseDiscoveryRuleSegment segment = new DatabaseDiscoveryRuleSegment();
+        segment.setName("pr_ds");
+        segment.setDiscoveryTypeName("MGR");
+        segment.setDataSources(Arrays.asList("resource0", "resource1"));
+        Properties properties = new Properties();
+        properties.setProperty("test", "value");
+        segment.setProps(properties);
+        return Collections.singleton(segment);
+    }
+}
diff --git a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4 b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/exception/DatabaseDiscoveryRuleExistsException.java
similarity index 51%
copy from shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4
copy to shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/exception/DatabaseDiscoveryRuleExistsException.java
index 724288a..2998737 100644
--- a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/exception/DatabaseDiscoveryRuleExistsException.java
@@ -15,33 +15,19 @@
  * limitations under the License.
  */
 
-grammar DistSQLStatement;
+package org.apache.shardingsphere.proxy.backend.exception;
 
-import Symbol, RDLStatement, RQLStatement, RALStatement;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
 
-execute
-    : (addResource
-    | dropResource
-    | createShardingTableRule
-    | createShardingBindingTableRules
-    | createShardingBroadcastTableRules
-    | createReadwriteSplittingRule
-    | alterShardingTableRule
-    | alterShardingBindingTableRules
-    | alterShardingBroadcastTableRules
-    | dropShardingTableRule
-    | dropShardingBindingTableRules
-    | dropShardingBroadcastTableRules
-    | alterReadwriteSplittingRule
-    | dropReadwriteSplittingRule
-    | showResources
-    | showRule
-    | showScalingJobList
-    | showScalingJobStatus
-    | startScalingJob
-    | stopScalingJob
-    | dropScalingJob
-    | resetScalingJob
-    | checkScalingJob
-    ) SEMI?
-    ;
+/**
+ * Database discovery rule exists exception.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class DatabaseDiscoveryRuleExistsException extends BackendException {
+
+    private static final long serialVersionUID = 2601434420083783457L;
+
+    private final String schemaName;
+}
diff --git a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4 b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/exception/InvalidDatabaseDiscoveryTypesException.java
similarity index 51%
copy from shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4
copy to shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/exception/InvalidDatabaseDiscoveryTypesException.java
index 724288a..1304e2b 100644
--- a/shardingsphere-distsql-parser/shardingsphere-distsql-parser-engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/DistSQLStatement.g4
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/exception/InvalidDatabaseDiscoveryTypesException.java
@@ -15,33 +15,21 @@
  * limitations under the License.
  */
 
-grammar DistSQLStatement;
+package org.apache.shardingsphere.proxy.backend.exception;
 
-import Symbol, RDLStatement, RQLStatement, RALStatement;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
 
-execute
-    : (addResource
-    | dropResource
-    | createShardingTableRule
-    | createShardingBindingTableRules
-    | createShardingBroadcastTableRules
-    | createReadwriteSplittingRule
-    | alterShardingTableRule
-    | alterShardingBindingTableRules
-    | alterShardingBroadcastTableRules
-    | dropShardingTableRule
-    | dropShardingBindingTableRules
-    | dropShardingBroadcastTableRules
-    | alterReadwriteSplittingRule
-    | dropReadwriteSplittingRule
-    | showResources
-    | showRule
-    | showScalingJobList
-    | showScalingJobStatus
-    | startScalingJob
-    | stopScalingJob
-    | dropScalingJob
-    | resetScalingJob
-    | checkScalingJob
-    ) SEMI?
-    ;
+import java.util.Collection;
+
+/**
+ * Invalid database discovery types exception.
+ */
+@AllArgsConstructor
+@Getter
+public final class InvalidDatabaseDiscoveryTypesException extends BackendException {
+
+    private static final long serialVersionUID = -6919328513016324005L;
+
+    private final Collection<String> databaseDiscoveryTypes;
+}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/RDLBackendHandlerFactory.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/RDLBackendHandlerFactory.java
index a4081e5..497b644 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/RDLBackendHandlerFactory.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/RDLBackendHandlerFactory.java
@@ -24,6 +24,7 @@ import org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterShardin
 import org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterShardingBroadcastTableRulesStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterShardingTableRuleStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.AddResourceStatement;
+import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateDatabaseDiscoveryRuleStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateReadwriteSplittingRuleStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateShardingBindingTableRulesStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateShardingBroadcastTableRulesStatement;
@@ -44,6 +45,7 @@ import org.apache.shardingsphere.proxy.backend.text.distsql.rdl.impl.AlterShardi
 import org.apache.shardingsphere.proxy.backend.text.distsql.rdl.impl.AlterShardingBroadcastTableRulesBackendHandler;
 import org.apache.shardingsphere.proxy.backend.text.distsql.rdl.impl.AlterShardingTableRuleBackendHandler;
 import org.apache.shardingsphere.proxy.backend.text.distsql.rdl.impl.CreateDatabaseBackendHandler;
+import org.apache.shardingsphere.proxy.backend.text.distsql.rdl.impl.CreateDatabaseDiscoveryRuleBackendHandler;
 import org.apache.shardingsphere.proxy.backend.text.distsql.rdl.impl.CreateReadwriteSplittingRuleBackendHandler;
 import org.apache.shardingsphere.proxy.backend.text.distsql.rdl.impl.CreateShardingBindingTableRulesBackendHandler;
 import org.apache.shardingsphere.proxy.backend.text.distsql.rdl.impl.CreateShardingBroadcastTableRulesBackendHandler;
@@ -142,6 +144,9 @@ public final class RDLBackendHandlerFactory {
         if (sqlStatement instanceof DropShardingBroadcastTableRulesStatement) {
             return Optional.of(new DropShardingBroadcastTableRulesBackendHandler((DropShardingBroadcastTableRulesStatement) sqlStatement, backendConnection));
         }
+        if (sqlStatement instanceof CreateDatabaseDiscoveryRuleStatement) {
+            return Optional.of(new CreateDatabaseDiscoveryRuleBackendHandler((CreateDatabaseDiscoveryRuleStatement) sqlStatement, backendConnection));
+        }
         return Optional.empty();
     }
 }
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/impl/CreateDatabaseDiscoveryRuleBackendHandler.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/impl/CreateDatabaseDiscoveryRuleBackendHandler.java
new file mode 100644
index 0000000..b9c9b1e
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/impl/CreateDatabaseDiscoveryRuleBackendHandler.java
@@ -0,0 +1,90 @@
+/*
+ * 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.proxy.backend.text.distsql.rdl.impl;
+
+import org.apache.shardingsphere.dbdiscovery.api.config.DatabaseDiscoveryRuleConfiguration;
+import org.apache.shardingsphere.dbdiscovery.common.yaml.config.YamlDatabaseDiscoveryRuleConfiguration;
+import org.apache.shardingsphere.dbdiscovery.common.yaml.converter.DatabaseDiscoveryRuleStatementConverter;
+import org.apache.shardingsphere.dbdiscovery.spi.DatabaseDiscoveryType;
+import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateDatabaseDiscoveryRuleStatement;
+import org.apache.shardingsphere.governance.core.registry.listener.event.rule.RuleConfigurationsAlteredEvent;
+import org.apache.shardingsphere.infra.config.RuleConfiguration;
+import org.apache.shardingsphere.infra.eventbus.ShardingSphereEventBus;
+import org.apache.shardingsphere.infra.spi.typed.TypedSPIRegistry;
+import org.apache.shardingsphere.infra.yaml.swapper.YamlRuleConfigurationSwapperEngine;
+import org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import org.apache.shardingsphere.proxy.backend.exception.DatabaseDiscoveryRuleExistsException;
+import org.apache.shardingsphere.proxy.backend.exception.InvalidDatabaseDiscoveryTypesException;
+import org.apache.shardingsphere.proxy.backend.exception.ResourceNotExistedException;
+import org.apache.shardingsphere.proxy.backend.response.header.ResponseHeader;
+import org.apache.shardingsphere.proxy.backend.response.header.update.UpdateResponseHeader;
+import org.apache.shardingsphere.proxy.backend.text.SchemaRequiredBackendHandler;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.stream.Collectors;
+
+/**
+ * Create database discovery rule backend handler.
+ */
+public final class CreateDatabaseDiscoveryRuleBackendHandler extends SchemaRequiredBackendHandler<CreateDatabaseDiscoveryRuleStatement> {
+
+    public CreateDatabaseDiscoveryRuleBackendHandler(final CreateDatabaseDiscoveryRuleStatement sqlStatement, final BackendConnection backendConnection) {
+        super(sqlStatement, backendConnection);
+    }
+    
+    @Override
+    public ResponseHeader execute(final String schemaName, final CreateDatabaseDiscoveryRuleStatement sqlStatement) {
+        check(schemaName, sqlStatement);
+        YamlDatabaseDiscoveryRuleConfiguration config = DatabaseDiscoveryRuleStatementConverter.convert(sqlStatement.getDatabaseDiscoveryRules());
+        Collection<RuleConfiguration> rules = new YamlRuleConfigurationSwapperEngine().swapToRuleConfigurations(Collections.singleton(config));
+        post(schemaName, rules);
+        return new UpdateResponseHeader(sqlStatement);
+    }
+    
+    private void check(final String schemaName, final CreateDatabaseDiscoveryRuleStatement sqlStatement) {
+        if (ProxyContext.getInstance().getMetaData(schemaName).getRuleMetaData().getConfigurations().stream().anyMatch(each -> each instanceof DatabaseDiscoveryRuleConfiguration)) {
+            throw new DatabaseDiscoveryRuleExistsException(schemaName);
+        }
+        Collection<String> resources = new LinkedHashSet<>();
+        sqlStatement.getDatabaseDiscoveryRules().forEach(each -> resources.addAll(each.getDataSources()));
+        Collection<String> notExistResources = resources.stream().filter(each -> !this.isValidResource(schemaName, each)).collect(Collectors.toList());
+        if (!notExistResources.isEmpty()) {
+            throw new ResourceNotExistedException(notExistResources);
+        }
+        Collection<String> invalidDiscoveryTypes = sqlStatement.getDatabaseDiscoveryRules().stream().map(each -> each.getDiscoveryTypeName()).distinct()
+                .filter(each -> !TypedSPIRegistry.findRegisteredService(DatabaseDiscoveryType.class, each, new Properties()).isPresent())
+                .collect(Collectors.toList());
+        if (!invalidDiscoveryTypes.isEmpty()) {
+            throw new InvalidDatabaseDiscoveryTypesException(invalidDiscoveryTypes);
+        }
+    }
+
+    private boolean isValidResource(final String schemaName, final String resourceName) {
+        return Objects.nonNull(ProxyContext.getInstance().getMetaData(schemaName).getResource())
+                && ProxyContext.getInstance().getMetaData(schemaName).getResource().getDataSources().containsKey(resourceName);
+    }
+
+    private void post(final String schemaName, final Collection<RuleConfiguration> rules) {
+        ShardingSphereEventBus.getInstance().post(new RuleConfigurationsAlteredEvent(schemaName, rules));
+    }
+}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/fixture/TestDatabaseDiscoveryType.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/fixture/TestDatabaseDiscoveryType.java
new file mode 100644
index 0000000..d3c85ae
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/fixture/TestDatabaseDiscoveryType.java
@@ -0,0 +1,58 @@
+/*
+ * 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.proxy.backend.text.distsql.fixture;
+
+import org.apache.shardingsphere.dbdiscovery.spi.DatabaseDiscoveryType;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Test database discovery type.
+ */
+public final class TestDatabaseDiscoveryType implements DatabaseDiscoveryType {
+    @Override
+    public void checkDatabaseDiscoveryConfig(final Map<String, DataSource> dataSourceMap, final String schemaName) throws SQLException {
+    }
+
+    @Override
+    public void updatePrimaryDataSource(final Map<String, DataSource> dataSourceMap, final String schemaName,
+                                        final Collection<String> disabledDataSourceNames, final String groupName, final String primaryDataSourceName) {
+    }
+
+    @Override
+    public void updateMemberState(final Map<String, DataSource> dataSourceMap, final String schemaName, final Collection<String> disabledDataSourceNames) {
+    }
+
+    @Override
+    public void startPeriodicalUpdate(final Map<String, DataSource> dataSourceMap, final String schemaName,
+                                      final Collection<String> disabledDataSourceNames, final String groupName, final String primaryDataSourceName) {
+    }
+
+    @Override
+    public String getPrimaryDataSource() {
+        return null;
+    }
+
+    @Override
+    public String getType() {
+        return "TEST";
+    }
+}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/impl/CreateDatabaseDiscoveryRuleBackendHandlerTest.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/impl/CreateDatabaseDiscoveryRuleBackendHandlerTest.java
new file mode 100644
index 0000000..ca1b978
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/impl/CreateDatabaseDiscoveryRuleBackendHandlerTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.proxy.backend.text.distsql.rdl.impl;
+
+import com.google.common.collect.Maps;
+import org.apache.shardingsphere.dbdiscovery.api.config.DatabaseDiscoveryRuleConfiguration;
+import org.apache.shardingsphere.dbdiscovery.spi.DatabaseDiscoveryType;
+import org.apache.shardingsphere.distsql.parser.segment.rdl.DatabaseDiscoveryRuleSegment;
+import org.apache.shardingsphere.distsql.parser.statement.rdl.create.impl.CreateDatabaseDiscoveryRuleStatement;
+import org.apache.shardingsphere.infra.context.metadata.MetaDataContexts;
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import org.apache.shardingsphere.infra.metadata.resource.ShardingSphereResource;
+import org.apache.shardingsphere.infra.metadata.rule.ShardingSphereRuleMetaData;
+import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader;
+import org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import org.apache.shardingsphere.proxy.backend.exception.DatabaseDiscoveryRuleExistsException;
+import org.apache.shardingsphere.proxy.backend.exception.InvalidDatabaseDiscoveryTypesException;
+import org.apache.shardingsphere.proxy.backend.exception.ResourceNotExistedException;
+import org.apache.shardingsphere.proxy.backend.response.header.ResponseHeader;
+import org.apache.shardingsphere.proxy.backend.response.header.update.UpdateResponseHeader;
+import org.apache.shardingsphere.transaction.context.TransactionContexts;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import javax.sql.DataSource;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public final class CreateDatabaseDiscoveryRuleBackendHandlerTest {
+    
+    @Mock
+    private BackendConnection backendConnection;
+    
+    @Mock
+    private CreateDatabaseDiscoveryRuleStatement sqlStatement;
+    
+    @Mock
+    private MetaDataContexts metaDataContexts;
+    
+    @Mock
+    private TransactionContexts transactionContexts;
+    
+    @Mock
+    private ShardingSphereMetaData shardingSphereMetaData;
+    
+    @Mock
+    private ShardingSphereRuleMetaData ruleMetaData;
+
+    @Mock
+    private ShardingSphereResource shardingSphereResource;
+    
+    private CreateDatabaseDiscoveryRuleBackendHandler handler = new CreateDatabaseDiscoveryRuleBackendHandler(sqlStatement, backendConnection);
+    
+    @Before
+    public void setUp() {
+        ShardingSphereServiceLoader.register(DatabaseDiscoveryType.class);
+        ProxyContext.getInstance().init(metaDataContexts, transactionContexts);
+        when(metaDataContexts.getAllSchemaNames()).thenReturn(Collections.singletonList("test"));
+        when(metaDataContexts.getMetaData(eq("test"))).thenReturn(shardingSphereMetaData);
+        when(shardingSphereMetaData.getRuleMetaData()).thenReturn(ruleMetaData);
+    }
+    
+    @Test
+    public void assertExecute() {
+        DatabaseDiscoveryRuleSegment databaseDiscoveryRuleSegment = new DatabaseDiscoveryRuleSegment();
+        databaseDiscoveryRuleSegment.setName("pr_ds");
+        databaseDiscoveryRuleSegment.setDataSources(Arrays.asList("ds_read_0", "ds_read_1"));
+        databaseDiscoveryRuleSegment.setDiscoveryTypeName("TEST");
+        when(sqlStatement.getDatabaseDiscoveryRules()).thenReturn(Collections.singletonList(databaseDiscoveryRuleSegment));
+        when(shardingSphereMetaData.getResource()).thenReturn(shardingSphereResource);
+        Map<String, DataSource> dataSourceMap = mock(Map.class);
+        when(shardingSphereResource.getDataSources()).thenReturn(dataSourceMap);
+        when(dataSourceMap.containsKey(anyString())).thenReturn(true);
+        ResponseHeader responseHeader = handler.execute("test", sqlStatement);
+        assertNotNull(responseHeader);
+        assertTrue(responseHeader instanceof UpdateResponseHeader);
+    }
+    
+    @Test(expected = DatabaseDiscoveryRuleExistsException.class)
+    public void assertExecuteWithExistReadwriteSplittingRule() {
+        when(ruleMetaData.getConfigurations()).thenReturn(Collections.singletonList(new DatabaseDiscoveryRuleConfiguration(Collections.emptyList(), Maps.newHashMap())));
+        handler.execute("test", sqlStatement);
+    }
+    
+    @Test(expected = ResourceNotExistedException.class)
+    public void assertExecuteWithNotExistResources() {
+        DatabaseDiscoveryRuleSegment databaseDiscoveryRuleSegment = new DatabaseDiscoveryRuleSegment();
+        databaseDiscoveryRuleSegment.setName("pr_ds");
+        databaseDiscoveryRuleSegment.setDataSources(Arrays.asList("ds_read_0", "ds_read_1"));
+        when(sqlStatement.getDatabaseDiscoveryRules()).thenReturn(Collections.singletonList(databaseDiscoveryRuleSegment));
+        handler.execute("test", sqlStatement);
+    }
+
+    @Test(expected = InvalidDatabaseDiscoveryTypesException.class)
+    public void assertExecuteWithDatabaseDiscoveryType() {
+        DatabaseDiscoveryRuleSegment databaseDiscoveryRuleSegment = new DatabaseDiscoveryRuleSegment();
+        databaseDiscoveryRuleSegment.setName("pr_ds");
+        databaseDiscoveryRuleSegment.setDataSources(Arrays.asList("ds_read_0", "ds_read_1"));
+        databaseDiscoveryRuleSegment.setDiscoveryTypeName("notExistDiscoveryType");
+        when(sqlStatement.getDatabaseDiscoveryRules()).thenReturn(Collections.singletonList(databaseDiscoveryRuleSegment));
+        when(shardingSphereMetaData.getResource()).thenReturn(shardingSphereResource);
+        Map<String, DataSource> dataSourceMap = mock(Map.class);
+        when(shardingSphereResource.getDataSources()).thenReturn(dataSourceMap);
+        when(dataSourceMap.containsKey(anyString())).thenReturn(true);
+        handler.execute("test", sqlStatement);
+    }
+}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/resources/META-INF/services/org.apache.shardingsphere.dbdiscovery.spi.DatabaseDiscoveryType b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/resources/META-INF/services/org.apache.shardingsphere.dbdiscovery.spi.DatabaseDiscoveryType
new file mode 100644
index 0000000..84576e1
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/resources/META-INF/services/org.apache.shardingsphere.dbdiscovery.spi.DatabaseDiscoveryType
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.apache.shardingsphere.proxy.backend.text.distsql.fixture.TestDatabaseDiscoveryType
diff --git a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/err/MySQLErrPacketFactory.java b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/err/MySQLErrPacketFactory.java
index 2bed806..e5db727 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/err/MySQLErrPacketFactory.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-frontend/shardingsphere-proxy-frontend-mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/err/MySQLErrPacketFactory.java
@@ -27,8 +27,10 @@ import org.apache.shardingsphere.proxy.backend.exception.AddReadwriteSplittingRu
 import org.apache.shardingsphere.proxy.backend.exception.CircuitBreakException;
 import org.apache.shardingsphere.proxy.backend.exception.DBCreateExistsException;
 import org.apache.shardingsphere.proxy.backend.exception.DBDropExistsException;
+import org.apache.shardingsphere.proxy.backend.exception.DatabaseDiscoveryRuleExistsException;
 import org.apache.shardingsphere.proxy.backend.exception.DuplicateResourceException;
 import org.apache.shardingsphere.proxy.backend.exception.DuplicateTablesException;
+import org.apache.shardingsphere.proxy.backend.exception.InvalidDatabaseDiscoveryTypesException;
 import org.apache.shardingsphere.proxy.backend.exception.InvalidLoadBalancersException;
 import org.apache.shardingsphere.proxy.backend.exception.InvalidResourceException;
 import org.apache.shardingsphere.proxy.backend.exception.NoDatabaseSelectedException;
@@ -182,6 +184,12 @@ public final class MySQLErrPacketFactory {
         if (cause instanceof InvalidLoadBalancersException) {
             return new MySQLErrPacket(1, CommonErrorCode.INVALID_LOAD_BALANCERS, ((InvalidLoadBalancersException) cause).getLoadBalancers());
         }
+        if (cause instanceof DatabaseDiscoveryRuleExistsException) {
+            return new MySQLErrPacket(1, CommonErrorCode.DATABASE_DISCOVERY_RULE_EXIST, ((DatabaseDiscoveryRuleExistsException) cause).getSchemaName());
+        }
+        if (cause instanceof InvalidDatabaseDiscoveryTypesException) {
+            return new MySQLErrPacket(1, CommonErrorCode.INVALID_DATABASE_DISCOVERY_TYPES, ((InvalidDatabaseDiscoveryTypesException) cause).getDatabaseDiscoveryTypes());
+        }
         return new MySQLErrPacket(1, CommonErrorCode.UNKNOWN_EXCEPTION, cause.getMessage());
     }
 }