1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.encrypt.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.encrypt.api.config.EncryptRuleConfiguration;
25 import org.apache.shardingsphere.encrypt.api.config.rule.EncryptTableRuleConfiguration;
26 import org.apache.shardingsphere.encrypt.distsql.handler.converter.EncryptRuleStatementConverter;
27 import org.apache.shardingsphere.encrypt.distsql.segment.EncryptRuleSegment;
28 import org.apache.shardingsphere.encrypt.distsql.statement.AlterEncryptRuleStatement;
29 import org.apache.shardingsphere.encrypt.rule.EncryptRule;
30 import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm;
31 import org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
32 import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
33 import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.InvalidRuleConfigurationException;
34 import org.apache.shardingsphere.infra.exception.kernel.metadata.rule.MissingRequiredRuleException;
35 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
36 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
37
38 import java.util.Collection;
39 import java.util.Collections;
40 import java.util.HashMap;
41 import java.util.LinkedHashSet;
42 import java.util.Map;
43 import java.util.Objects;
44 import java.util.stream.Collectors;
45
46
47
48
49 @DistSQLExecutorCurrentRuleRequired(EncryptRule.class)
50 @Setter
51 public final class AlterEncryptRuleExecutor implements DatabaseRuleAlterExecutor<AlterEncryptRuleStatement, EncryptRule, EncryptRuleConfiguration> {
52
53 private ShardingSphereDatabase database;
54
55 private EncryptRule rule;
56
57 @Override
58 public void checkBeforeUpdate(final AlterEncryptRuleStatement sqlStatement) {
59 checkToBeAlteredRules(sqlStatement);
60 checkColumnNames(sqlStatement);
61 checkToBeAlteredEncryptors(sqlStatement);
62 }
63
64 private void checkToBeAlteredRules(final AlterEncryptRuleStatement sqlStatement) {
65 Collection<String> currentEncryptTableNames = rule.getConfiguration().getTables().stream().map(EncryptTableRuleConfiguration::getName).collect(Collectors.toList());
66 Collection<String> notExistEncryptTableNames = getToBeAlteredEncryptTableNames(sqlStatement).stream().filter(each -> !currentEncryptTableNames.contains(each)).collect(Collectors.toList());
67 if (!notExistEncryptTableNames.isEmpty()) {
68 throw new MissingRequiredRuleException("Encrypt", database.getName(), notExistEncryptTableNames);
69 }
70 }
71
72 private Collection<String> getToBeAlteredEncryptTableNames(final AlterEncryptRuleStatement sqlStatement) {
73 return sqlStatement.getRules().stream().map(EncryptRuleSegment::getTableName).collect(Collectors.toList());
74 }
75
76 private void checkColumnNames(final AlterEncryptRuleStatement sqlStatement) {
77 for (EncryptRuleSegment each : sqlStatement.getRules()) {
78 ShardingSpherePreconditions.checkState(isColumnNameNotConflicts(each),
79 () -> new InvalidRuleConfigurationException("encrypt", "assisted query column or like query column conflicts with logic column"));
80 }
81 }
82
83 private boolean isColumnNameNotConflicts(final EncryptRuleSegment rule) {
84 return rule.getColumns().stream().noneMatch(each -> null != each.getLikeQuery() && each.getName().equals(each.getLikeQuery().getName())
85 || null != each.getAssistedQuery() && each.getName().equals(each.getAssistedQuery().getName()));
86 }
87
88 private void checkToBeAlteredEncryptors(final AlterEncryptRuleStatement sqlStatement) {
89 Collection<AlgorithmSegment> encryptors = new LinkedHashSet<>();
90 sqlStatement.getRules().forEach(each -> each.getColumns().forEach(column -> {
91 encryptors.add(column.getCipher().getEncryptor());
92 if (null != column.getAssistedQuery()) {
93 encryptors.add(column.getAssistedQuery().getEncryptor());
94 }
95 if (null != column.getLikeQuery()) {
96 encryptors.add(column.getLikeQuery().getEncryptor());
97 }
98 }));
99 encryptors.stream().filter(Objects::nonNull).forEach(each -> TypedSPILoader.checkService(EncryptAlgorithm.class, each.getName(), each.getProps()));
100 }
101
102 @Override
103 public EncryptRuleConfiguration buildToBeAlteredRuleConfiguration(final AlterEncryptRuleStatement sqlStatement) {
104 return EncryptRuleStatementConverter.convert(sqlStatement.getRules());
105 }
106
107 @Override
108 public EncryptRuleConfiguration buildToBeDroppedRuleConfiguration(final EncryptRuleConfiguration toBeAlteredRuleConfig) {
109 Map<String, AlgorithmConfiguration> toBeDroppedEncryptors = new HashMap<>();
110 Collection<String> unusedEncryptor = UnusedAlgorithmFinder.findUnusedEncryptor(rule.getConfiguration());
111 unusedEncryptor.forEach(each -> toBeDroppedEncryptors.put(each, rule.getConfiguration().getEncryptors().get(each)));
112 return new EncryptRuleConfiguration(Collections.emptyList(), toBeDroppedEncryptors);
113 }
114
115 @Override
116 public Class<EncryptRule> getRuleClass() {
117 return EncryptRule.class;
118 }
119
120 @Override
121 public Class<AlterEncryptRuleStatement> getType() {
122 return AlterEncryptRuleStatement.class;
123 }
124 }