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 <[email protected]>
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;
+    }
 }

Reply via email to