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 0dcf5c6  [DistSQL]Support `alter traffic rule` syntax. (#15155)
0dcf5c6 is described below

commit 0dcf5c621f93ce0b2f185c234cbb97159da2ec39
Author: lanchengx <[email protected]>
AuthorDate: Sun Jan 30 10:33:00 2022 +0800

    [DistSQL]Support `alter traffic rule` syntax. (#15155)
    
    * Support `alter traffic rule` syntax.
    
    * Rename variable.
    
    * Add successful test.
    
    * Add converter.
---
 .../src/main/antlr4/imports/RALStatement.g4        |  20 ++--
 .../parser/autogen/CommonDistSQLStatement.g4       |   1 +
 .../core/common/CommonDistSQLStatementVisitor.java |   9 +-
 .../rdl/create/AlterTrafficRuleStatement.java      |  35 +++++++
 .../rule/RequiredRuleMissedException.java          |   4 +
 .../alter/AlterStatementExecutorFactory.java       |   5 +
 .../alter/excutor/AlterTrafficRuleExecutor.java    |  94 +++++++++++++++++
 .../ral/common/convert/TrafficRuleConverter.java   |  67 ++++++++++++
 .../common/create/CreateTrafficRuleHandler.java    |  34 +------
 .../common/alter/AlterTrafficRuleHandlerTest.java  | 112 +++++++++++++++++++++
 10 files changed, 340 insertions(+), 41 deletions(-)

diff --git 
a/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/imports/RALStatement.g4
 
b/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/imports/RALStatement.g4
index ab6c838..c28e031 100644
--- 
a/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/imports/RALStatement.g4
+++ 
b/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/imports/RALStatement.g4
@@ -83,6 +83,18 @@ createTrafficRule
     : CREATE TRAFFIC RULE trafficRuleDefinition (COMMA trafficRuleDefinition)* 
     ;
 
+alterTrafficRule
+    : ALTER TRAFFIC RULE trafficRuleDefinition (COMMA trafficRuleDefinition)* 
+    ;
+
+showTrafficRules
+    : SHOW TRAFFIC (RULES | RULE ruleName)
+    ;
+
+dropTrafficRule
+    : DROP TRAFFIC RULE ifExists? ruleName (COMMA ruleName)*
+    ;
+
 trafficRuleDefinition
     : ruleName LP labelDefinition COMMA trafficAlgorithmDefinition COMMA 
loadBanlanceDefinition RP
     ;
@@ -107,14 +119,6 @@ typeName
     : IDENTIFIER
     ;
 
-showTrafficRules
-    : SHOW TRAFFIC (RULES | RULE ruleName)
-    ;
-
-dropTrafficRule
-    : DROP TRAFFIC RULE ifExists? ruleName (COMMA ruleName)*
-    ;
-
 exportSchemaConfiguration
     : EXPORT SCHEMA (CONFIGURATION | CONFIG) (FROM schemaName)? (COMMA? FILE 
EQ filePath)?
     ;
diff --git 
a/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/CommonDistSQLStatement.g4
 
b/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/CommonDistSQLStatement.g4
index c9c6575..6100550 100644
--- 
a/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/CommonDistSQLStatement.g4
+++ 
b/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/CommonDistSQLStatement.g4
@@ -48,6 +48,7 @@ execute
     | showTrafficRules
     | dropTrafficRule
     | createTrafficRule
+    | alterTrafficRule
     | exportSchemaConfiguration
     ) SEMI?
     ;
diff --git 
a/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/java/org/apache/shardingsphere/distsql/parser/core/common/CommonDistSQLStatementVisitor.java
 
b/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/java/org/apache/shardingsphere/distsql/parser/core/common/CommonDistSQLStatementVisitor.java
index 5cb4e3c..7ee4d87 100644
--- 
a/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/java/org/apache/shardingsphere/distsql/parser/core/common/CommonDistSQLStatementVisitor.java
+++ 
b/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/java/org/apache/shardingsphere/distsql/parser/core/common/CommonDistSQLStatementVisitor.java
@@ -26,6 +26,7 @@ import 
org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementPa
 import 
org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.AlterDefaultSingleTableRuleContext;
 import 
org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.AlterResourceContext;
 import 
org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.AlterSQLParserRuleContext;
+import 
org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.AlterTrafficRuleContext;
 import 
org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.AlterTransactionRuleContext;
 import 
org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.CacheOptionContext;
 import 
org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.ClearHintContext;
@@ -89,6 +90,7 @@ import 
org.apache.shardingsphere.distsql.parser.statement.ral.common.show.ShowVa
 import 
org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterResourceStatement;
 import 
org.apache.shardingsphere.distsql.parser.statement.rdl.create.AddResourceStatement;
 import 
org.apache.shardingsphere.distsql.parser.statement.rdl.create.AlterDefaultSingleTableRuleStatement;
+import 
org.apache.shardingsphere.distsql.parser.statement.rdl.create.AlterTrafficRuleStatement;
 import 
org.apache.shardingsphere.distsql.parser.statement.rdl.create.CreateDefaultSingleTableRuleStatement;
 import 
org.apache.shardingsphere.distsql.parser.statement.rdl.create.CreateTrafficRuleStatement;
 import 
org.apache.shardingsphere.distsql.parser.statement.rdl.drop.DropDefaultSingleTableRuleStatement;
@@ -354,6 +356,11 @@ public final class CommonDistSQLStatementVisitor extends 
CommonDistSQLStatementB
     }
     
     @Override
+    public ASTNode visitAlterTrafficRule(final AlterTrafficRuleContext ctx) {
+        return new 
AlterTrafficRuleStatement(ctx.trafficRuleDefinition().stream().map(each -> 
(TrafficRuleSegment) 
visit(each)).collect(Collectors.toCollection(LinkedList::new)));
+    }
+    
+    @Override
     public ASTNode visitShowTrafficRules(final ShowTrafficRulesContext ctx) {
         ShowTrafficRulesStatement result = new ShowTrafficRulesStatement();
         if (null != ctx.ruleName()) {
@@ -364,7 +371,7 @@ public final class CommonDistSQLStatementVisitor extends 
CommonDistSQLStatementB
     
     @Override
     public ASTNode visitTrafficRuleDefinition(final 
TrafficRuleDefinitionContext ctx) {
-        return new TrafficRuleSegment(getIdentifierValue(ctx.ruleName()), 
buildLabels(ctx.labelDefinition()), 
+        return new TrafficRuleSegment(getIdentifierValue(ctx.ruleName()), 
buildLabels(ctx.labelDefinition()),
                 (AlgorithmSegment) 
visit(ctx.trafficAlgorithmDefinition().algorithmDefinition()), 
(AlgorithmSegment) visit(ctx.loadBanlanceDefinition().algorithmDefinition()));
     }
     
diff --git 
a/shardingsphere-distsql/shardingsphere-distsql-statement/src/main/java/org/apache/shardingsphere/distsql/parser/statement/rdl/create/AlterTrafficRuleStatement.java
 
b/shardingsphere-distsql/shardingsphere-distsql-statement/src/main/java/org/apache/shardingsphere/distsql/parser/statement/rdl/create/AlterTrafficRuleStatement.java
new file mode 100644
index 0000000..af93048
--- /dev/null
+++ 
b/shardingsphere-distsql/shardingsphere-distsql-statement/src/main/java/org/apache/shardingsphere/distsql/parser/statement/rdl/create/AlterTrafficRuleStatement.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.distsql.parser.statement.rdl.create;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.distsql.parser.segment.TrafficRuleSegment;
+import 
org.apache.shardingsphere.distsql.parser.statement.ral.common.AlterDistSQLStatement;
+
+import java.util.Collection;
+
+/**
+ * Alter traffic rule statement.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class AlterTrafficRuleStatement extends AlterDistSQLStatement {
+    
+    private final Collection<TrafficRuleSegment> segments;
+}
diff --git 
a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/distsql/exception/rule/RequiredRuleMissedException.java
 
b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/distsql/exception/rule/RequiredRuleMissedException.java
index 6964b68..8bad342 100644
--- 
a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/distsql/exception/rule/RequiredRuleMissedException.java
+++ 
b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/distsql/exception/rule/RequiredRuleMissedException.java
@@ -34,6 +34,10 @@ public final class RequiredRuleMissedException extends 
RuleDefinitionViolationEx
         super(1112, String.format("%s rule does not exist in schema `%s`.", 
ruleType, schemaName));
     }
     
+    public RequiredRuleMissedException(final String ruleType, final 
Collection<String> ruleNames) {
+        super(1112, String.format("%s rules `%s` do not exist.", ruleType, 
ruleNames));
+    }
+    
     public RequiredRuleMissedException(final String ruleType, final String 
schemaName, final String ruleName) {
         super(1112, String.format("%s rule `%s` do not exist in schema `%s`.", 
ruleType, ruleName, schemaName));
     }
diff --git 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterStatementExecutorFactory.java
 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterStatementExecutorFactory.java
index 1ca4015..3a98a2e 100644
--- 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterStatementExecutorFactory.java
+++ 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterStatementExecutorFactory.java
@@ -20,8 +20,10 @@ package 
org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter;
 import 
org.apache.shardingsphere.distsql.parser.statement.ral.common.AlterDistSQLStatement;
 import 
org.apache.shardingsphere.distsql.parser.statement.ral.common.alter.AlterSQLParserRuleStatement;
 import 
org.apache.shardingsphere.distsql.parser.statement.ral.common.alter.AlterTransactionRuleStatement;
+import 
org.apache.shardingsphere.distsql.parser.statement.rdl.create.AlterTrafficRuleStatement;
 import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
 import 
org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter.excutor.AlterSQLParserRuleExecutor;
+import 
org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter.excutor.AlterTrafficRuleExecutor;
 import 
org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter.excutor.AlterTransactionRuleExecutor;
 
 import java.sql.SQLException;
@@ -46,6 +48,9 @@ public final class AlterStatementExecutorFactory {
         if (sqlStatement instanceof AlterSQLParserRuleStatement) {
             return new 
AlterSQLParserRuleExecutor((AlterSQLParserRuleStatement) sqlStatement);
         }
+        if (sqlStatement instanceof AlterTrafficRuleStatement) {
+            return new AlterTrafficRuleExecutor((AlterTrafficRuleStatement) 
sqlStatement);
+        }
         throw new 
UnsupportedOperationException(sqlStatement.getClass().getCanonicalName());
     }
 }
diff --git 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/excutor/AlterTrafficRuleExecutor.java
 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/excutor/AlterTrafficRuleExecutor.java
new file mode 100644
index 0000000..7841842
--- /dev/null
+++ 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/excutor/AlterTrafficRuleExecutor.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 
org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter.excutor;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.distsql.parser.segment.TrafficRuleSegment;
+import 
org.apache.shardingsphere.distsql.parser.statement.rdl.create.AlterTrafficRuleStatement;
+import org.apache.shardingsphere.infra.distsql.exception.DistSQLException;
+import 
org.apache.shardingsphere.infra.distsql.exception.rule.InvalidAlgorithmConfigurationException;
+import 
org.apache.shardingsphere.infra.distsql.exception.rule.RequiredRuleMissedException;
+import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
+import org.apache.shardingsphere.mode.metadata.persist.MetaDataPersistService;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import org.apache.shardingsphere.proxy.backend.response.header.ResponseHeader;
+import 
org.apache.shardingsphere.proxy.backend.response.header.update.UpdateResponseHeader;
+import 
org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter.AlterStatementExecutor;
+import 
org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.convert.TrafficRuleConverter;
+import org.apache.shardingsphere.spi.typed.TypedSPIRegistry;
+import org.apache.shardingsphere.traffic.api.config.TrafficRuleConfiguration;
+import 
org.apache.shardingsphere.traffic.api.config.TrafficStrategyConfiguration;
+import org.apache.shardingsphere.traffic.spi.TrafficAlgorithm;
+import org.apache.shardingsphere.traffic.spi.TrafficLoadBalanceAlgorithm;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Alter traffic rule handler.
+ */
+@RequiredArgsConstructor
+public final class AlterTrafficRuleExecutor implements AlterStatementExecutor {
+    
+    private final AlterTrafficRuleStatement sqlStatement;
+    
+    @Override
+    public ResponseHeader execute() throws DistSQLException {
+        Optional<TrafficRuleConfiguration> currentConfiguration = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getGlobalRuleMetaData()
+                
.findRuleConfiguration(TrafficRuleConfiguration.class).stream().findAny();
+        check(sqlStatement, currentConfiguration);
+        TrafficRuleConfiguration toBeAlteredConfiguration = 
TrafficRuleConverter.convert(sqlStatement.getSegments());
+        updateToRepository(toBeAlteredConfiguration, 
currentConfiguration.get());
+        return new UpdateResponseHeader(sqlStatement);
+    }
+    
+    private void check(final AlterTrafficRuleStatement sqlStatement, final 
Optional<TrafficRuleConfiguration> currentConfiguration) throws 
DistSQLException {
+        DistSQLException.predictionThrow(currentConfiguration.isPresent(), new 
RequiredRuleMissedException("Traffic"));
+        Collection<String> currentRuleNames = 
currentConfiguration.get().getTrafficStrategies().stream().map(TrafficStrategyConfiguration::getName).collect(Collectors.toSet());
+        Set<String> notExistRuleNames = 
sqlStatement.getSegments().stream().map(TrafficRuleSegment::getName).filter(each
 -> !currentRuleNames.contains(each)).collect(Collectors.toSet());
+        DistSQLException.predictionThrow(notExistRuleNames.isEmpty(), new 
RequiredRuleMissedException("Traffic", notExistRuleNames));
+        Collection<String> invalidAlgorithmNames = 
getInvalidAlgorithmNames(sqlStatement.getSegments());
+        DistSQLException.predictionThrow(invalidAlgorithmNames.isEmpty(), new 
InvalidAlgorithmConfigurationException("traffic", invalidAlgorithmNames));
+    }
+    
+    private Collection<String> getInvalidAlgorithmNames(final 
Collection<TrafficRuleSegment> segments) {
+        Collection<String> result = new ArrayList<>(segments.size());
+        sqlStatement.getSegments().forEach(each -> {
+            if 
(!TypedSPIRegistry.findRegisteredService(TrafficAlgorithm.class, 
each.getAlgorithm().getName(), new Properties()).isPresent()) {
+                result.add(each.getAlgorithm().getName());
+            }
+            if 
(!TypedSPIRegistry.findRegisteredService(TrafficLoadBalanceAlgorithm.class, 
each.getLoadBalancer().getName(), new Properties()).isPresent()) {
+                result.add(each.getLoadBalancer().getName());
+            }
+        });
+        return result;
+    }
+    
+    private void updateToRepository(final TrafficRuleConfiguration 
toBeAlteredConfiguration, final TrafficRuleConfiguration currentConfiguration) {
+        
currentConfiguration.getTrafficStrategies().addAll(toBeAlteredConfiguration.getTrafficStrategies());
+        
currentConfiguration.getTrafficAlgorithms().putAll(toBeAlteredConfiguration.getTrafficAlgorithms());
+        
currentConfiguration.getLoadBalancers().putAll(toBeAlteredConfiguration.getLoadBalancers());
+        MetaDataContexts metaDataContexts = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts();
+        Optional<MetaDataPersistService> metaDataPersistService = 
metaDataContexts.getMetaDataPersistService();
+        metaDataPersistService.ifPresent(op -> 
op.getGlobalRuleService().persist(metaDataContexts.getGlobalRuleMetaData().getConfigurations(),
 true));
+    }
+}
diff --git 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/convert/TrafficRuleConverter.java
 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/convert/TrafficRuleConverter.java
new file mode 100644
index 0000000..32624bc
--- /dev/null
+++ 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/convert/TrafficRuleConverter.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 
org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.convert;
+
+import org.apache.shardingsphere.distsql.parser.segment.AlgorithmSegment;
+import org.apache.shardingsphere.distsql.parser.segment.TrafficRuleSegment;
+import 
org.apache.shardingsphere.infra.config.algorithm.ShardingSphereAlgorithmConfiguration;
+import org.apache.shardingsphere.traffic.api.config.TrafficRuleConfiguration;
+import 
org.apache.shardingsphere.traffic.api.config.TrafficStrategyConfiguration;
+
+import java.util.Collection;
+
+/**
+ * Traffic rule converter.
+ */
+public final class TrafficRuleConverter {
+    
+    /**
+     * Convert traffic rule segment to traffic rule configuration.
+     *
+     * @param segments traffic rule segments
+     * @return traffic rule configuration
+     */
+    public static TrafficRuleConfiguration convert(final 
Collection<TrafficRuleSegment> segments) {
+        TrafficRuleConfiguration result = new TrafficRuleConfiguration();
+        segments.forEach(each -> setConfigurationData(result, each));
+        return result;
+    }
+    
+    private static void setConfigurationData(final TrafficRuleConfiguration 
result, final TrafficRuleSegment each) {
+        ShardingSphereAlgorithmConfiguration trafficAlgorithm = 
createAlgorithmConfiguration(each.getAlgorithm());
+        ShardingSphereAlgorithmConfiguration loadBalancer = 
createAlgorithmConfiguration(each.getLoadBalancer());
+        String trafficAlgorithmName = createAlgorithmName(each.getName(), 
trafficAlgorithm);
+        String loadBalancerName = createAlgorithmName(each.getName(), 
loadBalancer);
+        TrafficStrategyConfiguration trafficStrategy = 
createTrafficStrategy(each, trafficAlgorithmName, loadBalancerName);
+        result.getTrafficStrategies().add(trafficStrategy);
+        result.getTrafficAlgorithms().put(trafficAlgorithmName, 
trafficAlgorithm);
+        result.getLoadBalancers().put(loadBalancerName, loadBalancer);
+    }
+    
+    private static ShardingSphereAlgorithmConfiguration 
createAlgorithmConfiguration(final AlgorithmSegment segment) {
+        return new ShardingSphereAlgorithmConfiguration(segment.getName(), 
segment.getProps());
+    }
+    
+    private static TrafficStrategyConfiguration createTrafficStrategy(final 
TrafficRuleSegment trafficRuleSegment, final String trafficAlgorithmName, final 
String loadBalancerName) {
+        return new TrafficStrategyConfiguration(trafficRuleSegment.getName(), 
trafficRuleSegment.getLabels(), trafficAlgorithmName, loadBalancerName);
+    }
+    
+    private static String createAlgorithmName(final String ruleName, final 
ShardingSphereAlgorithmConfiguration algorithm) {
+        return String.format("%s_%s", ruleName, 
algorithm.getType()).toLowerCase();
+    }
+}
diff --git 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/create/CreateTrafficRuleHandler.java
 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/create/CreateTrafficRuleHandler.java
index ee388f4..ac633ff 100644
--- 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/create/CreateTrafficRuleHandler.java
+++ 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/create/CreateTrafficRuleHandler.java
@@ -18,11 +18,9 @@
 package org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.create;
 
 import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.distsql.parser.segment.AlgorithmSegment;
 import org.apache.shardingsphere.distsql.parser.segment.TrafficRuleSegment;
 import 
org.apache.shardingsphere.distsql.parser.statement.rdl.create.CreateTrafficRuleStatement;
 import org.apache.shardingsphere.infra.config.RuleConfiguration;
-import 
org.apache.shardingsphere.infra.config.algorithm.ShardingSphereAlgorithmConfiguration;
 import org.apache.shardingsphere.infra.distsql.exception.DistSQLException;
 import 
org.apache.shardingsphere.infra.distsql.exception.rule.DuplicateRuleException;
 import 
org.apache.shardingsphere.infra.distsql.exception.rule.InvalidAlgorithmConfigurationException;
@@ -32,6 +30,7 @@ import 
org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.proxy.backend.response.header.ResponseHeader;
 import 
org.apache.shardingsphere.proxy.backend.response.header.update.UpdateResponseHeader;
 import org.apache.shardingsphere.proxy.backend.text.TextProtocolBackendHandler;
+import 
org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.convert.TrafficRuleConverter;
 import org.apache.shardingsphere.spi.typed.TypedSPIRegistry;
 import org.apache.shardingsphere.traffic.api.config.TrafficRuleConfiguration;
 import 
org.apache.shardingsphere.traffic.api.config.TrafficStrategyConfiguration;
@@ -58,7 +57,7 @@ public final class CreateTrafficRuleHandler implements 
TextProtocolBackendHandle
         Optional<TrafficRuleConfiguration> trafficRuleConfiguration = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getGlobalRuleMetaData()
                 
.findRuleConfiguration(TrafficRuleConfiguration.class).stream().findAny();
         check(sqlStatement, trafficRuleConfiguration);
-        TrafficRuleConfiguration toBeCreatedConfiguration = 
createTrafficRuleConfiguration(sqlStatement);
+        TrafficRuleConfiguration toBeCreatedConfiguration = 
TrafficRuleConverter.convert(sqlStatement.getSegments());
         updateToRepository(toBeCreatedConfiguration, trafficRuleConfiguration);
         return new UpdateResponseHeader(sqlStatement);
     }
@@ -86,31 +85,6 @@ public final class CreateTrafficRuleHandler implements 
TextProtocolBackendHandle
         return result;
     }
     
-    private TrafficRuleConfiguration createTrafficRuleConfiguration(final 
CreateTrafficRuleStatement sqlStatement) {
-        TrafficRuleConfiguration result = new TrafficRuleConfiguration();
-        sqlStatement.getSegments().forEach(each -> 
setConfigurationData(result, each));
-        return result;
-    }
-    
-    private void setConfigurationData(final TrafficRuleConfiguration result, 
final TrafficRuleSegment each) {
-        ShardingSphereAlgorithmConfiguration trafficAlgorithm = 
createAlgorithmConfiguration(each.getAlgorithm());
-        ShardingSphereAlgorithmConfiguration loadBalancer = 
createAlgorithmConfiguration(each.getLoadBalancer());
-        String trafficAlgorithmName = createAlgorithmName(each.getName(), 
trafficAlgorithm);
-        String loadBalancerName = createAlgorithmName(each.getName(), 
loadBalancer);
-        TrafficStrategyConfiguration trafficStrategy = 
createTrafficStrategy(each, trafficAlgorithmName, loadBalancerName);
-        result.getTrafficStrategies().add(trafficStrategy);
-        result.getTrafficAlgorithms().put(trafficAlgorithmName, 
trafficAlgorithm);
-        result.getLoadBalancers().put(loadBalancerName, loadBalancer);
-    }
-    
-    private ShardingSphereAlgorithmConfiguration 
createAlgorithmConfiguration(final AlgorithmSegment segment) {
-        return new ShardingSphereAlgorithmConfiguration(segment.getName(), 
segment.getProps());
-    }
-    
-    private TrafficStrategyConfiguration createTrafficStrategy(final 
TrafficRuleSegment trafficRuleSegment, final String trafficAlgorithmName, final 
String loadBalancerName) {
-        return new TrafficStrategyConfiguration(trafficRuleSegment.getName(), 
trafficRuleSegment.getLabels(), trafficAlgorithmName, loadBalancerName);
-    }
-    
     private void updateToRepository(final TrafficRuleConfiguration 
toBeCreatedRuleConfiguration, final Optional<TrafficRuleConfiguration> 
currentRuleConfiguration) {
         MetaDataContexts metaDataContexts = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts();
         Collection<RuleConfiguration> globalRuleConfigurations = 
metaDataContexts.getGlobalRuleMetaData().getConfigurations();
@@ -124,8 +98,4 @@ public final class CreateTrafficRuleHandler implements 
TextProtocolBackendHandle
         Optional<MetaDataPersistService> metaDataPersistService = 
metaDataContexts.getMetaDataPersistService();
         metaDataPersistService.ifPresent(op -> 
op.getGlobalRuleService().persist(globalRuleConfigurations, true));
     }
-    
-    private String createAlgorithmName(final String ruleName, final 
ShardingSphereAlgorithmConfiguration algorithm) {
-        return String.format("%s_%s", ruleName, 
algorithm.getType()).toLowerCase();
-    }
 }
diff --git 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterTrafficRuleHandlerTest.java
 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterTrafficRuleHandlerTest.java
new file mode 100644
index 0000000..e998475
--- /dev/null
+++ 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterTrafficRuleHandlerTest.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter;
+
+import org.apache.shardingsphere.distsql.parser.segment.AlgorithmSegment;
+import org.apache.shardingsphere.distsql.parser.segment.TrafficRuleSegment;
+import 
org.apache.shardingsphere.distsql.parser.statement.rdl.create.AlterTrafficRuleStatement;
+import org.apache.shardingsphere.infra.config.RuleConfiguration;
+import 
org.apache.shardingsphere.infra.config.algorithm.ShardingSphereAlgorithmConfiguration;
+import org.apache.shardingsphere.infra.distsql.exception.DistSQLException;
+import 
org.apache.shardingsphere.infra.distsql.exception.rule.InvalidAlgorithmConfigurationException;
+import 
org.apache.shardingsphere.infra.distsql.exception.rule.RequiredRuleMissedException;
+import org.apache.shardingsphere.mode.manager.ContextManager;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import 
org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter.excutor.AlterTrafficRuleExecutor;
+import org.apache.shardingsphere.spi.ShardingSphereServiceLoader;
+import org.apache.shardingsphere.traffic.api.config.TrafficRuleConfiguration;
+import 
org.apache.shardingsphere.traffic.api.config.TrafficStrategyConfiguration;
+import org.apache.shardingsphere.traffic.spi.TrafficAlgorithm;
+import org.apache.shardingsphere.traffic.spi.TrafficLoadBalanceAlgorithm;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.Properties;
+
+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.when;
+
+public class AlterTrafficRuleHandlerTest {
+    
+    static {
+        ShardingSphereServiceLoader.register(TrafficAlgorithm.class);
+        
ShardingSphereServiceLoader.register(TrafficLoadBalanceAlgorithm.class);
+    }
+    
+    @Test(expected = RequiredRuleMissedException.class)
+    public void assertCheckWithEmptyRule() throws DistSQLException {
+        ContextManager contextManager = mock(ContextManager.class, 
RETURNS_DEEP_STUBS);
+        
when(contextManager.getMetaDataContexts().getGlobalRuleMetaData().findRuleConfiguration(any())).thenReturn(new
 LinkedList<>());
+        ProxyContext.getInstance().init(contextManager);
+        TrafficRuleSegment trafficRuleSegment = new 
TrafficRuleSegment("input_rule_name", Arrays.asList("olap", "order_by"),
+                new AlgorithmSegment("invalid", new Properties()), new 
AlgorithmSegment("invalid", new Properties()));
+        new 
AlterTrafficRuleExecutor(getSQLStatement(trafficRuleSegment)).execute();
+    }
+    
+    @Test(expected = InvalidAlgorithmConfigurationException.class)
+    public void assertCheckWithInvalidAlgorithmType() throws DistSQLException {
+        ContextManager contextManager = mock(ContextManager.class, 
RETURNS_DEEP_STUBS);
+        
when(contextManager.getMetaDataContexts().getGlobalRuleMetaData().findRuleConfiguration(any())).thenReturn(createTrafficRule());
+        ProxyContext.getInstance().init(contextManager);
+        TrafficRuleSegment trafficRuleSegment = new 
TrafficRuleSegment("rule_name_1", Arrays.asList("olap", "order_by"), 
+                new AlgorithmSegment("invalid", new Properties()), new 
AlgorithmSegment("invalid", new Properties()));
+        new 
AlterTrafficRuleExecutor(getSQLStatement(trafficRuleSegment)).execute();
+    }
+    
+    @Test(expected = RequiredRuleMissedException.class)
+    public void assertCheckWithNotExistRuleName() throws DistSQLException {
+        ContextManager contextManager = mock(ContextManager.class, 
RETURNS_DEEP_STUBS);
+        
when(contextManager.getMetaDataContexts().getGlobalRuleMetaData().findRuleConfiguration(any())).thenReturn(createTrafficRule());
+        ProxyContext.getInstance().init(contextManager);
+        TrafficRuleSegment trafficRuleSegment = new 
TrafficRuleSegment("rule_name_3", Arrays.asList("olap", "order_by"), 
+                new AlgorithmSegment("TEST", new Properties()), new 
AlgorithmSegment("TEST", new Properties()));
+        new 
AlterTrafficRuleExecutor(getSQLStatement(trafficRuleSegment)).execute();
+    }
+    
+    @Test
+    public void assertCheckSuccess() throws DistSQLException {
+        ContextManager contextManager = mock(ContextManager.class, 
RETURNS_DEEP_STUBS);
+        
when(contextManager.getMetaDataContexts().getGlobalRuleMetaData().findRuleConfiguration(any())).thenReturn(createTrafficRule());
+        ProxyContext.getInstance().init(contextManager);
+        TrafficRuleSegment trafficRuleSegment = new 
TrafficRuleSegment("rule_name_1", Arrays.asList("olap", "order_by"),
+                new AlgorithmSegment("TEST", new Properties()), new 
AlgorithmSegment("TEST", new Properties()));
+        new 
AlterTrafficRuleExecutor(getSQLStatement(trafficRuleSegment)).execute();
+    }
+    
+    private Collection<RuleConfiguration> createTrafficRule() {
+        TrafficRuleConfiguration trafficRuleConfiguration = new 
TrafficRuleConfiguration();
+        trafficRuleConfiguration.getTrafficStrategies().add(new 
TrafficStrategyConfiguration("rule_name_1", Arrays.asList("olap", "order_by"), 
"algorithm_1", "load_balancer_1"));
+        trafficRuleConfiguration.getTrafficStrategies().add(new 
TrafficStrategyConfiguration("rule_name_2", Collections.singletonList("oltp"), 
"algorithm_2", "load_balancer_2"));
+        Properties algorithmProperties = new Properties();
+        algorithmProperties.put("sql", "select * from t_order");
+        trafficRuleConfiguration.getTrafficAlgorithms().put("algorithm_1", new 
ShardingSphereAlgorithmConfiguration("SQL_MATCH", algorithmProperties));
+        trafficRuleConfiguration.getTrafficAlgorithms().put("algorithm_2", new 
ShardingSphereAlgorithmConfiguration("SQL_HINT", new Properties()));
+        trafficRuleConfiguration.getLoadBalancers().put("load_balancer_1", new 
ShardingSphereAlgorithmConfiguration("RANDOM", new Properties()));
+        trafficRuleConfiguration.getLoadBalancers().put("load_balancer_2", new 
ShardingSphereAlgorithmConfiguration("ROBIN", new Properties()));
+        return Collections.singletonList(trafficRuleConfiguration);
+    }
+    
+    private AlterTrafficRuleStatement getSQLStatement(final 
TrafficRuleSegment... segments) {
+        return new AlterTrafficRuleStatement(Arrays.asList(segments));
+    }
+}

Reply via email to