1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.sharding.cache.route;
19
20 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
21 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
22 import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
23 import org.apache.shardingsphere.infra.route.context.RouteContext;
24 import org.apache.shardingsphere.infra.session.query.QueryContext;
25 import org.apache.shardingsphere.sharding.cache.ShardingCache;
26 import org.apache.shardingsphere.sharding.cache.checker.ShardingRouteCacheableCheckResult;
27 import org.apache.shardingsphere.sharding.cache.route.cache.ShardingRouteCacheKey;
28 import org.apache.shardingsphere.sharding.cache.route.cache.ShardingRouteCacheValue;
29 import org.apache.shardingsphere.sharding.rule.ShardingRule;
30
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.List;
34 import java.util.Optional;
35
36
37
38
39 public final class CachedShardingSQLRouter {
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public Optional<RouteContext> loadRouteContext(final OriginSQLRouter originSQLRouter, final QueryContext queryContext, final RuleMetaData globalRuleMetaData,
54 final ShardingSphereDatabase database, final ShardingCache shardingCache, final Collection<String> tableNames, final ConfigurationProperties props) {
55 if (queryContext.getSql().length() > shardingCache.getConfiguration().getAllowedMaxSqlLength()) {
56 return Optional.empty();
57 }
58 ShardingRouteCacheableCheckResult cacheableCheckResult = shardingCache.getRouteCacheableChecker().check(database, queryContext);
59 if (!cacheableCheckResult.isProbablyCacheable()) {
60 return Optional.empty();
61 }
62 List<Object> shardingConditionParams = new ArrayList<>(cacheableCheckResult.getShardingConditionParameterMarkerIndexes().size());
63 for (int each : cacheableCheckResult.getShardingConditionParameterMarkerIndexes()) {
64 if (each >= queryContext.getParameters().size()) {
65 return Optional.empty();
66 }
67 shardingConditionParams.add(queryContext.getParameters().get(each));
68 }
69 Optional<RouteContext> cachedResult = shardingCache.getRouteCache().get(new ShardingRouteCacheKey(queryContext.getSql(), shardingConditionParams))
70 .flatMap(ShardingRouteCacheValue::getCachedRouteContext);
71 RouteContext result = cachedResult.orElseGet(() -> originSQLRouter.createRouteContext(queryContext, globalRuleMetaData, database, shardingCache.getShardingRule(), tableNames, props));
72 if (!cachedResult.isPresent() && hitOneShardOnly(result)) {
73 shardingCache.getRouteCache().put(new ShardingRouteCacheKey(queryContext.getSql(), shardingConditionParams), new ShardingRouteCacheValue(result));
74 }
75 return Optional.of(result);
76 }
77
78 private boolean hitOneShardOnly(final RouteContext routeContext) {
79 return 1 == routeContext.getRouteUnits().size() && 1 == routeContext.getRouteUnits().iterator().next().getTableMappers().size()
80 && 1 == routeContext.getOriginalDataNodes().size() && 1 == routeContext.getOriginalDataNodes().iterator().next().size();
81 }
82
83 @FunctionalInterface
84 public interface OriginSQLRouter {
85
86
87
88
89
90
91
92
93
94
95
96
97 RouteContext createRouteContext(QueryContext queryContext, RuleMetaData globalRuleMetaData, ShardingSphereDatabase database, ShardingRule rule, Collection<String> tableNames,
98 ConfigurationProperties props);
99 }
100 }