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