View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shardingsphere.sharding.distsql.handler.update;
19  
20  import lombok.Setter;
21  import org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleAlterExecutor;
22  import org.apache.shardingsphere.distsql.handler.required.DistSQLExecutorCurrentRuleRequired;
23  import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
24  import org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
25  import org.apache.shardingsphere.infra.algorithm.core.exception.MissingRequiredAlgorithmException;
26  import org.apache.shardingsphere.infra.algorithm.core.exception.InvalidAlgorithmConfigurationException;
27  import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
28  import org.apache.shardingsphere.infra.exception.core.external.sql.identifier.SQLExceptionIdentifier;
29  import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.MissingRequiredRuleException;
30  import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
31  import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
32  import org.apache.shardingsphere.sharding.api.config.strategy.sharding.NoneShardingStrategyConfiguration;
33  import org.apache.shardingsphere.sharding.api.config.strategy.sharding.ShardingStrategyConfiguration;
34  import org.apache.shardingsphere.sharding.distsql.handler.converter.ShardingTableRuleStatementConverter;
35  import org.apache.shardingsphere.sharding.distsql.handler.enums.ShardingStrategyLevelType;
36  import org.apache.shardingsphere.sharding.distsql.handler.enums.ShardingStrategyType;
37  import org.apache.shardingsphere.sharding.distsql.statement.AlterDefaultShardingStrategyStatement;
38  import org.apache.shardingsphere.sharding.rule.ShardingRule;
39  
40  import java.util.Optional;
41  
42  /**
43   * Alter default sharding strategy executor.
44   */
45  @DistSQLExecutorCurrentRuleRequired(ShardingRule.class)
46  @Setter
47  public final class AlterDefaultShardingStrategyExecutor implements DatabaseRuleAlterExecutor<AlterDefaultShardingStrategyStatement, ShardingRule, ShardingRuleConfiguration> {
48      
49      private ShardingSphereDatabase database;
50      
51      private ShardingRule rule;
52      
53      @Override
54      public void checkBeforeUpdate(final AlterDefaultShardingStrategyStatement sqlStatement) {
55          if (!"none".equalsIgnoreCase(sqlStatement.getStrategyType())) {
56              checkAlgorithm(sqlStatement);
57          }
58          checkExist(sqlStatement);
59      }
60      
61      private void checkAlgorithm(final AlterDefaultShardingStrategyStatement sqlStatement) {
62          ShardingSpherePreconditions.checkState(ShardingStrategyType.isValidType(sqlStatement.getStrategyType()), () -> new InvalidAlgorithmConfigurationException(sqlStatement.getStrategyType()));
63          ShardingSpherePreconditions.checkState(ShardingStrategyType.getValueOf(sqlStatement.getStrategyType()).isValid(sqlStatement.getShardingColumn()),
64                  () -> new InvalidAlgorithmConfigurationException(sqlStatement.getStrategyType()));
65          ShardingSpherePreconditions.checkState(isAlgorithmDefinitionExists(sqlStatement), () -> new MissingRequiredAlgorithmException("Sharding", new SQLExceptionIdentifier("")));
66      }
67      
68      private boolean isAlgorithmDefinitionExists(final AlterDefaultShardingStrategyStatement sqlStatement) {
69          return null != sqlStatement.getAlgorithmSegment();
70      }
71      
72      private void checkExist(final AlterDefaultShardingStrategyStatement sqlStatement) {
73          Optional<ShardingStrategyConfiguration> strategyConfig = getStrategyConfiguration(sqlStatement.getDefaultType());
74          ShardingSpherePreconditions.checkState(strategyConfig.isPresent(),
75                  () -> new MissingRequiredRuleException(String.format("Default sharding %s strategy", sqlStatement.getDefaultType().toLowerCase()), database.getName()));
76      }
77      
78      private Optional<ShardingStrategyConfiguration> getStrategyConfiguration(final String type) {
79          ShardingStrategyConfiguration result = type.equalsIgnoreCase(ShardingStrategyLevelType.TABLE.name())
80                  ? rule.getConfiguration().getDefaultTableShardingStrategy()
81                  : rule.getConfiguration().getDefaultDatabaseShardingStrategy();
82          return Optional.ofNullable(result);
83      }
84      
85      @Override
86      public ShardingRuleConfiguration buildToBeAlteredRuleConfiguration(final AlterDefaultShardingStrategyStatement sqlStatement) {
87          ShardingRuleConfiguration result = new ShardingRuleConfiguration();
88          if ("none".equalsIgnoreCase(sqlStatement.getStrategyType())) {
89              setStrategyConfiguration(result, sqlStatement.getDefaultType(), new NoneShardingStrategyConfiguration());
90          } else {
91              String shardingAlgorithmName = getShardingAlgorithmName(sqlStatement, result);
92              ShardingStrategyConfiguration strategyConfig = ShardingTableRuleStatementConverter.createStrategyConfiguration(
93                      sqlStatement.getStrategyType(), sqlStatement.getShardingColumn(), shardingAlgorithmName);
94              setStrategyConfiguration(result, sqlStatement.getDefaultType(), strategyConfig);
95          }
96          return result;
97      }
98      
99      private String getShardingAlgorithmName(final AlterDefaultShardingStrategyStatement sqlStatement, final ShardingRuleConfiguration shardingRuleConfig) {
100         return createDefaultAlgorithm(sqlStatement, shardingRuleConfig);
101     }
102     
103     private String createDefaultAlgorithm(final AlterDefaultShardingStrategyStatement sqlStatement, final ShardingRuleConfiguration shardingRuleConfig) {
104         String result = getDefaultShardingAlgorithmName(sqlStatement.getDefaultType(), sqlStatement.getAlgorithmSegment().getName());
105         shardingRuleConfig.getShardingAlgorithms().put(result, createAlgorithmConfiguration(sqlStatement.getAlgorithmSegment()));
106         return result;
107     }
108     
109     private AlgorithmConfiguration createAlgorithmConfiguration(final AlgorithmSegment segment) {
110         return new AlgorithmConfiguration(segment.getName(), segment.getProps());
111     }
112     
113     private String getDefaultShardingAlgorithmName(final String defaultType, final String algorithmType) {
114         return String.format("default_%s_%s", defaultType, algorithmType).toLowerCase();
115     }
116     
117     private void setStrategyConfiguration(final ShardingRuleConfiguration ruleConfig, final String type, final ShardingStrategyConfiguration shardingStrategyConfig) {
118         if (type.equalsIgnoreCase(ShardingStrategyLevelType.TABLE.name())) {
119             ruleConfig.setDefaultTableShardingStrategy(shardingStrategyConfig);
120         } else {
121             ruleConfig.setDefaultDatabaseShardingStrategy(shardingStrategyConfig);
122         }
123     }
124     
125     @Override
126     public ShardingRuleConfiguration buildToBeDroppedRuleConfiguration(final ShardingRuleConfiguration toBeAlteredRuleConfig) {
127         ShardingRuleConfiguration result = new ShardingRuleConfiguration();
128         UnusedAlgorithmFinder.findUnusedShardingAlgorithm(rule.getConfiguration()).forEach(each -> result.getShardingAlgorithms().put(each, rule.getConfiguration().getShardingAlgorithms().get(each)));
129         return result;
130     }
131     
132     @Override
133     public Class<ShardingRule> getRuleClass() {
134         return ShardingRule.class;
135     }
136     
137     @Override
138     public Class<AlterDefaultShardingStrategyStatement> getType() {
139         return AlterDefaultShardingStrategyStatement.class;
140     }
141 }