1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.sharding.rule;
19
20 import com.cedarsoftware.util.CaseInsensitiveMap;
21 import com.google.common.base.Splitter;
22 import com.google.common.base.Strings;
23 import lombok.Getter;
24 import org.apache.shardingsphere.infra.algorithm.core.context.AlgorithmSQLContext;
25 import org.apache.shardingsphere.infra.algorithm.core.exception.AlgorithmInitializationException;
26 import org.apache.shardingsphere.infra.algorithm.keygen.core.KeyGenerateAlgorithm;
27 import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
28 import org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
29 import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
30 import org.apache.shardingsphere.infra.datanode.DataNode;
31 import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
32 import org.apache.shardingsphere.infra.expr.core.InlineExpressionParserFactory;
33 import org.apache.shardingsphere.infra.instance.InstanceContext;
34 import org.apache.shardingsphere.infra.instance.InstanceContextAware;
35 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
36 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
37 import org.apache.shardingsphere.infra.rule.attribute.RuleAttributes;
38 import org.apache.shardingsphere.infra.rule.scope.DatabaseRule;
39 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
40 import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
41 import org.apache.shardingsphere.sharding.api.config.rule.ShardingAutoTableRuleConfiguration;
42 import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableReferenceRuleConfiguration;
43 import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
44 import org.apache.shardingsphere.sharding.api.config.strategy.audit.ShardingAuditStrategyConfiguration;
45 import org.apache.shardingsphere.sharding.api.config.strategy.keygen.KeyGenerateStrategyConfiguration;
46 import org.apache.shardingsphere.sharding.api.config.strategy.sharding.ComplexShardingStrategyConfiguration;
47 import org.apache.shardingsphere.sharding.api.config.strategy.sharding.NoneShardingStrategyConfiguration;
48 import org.apache.shardingsphere.sharding.api.config.strategy.sharding.ShardingStrategyConfiguration;
49 import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration;
50 import org.apache.shardingsphere.sharding.api.sharding.ShardingAutoTableAlgorithm;
51 import org.apache.shardingsphere.sharding.cache.ShardingCache;
52 import org.apache.shardingsphere.sharding.exception.metadata.ShardingTableRuleNotFoundException;
53 import org.apache.shardingsphere.sharding.rule.attribute.ShardingDataNodeRuleAttribute;
54 import org.apache.shardingsphere.sharding.rule.attribute.ShardingTableNamesRuleAttribute;
55 import org.apache.shardingsphere.sharding.rule.checker.ShardingRuleChecker;
56 import org.apache.shardingsphere.sharding.spi.ShardingAlgorithm;
57 import org.apache.shardingsphere.sharding.spi.ShardingAuditAlgorithm;
58 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
59 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
60 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
61 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
62 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
63 import org.apache.shardingsphere.sql.parser.sql.common.util.ExpressionExtractUtils;
64
65 import javax.sql.DataSource;
66 import java.util.Arrays;
67 import java.util.Collection;
68 import java.util.Collections;
69 import java.util.HashSet;
70 import java.util.LinkedHashMap;
71 import java.util.LinkedHashSet;
72 import java.util.LinkedList;
73 import java.util.List;
74 import java.util.Map;
75 import java.util.Objects;
76 import java.util.Optional;
77 import java.util.TreeSet;
78 import java.util.function.Function;
79 import java.util.stream.Collectors;
80
81
82
83
84 @Getter
85 public final class ShardingRule implements DatabaseRule {
86
87 private static final String ALGORITHM_EXPRESSION_KEY = "algorithm-expression";
88
89 private final ShardingRuleConfiguration configuration;
90
91 private final Collection<String> dataSourceNames;
92
93 private final Map<String, ShardingAlgorithm> shardingAlgorithms = new CaseInsensitiveMap<>();
94
95 private final Map<String, KeyGenerateAlgorithm> keyGenerators = new CaseInsensitiveMap<>();
96
97 private final Map<String, ShardingAuditAlgorithm> auditors = new CaseInsensitiveMap<>();
98
99 private final Map<String, ShardingTable> shardingTables = new CaseInsensitiveMap<>();
100
101 private final Map<String, BindingTableRule> bindingTableRules = new CaseInsensitiveMap<>();
102
103 private final ShardingStrategyConfiguration defaultDatabaseShardingStrategyConfig;
104
105 private final ShardingStrategyConfiguration defaultTableShardingStrategyConfig;
106
107 private final ShardingAuditStrategyConfiguration defaultAuditStrategy;
108
109 private final KeyGenerateAlgorithm defaultKeyGenerateAlgorithm;
110
111 private final String defaultShardingColumn;
112
113 private final ShardingCache shardingCache;
114
115 private final RuleAttributes attributes;
116
117 private final ShardingRuleChecker shardingRuleChecker = new ShardingRuleChecker(this);
118
119 public ShardingRule(final ShardingRuleConfiguration ruleConfig, final Map<String, DataSource> dataSources, final InstanceContext instanceContext) {
120 configuration = ruleConfig;
121 this.dataSourceNames = getDataSourceNames(ruleConfig.getTables(), ruleConfig.getAutoTables(), dataSources.keySet());
122 ruleConfig.getShardingAlgorithms().forEach((key, value) -> shardingAlgorithms.put(key, TypedSPILoader.getService(ShardingAlgorithm.class, value.getType(), value.getProps())));
123 ruleConfig.getKeyGenerators().forEach((key, value) -> keyGenerators.put(key, TypedSPILoader.getService(KeyGenerateAlgorithm.class, value.getType(), value.getProps())));
124 ruleConfig.getAuditors().forEach((key, value) -> auditors.put(key, TypedSPILoader.getService(ShardingAuditAlgorithm.class, value.getType(), value.getProps())));
125 shardingTables.putAll(createShardingTables(ruleConfig.getTables(), ruleConfig.getDefaultKeyGenerateStrategy()));
126 shardingTables.putAll(createShardingAutoTables(ruleConfig.getAutoTables(), ruleConfig.getDefaultKeyGenerateStrategy()));
127 bindingTableRules.putAll(createBindingTableRules(ruleConfig.getBindingTableGroups()));
128 defaultDatabaseShardingStrategyConfig = createDefaultDatabaseShardingStrategyConfiguration(ruleConfig);
129 defaultTableShardingStrategyConfig = createDefaultTableShardingStrategyConfiguration(ruleConfig);
130 defaultAuditStrategy = null == ruleConfig.getDefaultAuditStrategy() ? new ShardingAuditStrategyConfiguration(Collections.emptyList(), true) : ruleConfig.getDefaultAuditStrategy();
131 defaultKeyGenerateAlgorithm = null == ruleConfig.getDefaultKeyGenerateStrategy()
132 ? TypedSPILoader.getService(KeyGenerateAlgorithm.class, null)
133 : keyGenerators.get(ruleConfig.getDefaultKeyGenerateStrategy().getKeyGeneratorName());
134 defaultShardingColumn = ruleConfig.getDefaultShardingColumn();
135 keyGenerators.values().stream().filter(InstanceContextAware.class::isInstance).forEach(each -> ((InstanceContextAware) each).setInstanceContext(instanceContext));
136 if (defaultKeyGenerateAlgorithm instanceof InstanceContextAware && -1 == instanceContext.getWorkerId()) {
137 ((InstanceContextAware) defaultKeyGenerateAlgorithm).setInstanceContext(instanceContext);
138 }
139 shardingCache = null == ruleConfig.getShardingCache() ? null : new ShardingCache(ruleConfig.getShardingCache(), this);
140 attributes = new RuleAttributes(new ShardingDataNodeRuleAttribute(shardingTables), new ShardingTableNamesRuleAttribute(shardingTables.values()));
141 shardingRuleChecker.check(ruleConfig);
142 }
143
144 private ShardingStrategyConfiguration createDefaultDatabaseShardingStrategyConfiguration(final ShardingRuleConfiguration ruleConfig) {
145 Optional.ofNullable(ruleConfig.getDefaultDatabaseShardingStrategy()).ifPresent(optional -> checkManualShardingAlgorithm(optional.getShardingAlgorithmName(), "default"));
146 return null == ruleConfig.getDefaultDatabaseShardingStrategy() ? new NoneShardingStrategyConfiguration() : ruleConfig.getDefaultDatabaseShardingStrategy();
147 }
148
149 private ShardingStrategyConfiguration createDefaultTableShardingStrategyConfiguration(final ShardingRuleConfiguration ruleConfig) {
150 Optional.ofNullable(ruleConfig.getDefaultTableShardingStrategy()).ifPresent(optional -> checkManualShardingAlgorithm(optional.getShardingAlgorithmName(), "default"));
151 return null == ruleConfig.getDefaultTableShardingStrategy() ? new NoneShardingStrategyConfiguration() : ruleConfig.getDefaultTableShardingStrategy();
152 }
153
154 private Collection<String> getDataSourceNames(final Collection<ShardingTableRuleConfiguration> tableRuleConfigs,
155 final Collection<ShardingAutoTableRuleConfiguration> autoTableRuleConfigs, final Collection<String> dataSourceNames) {
156 if (tableRuleConfigs.isEmpty() && autoTableRuleConfigs.isEmpty()) {
157 return dataSourceNames;
158 }
159 if (tableRuleConfigs.stream().map(ShardingTableRuleConfiguration::getActualDataNodes).anyMatch(each -> null == each || each.isEmpty())) {
160 return dataSourceNames;
161 }
162 Collection<String> result = new LinkedHashSet<>();
163 tableRuleConfigs.forEach(each -> result.addAll(getDataSourceNames(each)));
164 autoTableRuleConfigs.forEach(each -> result.addAll(getDataSourceNames(each)));
165 return result;
166 }
167
168 private Collection<String> getDataSourceNames(final ShardingAutoTableRuleConfiguration shardingAutoTableRuleConfig) {
169 List<String> actualDataSources = InlineExpressionParserFactory.newInstance(shardingAutoTableRuleConfig.getActualDataSources()).splitAndEvaluate();
170 return new HashSet<>(actualDataSources);
171 }
172
173 private Collection<String> getDataSourceNames(final ShardingTableRuleConfiguration shardingTableRuleConfig) {
174 List<String> actualDataNodes = InlineExpressionParserFactory.newInstance(shardingTableRuleConfig.getActualDataNodes()).splitAndEvaluate();
175 return actualDataNodes.stream().map(each -> new DataNode(each).getDataSourceName()).collect(Collectors.toList());
176 }
177
178 private Map<String, ShardingTable> createShardingTables(final Collection<ShardingTableRuleConfiguration> tableRuleConfigs,
179 final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig) {
180 return tableRuleConfigs.stream().map(each -> createShardingTable(each, defaultKeyGenerateStrategyConfig))
181 .collect(Collectors.toMap(ShardingTable::getLogicTable, Function.identity(), (oldValue, currentValue) -> oldValue, CaseInsensitiveMap::new));
182 }
183
184 private ShardingTable createShardingTable(final ShardingTableRuleConfiguration tableRuleConfig, final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig) {
185 Optional.ofNullable(tableRuleConfig.getDatabaseShardingStrategy()).ifPresent(optional -> checkManualShardingAlgorithm(optional.getShardingAlgorithmName(), tableRuleConfig.getLogicTable()));
186 Optional.ofNullable(tableRuleConfig.getTableShardingStrategy()).ifPresent(optional -> checkManualShardingAlgorithm(optional.getShardingAlgorithmName(), tableRuleConfig.getLogicTable()));
187 return new ShardingTable(tableRuleConfig, dataSourceNames, getDefaultGenerateKeyColumn(defaultKeyGenerateStrategyConfig));
188 }
189
190 private void checkManualShardingAlgorithm(final String shardingAlgorithmName, final String logicTable) {
191 ShardingAlgorithm shardingAlgorithm = shardingAlgorithms.get(shardingAlgorithmName);
192 ShardingSpherePreconditions.checkState(!(shardingAlgorithm instanceof ShardingAutoTableAlgorithm),
193 () -> new AlgorithmInitializationException(shardingAlgorithm, "`%s` tables sharding configuration can not use auto sharding algorithm.", logicTable));
194 }
195
196 private Map<String, ShardingTable> createShardingAutoTables(final Collection<ShardingAutoTableRuleConfiguration> autoTableRuleConfigs,
197 final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig) {
198 return autoTableRuleConfigs.stream().map(each -> createShardingAutoTable(defaultKeyGenerateStrategyConfig, each))
199 .collect(Collectors.toMap(ShardingTable::getLogicTable, Function.identity(), (oldValue, currentValue) -> oldValue, CaseInsensitiveMap::new));
200 }
201
202 private ShardingTable createShardingAutoTable(final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig, final ShardingAutoTableRuleConfiguration autoTableRuleConfig) {
203 checkAutoShardingAlgorithm(autoTableRuleConfig.getShardingStrategy().getShardingAlgorithmName(), autoTableRuleConfig.getLogicTable());
204 ShardingAlgorithm shardingAlgorithm = shardingAlgorithms.get(autoTableRuleConfig.getShardingStrategy().getShardingAlgorithmName());
205 return new ShardingTable(autoTableRuleConfig, dataSourceNames, (ShardingAutoTableAlgorithm) shardingAlgorithm, getDefaultGenerateKeyColumn(defaultKeyGenerateStrategyConfig));
206 }
207
208 private void checkAutoShardingAlgorithm(final String shardingAlgorithmName, final String logicTable) {
209 ShardingAlgorithm shardingAlgorithm = shardingAlgorithms.get(shardingAlgorithmName);
210 ShardingSpherePreconditions.checkState(shardingAlgorithm instanceof ShardingAutoTableAlgorithm,
211 () -> new AlgorithmInitializationException(shardingAlgorithm, "`%s` autoTables sharding configuration must use auto sharding algorithm.", logicTable));
212 }
213
214 private String getDefaultGenerateKeyColumn(final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig) {
215 return Optional.ofNullable(defaultKeyGenerateStrategyConfig).map(KeyGenerateStrategyConfiguration::getColumn).orElse(null);
216 }
217
218 private Map<String, BindingTableRule> createBindingTableRules(final Collection<ShardingTableReferenceRuleConfiguration> bindingTableGroups) {
219 Map<String, BindingTableRule> result = new LinkedHashMap<>();
220 for (ShardingTableReferenceRuleConfiguration each : bindingTableGroups) {
221 BindingTableRule bindingTableRule = createBindingTableRule(each.getReference());
222 for (String logicTable : bindingTableRule.getAllLogicTables()) {
223 result.put(logicTable, bindingTableRule);
224 }
225 }
226 return result;
227 }
228
229 private BindingTableRule createBindingTableRule(final String bindingTableGroup) {
230 Map<String, ShardingTable> shardingTables = Splitter.on(",").trimResults().splitToList(bindingTableGroup).stream()
231 .map(this::getShardingTable).collect(Collectors.toMap(ShardingTable::getLogicTable, Function.identity(), (oldValue, currentValue) -> oldValue, LinkedHashMap::new));
232 BindingTableRule result = new BindingTableRule();
233 result.getShardingTables().putAll(shardingTables);
234 return result;
235 }
236
237
238
239
240
241
242
243 public ShardingStrategyConfiguration getDatabaseShardingStrategyConfiguration(final ShardingTable shardingTable) {
244 return getDatabaseShardingStrategyConfiguration(shardingTable, defaultDatabaseShardingStrategyConfig);
245 }
246
247 private ShardingStrategyConfiguration getDatabaseShardingStrategyConfiguration(final ShardingTable shardingTable, final ShardingStrategyConfiguration defaultDatabaseShardingStrategyConfig) {
248 return null == shardingTable.getDatabaseShardingStrategyConfig() ? defaultDatabaseShardingStrategyConfig : shardingTable.getDatabaseShardingStrategyConfig();
249 }
250
251
252
253
254
255
256
257 public ShardingStrategyConfiguration getTableShardingStrategyConfiguration(final ShardingTable shardingTable) {
258 return getTableShardingStrategyConfiguration(shardingTable, defaultTableShardingStrategyConfig);
259 }
260
261 private ShardingStrategyConfiguration getTableShardingStrategyConfiguration(final ShardingTable shardingTable, final ShardingStrategyConfiguration defaultTableShardingStrategyConfig) {
262 return null == shardingTable.getTableShardingStrategyConfig() ? defaultTableShardingStrategyConfig : shardingTable.getTableShardingStrategyConfig();
263 }
264
265
266
267
268
269
270
271 public ShardingAuditStrategyConfiguration getAuditStrategyConfiguration(final ShardingTable shardingTable) {
272 return null == shardingTable.getAuditStrategyConfig() ? defaultAuditStrategy : shardingTable.getAuditStrategyConfig();
273 }
274
275
276
277
278
279
280
281 public Optional<ShardingTable> findShardingTable(final String logicTableName) {
282 if (Strings.isNullOrEmpty(logicTableName) || !shardingTables.containsKey(logicTableName)) {
283 return Optional.empty();
284 }
285 return Optional.of(shardingTables.get(logicTableName));
286 }
287
288
289
290
291
292
293
294 public Optional<ShardingTable> findShardingTableByActualTable(final String actualTableName) {
295 for (ShardingTable each : shardingTables.values()) {
296 if (each.isExisted(actualTableName)) {
297 return Optional.of(each);
298 }
299 }
300 return Optional.empty();
301 }
302
303
304
305
306
307
308
309
310 public ShardingTable getShardingTable(final String logicTableName) {
311 Optional<ShardingTable> shardingTable = findShardingTable(logicTableName);
312 ShardingSpherePreconditions.checkState(shardingTable.isPresent(), () -> new ShardingTableRuleNotFoundException(Collections.singleton(logicTableName)));
313 return shardingTable.get();
314 }
315
316
317
318
319
320
321
322 public boolean isAllBindingTables(final Collection<String> logicTableNames) {
323 if (logicTableNames.isEmpty()) {
324 return false;
325 }
326 Optional<BindingTableRule> bindingTableRule = findBindingTableRule(logicTableNames);
327 if (!bindingTableRule.isPresent()) {
328 return false;
329 }
330 Collection<String> result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
331 result.addAll(bindingTableRule.get().getAllLogicTables());
332 return !result.isEmpty() && result.containsAll(logicTableNames);
333 }
334
335
336
337
338
339
340
341
342
343 public boolean isAllBindingTables(final ShardingSphereDatabase database, final SQLStatementContext sqlStatementContext, final Collection<String> logicTableNames) {
344 if (!(sqlStatementContext instanceof SelectStatementContext && ((SelectStatementContext) sqlStatementContext).isContainsJoinQuery())) {
345 return isAllBindingTables(logicTableNames);
346 }
347 if (!isAllBindingTables(logicTableNames)) {
348 return false;
349 }
350 String defaultSchemaName = new DatabaseTypeRegistry(sqlStatementContext.getDatabaseType()).getDefaultSchemaName(database.getName());
351 ShardingSphereSchema schema = sqlStatementContext.getTablesContext().getSchemaName().map(database::getSchema).orElseGet(() -> database.getSchema(defaultSchemaName));
352 SelectStatementContext select = (SelectStatementContext) sqlStatementContext;
353 return isJoinConditionContainsShardingColumns(schema, select, logicTableNames, select.getWhereSegments());
354 }
355
356 private Optional<BindingTableRule> findBindingTableRule(final Collection<String> logicTableNames) {
357 for (String each : logicTableNames) {
358 Optional<BindingTableRule> result = findBindingTableRule(each);
359 if (result.isPresent()) {
360 return result;
361 }
362 }
363 return Optional.empty();
364 }
365
366
367
368
369
370
371
372 public Optional<BindingTableRule> findBindingTableRule(final String logicTableName) {
373 return Optional.ofNullable(bindingTableRules.get(logicTableName));
374 }
375
376
377
378
379
380
381
382 public boolean isAllShardingTables(final Collection<String> logicTableNames) {
383 if (logicTableNames.isEmpty()) {
384 return false;
385 }
386 for (String each : logicTableNames) {
387 if (!isShardingTable(each)) {
388 return false;
389 }
390 }
391 return true;
392 }
393
394
395
396
397
398
399
400 public boolean isShardingTable(final String logicTableName) {
401 return shardingTables.containsKey(logicTableName);
402 }
403
404
405
406
407
408
409
410 public boolean isAllTablesInSameDataSource(final Collection<String> logicTableNames) {
411 Collection<String> dataSourceNames = logicTableNames.stream().map(shardingTables::get)
412 .filter(Objects::nonNull).flatMap(each -> each.getActualDataSourceNames().stream()).collect(Collectors.toSet());
413 return 1 == dataSourceNames.size();
414 }
415
416
417
418
419
420
421
422 public boolean containsShardingTable(final Collection<String> logicTableNames) {
423 for (String each : logicTableNames) {
424 if (isShardingTable(each)) {
425 return true;
426 }
427 }
428 return false;
429 }
430
431
432
433
434
435
436
437
438 public Optional<String> findShardingColumn(final String columnName, final String tableName) {
439 return Optional.ofNullable(shardingTables.get(tableName)).flatMap(optional -> findShardingColumn(optional, columnName));
440 }
441
442 private Optional<String> findShardingColumn(final ShardingTable shardingTable, final String columnName) {
443 Optional<String> databaseShardingColumn = findShardingColumn(getDatabaseShardingStrategyConfiguration(shardingTable), columnName);
444 if (databaseShardingColumn.isPresent()) {
445 return databaseShardingColumn;
446 }
447 return findShardingColumn(getTableShardingStrategyConfiguration(shardingTable), columnName);
448 }
449
450 private Optional<String> findShardingColumn(final ShardingStrategyConfiguration shardingStrategyConfig, final String columnName) {
451 if (shardingStrategyConfig instanceof StandardShardingStrategyConfiguration) {
452 String shardingColumn = null == ((StandardShardingStrategyConfiguration) shardingStrategyConfig).getShardingColumn()
453 ? defaultShardingColumn
454 : ((StandardShardingStrategyConfiguration) shardingStrategyConfig).getShardingColumn();
455 return shardingColumn.equalsIgnoreCase(columnName) ? Optional.of(shardingColumn) : Optional.empty();
456 }
457 if (shardingStrategyConfig instanceof ComplexShardingStrategyConfiguration) {
458 List<String> shardingColumns = Splitter.on(",").trimResults().splitToList(((ComplexShardingStrategyConfiguration) shardingStrategyConfig).getShardingColumns());
459 for (String each : shardingColumns) {
460 if (each.equalsIgnoreCase(columnName)) {
461 return Optional.of(each);
462 }
463 }
464 }
465 return Optional.empty();
466 }
467
468
469
470
471
472
473
474
475 public boolean isGenerateKeyColumn(final String columnName, final String tableName) {
476 return Optional.ofNullable(shardingTables.get(tableName)).filter(each -> isGenerateKeyColumn(each, columnName)).isPresent();
477 }
478
479 private boolean isGenerateKeyColumn(final ShardingTable shardingTable, final String columnName) {
480 Optional<String> generateKeyColumn = shardingTable.getGenerateKeyColumn();
481 return generateKeyColumn.isPresent() && generateKeyColumn.get().equalsIgnoreCase(columnName);
482 }
483
484
485
486
487
488
489
490 public Optional<String> findGenerateKeyColumnName(final String logicTableName) {
491 return Optional.ofNullable(shardingTables.get(logicTableName)).filter(each -> each.getGenerateKeyColumn().isPresent()).flatMap(ShardingTable::getGenerateKeyColumn);
492 }
493
494
495
496
497
498
499
500
501 public Collection<? extends Comparable<?>> generateKeys(final AlgorithmSQLContext algorithmSQLContext, final int keyGenerateCount) {
502 return getKeyGenerateAlgorithm(algorithmSQLContext.getTableName()).generateKeys(algorithmSQLContext, keyGenerateCount);
503 }
504
505
506
507
508
509
510
511 public boolean isSupportAutoIncrement(final String logicTableName) {
512 return getKeyGenerateAlgorithm(logicTableName).isSupportAutoIncrement();
513 }
514
515 private KeyGenerateAlgorithm getKeyGenerateAlgorithm(final String logicTableName) {
516 ShardingTable shardingTable = getShardingTable(logicTableName);
517 return null == shardingTable.getKeyGeneratorName() ? defaultKeyGenerateAlgorithm : keyGenerators.get(shardingTable.getKeyGeneratorName());
518 }
519
520
521
522
523
524
525
526 public DataNode getDataNode(final String logicTableName) {
527 ShardingTable shardingTable = getShardingTable(logicTableName);
528 return shardingTable.getActualDataNodes().get(0);
529 }
530
531
532
533
534
535
536
537 public Collection<String> getShardingLogicTableNames(final Collection<String> logicTableNames) {
538 Collection<String> result = new LinkedList<>();
539 for (String each : logicTableNames) {
540 if (isShardingTable(each)) {
541 result.add(each);
542 }
543 }
544 return result;
545 }
546
547
548
549
550
551
552
553 public Collection<String> getShardingRuleTableNames(final Collection<String> logicTableNames) {
554 return logicTableNames.stream().filter(this::isShardingTable).collect(Collectors.toList());
555 }
556
557
558
559
560
561
562
563
564
565
566 public Map<String, String> getLogicAndActualTablesFromBindingTable(final String dataSourceName,
567 final String logicTable, final String actualTable, final Collection<String> availableLogicBindingTables) {
568 return findBindingTableRule(logicTable).map(optional -> optional.getLogicAndActualTables(dataSourceName, logicTable, actualTable, availableLogicBindingTables))
569 .orElseGet(Collections::emptyMap);
570 }
571
572
573
574
575
576
577 public boolean isShardingCacheEnabled() {
578 return null != shardingCache;
579 }
580
581 private boolean isJoinConditionContainsShardingColumns(final ShardingSphereSchema schema, final SelectStatementContext select,
582 final Collection<String> tableNames, final Collection<WhereSegment> whereSegments) {
583 Collection<String> databaseJoinConditionTables = new HashSet<>(tableNames.size(), 1F);
584 Collection<String> tableJoinConditionTables = new HashSet<>(tableNames.size(), 1F);
585 for (WhereSegment each : whereSegments) {
586 Collection<AndPredicate> andPredicates = ExpressionExtractUtils.getAndPredicates(each.getExpr());
587 if (andPredicates.size() > 1) {
588 return false;
589 }
590 for (AndPredicate andPredicate : andPredicates) {
591 databaseJoinConditionTables.addAll(getJoinConditionTables(schema, select, andPredicate.getPredicates(), true));
592 tableJoinConditionTables.addAll(getJoinConditionTables(schema, select, andPredicate.getPredicates(), false));
593 }
594 }
595 ShardingTable shardingTable = getShardingTable(tableNames.iterator().next());
596 boolean containsDatabaseShardingColumns = !(getDatabaseShardingStrategyConfiguration(shardingTable) instanceof StandardShardingStrategyConfiguration)
597 || databaseJoinConditionTables.containsAll(tableNames);
598 boolean containsTableShardingColumns =
599 !(getTableShardingStrategyConfiguration(shardingTable) instanceof StandardShardingStrategyConfiguration) || tableJoinConditionTables.containsAll(tableNames);
600 return containsDatabaseShardingColumns && containsTableShardingColumns;
601 }
602
603 private Collection<String> getJoinConditionTables(final ShardingSphereSchema schema, final SelectStatementContext select,
604 final Collection<ExpressionSegment> predicates, final boolean isDatabaseJoinCondition) {
605 Collection<String> result = new LinkedList<>();
606 for (ExpressionSegment each : predicates) {
607 if (!isJoinConditionExpression(each)) {
608 continue;
609 }
610 ColumnSegment leftColumn = (ColumnSegment) ((BinaryOperationExpression) each).getLeft();
611 ColumnSegment rightColumn = (ColumnSegment) ((BinaryOperationExpression) each).getRight();
612 Map<String, String> columnExpressionTableNames = select.getTablesContext().findTableNamesByColumnSegment(Arrays.asList(leftColumn, rightColumn), schema);
613 Optional<ShardingTable> leftShardingTable = findShardingTable(columnExpressionTableNames.get(leftColumn.getExpression()));
614 Optional<ShardingTable> rightShardingTable = findShardingTable(columnExpressionTableNames.get(rightColumn.getExpression()));
615 if (!leftShardingTable.isPresent() || !rightShardingTable.isPresent()) {
616 continue;
617 }
618 ShardingStrategyConfiguration leftConfig = isDatabaseJoinCondition
619 ? getDatabaseShardingStrategyConfiguration(leftShardingTable.get())
620 : getTableShardingStrategyConfiguration(leftShardingTable.get());
621 ShardingStrategyConfiguration rightConfig = isDatabaseJoinCondition
622 ? getDatabaseShardingStrategyConfiguration(rightShardingTable.get())
623 : getTableShardingStrategyConfiguration(rightShardingTable.get());
624 if (findShardingColumn(leftConfig, leftColumn.getIdentifier().getValue()).isPresent()
625 && findShardingColumn(rightConfig, rightColumn.getIdentifier().getValue()).isPresent()) {
626 result.add(columnExpressionTableNames.get(leftColumn.getExpression()));
627 result.add(columnExpressionTableNames.get(rightColumn.getExpression()));
628 }
629 }
630 return result;
631 }
632
633 private boolean isJoinConditionExpression(final ExpressionSegment expression) {
634 if (!(expression instanceof BinaryOperationExpression)) {
635 return false;
636 }
637 BinaryOperationExpression binaryExpression = (BinaryOperationExpression) expression;
638 return binaryExpression.getLeft() instanceof ColumnSegment && binaryExpression.getRight() instanceof ColumnSegment && "=".equals(binaryExpression.getOperator());
639 }
640 }