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