1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.infra.route.engine.impl;
19
20 import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation;
21 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
22 import org.apache.shardingsphere.infra.hint.HintManager;
23 import org.apache.shardingsphere.infra.hint.HintValueContext;
24 import org.apache.shardingsphere.infra.exception.kernel.syntax.hint.DataSourceHintNotExistsException;
25 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
26 import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit;
27 import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
28 import org.apache.shardingsphere.infra.route.SQLRouter;
29 import org.apache.shardingsphere.infra.route.context.RouteContext;
30 import org.apache.shardingsphere.infra.route.context.RouteMapper;
31 import org.apache.shardingsphere.infra.route.context.RouteUnit;
32 import org.apache.shardingsphere.infra.route.engine.SQLRouteExecutor;
33 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
34 import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
35 import org.apache.shardingsphere.infra.session.query.QueryContext;
36 import org.apache.shardingsphere.infra.spi.type.ordered.OrderedSPILoader;
37
38 import java.util.Collection;
39 import java.util.Collections;
40 import java.util.Map;
41 import java.util.Map.Entry;
42 import java.util.Optional;
43
44
45
46
47 @HighFrequencyInvocation
48 public final class PartialSQLRouteExecutor implements SQLRouteExecutor {
49
50 private final ConfigurationProperties props;
51
52 @SuppressWarnings("rawtypes")
53 private final Map<ShardingSphereRule, SQLRouter> routers;
54
55 public PartialSQLRouteExecutor(final Collection<ShardingSphereRule> rules, final ConfigurationProperties props) {
56 this.props = props;
57 routers = OrderedSPILoader.getServices(SQLRouter.class, rules);
58 }
59
60 @Override
61 @SuppressWarnings({"unchecked", "rawtypes"})
62 public RouteContext route(final ConnectionContext connectionContext, final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database) {
63 RouteContext result = new RouteContext();
64 Optional<String> dataSourceName = findDataSourceByHint(queryContext.getHintValueContext(), database.getResourceMetaData().getStorageUnits());
65 if (dataSourceName.isPresent()) {
66 result.getRouteUnits().add(new RouteUnit(new RouteMapper(dataSourceName.get(), dataSourceName.get()), Collections.emptyList()));
67 return result;
68 }
69 for (Entry<ShardingSphereRule, SQLRouter> entry : routers.entrySet()) {
70 if (result.getRouteUnits().isEmpty()) {
71 result = entry.getValue().createRouteContext(queryContext, globalRuleMetaData, database, entry.getKey(), props, connectionContext);
72 } else {
73 entry.getValue().decorateRouteContext(result, queryContext, database, entry.getKey(), props, connectionContext);
74 }
75 }
76 if (result.getRouteUnits().isEmpty() && 1 == database.getResourceMetaData().getStorageUnits().size()) {
77 String singleDataSourceName = database.getResourceMetaData().getStorageUnits().keySet().iterator().next();
78 result.getRouteUnits().add(new RouteUnit(new RouteMapper(singleDataSourceName, singleDataSourceName), Collections.emptyList()));
79 }
80 return result;
81 }
82
83 private Optional<String> findDataSourceByHint(final HintValueContext hintValueContext, final Map<String, StorageUnit> storageUnits) {
84 Optional<String> result = HintManager.isInstantiated() && HintManager.getDataSourceName().isPresent() ? HintManager.getDataSourceName() : hintValueContext.findHintDataSourceName();
85 if (result.isPresent() && !storageUnits.containsKey(result.get())) {
86 throw new DataSourceHintNotExistsException(result.get());
87 }
88 return result;
89 }
90 }