1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.sharding.distsql.handler.update;
19
20 import com.cedarsoftware.util.CaseInsensitiveSet;
21 import lombok.Setter;
22 import org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleAlterExecutor;
23 import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.DuplicateRuleException;
24 import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.InvalidRuleConfigurationException;
25 import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.MissingRequiredRuleException;
26 import org.apache.shardingsphere.distsql.handler.required.DistSQLExecutorCurrentRuleRequired;
27 import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
28 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
29 import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
30 import org.apache.shardingsphere.sharding.api.config.rule.ShardingAutoTableRuleConfiguration;
31 import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableReferenceRuleConfiguration;
32 import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
33 import org.apache.shardingsphere.sharding.distsql.handler.checker.ShardingTableRuleStatementChecker;
34 import org.apache.shardingsphere.sharding.distsql.segment.table.TableReferenceRuleSegment;
35 import org.apache.shardingsphere.sharding.distsql.statement.AlterShardingTableReferenceRuleStatement;
36 import org.apache.shardingsphere.sharding.rule.ShardingRule;
37
38 import java.util.Arrays;
39 import java.util.Collection;
40 import java.util.Collections;
41 import java.util.HashSet;
42 import java.util.stream.Collectors;
43
44
45
46
47 @DistSQLExecutorCurrentRuleRequired(ShardingRule.class)
48 @Setter
49 public final class AlterShardingTableReferenceRuleExecutor implements DatabaseRuleAlterExecutor<AlterShardingTableReferenceRuleStatement, ShardingRule, ShardingRuleConfiguration> {
50
51 private ShardingSphereDatabase database;
52
53 private ShardingRule rule;
54
55 @Override
56 public void checkBeforeUpdate(final AlterShardingTableReferenceRuleStatement sqlStatement) {
57 checkToBeAlteredRulesExisted(sqlStatement);
58 checkDuplicatedTablesInShardingTableReferenceRules(sqlStatement);
59 checkToBeReferencedShardingTablesExisted(sqlStatement);
60 checkShardingTableReferenceRulesValid(sqlStatement);
61 }
62
63 private void checkToBeAlteredRulesExisted(final AlterShardingTableReferenceRuleStatement sqlStatement) {
64 Collection<String> currentRuleNames = rule.getConfiguration().getBindingTableGroups().stream().map(ShardingTableReferenceRuleConfiguration::getName).collect(Collectors.toSet());
65 Collection<String> notExistedRuleNames = sqlStatement.getRules().stream().map(TableReferenceRuleSegment::getName).filter(each -> !currentRuleNames.contains(each)).collect(Collectors.toSet());
66 ShardingSpherePreconditions.checkMustEmpty(notExistedRuleNames, () -> new MissingRequiredRuleException("Sharding table reference", database.getName(), notExistedRuleNames));
67 }
68
69 private void checkDuplicatedTablesInShardingTableReferenceRules(final AlterShardingTableReferenceRuleStatement sqlStatement) {
70 Collection<String> currentReferencedTableNames = getReferencedTableNames(getToBeAlteredRuleNames(sqlStatement));
71 Collection<String> duplicatedTableNames = sqlStatement.getTableNames().stream().filter(currentReferencedTableNames::contains).collect(Collectors.toSet());
72 ShardingSpherePreconditions.checkMustEmpty(duplicatedTableNames, () -> new DuplicateRuleException("sharding table reference", database.getName(), duplicatedTableNames));
73 }
74
75 private Collection<String> getReferencedTableNames(final Collection<String> getToBeAlteredRuleNames) {
76 Collection<String> result = new HashSet<>();
77 rule.getConfiguration().getBindingTableGroups().forEach(each -> {
78 if (!getToBeAlteredRuleNames.contains(each.getName())) {
79 result.addAll(Arrays.stream(each.getReference().split(",")).map(String::trim).collect(Collectors.toSet()));
80 }
81 });
82 return result;
83 }
84
85 private Collection<String> getToBeAlteredRuleNames(final AlterShardingTableReferenceRuleStatement sqlStatement) {
86 return sqlStatement.getRules().stream().map(TableReferenceRuleSegment::getName).collect(Collectors.toSet());
87 }
88
89 private void checkToBeReferencedShardingTablesExisted(final AlterShardingTableReferenceRuleStatement sqlStatement) {
90 Collection<String> currentShardingTableNames = getCurrentShardingTableNames();
91 Collection<String> notExistedTableNames = sqlStatement.getTableNames().stream().filter(each -> !currentShardingTableNames.contains(each)).collect(Collectors.toSet());
92 ShardingSpherePreconditions.checkMustEmpty(notExistedTableNames, () -> new MissingRequiredRuleException("Sharding", database.getName(), notExistedTableNames));
93 }
94
95 private Collection<String> getCurrentShardingTableNames() {
96 Collection<String> result = new CaseInsensitiveSet<>();
97 result.addAll(rule.getConfiguration().getTables().stream().map(ShardingTableRuleConfiguration::getLogicTable).collect(Collectors.toSet()));
98 result.addAll(rule.getConfiguration().getAutoTables().stream().map(ShardingAutoTableRuleConfiguration::getLogicTable).collect(Collectors.toSet()));
99 return result;
100 }
101
102 private void checkShardingTableReferenceRulesValid(final AlterShardingTableReferenceRuleStatement sqlStatement) {
103 Collection<ShardingTableReferenceRuleConfiguration> toBeAlteredShardingTableReferenceRules = buildToBeAlteredRuleConfiguration(sqlStatement).getBindingTableGroups();
104 Collection<String> ruleNames = toBeAlteredShardingTableReferenceRules.stream().map(ShardingTableReferenceRuleConfiguration::getName).collect(Collectors.toList());
105 ShardingSpherePreconditions.checkState(ShardingTableRuleStatementChecker.isValidBindingTableGroups(toBeAlteredShardingTableReferenceRules, rule.getConfiguration()),
106 () -> new InvalidRuleConfigurationException("sharding table", ruleNames, Collections.singleton("invalid sharding table reference.")));
107 }
108
109 @Override
110 public ShardingRuleConfiguration buildToBeAlteredRuleConfiguration(final AlterShardingTableReferenceRuleStatement sqlStatement) {
111 ShardingRuleConfiguration result = new ShardingRuleConfiguration();
112 sqlStatement.getRules().forEach(each -> result.getBindingTableGroups().add(new ShardingTableReferenceRuleConfiguration(each.getName(), each.getReference())));
113 return result;
114 }
115
116 @Override
117 public ShardingRuleConfiguration buildToBeDroppedRuleConfiguration(final ShardingRuleConfiguration toBeAlteredRuleConfig) {
118 return null;
119 }
120
121 @Override
122 public Class<ShardingRule> getRuleClass() {
123 return ShardingRule.class;
124 }
125
126 @Override
127 public Class<AlterShardingTableReferenceRuleStatement> getType() {
128 return AlterShardingTableReferenceRuleStatement.class;
129 }
130 }