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, sqlStatement, logicTableNames);
76 }
77 if (sqlStatement instanceof DALStatement) {
78 return getDALRouteEngine(database, sqlStatementContext.getSqlStatement(), 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 SQLStatement sqlStatement, final Collection<String> logicTableNames) {
87 boolean procedureStatement = sqlStatement instanceof CreateProcedureStatement || sqlStatement instanceof AlterProcedureStatement || sqlStatement instanceof DropProcedureStatement;
88 if (procedureStatement) {
89 return new ShardingDatabaseBroadcastRouteEngine();
90 }
91 return new ShardingTableBroadcastRouteEngine(database, sqlStatement, logicTableNames);
92 }
93
94 private static ShardingRouteEngine getCursorRouteEngine(final ShardingRule rule, final SQLStatementContext sqlStatementContext,
95 final HintValueContext hintValueContext, final ShardingConditions shardingConditions, final Collection<String> logicTableNames,
96 final ConfigurationProperties props) {
97 boolean allBindingTables = logicTableNames.size() > 1 && rule.isBindingTablesUseShardingColumnsJoin(sqlStatementContext, logicTableNames);
98 if (isShardingStandardQuery(rule, logicTableNames, allBindingTables)) {
99 return new ShardingStandardRouteEngine(getLogicTableName(shardingConditions, logicTableNames), shardingConditions, sqlStatementContext, hintValueContext, props);
100 }
101 return new ShardingIgnoreRouteEngine();
102 }
103
104 private static ShardingRouteEngine getDALRouteEngine(final ShardingSphereDatabase database, final SQLStatement sqlStatement,
105 final ConnectionContext connectionContext, final Collection<String> logicTableNames) {
106 if (sqlStatement.getAttributes().findAttribute(TableBroadcastRouteSQLStatementAttribute.class).isPresent()) {
107 return new ShardingTableBroadcastRouteEngine(database, sqlStatement, logicTableNames);
108 }
109 return new ShardingUnicastRouteEngine(sqlStatement, logicTableNames, connectionContext);
110 }
111
112 private static ShardingRouteEngine getDCLRouteEngine(final ShardingSphereDatabase database, final SQLStatementContext sqlStatementContext, final Collection<String> logicTableNames) {
113 return isDCLForSingleTable(sqlStatementContext) ? new ShardingTableBroadcastRouteEngine(database, sqlStatementContext.getSqlStatement(), logicTableNames)
114 : new ShardingInstanceBroadcastRouteEngine(database.getResourceMetaData());
115 }
116
117 private static boolean isDCLForSingleTable(final SQLStatementContext sqlStatementContext) {
118 return 1 == sqlStatementContext.getTablesContext().getSimpleTables().size()
119 && !"*".equals(sqlStatementContext.getTablesContext().getSimpleTables().iterator().next().getTableName().getIdentifier().getValue());
120 }
121
122 private static ShardingRouteEngine getDQLRouteEngine(final ShardingRule rule, final SQLStatementContext sqlStatementContext,
123 final QueryContext queryContext, final ShardingConditions shardingConditions, final Collection<String> logicTableNames,
124 final ConfigurationProperties props) {
125 Collection<String> tableNames = sqlStatementContext.getTablesContext().getTableNames();
126 if (sqlStatementContext.getSqlStatement() instanceof DMLStatement && shardingConditions.isAlwaysFalse() || tableNames.isEmpty()) {
127 return new ShardingUnicastRouteEngine(sqlStatementContext.getSqlStatement(), tableNames, queryContext.getConnectionContext());
128 }
129 return getDQLRouteEngineForShardingTable(rule, sqlStatementContext, queryContext.getHintValueContext(), shardingConditions, logicTableNames, props);
130 }
131
132 private static ShardingRouteEngine getDQLRouteEngineForShardingTable(final ShardingRule rule, final SQLStatementContext sqlStatementContext, final HintValueContext hintValueContext,
133 final ShardingConditions shardingConditions, final Collection<String> logicTableNames, final ConfigurationProperties props) {
134 boolean allBindingTables = logicTableNames.size() > 1 && rule.isBindingTablesUseShardingColumnsJoin(sqlStatementContext, logicTableNames);
135 if (isShardingStandardQuery(rule, logicTableNames, allBindingTables)) {
136 return new ShardingStandardRouteEngine(getLogicTableName(shardingConditions, logicTableNames), shardingConditions, sqlStatementContext, hintValueContext, props);
137 }
138
139 return new ShardingComplexRouteEngine(shardingConditions, sqlStatementContext, hintValueContext, props, logicTableNames);
140 }
141
142 private static String getLogicTableName(final ShardingConditions shardingConditions, final Collection<String> tableNames) {
143 if (shardingConditions.getConditions().isEmpty()) {
144 return tableNames.iterator().next();
145 }
146 ShardingCondition shardingCondition = shardingConditions.getConditions().iterator().next();
147 return shardingCondition.getValues().isEmpty() ? tableNames.iterator().next() : shardingCondition.getValues().iterator().next().getTableName();
148 }
149
150 private static boolean isShardingStandardQuery(final ShardingRule rule, final Collection<String> logicTableNames, final boolean allBindingTables) {
151 return 1 == logicTableNames.size() && rule.isAllShardingTables(logicTableNames) || allBindingTables;
152 }
153 }