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.config.props.ConfigurationProperties;
22 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
23 import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
24 import org.apache.shardingsphere.infra.route.context.RouteContext;
25 import org.apache.shardingsphere.infra.route.lifecycle.EntranceSQLRouter;
26 import org.apache.shardingsphere.infra.session.query.QueryContext;
27 import org.apache.shardingsphere.sharding.cache.route.CachedShardingSQLRouter;
28 import org.apache.shardingsphere.sharding.constant.ShardingOrder;
29 import org.apache.shardingsphere.sharding.route.engine.checker.ShardingRouteContextCheckerFactory;
30 import org.apache.shardingsphere.sharding.route.engine.condition.ShardingCondition;
31 import org.apache.shardingsphere.sharding.route.engine.condition.ShardingConditions;
32 import org.apache.shardingsphere.sharding.route.engine.condition.engine.ShardingConditionEngine;
33 import org.apache.shardingsphere.sharding.route.engine.type.ShardingRouteEngineFactory;
34 import org.apache.shardingsphere.sharding.rule.ShardingRule;
35 import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement;
36 import org.apache.shardingsphere.sql.parser.statement.core.statement.attribute.type.CursorSQLStatementAttribute;
37 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.DMLStatement;
38
39 import java.util.Collection;
40 import java.util.Collections;
41 import java.util.List;
42 import java.util.Optional;
43
44
45
46
47 @HighFrequencyInvocation
48 public final class ShardingSQLRouter implements EntranceSQLRouter<ShardingRule> {
49
50 @Override
51 public RouteContext createRouteContext(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database,
52 final ShardingRule rule, final Collection<String> tableNames, final ConfigurationProperties props) {
53 if (rule.isShardingCacheEnabled()) {
54 Optional<RouteContext> result = new CachedShardingSQLRouter()
55 .loadRouteContext(this::createRouteContext0, queryContext, globalRuleMetaData, database, rule.getShardingCache(), tableNames, props);
56 if (result.isPresent()) {
57 return result.get();
58 }
59 }
60 return createRouteContext0(queryContext, globalRuleMetaData, database, rule, tableNames, props);
61 }
62
63 private RouteContext createRouteContext0(final QueryContext queryContext, final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database, final ShardingRule rule,
64 final Collection<String> tableNames, final ConfigurationProperties props) {
65 Collection<String> logicTableNames = rule.getShardingLogicTableNames(tableNames);
66 if (logicTableNames.isEmpty()) {
67 return new RouteContext();
68 }
69 SQLStatement sqlStatement = queryContext.getSqlStatementContext().getSqlStatement();
70 ShardingConditions shardingConditions = createShardingConditions(queryContext, globalRuleMetaData, database, rule);
71 if (sqlStatement instanceof DMLStatement && shardingConditions.isNeedMerge()) {
72 shardingConditions.merge();
73 }
74 RouteContext result = ShardingRouteEngineFactory.newInstance(rule, database, queryContext, shardingConditions, logicTableNames, props).route(rule);
75 checkRouteContext(queryContext, database, rule, props, sqlStatement, shardingConditions, result);
76 return result;
77 }
78
79 private ShardingConditions createShardingConditions(final QueryContext queryContext,
80 final RuleMetaData globalRuleMetaData, final ShardingSphereDatabase database, final ShardingRule rule) {
81 List<ShardingCondition> shardingConditions;
82 if (queryContext.getSqlStatementContext().getSqlStatement() instanceof DMLStatement
83 || queryContext.getSqlStatementContext().getSqlStatement().getAttributes().findAttribute(CursorSQLStatementAttribute.class).isPresent()) {
84 shardingConditions = new ShardingConditionEngine(globalRuleMetaData, database, rule).createShardingConditions(queryContext.getSqlStatementContext(), queryContext.getParameters());
85 } else {
86 shardingConditions = Collections.emptyList();
87 }
88 return new ShardingConditions(shardingConditions, queryContext.getSqlStatementContext(), rule);
89 }
90
91 private void checkRouteContext(final QueryContext queryContext, final ShardingSphereDatabase database, final ShardingRule rule, final ConfigurationProperties props,
92 final SQLStatement sqlStatement, final ShardingConditions shardingConditions, final RouteContext routeContext) {
93 ShardingRouteContextCheckerFactory.newInstance(sqlStatement, shardingConditions).ifPresent(optional -> optional.check(rule, queryContext, database, props, routeContext));
94 }
95
96 @Override
97 public Type getType() {
98 return Type.DATA_NODE;
99 }
100
101 @Override
102 public int getOrder() {
103 return ShardingOrder.ORDER;
104 }
105
106 @Override
107 public Class<ShardingRule> getTypeClass() {
108 return ShardingRule.class;
109 }
110 }