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.type;
19
20 import lombok.AccessLevel;
21 import lombok.NoArgsConstructor;
22 import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
23 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
24 import org.apache.shardingsphere.infra.hint.HintValueContext;
25 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
26 import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
27 import org.apache.shardingsphere.infra.session.query.QueryContext;
28 import org.apache.shardingsphere.sharding.route.engine.condition.ShardingCondition;
29 import org.apache.shardingsphere.sharding.route.engine.condition.ShardingConditions;
30 import org.apache.shardingsphere.sharding.route.engine.type.broadcast.ShardingDatabaseBroadcastRouteEngine;
31 import org.apache.shardingsphere.sharding.route.engine.type.broadcast.ShardingInstanceBroadcastRouteEngine;
32 import org.apache.shardingsphere.sharding.route.engine.type.broadcast.ShardingTableBroadcastRouteEngine;
33 import org.apache.shardingsphere.sharding.route.engine.type.complex.ShardingComplexRouteEngine;
34 import org.apache.shardingsphere.sharding.route.engine.type.ignore.ShardingIgnoreRouteEngine;
35 import org.apache.shardingsphere.sharding.route.engine.type.standard.ShardingStandardRouteEngine;
36 import org.apache.shardingsphere.sharding.route.engine.type.unicast.ShardingUnicastRouteEngine;
37 import org.apache.shardingsphere.sharding.rule.ShardingRule;
38 import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement;
39 import org.apache.shardingsphere.sql.parser.statement.core.statement.attribute.type.CursorSQLStatementAttribute;
40 import org.apache.shardingsphere.sql.parser.statement.core.statement.attribute.type.TableBroadcastRouteSQLStatementAttribute;
41 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dal.DALStatement;
42 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dcl.DCLStatement;
43 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.ddl.DDLStatement;
44 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.ddl.procedure.AlterProcedureStatement;
45 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.ddl.procedure.CreateProcedureStatement;
46 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.ddl.procedure.DropProcedureStatement;
47 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.DMLStatement;
48
49 import java.util.Collection;
50
51
52
53
54 @NoArgsConstructor(access = AccessLevel.PRIVATE)
55 public final class ShardingRouteEngineFactory {
56
57
58
59
60
61
62
63
64
65
66
67
68 public static ShardingRouteEngine newInstance(final ShardingRule rule, final ShardingSphereDatabase database, final QueryContext queryContext,
69 final ShardingConditions shardingConditions, final Collection<String> logicTableNames, final ConfigurationProperties props) {
70 SQLStatementContext sqlStatementContext = queryContext.getSqlStatementContext();
71 SQLStatement sqlStatement = sqlStatementContext.getSqlStatement();
72 if (sqlStatement instanceof DDLStatement) {
73 return queryContext.getSqlStatementContext().getSqlStatement().getAttributes().findAttribute(CursorSQLStatementAttribute.class).isPresent()
74 ? getCursorRouteEngine(rule, sqlStatementContext, queryContext.getHintValueContext(), shardingConditions, logicTableNames, props)
75 : getDDLRouteEngine(database, sqlStatementContext, logicTableNames);
76 }
77 if (sqlStatement instanceof DALStatement) {
78 return getDALRouteEngine(database, sqlStatementContext, queryContext.getConnectionContext(), logicTableNames);
79 }
80 if (sqlStatement instanceof DCLStatement) {
81 return getDCLRouteEngine(database, sqlStatementContext, logicTableNames);
82 }
83 return getDQLRouteEngine(rule, sqlStatementContext, queryContext, shardingConditions, logicTableNames, props);
84 }
85
86 private static ShardingRouteEngine getDDLRouteEngine(final ShardingSphereDatabase database, final SQLStatementContext sqlStatementContext, final Collection<String> logicTableNames) {
87 SQLStatement sqlStatement = sqlStatementContext.getSqlStatement();
88 boolean procedureStatement = sqlStatement instanceof CreateProcedureStatement || sqlStatement instanceof AlterProcedureStatement || sqlStatement instanceof DropProcedureStatement;
89 if (procedureStatement) {
90 return new ShardingDatabaseBroadcastRouteEngine();
91 }
92 return new ShardingTableBroadcastRouteEngine(database, sqlStatementContext, logicTableNames);
93 }
94
95 private static ShardingRouteEngine getCursorRouteEngine(final ShardingRule rule, final SQLStatementContext sqlStatementContext,
96 final HintValueContext hintValueContext, final ShardingConditions shardingConditions, final Collection<String> logicTableNames,
97 final ConfigurationProperties props) {
98 boolean allBindingTables = logicTableNames.size() > 1 && rule.isBindingTablesUseShardingColumnsJoin(sqlStatementContext, logicTableNames);
99 if (isShardingStandardQuery(rule, logicTableNames, allBindingTables)) {
100 return new ShardingStandardRouteEngine(getLogicTableName(shardingConditions, logicTableNames), shardingConditions, sqlStatementContext, hintValueContext, props);
101 }
102 return new ShardingIgnoreRouteEngine();
103 }
104
105 private static ShardingRouteEngine getDALRouteEngine(final ShardingSphereDatabase database, final SQLStatementContext sqlStatementContext,
106 final ConnectionContext connectionContext, final Collection<String> logicTableNames) {
107 if (sqlStatementContext.getSqlStatement().getAttributes().findAttribute(TableBroadcastRouteSQLStatementAttribute.class).isPresent()) {
108 return new ShardingTableBroadcastRouteEngine(database, sqlStatementContext, logicTableNames);
109 }
110 return new ShardingUnicastRouteEngine(sqlStatementContext, logicTableNames, connectionContext);
111 }
112
113 private static ShardingRouteEngine getDCLRouteEngine(final ShardingSphereDatabase database, final SQLStatementContext sqlStatementContext, final Collection<String> logicTableNames) {
114 return isDCLForSingleTable(sqlStatementContext) ? new ShardingTableBroadcastRouteEngine(database, sqlStatementContext, logicTableNames)
115 : new ShardingInstanceBroadcastRouteEngine(database.getResourceMetaData());
116 }
117
118 private static boolean isDCLForSingleTable(final SQLStatementContext sqlStatementContext) {
119 return 1 == sqlStatementContext.getTablesContext().getSimpleTables().size()
120 && !"*".equals(sqlStatementContext.getTablesContext().getSimpleTables().iterator().next().getTableName().getIdentifier().getValue());
121 }
122
123 private static ShardingRouteEngine getDQLRouteEngine(final ShardingRule rule, final SQLStatementContext sqlStatementContext,
124 final QueryContext queryContext, final ShardingConditions shardingConditions, final Collection<String> logicTableNames,
125 final ConfigurationProperties props) {
126 Collection<String> tableNames = sqlStatementContext.getTablesContext().getTableNames();
127 if (sqlStatementContext.getSqlStatement() instanceof DMLStatement && shardingConditions.isAlwaysFalse() || tableNames.isEmpty()) {
128 return new ShardingUnicastRouteEngine(sqlStatementContext, tableNames, queryContext.getConnectionContext());
129 }
130 return getDQLRouteEngineForShardingTable(rule, sqlStatementContext, queryContext.getHintValueContext(), shardingConditions, logicTableNames, props);
131 }
132
133 private static ShardingRouteEngine getDQLRouteEngineForShardingTable(final ShardingRule rule, final SQLStatementContext sqlStatementContext, final HintValueContext hintValueContext,
134 final ShardingConditions shardingConditions, final Collection<String> logicTableNames, final ConfigurationProperties props) {
135 boolean allBindingTables = logicTableNames.size() > 1 && rule.isBindingTablesUseShardingColumnsJoin(sqlStatementContext, logicTableNames);
136 if (isShardingStandardQuery(rule, logicTableNames, allBindingTables)) {
137 return new ShardingStandardRouteEngine(getLogicTableName(shardingConditions, logicTableNames), shardingConditions, sqlStatementContext, hintValueContext, props);
138 }
139
140 return new ShardingComplexRouteEngine(shardingConditions, sqlStatementContext, hintValueContext, props, logicTableNames);
141 }
142
143 private static String getLogicTableName(final ShardingConditions shardingConditions, final Collection<String> tableNames) {
144 if (shardingConditions.getConditions().isEmpty()) {
145 return tableNames.iterator().next();
146 }
147 ShardingCondition shardingCondition = shardingConditions.getConditions().iterator().next();
148 return shardingCondition.getValues().isEmpty() ? tableNames.iterator().next() : shardingCondition.getValues().iterator().next().getTableName();
149 }
150
151 private static boolean isShardingStandardQuery(final ShardingRule rule, final Collection<String> logicTableNames, final boolean allBindingTables) {
152 return 1 == logicTableNames.size() && rule.isAllShardingTables(logicTableNames) || allBindingTables;
153 }
154 }