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.connection.ConnectionContext;
25 import org.apache.shardingsphere.infra.session.query.QueryContext;
26 import org.apache.shardingsphere.sharding.cache.ShardingCache;
27 import org.apache.shardingsphere.sharding.cache.checker.ShardingRouteCacheableCheckResult;
28 import org.apache.shardingsphere.sharding.cache.route.cache.ShardingRouteCacheKey;
29 import org.apache.shardingsphere.sharding.cache.route.cache.ShardingRouteCacheValue;
30 import org.apache.shardingsphere.sharding.rule.ShardingRule;
31
32 import java.util.ArrayList;
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 ConfigurationProperties props,
55 final ConnectionContext connectionContext) {
56 if (queryContext.getSql().length() > shardingCache.getConfiguration().getAllowedMaxSqlLength()) {
57 return Optional.empty();
58 }
59 ShardingRouteCacheableCheckResult cacheableCheckResult = shardingCache.getRouteCacheableChecker().check(database, queryContext);
60 if (!cacheableCheckResult.isProbablyCacheable()) {
61 return Optional.empty();
62 }
63 List<Object> shardingConditionParams = new ArrayList<>(cacheableCheckResult.getShardingConditionParameterMarkerIndexes().size());
64 for (int each : cacheableCheckResult.getShardingConditionParameterMarkerIndexes()) {
65 if (each >= queryContext.getParameters().size()) {
66 return Optional.empty();
67 }
68 shardingConditionParams.add(queryContext.getParameters().get(each));
69 }
70 Optional<RouteContext> cachedResult = shardingCache.getRouteCache().get(new ShardingRouteCacheKey(queryContext.getSql(), shardingConditionParams))
71 .flatMap(ShardingRouteCacheValue::getCachedRouteContext);
72 RouteContext result = cachedResult.orElseGet(
73 () -> originSQLRouter.createRouteContext(queryContext, globalRuleMetaData, database, shardingCache.getShardingRule(), props, connectionContext));
74 if (!cachedResult.isPresent() && hitOneShardOnly(result)) {
75 shardingCache.getRouteCache().put(new ShardingRouteCacheKey(queryContext.getSql(), shardingConditionParams), new ShardingRouteCacheValue(result));
76 }
77 return Optional.of(result);
78 }
79
80 private boolean hitOneShardOnly(final RouteContext routeContext) {
81 return 1 == routeContext.getRouteUnits().size() && 1 == routeContext.getRouteUnits().iterator().next().getTableMappers().size()
82 && 1 == routeContext.getOriginalDataNodes().size() && 1 == routeContext.getOriginalDataNodes().iterator().next().size();
83 }
84
85 @FunctionalInterface
86 public interface OriginSQLRouter {
87
88
89
90
91
92
93
94
95
96
97
98
99 RouteContext createRouteContext(QueryContext queryContext, RuleMetaData globalRuleMetaData, ShardingSphereDatabase database, ShardingRule rule,
100 ConfigurationProperties props, ConnectionContext connectionContext);
101 }
102 }