1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.sharding.route.engine;
19
20 import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation;
21 import org.apache.shardingsphere.infra.binder.context.type.CursorAvailable;
22 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
23 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
24 import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
25 import org.apache.shardingsphere.infra.route.SQLRouter;
26 import org.apache.shardingsphere.infra.route.context.RouteContext;
27 import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
28 import org.apache.shardingsphere.infra.session.query.QueryContext;
29 import org.apache.shardingsphere.sharding.cache.route.CachedShardingSQLRouter;
30 import org.apache.shardingsphere.sharding.constant.ShardingOrder;
31 import org.apache.shardingsphere.sharding.route.engine.condition.ShardingCondition;
32 import org.apache.shardingsphere.sharding.route.engine.condition.ShardingConditions;
33 import org.apache.shardingsphere.sharding.route.engine.condition.engine.ShardingConditionEngine;
34 import org.apache.shardingsphere.sharding.route.engine.type.ShardingRouteEngineFactory;
35 import org.apache.shardingsphere.sharding.route.engine.validator.ShardingStatementValidator;
36 import org.apache.shardingsphere.sharding.route.engine.validator.ShardingStatementValidatorFactory;
37 import org.apache.shardingsphere.sharding.rule.ShardingRule;
38 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
39 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
40
41 import java.util.Collections;
42 import java.util.List;
43 import java.util.Optional;
44
45
46
47
48 @HighFrequencyInvocation
49 public final class ShardingSQLRouter implements SQLRouter<ShardingRule> {
50
51 @Override
52 public RouteContext createRouteContext(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database, final ShardingRule rule,
53 final ConfigurationProperties props, final ConnectionContext connectionContext) {
54 if (rule.isShardingCacheEnabled()) {
55 Optional<RouteContext> result = new CachedShardingSQLRouter()
56 .loadRouteContext(this::createRouteContext0, queryContext, globalRuleMetaData, database, rule.getShardingCache(), props, connectionContext);
57 if (result.isPresent()) {
58 return result.get();
59 }
60 }
61 return createRouteContext0(queryContext, globalRuleMetaData, database, rule, props, connectionContext);
62 }
63
64 private RouteContext createRouteContext0(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database, final ShardingRule rule,
65 final ConfigurationProperties props, final ConnectionContext connectionContext) {
66 SQLStatement sqlStatement = queryContext.getSqlStatementContext().getSqlStatement();
67 ShardingConditions shardingConditions = createShardingConditions(queryContext, globalRuleMetaData, database, rule);
68 Optional<ShardingStatementValidator> validator = ShardingStatementValidatorFactory.newInstance(sqlStatement, shardingConditions, globalRuleMetaData);
69 validator.ifPresent(optional -> optional.preValidate(rule, queryContext.getSqlStatementContext(), queryContext.getParameters(), database, props));
70 if (sqlStatement instanceof DMLStatement && shardingConditions.isNeedMerge()) {
71 shardingConditions.merge();
72 }
73 RouteContext result = ShardingRouteEngineFactory.newInstance(rule, database, queryContext, shardingConditions, props, connectionContext, globalRuleMetaData).route(rule);
74 validator.ifPresent(optional -> optional.postValidate(rule, queryContext.getSqlStatementContext(), queryContext.getHintValueContext(), queryContext.getParameters(), database, props, result));
75 return result;
76 }
77
78 private ShardingConditions createShardingConditions(final QueryContext queryContext,
79 final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database, final ShardingRule rule) {
80 List<ShardingCondition> shardingConditions;
81 if (queryContext.getSqlStatementContext().getSqlStatement() instanceof DMLStatement || queryContext.getSqlStatementContext() instanceof CursorAvailable) {
82 shardingConditions = new ShardingConditionEngine(globalRuleMetaData, database, rule).createShardingConditions(queryContext.getSqlStatementContext(), queryContext.getParameters());
83 } else {
84 shardingConditions = Collections.emptyList();
85 }
86 return new ShardingConditions(shardingConditions, queryContext.getSqlStatementContext(), rule);
87 }
88
89 @Override
90 public void decorateRouteContext(final RouteContext routeContext, final QueryContext queryContext, final ShardingSphereDatabase database, final ShardingRule rule,
91 final ConfigurationProperties props, final ConnectionContext connectionContext) {
92
93 }
94
95 @Override
96 public int getOrder() {
97 return ShardingOrder.ORDER;
98 }
99
100 @Override
101 public Class<ShardingRule> getTypeClass() {
102 return ShardingRule.class;
103 }
104 }