1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.sharding.algorithm.sharding.inline;
19
20 import groovy.lang.MissingMethodException;
21 import org.apache.shardingsphere.infra.algorithm.core.exception.AlgorithmInitializationException;
22 import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
23 import org.apache.shardingsphere.infra.exception.generic.UnsupportedSQLOperationException;
24 import org.apache.shardingsphere.infra.expr.core.InlineExpressionParserFactory;
25 import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
26 import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
27 import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
28 import org.apache.shardingsphere.sharding.exception.algorithm.MismatchedInlineShardingAlgorithmExpressionAndColumnException;
29 import org.apache.shardingsphere.sharding.exception.data.NullShardingValueException;
30
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.Optional;
34 import java.util.Properties;
35
36
37
38
39 public final class InlineShardingAlgorithm implements StandardShardingAlgorithm<Comparable<?>> {
40
41 private static final String ALGORITHM_EXPRESSION_KEY = "algorithm-expression";
42
43 private static final String ALLOW_RANGE_QUERY_KEY = "allow-range-query-with-inline-sharding";
44
45 private String algorithmExpression;
46
47 private boolean allowRangeQuery;
48
49 @Override
50 public void init(final Properties props) {
51 algorithmExpression = getAlgorithmExpression(props);
52 allowRangeQuery = isAllowRangeQuery(props);
53 }
54
55 private String getAlgorithmExpression(final Properties props) {
56 String expression = props.getProperty(ALGORITHM_EXPRESSION_KEY);
57 ShardingSpherePreconditions.checkNotEmpty(expression, () -> new AlgorithmInitializationException(this, "Inline sharding algorithm expression cannot be null or empty"));
58 return InlineExpressionParserFactory.newInstance(expression.trim()).handlePlaceHolder();
59 }
60
61 private boolean isAllowRangeQuery(final Properties props) {
62 return Boolean.parseBoolean(props.getOrDefault(ALLOW_RANGE_QUERY_KEY, Boolean.FALSE.toString()).toString());
63 }
64
65 @Override
66 public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<Comparable<?>> shardingValue) {
67 ShardingSpherePreconditions.checkNotNull(shardingValue.getValue(), NullShardingValueException::new);
68 String columnName = shardingValue.getColumnName();
69 ShardingSpherePreconditions.checkState(algorithmExpression.contains(columnName), () -> new MismatchedInlineShardingAlgorithmExpressionAndColumnException(algorithmExpression, columnName));
70 try {
71 return InlineExpressionParserFactory.newInstance(algorithmExpression).evaluateWithArgs(Collections.singletonMap(columnName, shardingValue.getValue()));
72 } catch (final MissingMethodException ignored) {
73 throw new MismatchedInlineShardingAlgorithmExpressionAndColumnException(algorithmExpression, columnName);
74 }
75 }
76
77 @Override
78 public Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<Comparable<?>> shardingValue) {
79 ShardingSpherePreconditions.checkState(allowRangeQuery,
80 () -> new UnsupportedSQLOperationException(String.format("Since the property of `%s` is false, inline sharding algorithm can not tackle with range query", ALLOW_RANGE_QUERY_KEY)));
81 return availableTargetNames;
82 }
83
84 @Override
85 public Optional<String> getAlgorithmStructure(final String dataNodePrefix, final String shardingColumn) {
86 return Optional.of(algorithmExpression.replaceFirst(dataNodePrefix, "").replaceFirst(shardingColumn, "").replaceAll(" ", ""));
87 }
88
89 @Override
90 public String getType() {
91 return "INLINE";
92 }
93 }