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.DatabaseRuleCreateExecutor;
22  import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
23  import org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
24  import org.apache.shardingsphere.infra.algorithm.core.exception.MissingRequiredAlgorithmException;
25  import org.apache.shardingsphere.infra.algorithm.core.exception.InvalidAlgorithmConfigurationException;
26  import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
27  import org.apache.shardingsphere.infra.exception.core.external.sql.identifier.SQLExceptionIdentifier;
28  import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.DuplicateRuleException;
29  import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
30  import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
31  import org.apache.shardingsphere.sharding.api.config.strategy.sharding.NoneShardingStrategyConfiguration;
32  import org.apache.shardingsphere.sharding.api.config.strategy.sharding.ShardingStrategyConfiguration;
33  import org.apache.shardingsphere.sharding.distsql.handler.converter.ShardingTableRuleStatementConverter;
34  import org.apache.shardingsphere.sharding.distsql.handler.enums.ShardingStrategyLevelType;
35  import org.apache.shardingsphere.sharding.distsql.handler.enums.ShardingStrategyType;
36  import org.apache.shardingsphere.sharding.distsql.statement.CreateDefaultShardingStrategyStatement;
37  import org.apache.shardingsphere.sharding.rule.ShardingRule;
38  
39  import java.util.Optional;
40  
41  /**
42   * Create default sharding strategy executor.
43   */
44  @Setter
45  public final class CreateDefaultShardingStrategyExecutor implements DatabaseRuleCreateExecutor<CreateDefaultShardingStrategyStatement, ShardingRule, ShardingRuleConfiguration> {
46      
47      private ShardingSphereDatabase database;
48      
49      private ShardingRule rule;
50      
51      @Override
52      public void checkBeforeUpdate(final CreateDefaultShardingStrategyStatement sqlStatement) {
53          if (!"none".equalsIgnoreCase(sqlStatement.getStrategyType())) {
54              checkAlgorithm(sqlStatement);
55          }
56          if (!sqlStatement.isIfNotExists()) {
57              checkExist(sqlStatement);
58          }
59      }
60      
61      private void checkAlgorithm(final CreateDefaultShardingStrategyStatement sqlStatement) {
62          ShardingSpherePreconditions.checkState(ShardingStrategyType.isValidType(sqlStatement.getStrategyType()), () -> new InvalidAlgorithmConfigurationException(sqlStatement.getStrategyType()));
63          ShardingSpherePreconditions.checkState(ShardingStrategyType.getValueOf(sqlStatement.getStrategyType())
64                  .isValid(sqlStatement.getShardingColumn()), () -> new InvalidAlgorithmConfigurationException(sqlStatement.getStrategyType()));
65          ShardingSpherePreconditions.checkNotNull(sqlStatement.getAlgorithmSegment(), () -> new MissingRequiredAlgorithmException("Sharding", new SQLExceptionIdentifier("")));
66      }
67      
68      private void checkExist(final CreateDefaultShardingStrategyStatement sqlStatement) {
69          if (null == rule) {
70              return;
71          }
72          ShardingSpherePreconditions.checkState(!getStrategyConfiguration(sqlStatement.getDefaultType()).isPresent(),
73                  () -> new DuplicateRuleException(String.format("default sharding %s strategy", sqlStatement.getDefaultType().toLowerCase()), database.getName()));
74      }
75      
76      private Optional<ShardingStrategyConfiguration> getStrategyConfiguration(final String type) {
77          ShardingStrategyConfiguration result = type.equalsIgnoreCase(ShardingStrategyLevelType.TABLE.name())
78                  ? rule.getConfiguration().getDefaultTableShardingStrategy()
79                  : rule.getConfiguration().getDefaultDatabaseShardingStrategy();
80          return Optional.ofNullable(result);
81      }
82      
83      @Override
84      public ShardingRuleConfiguration buildToBeCreatedRuleConfiguration(final CreateDefaultShardingStrategyStatement sqlStatement) {
85          ShardingRuleConfiguration result = new ShardingRuleConfiguration();
86          if ("none".equalsIgnoreCase(sqlStatement.getStrategyType())) {
87              setStrategyConfiguration(result, sqlStatement.getDefaultType(), new NoneShardingStrategyConfiguration());
88          } else {
89              String shardingAlgorithmName = getShardingAlgorithmName(sqlStatement, result);
90              ShardingStrategyConfiguration strategyConfig = ShardingTableRuleStatementConverter.createStrategyConfiguration(
91                      sqlStatement.getStrategyType(), sqlStatement.getShardingColumn(), shardingAlgorithmName);
92              setStrategyConfiguration(result, sqlStatement.getDefaultType(), strategyConfig);
93          }
94          return result;
95      }
96      
97      private String getShardingAlgorithmName(final CreateDefaultShardingStrategyStatement sqlStatement, final ShardingRuleConfiguration ruleConfig) {
98          return createDefaultAlgorithm(sqlStatement, ruleConfig);
99      }
100     
101     private String createDefaultAlgorithm(final CreateDefaultShardingStrategyStatement sqlStatement, final ShardingRuleConfiguration ruleConfig) {
102         String result = getDefaultShardingAlgorithmName(sqlStatement.getDefaultType(), sqlStatement.getAlgorithmSegment().getName());
103         ruleConfig.getShardingAlgorithms().put(result, createAlgorithmConfiguration(sqlStatement.getAlgorithmSegment()));
104         return result;
105     }
106     
107     private AlgorithmConfiguration createAlgorithmConfiguration(final AlgorithmSegment segment) {
108         return new AlgorithmConfiguration(segment.getName(), segment.getProps());
109     }
110     
111     private String getDefaultShardingAlgorithmName(final String defaultType, final String algorithmType) {
112         return String.format("default_%s_%s", defaultType, algorithmType).toLowerCase();
113     }
114     
115     private void setStrategyConfiguration(final ShardingRuleConfiguration ruleConfig, final String type, final ShardingStrategyConfiguration shardingStrategyConfig) {
116         if (type.equalsIgnoreCase(ShardingStrategyLevelType.TABLE.name())) {
117             ruleConfig.setDefaultTableShardingStrategy(shardingStrategyConfig);
118         } else {
119             ruleConfig.setDefaultDatabaseShardingStrategy(shardingStrategyConfig);
120         }
121     }
122     
123     @Override
124     public Class<ShardingRule> getRuleClass() {
125         return ShardingRule.class;
126     }
127     
128     @Override
129     public Class<CreateDefaultShardingStrategyStatement> getType() {
130         return CreateDefaultShardingStrategyStatement.class;
131     }
132 }