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/25 14:57:43 UTC

[shardingsphere] branch master updated: Add IF NOT EXISTS to CREATE SHADOW RULE. (#23086)

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 c502722672f Add IF NOT EXISTS to CREATE SHADOW RULE. (#23086)
c502722672f is described below

commit c502722672fb006f5b4832ef1ec449d4296af65f
Author: yx9o <ya...@163.com>
AuthorDate: Sun Dec 25 22:57:36 2022 +0800

    Add IF NOT EXISTS to CREATE SHADOW RULE. (#23086)
    
    * Add IF NOT EXISTS to CREATE SHADOW RULE.
    
    * Update.
---
 .../update/CreateShadowRuleStatementUpdater.java   | 46 +++++++++++---------
 .../CreateShadowRuleStatementUpdaterTest.java      | 49 ++++++++++++----------
 .../src/main/antlr4/imports/shadow/RDLStatement.g4 |  2 +-
 .../parser/core/ShadowDistSQLStatementVisitor.java |  2 +-
 .../statement/CreateShadowRuleStatement.java       |  7 +++-
 5 files changed, 60 insertions(+), 46 deletions(-)

diff --git a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateShadowRuleStatementUpdater.java b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateShadowRuleStatementUpdater.java
index 2bbea7c7592..e9ff092ae15 100644
--- a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateShadowRuleStatementUpdater.java
+++ b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateShadowRuleStatementUpdater.java
@@ -17,10 +17,10 @@
 
 package org.apache.shardingsphere.shadow.distsql.handler.update;
 
-import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
-import org.apache.shardingsphere.distsql.handler.exception.rule.DuplicateRuleException;
 import org.apache.shardingsphere.distsql.handler.exception.algorithm.InvalidAlgorithmConfigurationException;
+import org.apache.shardingsphere.distsql.handler.exception.rule.DuplicateRuleException;
 import org.apache.shardingsphere.distsql.handler.update.RuleDefinitionCreateUpdater;
+import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
 import org.apache.shardingsphere.shadow.api.config.ShadowRuleConfiguration;
@@ -28,7 +28,6 @@ import org.apache.shardingsphere.shadow.api.config.table.ShadowTableConfiguratio
 import org.apache.shardingsphere.shadow.distsql.handler.checker.ShadowRuleStatementChecker;
 import org.apache.shardingsphere.shadow.distsql.handler.converter.ShadowRuleStatementConverter;
 import org.apache.shardingsphere.shadow.distsql.handler.supporter.ShadowRuleStatementSupporter;
-import org.apache.shardingsphere.shadow.distsql.parser.segment.ShadowAlgorithmSegment;
 import org.apache.shardingsphere.shadow.distsql.parser.segment.ShadowRuleSegment;
 import org.apache.shardingsphere.shadow.distsql.parser.statement.CreateShadowRuleStatement;
 import org.apache.shardingsphere.shadow.factory.ShadowAlgorithmFactory;
@@ -44,9 +43,15 @@ public final class CreateShadowRuleStatementUpdater implements RuleDefinitionCre
     
     private static final String SHADOW = "shadow";
     
+    private Collection<String> identicalRuleNames;
+    
     @Override
     public RuleConfiguration buildToBeCreatedRuleConfiguration(final CreateShadowRuleStatement sqlStatement) {
-        return ShadowRuleStatementConverter.convert(sqlStatement.getRules());
+        Collection<ShadowRuleSegment> rules = sqlStatement.getRules();
+        if (null != identicalRuleNames && !identicalRuleNames.isEmpty()) {
+            rules = sqlStatement.getRules().stream().filter(each -> !identicalRuleNames.contains(each.getRuleName())).collect(Collectors.toSet());
+        }
+        return ShadowRuleStatementConverter.convert(rules);
     }
     
     @Override
@@ -66,33 +71,34 @@ public final class CreateShadowRuleStatementUpdater implements RuleDefinitionCre
     public void checkSQLStatement(final ShardingSphereDatabase database, final CreateShadowRuleStatement sqlStatement, final ShadowRuleConfiguration currentRuleConfig) {
         String databaseName = database.getName();
         Collection<ShadowRuleSegment> rules = sqlStatement.getRules();
-        checkRuleNames(databaseName, rules, currentRuleConfig);
+        checkRuleNames(databaseName, sqlStatement, currentRuleConfig);
         checkResources(database, rules);
-        checkAlgorithms(databaseName, sqlStatement.getRules());
-        checkAlgorithmType(sqlStatement);
+        checkAlgorithms(databaseName, rules);
+        checkAlgorithmType(rules);
     }
     
-    private void checkRuleNames(final String databaseName, final Collection<ShadowRuleSegment> rules, final ShadowRuleConfiguration currentRuleConfig) {
-        Collection<String> requireRuleNames = ShadowRuleStatementSupporter.getRuleNames(rules);
-        ShadowRuleStatementChecker.checkAnyDuplicate(requireRuleNames, duplicated -> new DuplicateRuleException(SHADOW, databaseName, duplicated));
-        Collection<String> currentRuleName = ShadowRuleStatementSupporter.getRuleNames(currentRuleConfig);
-        ShadowRuleStatementChecker.checkAnyDuplicate(requireRuleNames, currentRuleName, identical -> new DuplicateRuleException(SHADOW, databaseName, identical));
+    private void checkRuleNames(final String databaseName, final CreateShadowRuleStatement sqlStatement, final ShadowRuleConfiguration currentRuleConfig) {
+        Collection<String> toBeCreatedRuleNames = ShadowRuleStatementSupporter.getRuleNames(sqlStatement.getRules());
+        ShadowRuleStatementChecker.checkAnyDuplicate(toBeCreatedRuleNames, duplicated -> new DuplicateRuleException(SHADOW, databaseName, duplicated));
+        toBeCreatedRuleNames.retainAll(ShadowRuleStatementSupporter.getRuleNames(currentRuleConfig));
+        if (sqlStatement.isIfNotExists()) {
+            identicalRuleNames = toBeCreatedRuleNames;
+            return;
+        }
+        ShardingSpherePreconditions.checkState(toBeCreatedRuleNames.isEmpty(), () -> new DuplicateRuleException(SHADOW, databaseName, toBeCreatedRuleNames));
     }
     
     private void checkResources(final ShardingSphereDatabase database, final Collection<ShadowRuleSegment> rules) {
-        Collection<String> requireResource = ShadowRuleStatementSupporter.getResourceNames(rules);
-        ShadowRuleStatementChecker.checkResourceExist(requireResource, database);
+        ShadowRuleStatementChecker.checkResourceExist(ShadowRuleStatementSupporter.getResourceNames(rules), database);
     }
     
     private void checkAlgorithms(final String databaseName, final Collection<ShadowRuleSegment> rules) {
-        Collection<ShadowAlgorithmSegment> shadowAlgorithmSegment = ShadowRuleStatementSupporter.getShadowAlgorithmSegment(rules);
-        ShadowRuleStatementChecker.checkAlgorithmCompleteness(shadowAlgorithmSegment);
-        Collection<String> requireAlgorithms = ShadowRuleStatementSupporter.getAlgorithmNames(rules);
-        ShadowRuleStatementChecker.checkAnyDuplicate(requireAlgorithms, duplicated -> new DuplicateRuleException("Shadow", databaseName, duplicated));
+        ShadowRuleStatementChecker.checkAlgorithmCompleteness(ShadowRuleStatementSupporter.getShadowAlgorithmSegment(rules));
+        ShadowRuleStatementChecker.checkAnyDuplicate(ShadowRuleStatementSupporter.getAlgorithmNames(rules), duplicated -> new DuplicateRuleException(SHADOW, databaseName, duplicated));
     }
     
-    private void checkAlgorithmType(final CreateShadowRuleStatement sqlStatement) {
-        Collection<String> nonexistentAlgorithmTypes = sqlStatement.getRules().stream().flatMap(each -> each.getShadowTableRules().values().stream()).flatMap(Collection::stream)
+    private void checkAlgorithmType(final Collection<ShadowRuleSegment> rules) {
+        Collection<String> nonexistentAlgorithmTypes = rules.stream().flatMap(each -> each.getShadowTableRules().values().stream()).flatMap(Collection::stream)
                 .map(each -> each.getAlgorithmSegment().getName()).collect(Collectors.toSet()).stream().filter(each -> !ShadowAlgorithmFactory.contains(each)).collect(Collectors.toSet());
         ShardingSpherePreconditions.checkState(nonexistentAlgorithmTypes.isEmpty(), () -> new InvalidAlgorithmConfigurationException(SHADOW, nonexistentAlgorithmTypes));
     }
diff --git a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/CreateShadowRuleStatementUpdaterTest.java b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/CreateShadowRuleStatementUpdaterTest.java
index 496dc25acb1..2efdf8d0f89 100644
--- a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/CreateShadowRuleStatementUpdaterTest.java
+++ b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/CreateShadowRuleStatementUpdaterTest.java
@@ -17,10 +17,10 @@
 
 package org.apache.shardingsphere.shadow.distsql.update;
 
-import org.apache.shardingsphere.distsql.parser.segment.AlgorithmSegment;
+import org.apache.shardingsphere.distsql.handler.exception.algorithm.InvalidAlgorithmConfigurationException;
 import org.apache.shardingsphere.distsql.handler.exception.resource.MissingRequiredResourcesException;
 import org.apache.shardingsphere.distsql.handler.exception.rule.DuplicateRuleException;
-import org.apache.shardingsphere.distsql.handler.exception.algorithm.InvalidAlgorithmConfigurationException;
+import org.apache.shardingsphere.distsql.parser.segment.AlgorithmSegment;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.resource.ShardingSphereResourceMetaData;
 import org.apache.shardingsphere.shadow.api.config.ShadowRuleConfiguration;
@@ -38,7 +38,6 @@ import org.mockito.junit.MockitoJUnitRunner;
 
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.List;
 import java.util.Properties;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -68,54 +67,60 @@ public final class CreateShadowRuleStatementUpdaterTest {
     @Test(expected = DuplicateRuleException.class)
     public void assertExecuteWithDuplicateRuleName() {
         ShadowRuleSegment ruleSegment = new ShadowRuleSegment("ruleName", null, null, null);
-        updater.checkSQLStatement(database, createSQLStatement(ruleSegment, ruleSegment), null);
+        updater.checkSQLStatement(database, createSQLStatement(false, ruleSegment, ruleSegment), null);
     }
     
     @Test(expected = DuplicateRuleException.class)
     public void assertExecuteWithDuplicateRuleNameInMetaData() {
         when(currentConfig.getDataSources()).thenReturn(Collections.singletonList(new ShadowDataSourceConfiguration("ruleName", "ds", "ds_shadow")));
         ShadowRuleSegment ruleSegment = new ShadowRuleSegment("ruleName", null, null, null);
-        updater.checkSQLStatement(database, createSQLStatement(ruleSegment), currentConfig);
+        updater.checkSQLStatement(database, createSQLStatement(false, ruleSegment), currentConfig);
     }
     
     @Test(expected = MissingRequiredResourcesException.class)
     public void assertExecuteWithNotExistResource() {
-        List<String> dataSources = Arrays.asList("ds0", "ds1");
-        when(resourceMetaData.getNotExistedResources(any())).thenReturn(dataSources);
-        CreateShadowRuleStatement sqlStatement = createSQLStatement(new ShadowRuleSegment("ruleName", "ds1", null, null));
+        when(resourceMetaData.getNotExistedResources(any())).thenReturn(Arrays.asList("ds0", "ds1"));
+        CreateShadowRuleStatement sqlStatement = createSQLStatement(false, new ShadowRuleSegment("ruleName", "ds1", null, null));
         updater.checkSQLStatement(database, sqlStatement, currentConfig);
     }
     
     @Test(expected = DuplicateRuleException.class)
     public void assertExecuteDuplicateAlgorithm() {
-        Properties prop = new Properties();
-        prop.setProperty("type", "value");
-        ShadowAlgorithmSegment segment = new ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("name", prop));
-        CreateShadowRuleStatement sqlStatement = createSQLStatement(new ShadowRuleSegment("ruleName", "ds", null, Collections.singletonMap("t_order", Collections.singleton(segment))),
+        ShadowAlgorithmSegment segment = new ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("name", createProperties()));
+        CreateShadowRuleStatement sqlStatement = createSQLStatement(false, new ShadowRuleSegment("ruleName", "ds", null, Collections.singletonMap("t_order", Collections.singleton(segment))),
                 new ShadowRuleSegment("ruleName", "ds1", null, Collections.singletonMap("t_order_1", Collections.singletonList(segment))));
         updater.checkSQLStatement(database, sqlStatement, currentConfig);
     }
     
     @Test(expected = DuplicateRuleException.class)
     public void assertExecuteDuplicateAlgorithmWithoutConfiguration() {
-        Properties prop = new Properties();
-        prop.setProperty("type", "value");
-        ShadowAlgorithmSegment segment = new ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("name", prop));
-        CreateShadowRuleStatement sqlStatement = createSQLStatement(new ShadowRuleSegment("ruleName", "ds", null, Collections.singletonMap("t_order", Collections.singleton(segment))),
+        ShadowAlgorithmSegment segment = new ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("name", createProperties()));
+        CreateShadowRuleStatement sqlStatement = createSQLStatement(false, new ShadowRuleSegment("ruleName", "ds", null, Collections.singletonMap("t_order", Collections.singleton(segment))),
                 new ShadowRuleSegment("ruleName1", "ds1", null, Collections.singletonMap("t_order_1", Collections.singletonList(segment))));
         updater.checkSQLStatement(database, sqlStatement, null);
     }
     
     @Test(expected = InvalidAlgorithmConfigurationException.class)
     public void assertInvalidAlgorithmConfiguration() {
-        Properties prop = new Properties();
-        prop.setProperty("type", "value");
-        ShadowAlgorithmSegment segment = new ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("type", prop));
-        CreateShadowRuleStatement sqlStatement = createSQLStatement(new ShadowRuleSegment("ruleName", "ds", null, Collections.singletonMap("t_order", Collections.singleton(segment))));
+        ShadowAlgorithmSegment segment = new ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("type", createProperties()));
+        CreateShadowRuleStatement sqlStatement = createSQLStatement(false, new ShadowRuleSegment("ruleName", "ds", null, Collections.singletonMap("t_order", Collections.singleton(segment))));
         updater.checkSQLStatement(database, sqlStatement, currentConfig);
     }
     
-    private CreateShadowRuleStatement createSQLStatement(final ShadowRuleSegment... ruleSegments) {
-        return new CreateShadowRuleStatement(Arrays.asList(ruleSegments));
+    @Test
+    public void assertExecuteWithIfNotExists() {
+        ShadowAlgorithmSegment segment = new ShadowAlgorithmSegment("algorithmName", new AlgorithmSegment("SIMPLE_HINT", createProperties()));
+        CreateShadowRuleStatement sqlStatement = createSQLStatement(true, new ShadowRuleSegment("initRuleName", "ds", null, Collections.singletonMap("t_order", Collections.singleton(segment))));
+        updater.checkSQLStatement(database, sqlStatement, currentConfig);
+    }
+    
+    private CreateShadowRuleStatement createSQLStatement(final boolean ifNotExists, final ShadowRuleSegment... ruleSegments) {
+        return new CreateShadowRuleStatement(ifNotExists, Arrays.asList(ruleSegments));
+    }
+    
+    private Properties createProperties() {
+        Properties result = new Properties();
+        result.setProperty("type", "value");
+        return result;
     }
 }
diff --git a/features/shadow/distsql/parser/src/main/antlr4/imports/shadow/RDLStatement.g4 b/features/shadow/distsql/parser/src/main/antlr4/imports/shadow/RDLStatement.g4
index 715a56c73de..c5070ec67d0 100644
--- a/features/shadow/distsql/parser/src/main/antlr4/imports/shadow/RDLStatement.g4
+++ b/features/shadow/distsql/parser/src/main/antlr4/imports/shadow/RDLStatement.g4
@@ -20,7 +20,7 @@ grammar RDLStatement;
 import BaseRule;
 
 createShadowRule
-    : CREATE SHADOW RULE shadowRuleDefinition (COMMA_ shadowRuleDefinition)*
+    : CREATE SHADOW RULE ifNotExists? shadowRuleDefinition (COMMA_ shadowRuleDefinition)*
     ;
 
 alterShadowRule
diff --git a/features/shadow/distsql/parser/src/main/java/org/apache/shardingsphere/shadow/distsql/parser/core/ShadowDistSQLStatementVisitor.java b/features/shadow/distsql/parser/src/main/java/org/apache/shardingsphere/shadow/distsql/parser/core/ShadowDistSQLStatementVisitor.java
index 4b45a095ab6..f8d5960c853 100644
--- a/features/shadow/distsql/parser/src/main/java/org/apache/shardingsphere/shadow/distsql/parser/core/ShadowDistSQLStatementVisitor.java
+++ b/features/shadow/distsql/parser/src/main/java/org/apache/shardingsphere/shadow/distsql/parser/core/ShadowDistSQLStatementVisitor.java
@@ -74,7 +74,7 @@ public final class ShadowDistSQLStatementVisitor extends ShadowDistSQLStatementB
     @Override
     public ASTNode visitCreateShadowRule(final CreateShadowRuleContext ctx) {
         List<ShadowRuleSegment> shadowRuleSegments = ctx.shadowRuleDefinition().stream().map(this::visit).map(each -> (ShadowRuleSegment) each).collect(Collectors.toList());
-        return new CreateShadowRuleStatement(autoCreateAlgorithmName(shadowRuleSegments));
+        return new CreateShadowRuleStatement(null != ctx.ifNotExists(), autoCreateAlgorithmName(shadowRuleSegments));
     }
     
     @Override
diff --git a/features/shadow/distsql/statement/src/main/java/org/apache/shardingsphere/shadow/distsql/parser/statement/CreateShadowRuleStatement.java b/features/shadow/distsql/statement/src/main/java/org/apache/shardingsphere/shadow/distsql/parser/statement/CreateShadowRuleStatement.java
index bd570112964..df86e08647f 100644
--- a/features/shadow/distsql/statement/src/main/java/org/apache/shardingsphere/shadow/distsql/parser/statement/CreateShadowRuleStatement.java
+++ b/features/shadow/distsql/statement/src/main/java/org/apache/shardingsphere/shadow/distsql/parser/statement/CreateShadowRuleStatement.java
@@ -18,7 +18,6 @@
 package org.apache.shardingsphere.shadow.distsql.parser.statement;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.CreateRuleStatement;
 import org.apache.shardingsphere.shadow.distsql.parser.segment.ShadowRuleSegment;
 
@@ -27,9 +26,13 @@ import java.util.Collection;
 /**
  * Create shadow rule statement.
  */
-@RequiredArgsConstructor
 @Getter
 public final class CreateShadowRuleStatement extends CreateRuleStatement {
     
     private final Collection<ShadowRuleSegment> rules;
+    
+    public CreateShadowRuleStatement(final boolean ifNotExists, final Collection<ShadowRuleSegment> rules) {
+        super(ifNotExists);
+        this.rules = rules;
+    }
 }