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/12/28 17:02:43 UTC

[shardingsphere] branch master updated: Add `IF NOT EXISTS` to `create db_discovery rule` (#23127)

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 83ba8fa18ff Add `IF NOT EXISTS` to `create db_discovery rule` (#23127)
83ba8fa18ff is described below

commit 83ba8fa18ff6a3bf560feade856cae96662569d7
Author: Zichao <57...@users.noreply.github.com>
AuthorDate: Thu Dec 29 06:02:37 2022 +1300

    Add `IF NOT EXISTS` to `create db_discovery rule` (#23127)
    
    * Add `IF NOT EXISTS` to `create db_discovery rule`
    
    * Add `IF NOT EXISTS` to `create db_discovery rule`
    
    * Add `IF NOT EXISTS` to `create encrypt rule`
---
 ...reateDatabaseDiscoveryRuleStatementUpdater.java | 32 ++++++++++++-
 ...eDatabaseDiscoveryRuleStatementUpdaterTest.java | 55 +++++++++++++++++++---
 .../main/antlr4/imports/db-discovery/Keyword.g4    |  4 ++
 .../antlr4/imports/db-discovery/RDLStatement.g4    |  6 ++-
 .../DatabaseDiscoveryDistSQLStatementVisitor.java  |  3 +-
 .../CreateDatabaseDiscoveryRuleStatement.java      |  7 ++-
 6 files changed, 96 insertions(+), 11 deletions(-)

diff --git a/features/db-discovery/distsql/handler/src/main/java/org/apache/shardingsphere/dbdiscovery/distsql/handler/update/CreateDatabaseDiscoveryRuleStatementUpdater.java b/features/db-discovery/distsql/handler/src/main/java/org/apache/shardingsphere/dbdiscovery/distsql/handler/update/CreateDatabaseDiscoveryRuleStatementUpdater.java
index dcc0bcb169c..456f5c5d19e 100644
--- a/features/db-discovery/distsql/handler/src/main/java/org/apache/shardingsphere/dbdiscovery/distsql/handler/update/CreateDatabaseDiscoveryRuleStatementUpdater.java
+++ b/features/db-discovery/distsql/handler/src/main/java/org/apache/shardingsphere/dbdiscovery/distsql/handler/update/CreateDatabaseDiscoveryRuleStatementUpdater.java
@@ -36,6 +36,7 @@ import org.apache.shardingsphere.infra.util.exception.ShardingSpherePrecondition
 import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -48,10 +49,15 @@ public final class CreateDatabaseDiscoveryRuleStatementUpdater implements RuleDe
     
     private static final String RULE_TYPE = "Database discovery";
     
+    private boolean ifNotExists;
+    
     @Override
     public void checkSQLStatement(final ShardingSphereDatabase database, final CreateDatabaseDiscoveryRuleStatement sqlStatement, final DatabaseDiscoveryRuleConfiguration currentRuleConfig) {
         String databaseName = database.getName();
-        checkDuplicateRuleNames(databaseName, sqlStatement, currentRuleConfig);
+        ifNotExists = sqlStatement.isIfNotExists();
+        if (!ifNotExists) {
+            checkDuplicateRuleNames(databaseName, sqlStatement, currentRuleConfig);
+        }
         checkResources(databaseName, sqlStatement, database.getResourceMetaData());
         checkDiscoverTypeAndHeartbeat(databaseName, sqlStatement, currentRuleConfig);
     }
@@ -95,12 +101,36 @@ public final class CreateDatabaseDiscoveryRuleStatementUpdater implements RuleDe
     @Override
     public void updateCurrentRuleConfiguration(final DatabaseDiscoveryRuleConfiguration currentRuleConfig, final DatabaseDiscoveryRuleConfiguration toBeCreatedRuleConfig) {
         if (null != currentRuleConfig) {
+            if (ifNotExists) {
+                removeDuplicatedRules(currentRuleConfig, toBeCreatedRuleConfig);
+            }
+            if (toBeCreatedRuleConfig.getDataSources().isEmpty()) {
+                return;
+            }
             currentRuleConfig.getDataSources().addAll(toBeCreatedRuleConfig.getDataSources());
             currentRuleConfig.getDiscoveryTypes().putAll(toBeCreatedRuleConfig.getDiscoveryTypes());
             currentRuleConfig.getDiscoveryHeartbeats().putAll(toBeCreatedRuleConfig.getDiscoveryHeartbeats());
         }
     }
     
+    private void removeDuplicatedRules(final DatabaseDiscoveryRuleConfiguration currentRuleConfig, final DatabaseDiscoveryRuleConfiguration toBeCreatedRuleConfig) {
+        Collection<String> currentRules = new LinkedList<>();
+        Collection<String> toBeRemovedDataSources = new LinkedList<>();
+        Collection<String> toBeRemovedHeartBeats = new LinkedList<>();
+        Collection<String> toBeRemovedTypes = new LinkedList<>();
+        currentRuleConfig.getDataSources().forEach(each -> currentRules.add(each.getGroupName()));
+        toBeCreatedRuleConfig.getDataSources().forEach(each -> {
+            if (currentRules.contains(each.getGroupName())) {
+                toBeRemovedHeartBeats.add(each.getDiscoveryHeartbeatName());
+                toBeRemovedTypes.add(each.getDiscoveryTypeName());
+                toBeRemovedDataSources.add(each.getGroupName());
+            }
+        });
+        toBeCreatedRuleConfig.getDataSources().removeIf(each -> toBeRemovedDataSources.contains(each.getGroupName()));
+        toBeCreatedRuleConfig.getDiscoveryHeartbeats().keySet().removeIf(toBeRemovedHeartBeats::contains);
+        toBeCreatedRuleConfig.getDiscoveryTypes().keySet().removeIf(toBeRemovedTypes::contains);
+    }
+    
     @Override
     public Class<DatabaseDiscoveryRuleConfiguration> getRuleConfigurationClass() {
         return DatabaseDiscoveryRuleConfiguration.class;
diff --git a/features/db-discovery/distsql/handler/src/test/java/org/apache/shardingsphere/dbdiscovery/distsql/handler/update/CreateDatabaseDiscoveryRuleStatementUpdaterTest.java b/features/db-discovery/distsql/handler/src/test/java/org/apache/shardingsphere/dbdiscovery/distsql/handler/update/CreateDatabaseDiscoveryRuleStatementUpdaterTest.java
index aaaaa6c2c2e..046083a76ca 100644
--- a/features/db-discovery/distsql/handler/src/test/java/org/apache/shardingsphere/dbdiscovery/distsql/handler/update/CreateDatabaseDiscoveryRuleStatementUpdaterTest.java
+++ b/features/db-discovery/distsql/handler/src/test/java/org/apache/shardingsphere/dbdiscovery/distsql/handler/update/CreateDatabaseDiscoveryRuleStatementUpdaterTest.java
@@ -19,12 +19,13 @@ package org.apache.shardingsphere.dbdiscovery.distsql.handler.update;
 
 import org.apache.shardingsphere.dbdiscovery.api.config.DatabaseDiscoveryRuleConfiguration;
 import org.apache.shardingsphere.dbdiscovery.api.config.rule.DatabaseDiscoveryDataSourceRuleConfiguration;
+import org.apache.shardingsphere.dbdiscovery.distsql.parser.segment.AbstractDatabaseDiscoverySegment;
 import org.apache.shardingsphere.dbdiscovery.distsql.parser.segment.DatabaseDiscoveryDefinitionSegment;
 import org.apache.shardingsphere.dbdiscovery.distsql.parser.statement.CreateDatabaseDiscoveryRuleStatement;
+import org.apache.shardingsphere.distsql.handler.exception.algorithm.InvalidAlgorithmConfigurationException;
 import org.apache.shardingsphere.distsql.parser.segment.AlgorithmSegment;
 import org.apache.shardingsphere.distsql.handler.exception.storageunit.MissingRequiredStorageUnitsException;
 import org.apache.shardingsphere.distsql.handler.exception.rule.DuplicateRuleException;
-import org.apache.shardingsphere.distsql.handler.exception.algorithm.InvalidAlgorithmConfigurationException;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.resource.ShardingSphereResourceMetaData;
 import org.junit.Before;
@@ -35,6 +36,7 @@ import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
@@ -43,6 +45,7 @@ import java.util.stream.Collectors;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.when;
@@ -69,7 +72,7 @@ public final class CreateDatabaseDiscoveryRuleStatementUpdaterTest {
         Properties props = new Properties();
         DatabaseDiscoveryDefinitionSegment databaseDiscoveryDefinitionSegment =
                 new DatabaseDiscoveryDefinitionSegment("readwrite_ds", Collections.emptyList(), new AlgorithmSegment("MySQL.MGR", props), props);
-        updater.checkSQLStatement(database, new CreateDatabaseDiscoveryRuleStatement(Collections.singletonList(databaseDiscoveryDefinitionSegment)),
+        updater.checkSQLStatement(database, new CreateDatabaseDiscoveryRuleStatement(false, Collections.singletonList(databaseDiscoveryDefinitionSegment)),
                 new DatabaseDiscoveryRuleConfiguration(Collections.singleton(dataSourceRuleConfig), Collections.emptyMap(), Collections.emptyMap()));
     }
     
@@ -79,14 +82,14 @@ public final class CreateDatabaseDiscoveryRuleStatementUpdaterTest {
         Properties props = new Properties();
         DatabaseDiscoveryDefinitionSegment segment =
                 new DatabaseDiscoveryDefinitionSegment("readwrite_ds", Arrays.asList("ds_read_0", "ds_read_1"), new AlgorithmSegment("MySQL.MGR", props), props);
-        updater.checkSQLStatement(database, new CreateDatabaseDiscoveryRuleStatement(Collections.singleton(segment)), null);
+        updater.checkSQLStatement(database, new CreateDatabaseDiscoveryRuleStatement(false, Collections.singleton(segment)), null);
     }
     
     @Test(expected = InvalidAlgorithmConfigurationException.class)
     public void assertCheckSQLStatementWithDatabaseDiscoveryType() {
         AlgorithmSegment algorithmSegment = new AlgorithmSegment("INVALID_TYPE", new Properties());
         DatabaseDiscoveryDefinitionSegment segment = new DatabaseDiscoveryDefinitionSegment("readwrite_ds", Arrays.asList("ds_read_0", "ds_read_1"), algorithmSegment, new Properties());
-        updater.checkSQLStatement(database, new CreateDatabaseDiscoveryRuleStatement(Collections.singleton(segment)), null);
+        updater.checkSQLStatement(database, new CreateDatabaseDiscoveryRuleStatement(false, Collections.singleton(segment)), null);
     }
     
     @Test
@@ -94,7 +97,7 @@ public final class CreateDatabaseDiscoveryRuleStatementUpdaterTest {
         AlgorithmSegment algorithmSegment = new AlgorithmSegment("MySQL.MGR", new Properties());
         DatabaseDiscoveryDefinitionSegment definitionSegment = new DatabaseDiscoveryDefinitionSegment("readwrite_ds_1", Arrays.asList("ds_read_0", "ds_read_1"), algorithmSegment, new Properties());
         DatabaseDiscoveryRuleConfiguration ruleConfig =
-                updater.buildToBeCreatedRuleConfiguration(new CreateDatabaseDiscoveryRuleStatement(Collections.singletonList(definitionSegment)));
+                updater.buildToBeCreatedRuleConfiguration(new CreateDatabaseDiscoveryRuleStatement(false, Collections.singletonList(definitionSegment)));
         assertThat(ruleConfig.getDataSources().size(), is(1));
         assertTrue(ruleConfig.getDataSources().stream().map(DatabaseDiscoveryDataSourceRuleConfiguration::getGroupName)
                 .collect(Collectors.toList()).removeAll(Collections.singletonList("readwrite_ds_1")));
@@ -107,7 +110,7 @@ public final class CreateDatabaseDiscoveryRuleStatementUpdaterTest {
         AlgorithmSegment algorithmSegment = new AlgorithmSegment("MySQL.MGR", new Properties());
         DatabaseDiscoveryDefinitionSegment definitionSegment = new DatabaseDiscoveryDefinitionSegment("readwrite_ds_1", Arrays.asList("ds_read_0", "ds_read_1"), algorithmSegment, new Properties());
         DatabaseDiscoveryRuleConfiguration toBeCreatedRuleConfig = updater.buildToBeCreatedRuleConfiguration(
-                new CreateDatabaseDiscoveryRuleStatement(Collections.singletonList(definitionSegment)));
+                new CreateDatabaseDiscoveryRuleStatement(false, Collections.singletonList(definitionSegment)));
         DatabaseDiscoveryRuleConfiguration currentConfig = new DatabaseDiscoveryRuleConfiguration(new LinkedList<>(), new LinkedHashMap<>(), new LinkedHashMap<>());
         updater.updateCurrentRuleConfiguration(currentConfig, toBeCreatedRuleConfig);
         assertThat(currentConfig.getDataSources().size(), is(1));
@@ -116,4 +119,44 @@ public final class CreateDatabaseDiscoveryRuleStatementUpdaterTest {
         assertTrue(currentConfig.getDiscoveryTypes().containsKey("readwrite_ds_1_mysql_mgr"));
         assertTrue(currentConfig.getDiscoveryHeartbeats().containsKey("readwrite_ds_1_heartbeat"));
     }
+    
+    @Test
+    public void assertUpdateWithIfNotExists() {
+        AlgorithmSegment algorithmSegment = new AlgorithmSegment("MySQL.MGR", new Properties());
+        DatabaseDiscoveryDefinitionSegment definitionSegmentDS1 = new DatabaseDiscoveryDefinitionSegment("readwrite_ds_1",
+                Arrays.asList("ds_read_0", "ds_read_1"), algorithmSegment, new Properties());
+        DatabaseDiscoveryDefinitionSegment definitionSegmentDS2 = new DatabaseDiscoveryDefinitionSegment("readwrite_ds_2",
+                Arrays.asList("ds_read_0", "ds_read_1"), algorithmSegment, new Properties());
+        Collection<AbstractDatabaseDiscoverySegment> currentRules = new LinkedList<>();
+        currentRules.add(definitionSegmentDS1);
+        currentRules.add(definitionSegmentDS2);
+        DatabaseDiscoveryRuleConfiguration toBeCreatedRuleConfig = updater.buildToBeCreatedRuleConfiguration(
+                new CreateDatabaseDiscoveryRuleStatement(false, currentRules));
+        DatabaseDiscoveryRuleConfiguration currentConfig = new DatabaseDiscoveryRuleConfiguration(new LinkedList<>(), new LinkedHashMap<>(), new LinkedHashMap<>());
+        updater.updateCurrentRuleConfiguration(currentConfig, toBeCreatedRuleConfig);
+        definitionSegmentDS1 = new DatabaseDiscoveryDefinitionSegment("readwrite_ds_1", Arrays.asList("ds_read_0", "ds_read_1", "ds_read_3"), algorithmSegment, new Properties());
+        definitionSegmentDS2 = new DatabaseDiscoveryDefinitionSegment("readwrite_ds_2", Arrays.asList("ds_read_0", "ds_read_1", "ds_read_3"), algorithmSegment, new Properties());
+        Collection<AbstractDatabaseDiscoverySegment> rules = new LinkedList<>();
+        rules.add(definitionSegmentDS1);
+        rules.add(definitionSegmentDS2);
+        CreateDatabaseDiscoveryRuleStatement statement = new CreateDatabaseDiscoveryRuleStatement(true, rules);
+        updater.checkSQLStatement(database, statement, currentConfig);
+        toBeCreatedRuleConfig = updater.buildToBeCreatedRuleConfiguration(statement);
+        updater.updateCurrentRuleConfiguration(currentConfig, toBeCreatedRuleConfig);
+        assertThat(currentConfig.getDataSources().size(), is(2));
+        assertTrue(currentConfig.getDataSources().stream().map(DatabaseDiscoveryDataSourceRuleConfiguration::getGroupName)
+                .collect(Collectors.toList()).removeAll(Collections.singletonList("readwrite_ds_1")));
+        assertTrue(currentConfig.getDataSources().stream().map(DatabaseDiscoveryDataSourceRuleConfiguration::getGroupName)
+                .collect(Collectors.toList()).removeAll(Collections.singletonList("readwrite_ds_2")));
+        assertTrue(currentConfig.getDiscoveryTypes().containsKey("readwrite_ds_1_mysql_mgr"));
+        assertTrue(currentConfig.getDiscoveryTypes().containsKey("readwrite_ds_2_mysql_mgr"));
+        assertTrue(currentConfig.getDiscoveryHeartbeats().containsKey("readwrite_ds_1_heartbeat"));
+        assertTrue(currentConfig.getDiscoveryHeartbeats().containsKey("readwrite_ds_2_heartbeat"));
+        Collection<String> dataSources = new LinkedList<>();
+        currentConfig.getDataSources().forEach(each -> dataSources.addAll(each.getDataSourceNames()));
+        assertThat(dataSources.size(), is(4));
+        assertTrue(dataSources.contains("ds_read_0"));
+        assertTrue(dataSources.contains("ds_read_1"));
+        assertFalse(dataSources.contains("ds_read_3"));
+    }
 }
diff --git a/features/db-discovery/distsql/parser/src/main/antlr4/imports/db-discovery/Keyword.g4 b/features/db-discovery/distsql/parser/src/main/antlr4/imports/db-discovery/Keyword.g4
index b46ecb54fff..a9673a887f4 100644
--- a/features/db-discovery/distsql/parser/src/main/antlr4/imports/db-discovery/Keyword.g4
+++ b/features/db-discovery/distsql/parser/src/main/antlr4/imports/db-discovery/Keyword.g4
@@ -106,3 +106,7 @@ COUNT
 MYSQLMGR
     : M Y S Q L DOT_ M G R
     ;
+
+NOT
+    : N O T
+    ;
diff --git a/features/db-discovery/distsql/parser/src/main/antlr4/imports/db-discovery/RDLStatement.g4 b/features/db-discovery/distsql/parser/src/main/antlr4/imports/db-discovery/RDLStatement.g4
index ae099b14273..1f3b9c0df19 100644
--- a/features/db-discovery/distsql/parser/src/main/antlr4/imports/db-discovery/RDLStatement.g4
+++ b/features/db-discovery/distsql/parser/src/main/antlr4/imports/db-discovery/RDLStatement.g4
@@ -20,7 +20,7 @@ grammar RDLStatement;
 import BaseRule;
 
 createDatabaseDiscoveryRule
-    : CREATE DB_DISCOVERY RULE databaseDiscoveryRule (COMMA_ databaseDiscoveryRule)*
+    : CREATE DB_DISCOVERY RULE ifNotExists? databaseDiscoveryRule (COMMA_ databaseDiscoveryRule)*
     ;
 
 alterDatabaseDiscoveryRule
@@ -70,3 +70,7 @@ discoveryHeartbeatName
 ifExists
     : IF EXISTS
     ;
+
+ifNotExists
+    : IF NOT EXISTS
+    ;
diff --git a/features/db-discovery/distsql/parser/src/main/java/org/apache/shardingsphere/dbdiscovery/distsql/parser/core/DatabaseDiscoveryDistSQLStatementVisitor.java b/features/db-discovery/distsql/parser/src/main/java/org/apache/shardingsphere/dbdiscovery/distsql/parser/core/DatabaseDiscoveryDistSQLStatementVisitor.java
index 3ec641bc0ef..06adba3b19f 100644
--- a/features/db-discovery/distsql/parser/src/main/java/org/apache/shardingsphere/dbdiscovery/distsql/parser/core/DatabaseDiscoveryDistSQLStatementVisitor.java
+++ b/features/db-discovery/distsql/parser/src/main/java/org/apache/shardingsphere/dbdiscovery/distsql/parser/core/DatabaseDiscoveryDistSQLStatementVisitor.java
@@ -63,7 +63,8 @@ public final class DatabaseDiscoveryDistSQLStatementVisitor extends DatabaseDisc
     
     @Override
     public ASTNode visitCreateDatabaseDiscoveryRule(final CreateDatabaseDiscoveryRuleContext ctx) {
-        return new CreateDatabaseDiscoveryRuleStatement(ctx.databaseDiscoveryRule().stream().map(each -> (AbstractDatabaseDiscoverySegment) visit(each)).collect(Collectors.toList()));
+        return new CreateDatabaseDiscoveryRuleStatement(null != ctx.ifNotExists(),
+                ctx.databaseDiscoveryRule().stream().map(each -> (AbstractDatabaseDiscoverySegment) visit(each)).collect(Collectors.toList()));
     }
     
     @Override
diff --git a/features/db-discovery/distsql/statement/src/main/java/org/apache/shardingsphere/dbdiscovery/distsql/parser/statement/CreateDatabaseDiscoveryRuleStatement.java b/features/db-discovery/distsql/statement/src/main/java/org/apache/shardingsphere/dbdiscovery/distsql/parser/statement/CreateDatabaseDiscoveryRuleStatement.java
index 1c041f1af50..eb59f6953b0 100644
--- a/features/db-discovery/distsql/statement/src/main/java/org/apache/shardingsphere/dbdiscovery/distsql/parser/statement/CreateDatabaseDiscoveryRuleStatement.java
+++ b/features/db-discovery/distsql/statement/src/main/java/org/apache/shardingsphere/dbdiscovery/distsql/parser/statement/CreateDatabaseDiscoveryRuleStatement.java
@@ -18,7 +18,6 @@
 package org.apache.shardingsphere.dbdiscovery.distsql.parser.statement;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.dbdiscovery.distsql.parser.segment.AbstractDatabaseDiscoverySegment;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.CreateRuleStatement;
 
@@ -27,9 +26,13 @@ import java.util.Collection;
 /**
  * Create database discovery rule statement.
  */
-@RequiredArgsConstructor
 @Getter
 public final class CreateDatabaseDiscoveryRuleStatement extends CreateRuleStatement {
     
     private final Collection<AbstractDatabaseDiscoverySegment> rules;
+    
+    public CreateDatabaseDiscoveryRuleStatement(final boolean ifNotExists, final Collection<AbstractDatabaseDiscoverySegment> rules) {
+        super(ifNotExists);
+        this.rules = rules;
+    }
 }