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/29 03:01:24 UTC

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

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 07cc23297ea Add IF NOT EXISTS to CREATE READWRITE_SPLITTING RULE. (#23126)
07cc23297ea is described below

commit 07cc23297eac1b43a8e81dd4869d3ff0b7f309e2
Author: yx9o <ya...@163.com>
AuthorDate: Thu Dec 29 11:01:18 2022 +0800

    Add IF NOT EXISTS to CREATE READWRITE_SPLITTING RULE. (#23126)
    
    * Add IF NOT EXISTS to CREATE READWRITE_SPLITTING RULE.
    
    * Update.
    
    * Update.
---
 .../ReadwriteSplittingRuleStatementChecker.java    | 86 ++++++++++++----------
 ...eateReadwriteSplittingRuleStatementUpdater.java | 16 +++-
 ...ReadwriteSplittingRuleStatementUpdaterTest.java | 47 ++++++------
 .../antlr4/imports/readwrite-splitting/Keyword.g4  |  5 +-
 .../imports/readwrite-splitting/RDLStatement.g4    |  6 +-
 .../ReadwriteSplittingDistSQLStatementVisitor.java |  3 +-
 .../CreateReadwriteSplittingRuleStatement.java     |  9 ++-
 7 files changed, 100 insertions(+), 72 deletions(-)

diff --git a/features/readwrite-splitting/distsql/handler/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/handler/checker/ReadwriteSplittingRuleStatementChecker.java b/features/readwrite-splitting/distsql/handler/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/handler/checker/ReadwriteSplittingRuleStatementChecker.java
index 83ef736316c..abb311e4053 100644
--- a/features/readwrite-splitting/distsql/handler/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/handler/checker/ReadwriteSplittingRuleStatementChecker.java
+++ b/features/readwrite-splitting/distsql/handler/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/handler/checker/ReadwriteSplittingRuleStatementChecker.java
@@ -18,16 +18,16 @@
 package org.apache.shardingsphere.readwritesplitting.distsql.handler.checker;
 
 import com.google.common.base.Strings;
-import org.apache.shardingsphere.infra.rule.identifier.type.exportable.constant.ExportableConstants;
-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.distsql.handler.exception.rule.DuplicateRuleException;
 import org.apache.shardingsphere.distsql.handler.exception.rule.InvalidRuleConfigurationException;
 import org.apache.shardingsphere.distsql.handler.exception.rule.MissingRequiredRuleException;
+import org.apache.shardingsphere.distsql.handler.exception.storageunit.MissingRequiredStorageUnitsException;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.resource.ShardingSphereResourceMetaData;
 import org.apache.shardingsphere.infra.rule.identifier.type.exportable.ExportableRule;
 import org.apache.shardingsphere.infra.rule.identifier.type.exportable.RuleExportEngine;
+import org.apache.shardingsphere.infra.rule.identifier.type.exportable.constant.ExportableConstants;
 import org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
 import org.apache.shardingsphere.readwritesplitting.api.ReadwriteSplittingRuleConfiguration;
 import org.apache.shardingsphere.readwritesplitting.api.rule.ReadwriteSplittingDataSourceRuleConfiguration;
@@ -55,18 +55,21 @@ public final class ReadwriteSplittingRuleStatementChecker {
      * @param database database
      * @param segments segments
      * @param currentRuleConfig current rule config
+     * @param duplicatedRuleNames duplicated rule names
+     * @param ifNotExists rule if not exists
      */
-    public static void checkCreation(final ShardingSphereDatabase database, final Collection<ReadwriteSplittingRuleSegment> segments, final ReadwriteSplittingRuleConfiguration currentRuleConfig) {
+    public static void checkCreation(final ShardingSphereDatabase database, final Collection<ReadwriteSplittingRuleSegment> segments,
+                                     final ReadwriteSplittingRuleConfiguration currentRuleConfig, final Collection<String> duplicatedRuleNames, final boolean ifNotExists) {
         String databaseName = database.getName();
-        checkDuplicateRuleNames(databaseName, segments, currentRuleConfig, database.getResourceMetaData());
+        checkDuplicateRuleNames(databaseName, segments, currentRuleConfig, database.getResourceMetaData(), duplicatedRuleNames, ifNotExists);
         checkDataSourcesExist(databaseName, segments, database);
         checkDuplicatedDataSourceNames(databaseName, segments, currentRuleConfig, true);
         checkLoadBalancers(segments);
     }
     
     /**
-     *  Check alter readwrite splitting rule statement.
-     * 
+     * Check alter readwrite splitting rule statement.
+     *
      * @param database database
      * @param segments segments
      * @param currentRuleConfig current rule config
@@ -82,8 +85,8 @@ public final class ReadwriteSplittingRuleStatementChecker {
     }
     
     /**
-     *  Check current rule configuration exist.
-     * 
+     * Check current rule configuration exist.
+     *
      * @param database database
      * @param currentRuleConfig current rule config
      */
@@ -94,46 +97,54 @@ public final class ReadwriteSplittingRuleStatementChecker {
     private static void checkRuleNamesExist(final Collection<ReadwriteSplittingRuleSegment> segments, final ReadwriteSplittingRuleConfiguration currentRuleConfig, final String databaseName) {
         Collection<String> requiredRuleNames = segments.stream().map(ReadwriteSplittingRuleSegment::getName).collect(Collectors.toList());
         Collection<String> currentRuleNames = currentRuleConfig.getDataSources().stream().map(ReadwriteSplittingDataSourceRuleConfiguration::getName).collect(Collectors.toList());
-        Collection<String> notExistRuleNames = requiredRuleNames.stream().filter(each -> !currentRuleNames.contains(each)).collect(Collectors.toSet());
-        ShardingSpherePreconditions.checkState(notExistRuleNames.isEmpty(), () -> new MissingRequiredRuleException(databaseName, notExistRuleNames));
+        Collection<String> notExistedRuleNames = requiredRuleNames.stream().filter(each -> !currentRuleNames.contains(each)).collect(Collectors.toSet());
+        ShardingSpherePreconditions.checkState(notExistedRuleNames.isEmpty(), () -> new MissingRequiredRuleException(databaseName, notExistedRuleNames));
     }
     
-    private static void checkDuplicateRuleNames(final String databaseName, final Collection<ReadwriteSplittingRuleSegment> segments,
-                                                final ReadwriteSplittingRuleConfiguration currentRuleConfig, final ShardingSphereResourceMetaData resourceMetaData) {
+    private static void checkDuplicateRuleNames(final String databaseName, final Collection<ReadwriteSplittingRuleSegment> segments, final ReadwriteSplittingRuleConfiguration currentRuleConfig,
+                                                final ShardingSphereResourceMetaData resourceMetaData, final Collection<String> duplicatedRuleNames, final boolean ifNotExists) {
         checkDuplicateRuleNamesWithSelf(databaseName, segments);
-        checkDuplicateRuleNamesWithResourceMetaData(segments, resourceMetaData);
-        checkDuplicateRuleNamesWithRuleConfiguration(databaseName, segments, currentRuleConfig);
+        checkDuplicateRuleNamesWithResourceMetaData(resourceMetaData, ifNotExists, duplicatedRuleNames, segments);
+        checkDuplicateRuleNamesWithRuleConfiguration(databaseName, currentRuleConfig, ifNotExists, duplicatedRuleNames, segments);
     }
     
     private static void checkDuplicateRuleNamesWithSelf(final String databaseName, final Collection<ReadwriteSplittingRuleSegment> segments) {
-        Collection<String> requiredRuleNames = segments.stream().map(ReadwriteSplittingRuleSegment::getName).collect(Collectors.toList());
-        Collection<String> duplicateRuleNames = getDuplicate(requiredRuleNames);
-        ShardingSpherePreconditions.checkState(duplicateRuleNames.isEmpty(), () -> new DuplicateRuleException("Readwrite splitting", databaseName, duplicateRuleNames));
+        Collection<String> duplicatedRuleNames = getDuplicated(segments.stream().map(ReadwriteSplittingRuleSegment::getName).collect(Collectors.toList()));
+        ShardingSpherePreconditions.checkState(duplicatedRuleNames.isEmpty(), () -> new DuplicateRuleException("Readwrite splitting", databaseName, duplicatedRuleNames));
     }
     
-    private static Collection<String> getDuplicate(final Collection<String> require) {
-        return require.stream().collect(Collectors.groupingBy(each -> each, Collectors.counting())).entrySet().stream()
+    private static Collection<String> getDuplicated(final Collection<String> required) {
+        return required.stream().collect(Collectors.groupingBy(each -> each, Collectors.counting())).entrySet().stream()
                 .filter(each -> each.getValue() > 1).map(Map.Entry::getKey).collect(Collectors.toSet());
     }
     
-    private static void checkDuplicateRuleNamesWithResourceMetaData(final Collection<ReadwriteSplittingRuleSegment> segments, final ShardingSphereResourceMetaData resourceMetaData) {
+    private static void checkDuplicateRuleNamesWithResourceMetaData(final ShardingSphereResourceMetaData resourceMetaData, final boolean ifNotExists, final Collection<String> duplicatedRuleNames,
+                                                                    final Collection<ReadwriteSplittingRuleSegment> segments) {
         Collection<String> currentRuleNames = new LinkedList<>();
         if (null != resourceMetaData && null != resourceMetaData.getDataSources()) {
             currentRuleNames.addAll(resourceMetaData.getDataSources().keySet());
         }
-        Collection<String> duplicateRuleNames = segments.stream().map(ReadwriteSplittingRuleSegment::getName).filter(currentRuleNames::contains).collect(Collectors.toList());
-        ShardingSpherePreconditions.checkState(duplicateRuleNames.isEmpty(), () -> new InvalidRuleConfigurationException("Readwrite splitting", duplicateRuleNames,
-                Collections.singleton(String.format("%s already exists in storage unit", duplicateRuleNames))));
+        Collection<String> toBeCreatedRuleNames = segments.stream().map(ReadwriteSplittingRuleSegment::getName).filter(currentRuleNames::contains).collect(Collectors.toList());
+        if (ifNotExists) {
+            duplicatedRuleNames.addAll(toBeCreatedRuleNames);
+            return;
+        }
+        ShardingSpherePreconditions.checkState(toBeCreatedRuleNames.isEmpty(), () -> new InvalidRuleConfigurationException("Readwrite splitting", toBeCreatedRuleNames,
+                Collections.singleton(String.format("%s already exists in storage unit", toBeCreatedRuleNames))));
     }
     
-    private static void checkDuplicateRuleNamesWithRuleConfiguration(final String databaseName, final Collection<ReadwriteSplittingRuleSegment> segments,
-                                                                     final ReadwriteSplittingRuleConfiguration currentRuleConfig) {
+    private static void checkDuplicateRuleNamesWithRuleConfiguration(final String databaseName, final ReadwriteSplittingRuleConfiguration currentRuleConfig, final boolean ifNotExists,
+                                                                     final Collection<String> duplicatedRuleNames, final Collection<ReadwriteSplittingRuleSegment> segments) {
         Collection<String> currentRuleNames = new LinkedList<>();
         if (null != currentRuleConfig) {
             currentRuleNames.addAll(currentRuleConfig.getDataSources().stream().map(ReadwriteSplittingDataSourceRuleConfiguration::getName).collect(Collectors.toList()));
         }
-        Collection<String> duplicateRuleNames = segments.stream().map(ReadwriteSplittingRuleSegment::getName).filter(currentRuleNames::contains).collect(Collectors.toList());
-        ShardingSpherePreconditions.checkState(duplicateRuleNames.isEmpty(), () -> new DuplicateRuleException("Readwrite splitting", databaseName, duplicateRuleNames));
+        Collection<String> toBeCreatedRuleNames = segments.stream().map(ReadwriteSplittingRuleSegment::getName).filter(currentRuleNames::contains).collect(Collectors.toList());
+        if (ifNotExists) {
+            duplicatedRuleNames.addAll(toBeCreatedRuleNames);
+            return;
+        }
+        ShardingSpherePreconditions.checkState(toBeCreatedRuleNames.isEmpty(), () -> new DuplicateRuleException("Readwrite splitting", databaseName, toBeCreatedRuleNames));
     }
     
     private static void checkDataSourcesExist(final String databaseName, final Collection<ReadwriteSplittingRuleSegment> segments, final ShardingSphereDatabase database) {
@@ -173,12 +184,12 @@ public final class ReadwriteSplittingRuleStatementChecker {
         Collection<String> existedReadDataSourceNames = new HashSet<>();
         if (null != currentRuleConfig) {
             Collection<String> toBeAlteredRuleNames = isCreating ? Collections.emptySet() : getToBeAlteredRuleNames(segments);
-            for (ReadwriteSplittingDataSourceRuleConfiguration each : currentRuleConfig.getDataSources()) {
+            currentRuleConfig.getDataSources().forEach(each -> {
                 if (null != each.getStaticStrategy() && !toBeAlteredRuleNames.contains(each.getName())) {
                     existedWriteDataSourceNames.add(each.getStaticStrategy().getWriteDataSourceName());
                     existedReadDataSourceNames.addAll(each.getStaticStrategy().getReadDataSourceNames());
                 }
-            }
+            });
         }
         checkDuplicateWriteDataSourceNames(databaseName, segments, existedWriteDataSourceNames);
         checkDuplicateReadDataSourceNames(databaseName, segments, existedReadDataSourceNames);
@@ -189,25 +200,24 @@ public final class ReadwriteSplittingRuleStatementChecker {
     }
     
     private static void checkDuplicateWriteDataSourceNames(final String databaseName, final Collection<ReadwriteSplittingRuleSegment> segments, final Collection<String> writeDataSourceNames) {
-        for (final ReadwriteSplittingRuleSegment each : segments) {
+        segments.forEach(each -> {
             if (!Strings.isNullOrEmpty(each.getWriteDataSource())) {
                 String writeDataSource = each.getWriteDataSource();
                 ShardingSpherePreconditions.checkState(writeDataSourceNames.add(writeDataSource), () -> new InvalidRuleConfigurationException("Readwrite splitting", each.getName(),
                         String.format("Can not config duplicate write storage unit `%s` in database `%s`", writeDataSource, databaseName)));
             }
-        }
+        });
     }
     
-    private static void checkDuplicateReadDataSourceNames(final String databaseName, final Collection<ReadwriteSplittingRuleSegment> segments,
-                                                          final Collection<String> readDataSourceNames) {
-        for (ReadwriteSplittingRuleSegment each : segments) {
+    private static void checkDuplicateReadDataSourceNames(final String databaseName, final Collection<ReadwriteSplittingRuleSegment> segments, final Collection<String> readDataSourceNames) {
+        segments.forEach(each -> {
             if (null != each.getReadDataSources()) {
-                for (String readDataSource : each.getReadDataSources()) {
+                each.getReadDataSources().forEach(readDataSource -> {
                     ShardingSpherePreconditions.checkState(readDataSourceNames.add(readDataSource), () -> new InvalidRuleConfigurationException("Readwrite splitting", each.getName(),
                             String.format("Can not config duplicate read storage unit `%s` in database `%s`", readDataSource, databaseName)));
-                }
+                });
             }
-        }
+        });
     }
     
     private static void checkLoadBalancers(final Collection<ReadwriteSplittingRuleSegment> segments) {
diff --git a/features/readwrite-splitting/distsql/handler/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/handler/update/CreateReadwriteSplittingRuleStatementUpdater.java b/features/readwrite-splitting/distsql/handler/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/handler/update/CreateReadwriteSplittingRuleStatementUpdater.java
index c8ad8836c93..16518701820 100644
--- a/features/readwrite-splitting/distsql/handler/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/handler/update/CreateReadwriteSplittingRuleStatementUpdater.java
+++ b/features/readwrite-splitting/distsql/handler/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/handler/update/CreateReadwriteSplittingRuleStatementUpdater.java
@@ -22,21 +22,33 @@ import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.readwritesplitting.api.ReadwriteSplittingRuleConfiguration;
 import org.apache.shardingsphere.readwritesplitting.distsql.handler.checker.ReadwriteSplittingRuleStatementChecker;
 import org.apache.shardingsphere.readwritesplitting.distsql.handler.converter.ReadwriteSplittingRuleStatementConverter;
+import org.apache.shardingsphere.readwritesplitting.distsql.parser.segment.ReadwriteSplittingRuleSegment;
 import org.apache.shardingsphere.readwritesplitting.distsql.parser.statement.CreateReadwriteSplittingRuleStatement;
 
+import java.util.Collection;
+import java.util.LinkedList;
+
 /**
  * Create readwrite-splitting rule statement updater.
  */
 public final class CreateReadwriteSplittingRuleStatementUpdater implements RuleDefinitionCreateUpdater<CreateReadwriteSplittingRuleStatement, ReadwriteSplittingRuleConfiguration> {
     
+    private Collection<String> duplicatedRuleNames = new LinkedList<>();
+    
     @Override
     public void checkSQLStatement(final ShardingSphereDatabase database, final CreateReadwriteSplittingRuleStatement sqlStatement, final ReadwriteSplittingRuleConfiguration currentRuleConfig) {
-        ReadwriteSplittingRuleStatementChecker.checkCreation(database, sqlStatement.getRules(), currentRuleConfig);
+        Collection<String> duplicatedRuleNames = new LinkedList<>();
+        ReadwriteSplittingRuleStatementChecker.checkCreation(database, sqlStatement.getRules(), currentRuleConfig, duplicatedRuleNames, sqlStatement.isIfNotExists());
+        this.duplicatedRuleNames = duplicatedRuleNames;
     }
     
     @Override
     public ReadwriteSplittingRuleConfiguration buildToBeCreatedRuleConfiguration(final CreateReadwriteSplittingRuleStatement sqlStatement) {
-        return ReadwriteSplittingRuleStatementConverter.convert(sqlStatement.getRules());
+        Collection<ReadwriteSplittingRuleSegment> segments = sqlStatement.getRules();
+        if (!duplicatedRuleNames.isEmpty()) {
+            segments.removeIf(each -> duplicatedRuleNames.contains(each.getName()));
+        }
+        return ReadwriteSplittingRuleStatementConverter.convert(segments);
     }
     
     @Override
diff --git a/features/readwrite-splitting/distsql/handler/src/test/java/org/apache/shardingsphere/readwritesplitting/distsql/handler/update/CreateReadwriteSplittingRuleStatementUpdaterTest.java b/features/readwrite-splitting/distsql/handler/src/test/java/org/apache/shardingsphere/readwritesplitting/distsql/handler/update/CreateReadwriteSplittingRuleStatementUpdaterTest.java
index 4952ee460dd..f3b4a494136 100644
--- a/features/readwrite-splitting/distsql/handler/src/test/java/org/apache/shardingsphere/readwritesplitting/distsql/handler/update/CreateReadwriteSplittingRuleStatementUpdaterTest.java
+++ b/features/readwrite-splitting/distsql/handler/src/test/java/org/apache/shardingsphere/readwritesplitting/distsql/handler/update/CreateReadwriteSplittingRuleStatementUpdaterTest.java
@@ -17,14 +17,14 @@
 
 package org.apache.shardingsphere.readwritesplitting.distsql.handler.update;
 
-import org.apache.shardingsphere.infra.rule.identifier.type.exportable.constant.ExportableConstants;
-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.distsql.handler.exception.rule.DuplicateRuleException;
 import org.apache.shardingsphere.distsql.handler.exception.rule.InvalidRuleConfigurationException;
+import org.apache.shardingsphere.distsql.handler.exception.storageunit.MissingRequiredStorageUnitsException;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.resource.ShardingSphereResourceMetaData;
 import org.apache.shardingsphere.infra.rule.identifier.type.exportable.ExportableRule;
+import org.apache.shardingsphere.infra.rule.identifier.type.exportable.constant.ExportableConstants;
 import org.apache.shardingsphere.infra.util.spi.ShardingSphereServiceLoader;
 import org.apache.shardingsphere.readwritesplitting.api.ReadwriteSplittingRuleConfiguration;
 import org.apache.shardingsphere.readwritesplitting.api.rule.ReadwriteSplittingDataSourceRuleConfiguration;
@@ -52,7 +52,6 @@ import java.util.Properties;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.mockStatic;
 import static org.mockito.Mockito.when;
@@ -75,15 +74,12 @@ public final class CreateReadwriteSplittingRuleStatementUpdaterTest {
     
     @Test(expected = DuplicateRuleException.class)
     public void assertCheckSQLStatementWithDuplicateRuleNames() {
-        ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS);
-        when(database.getResourceMetaData().getDataSources().keySet()).thenReturn(Collections.emptySet());
+        when(resourceMetaData.getDataSources()).thenReturn(Collections.emptyMap());
         updater.checkSQLStatement(database, createSQLStatement("TEST"), createCurrentRuleConfiguration());
     }
     
     @Test(expected = InvalidRuleConfigurationException.class)
     public void assertCheckSQLStatementWithDuplicateResource() {
-        ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS);
-        when(database.getResourceMetaData()).thenReturn(resourceMetaData);
         when(resourceMetaData.getDataSources()).thenReturn(Collections.singletonMap("write_ds", null));
         updater.checkSQLStatement(database, createSQLStatement("write_ds", "TEST"), createCurrentRuleConfiguration());
     }
@@ -100,7 +96,7 @@ public final class CreateReadwriteSplittingRuleStatementUpdaterTest {
         when(exportableRule.getExportData()).thenReturn(Collections.singletonMap(ExportableConstants.EXPORT_DB_DISCOVERY_PRIMARY_DATA_SOURCES, Collections.singletonMap("ms_group", "ds_0")));
         when(database.getRuleMetaData().findRules(ExportableRule.class)).thenReturn(Collections.singleton(exportableRule));
         ReadwriteSplittingRuleSegment ruleSegment = new ReadwriteSplittingRuleSegment("dynamic_rule", "ha_group", "false", "TEST", new Properties());
-        updater.checkSQLStatement(database, new CreateReadwriteSplittingRuleStatement(Collections.singleton(ruleSegment)), null);
+        updater.checkSQLStatement(database, createSQLStatement(false, ruleSegment), null);
     }
     
     @Test(expected = InvalidAlgorithmConfigurationException.class)
@@ -111,32 +107,30 @@ public final class CreateReadwriteSplittingRuleStatementUpdaterTest {
     
     @Test(expected = InvalidRuleConfigurationException.class)
     public void assertCheckSQLStatementWithDuplicateWriteResourceNamesInStatement() {
-        ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS);
-        when(database.getResourceMetaData()).thenReturn(resourceMetaData);
         updater.checkSQLStatement(database, createSQLStatementWithDuplicateWriteResourceNames("write_ds_0", "write_ds_1", "TEST"), null);
     }
     
     @Test(expected = InvalidRuleConfigurationException.class)
     public void assertCheckSQLStatementWithDuplicateWriteResourceNames() {
-        ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS);
-        when(database.getResourceMetaData()).thenReturn(resourceMetaData);
         updater.checkSQLStatement(database, createSQLStatement("readwrite_ds_1", "ds_write", Arrays.asList("read_ds_0", "read_ds_1"), "TEST"), createCurrentRuleConfiguration());
     }
     
     @Test(expected = InvalidRuleConfigurationException.class)
     public void assertCheckSQLStatementWithDuplicateReadResourceNamesInStatement() {
-        ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS);
-        when(database.getResourceMetaData()).thenReturn(resourceMetaData);
         updater.checkSQLStatement(database, createSQLStatementWithDuplicateReadResourceNames("write_ds_0", "write_ds_1", "TEST"), null);
     }
     
     @Test(expected = InvalidRuleConfigurationException.class)
     public void assertCheckSQLStatementWithDuplicateReadResourceNames() {
-        ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS);
-        when(database.getResourceMetaData()).thenReturn(resourceMetaData);
         updater.checkSQLStatement(database, createSQLStatement("readwrite_ds_1", "write_ds_1", Arrays.asList("read_ds_0", "read_ds_1"), "TEST"), createCurrentRuleConfiguration());
     }
     
+    @Test
+    public void assertCheckSQLStatementWithIfNotExists() {
+        ReadwriteSplittingRuleSegment staticSegment = new ReadwriteSplittingRuleSegment("readwrite_ds_0", "write_ds_0", Arrays.asList("read_ds_2", "read_ds_3"), null, new Properties());
+        updater.checkSQLStatement(database, createSQLStatement(true, staticSegment), createCurrentRuleConfiguration());
+    }
+    
     @Test
     public void assertUpdateSuccess() {
         ExportableRule exportableRule = mock(ExportableRule.class);
@@ -147,7 +141,7 @@ public final class CreateReadwriteSplittingRuleStatementUpdaterTest {
             ReadwriteSplittingRuleSegment dynamicSegment = new ReadwriteSplittingRuleSegment("dynamic_rule", "ms_group", "false", "TEST", new Properties());
             ReadwriteSplittingRuleSegment staticSegment = new ReadwriteSplittingRuleSegment("static_rule", "write_ds_0", Arrays.asList("read_ds_0", "read_ds_1"), "TEST", new Properties());
             ShardingSphereServiceLoader.register(ReadQueryLoadBalanceAlgorithm.class);
-            CreateReadwriteSplittingRuleStatement statement = new CreateReadwriteSplittingRuleStatement(Arrays.asList(dynamicSegment, staticSegment));
+            CreateReadwriteSplittingRuleStatement statement = createSQLStatement(false, dynamicSegment, staticSegment);
             updater.checkSQLStatement(database, statement, null);
             ReadwriteSplittingRuleConfiguration toBeCreatedRuleConfig = updater.buildToBeCreatedRuleConfiguration(statement);
             ReadwriteSplittingRuleConfiguration currentRuleConfig = new ReadwriteSplittingRuleConfiguration(new ArrayList<>(), new HashMap<>());
@@ -157,30 +151,31 @@ public final class CreateReadwriteSplittingRuleStatementUpdaterTest {
     }
     
     private CreateReadwriteSplittingRuleStatement createSQLStatement(final String loadBalancerName) {
-        ReadwriteSplittingRuleSegment ruleSegment = new ReadwriteSplittingRuleSegment("readwrite_ds_0", "write_ds", Arrays.asList("read_ds_0", "read_ds_1"), loadBalancerName, new Properties());
-        return new CreateReadwriteSplittingRuleStatement(Collections.singleton(ruleSegment));
+        return createSQLStatement(false, new ReadwriteSplittingRuleSegment("readwrite_ds_0", "write_ds", Arrays.asList("read_ds_0", "read_ds_1"), loadBalancerName, new Properties()));
     }
     
     private CreateReadwriteSplittingRuleStatement createSQLStatement(final String ruleName, final String loadBalancerName) {
-        ReadwriteSplittingRuleSegment ruleSegment = new ReadwriteSplittingRuleSegment(ruleName, "write_ds", Arrays.asList("read_ds_0", "read_ds_1"), loadBalancerName, new Properties());
-        return new CreateReadwriteSplittingRuleStatement(Collections.singleton(ruleSegment));
+        return createSQLStatement(false, new ReadwriteSplittingRuleSegment(ruleName, "write_ds", Arrays.asList("read_ds_0", "read_ds_1"), loadBalancerName, new Properties()));
     }
     
     private CreateReadwriteSplittingRuleStatement createSQLStatement(final String ruleName, final String writeDataSource, final Collection<String> readDataSources, final String loadBalancerName) {
-        ReadwriteSplittingRuleSegment ruleSegment = new ReadwriteSplittingRuleSegment(ruleName, writeDataSource, readDataSources, loadBalancerName, new Properties());
-        return new CreateReadwriteSplittingRuleStatement(Collections.singleton(ruleSegment));
+        return createSQLStatement(false, new ReadwriteSplittingRuleSegment(ruleName, writeDataSource, readDataSources, loadBalancerName, new Properties()));
+    }
+    
+    private CreateReadwriteSplittingRuleStatement createSQLStatement(final boolean ifNotExists, final ReadwriteSplittingRuleSegment... ruleSegments) {
+        return new CreateReadwriteSplittingRuleStatement(ifNotExists, Arrays.asList(ruleSegments));
     }
     
     private CreateReadwriteSplittingRuleStatement createSQLStatementWithDuplicateWriteResourceNames(final String ruleName0, final String ruleName1, final String loadBalancerName) {
         ReadwriteSplittingRuleSegment ruleSegment0 = new ReadwriteSplittingRuleSegment(ruleName0, "write_ds", Arrays.asList("read_ds_0", "read_ds_1"), loadBalancerName, new Properties());
         ReadwriteSplittingRuleSegment ruleSegment1 = new ReadwriteSplittingRuleSegment(ruleName1, "write_ds", Arrays.asList("read_ds_2", "read_ds_3"), loadBalancerName, new Properties());
-        return new CreateReadwriteSplittingRuleStatement(Arrays.asList(ruleSegment0, ruleSegment1));
+        return createSQLStatement(false, ruleSegment0, ruleSegment1);
     }
     
     private CreateReadwriteSplittingRuleStatement createSQLStatementWithDuplicateReadResourceNames(final String ruleName0, final String ruleName1, final String loadBalancerName) {
         ReadwriteSplittingRuleSegment ruleSegment0 = new ReadwriteSplittingRuleSegment(ruleName0, "write_ds_0", Arrays.asList("read_ds_0", "read_ds_1"), loadBalancerName, new Properties());
         ReadwriteSplittingRuleSegment ruleSegment1 = new ReadwriteSplittingRuleSegment(ruleName1, "write_ds_1", Arrays.asList("read_ds_0", "read_ds_1"), loadBalancerName, new Properties());
-        return new CreateReadwriteSplittingRuleStatement(Arrays.asList(ruleSegment0, ruleSegment1));
+        return createSQLStatement(false, ruleSegment0, ruleSegment1);
     }
     
     private ReadwriteSplittingRuleConfiguration createCurrentRuleConfiguration() {
diff --git a/features/readwrite-splitting/distsql/parser/src/main/antlr4/imports/readwrite-splitting/Keyword.g4 b/features/readwrite-splitting/distsql/parser/src/main/antlr4/imports/readwrite-splitting/Keyword.g4
index 5b9ce7fab0a..2cd6d3dfae9 100644
--- a/features/readwrite-splitting/distsql/parser/src/main/antlr4/imports/readwrite-splitting/Keyword.g4
+++ b/features/readwrite-splitting/distsql/parser/src/main/antlr4/imports/readwrite-splitting/Keyword.g4
@@ -123,7 +123,6 @@ EXISTS
     : E X I S T S
     ;  
 
-
 COUNT
     : C O U N T
     ;
@@ -179,3 +178,7 @@ FIXED_REPLICA_WEIGHT
 FIXED_PRIMARY
     : F I X E D UL_ P R I M A R Y
     ;
+
+NOT
+    : N O T
+    ;
diff --git a/features/readwrite-splitting/distsql/parser/src/main/antlr4/imports/readwrite-splitting/RDLStatement.g4 b/features/readwrite-splitting/distsql/parser/src/main/antlr4/imports/readwrite-splitting/RDLStatement.g4
index a3c2f4ad6bc..5d503885599 100644
--- a/features/readwrite-splitting/distsql/parser/src/main/antlr4/imports/readwrite-splitting/RDLStatement.g4
+++ b/features/readwrite-splitting/distsql/parser/src/main/antlr4/imports/readwrite-splitting/RDLStatement.g4
@@ -20,7 +20,7 @@ grammar RDLStatement;
 import BaseRule;
 
 createReadwriteSplittingRule
-    : CREATE READWRITE_SPLITTING RULE readwriteSplittingRuleDefinition (COMMA_ readwriteSplittingRuleDefinition)*
+    : CREATE READWRITE_SPLITTING RULE ifNotExists? readwriteSplittingRuleDefinition (COMMA_ readwriteSplittingRuleDefinition)*
     ;
 
 alterReadwriteSplittingRule
@@ -62,3 +62,7 @@ ifExists
 writeDataSourceQueryEnabled
     : TRUE | FALSE
     ;
+
+ifNotExists
+    : IF NOT EXISTS
+    ;
diff --git a/features/readwrite-splitting/distsql/parser/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/parser/core/ReadwriteSplittingDistSQLStatementVisitor.java b/features/readwrite-splitting/distsql/parser/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/parser/core/ReadwriteSplittingDistSQLStatementVisitor.java
index b013904efbb..69e60b46d2b 100644
--- a/features/readwrite-splitting/distsql/parser/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/parser/core/ReadwriteSplittingDistSQLStatementVisitor.java
+++ b/features/readwrite-splitting/distsql/parser/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/parser/core/ReadwriteSplittingDistSQLStatementVisitor.java
@@ -63,7 +63,8 @@ public final class ReadwriteSplittingDistSQLStatementVisitor extends ReadwriteSp
     
     @Override
     public ASTNode visitCreateReadwriteSplittingRule(final CreateReadwriteSplittingRuleContext ctx) {
-        return new CreateReadwriteSplittingRuleStatement(ctx.readwriteSplittingRuleDefinition().stream().map(each -> (ReadwriteSplittingRuleSegment) visit(each)).collect(Collectors.toList()));
+        return new CreateReadwriteSplittingRuleStatement(null != ctx.ifNotExists(),
+                ctx.readwriteSplittingRuleDefinition().stream().map(each -> (ReadwriteSplittingRuleSegment) visit(each)).collect(Collectors.toList()));
     }
     
     @Override
diff --git a/features/readwrite-splitting/distsql/statement/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/parser/statement/CreateReadwriteSplittingRuleStatement.java b/features/readwrite-splitting/distsql/statement/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/parser/statement/CreateReadwriteSplittingRuleStatement.java
index 87ac6f260ca..5e609a82e1e 100644
--- a/features/readwrite-splitting/distsql/statement/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/parser/statement/CreateReadwriteSplittingRuleStatement.java
+++ b/features/readwrite-splitting/distsql/statement/src/main/java/org/apache/shardingsphere/readwritesplitting/distsql/parser/statement/CreateReadwriteSplittingRuleStatement.java
@@ -18,18 +18,21 @@
 package org.apache.shardingsphere.readwritesplitting.distsql.parser.statement;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.readwritesplitting.distsql.parser.segment.ReadwriteSplittingRuleSegment;
 import org.apache.shardingsphere.distsql.parser.statement.rdl.create.CreateRuleStatement;
+import org.apache.shardingsphere.readwritesplitting.distsql.parser.segment.ReadwriteSplittingRuleSegment;
 
 import java.util.Collection;
 
 /**
  * Create readwrite-splitting rule statement.
  */
-@RequiredArgsConstructor
 @Getter
 public final class CreateReadwriteSplittingRuleStatement extends CreateRuleStatement {
     
     private final Collection<ReadwriteSplittingRuleSegment> rules;
+    
+    public CreateReadwriteSplittingRuleStatement(final boolean ifNotExists, final Collection<ReadwriteSplittingRuleSegment> rules) {
+        super(ifNotExists);
+        this.rules = rules;
+    }
 }