You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ji...@apache.org on 2023/04/13 05:56:21 UTC
[shardingsphere] branch master updated: Add check for CREATE/ALTER SHARDING TABLE RULE with NoneShardingStrategy (#25145)
This is an automated email from the ASF dual-hosted git repository.
jianglongtao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 507b2d427cb Add check for CREATE/ALTER SHARDING TABLE RULE with NoneShardingStrategy (#25145)
507b2d427cb is described below
commit 507b2d427cb423991c24a41749364b1b7606cd0d
Author: ChenJiaHao <Pa...@163.com>
AuthorDate: Thu Apr 13 13:56:08 2023 +0800
Add check for CREATE/ALTER SHARDING TABLE RULE with NoneShardingStrategy (#25145)
* Add check for CREATE/ALTER SHARDING TABLE RULE with NoneShardingStrategy
* Fix UT
* Fix code style
* Fix code style
---
...alidShardingStrategyConfigurationException.java | 33 ++
.../checker/ShardingTableRuleStatementChecker.java | 405 +++++++++++----------
.../checker/ShardingRuleStatementCheckerTest.java | 21 +-
...reateShardingTableRuleStatementUpdaterTest.java | 45 +++
4 files changed, 317 insertions(+), 187 deletions(-)
diff --git a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/exception/strategy/InvalidShardingStrategyConfigurationException.java b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/exception/strategy/InvalidShardingStrategyConfigurationException.java
new file mode 100644
index 00000000000..033565a3d88
--- /dev/null
+++ b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/exception/strategy/InvalidShardingStrategyConfigurationException.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sharding.exception.strategy;
+
+import org.apache.shardingsphere.infra.util.exception.external.sql.sqlstate.XOpenSQLState;
+import org.apache.shardingsphere.sharding.exception.ShardingSQLException;
+
+/**
+ * Invalid sharding strategy configuration exception.
+ */
+public final class InvalidShardingStrategyConfigurationException extends ShardingSQLException {
+
+ private static final long serialVersionUID = -5874317771225005670L;
+
+ public InvalidShardingStrategyConfigurationException(final String strategyLevel, final String strategyType, final String message) {
+ super(XOpenSQLState.GENERAL_ERROR, 99, String.format("Invalid %s strategy `%s`, %s.", strategyLevel, strategyType, message));
+ }
+}
diff --git a/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/checker/ShardingTableRuleStatementChecker.java b/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/checker/ShardingTableRuleStatementChecker.java
index 0e5586a9055..cc19ceaaaf5 100644
--- a/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/checker/ShardingTableRuleStatementChecker.java
+++ b/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/checker/ShardingTableRuleStatementChecker.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.sharding.distsql.handler.checker;
import com.google.common.base.Splitter;
import org.apache.shardingsphere.distsql.handler.exception.algorithm.InvalidAlgorithmConfigurationException;
+import org.apache.shardingsphere.sharding.exception.strategy.InvalidShardingStrategyConfigurationException;
import org.apache.shardingsphere.distsql.handler.exception.algorithm.MissingRequiredAlgorithmException;
import org.apache.shardingsphere.distsql.handler.exception.rule.DuplicateRuleException;
import org.apache.shardingsphere.distsql.handler.exception.rule.InvalidRuleConfigurationException;
@@ -117,11 +118,27 @@ public final class ShardingTableRuleStatementChecker {
public static boolean isValidBindingTableGroups(final Collection<ShardingTableReferenceRuleConfiguration> bindingTableGroups, final ShardingRuleConfiguration currentRuleConfig) {
ShardingRuleConfiguration toBeCheckedRuleConfig = createToBeCheckedShardingRuleConfiguration(currentRuleConfig);
toBeCheckedRuleConfig.setBindingTableGroups(bindingTableGroups);
- Collection<String> dataSourceNames = getRequiredDataSource(toBeCheckedRuleConfig);
- dataSourceNames.addAll(getRequiredDataSource(currentRuleConfig));
+ Collection<String> dataSourceNames = getRequiredDataSources(toBeCheckedRuleConfig);
+ dataSourceNames.addAll(getRequiredDataSources(currentRuleConfig));
return check(toBeCheckedRuleConfig, dataSourceNames);
}
+ private static ShardingRuleConfiguration createToBeCheckedShardingRuleConfiguration(final ShardingRuleConfiguration currentRuleConfig) {
+ ShardingRuleConfiguration result = new ShardingRuleConfiguration();
+ result.setTables(new LinkedList<>(currentRuleConfig.getTables()));
+ result.setAutoTables(new LinkedList<>(currentRuleConfig.getAutoTables()));
+ result.setBindingTableGroups(new LinkedList<>(currentRuleConfig.getBindingTableGroups()));
+ result.setBroadcastTables(new LinkedList<>(currentRuleConfig.getBroadcastTables()));
+ result.setDefaultTableShardingStrategy(currentRuleConfig.getDefaultTableShardingStrategy());
+ result.setDefaultDatabaseShardingStrategy(currentRuleConfig.getDefaultDatabaseShardingStrategy());
+ result.setDefaultKeyGenerateStrategy(currentRuleConfig.getDefaultKeyGenerateStrategy());
+ result.setDefaultShardingColumn(currentRuleConfig.getDefaultShardingColumn());
+ result.setShardingAlgorithms(new LinkedHashMap<>(currentRuleConfig.getShardingAlgorithms()));
+ result.setKeyGenerators(new LinkedHashMap<>(currentRuleConfig.getKeyGenerators()));
+ result.setAuditors(new LinkedHashMap<>(currentRuleConfig.getAuditors()));
+ return result;
+ }
+
private static void check(final ShardingSphereDatabase database, final Collection<AbstractTableRuleSegment> rules, final boolean ifNotExists, final ShardingRuleConfiguration currentRuleConfig,
final boolean isCreated) {
String databaseName = database.getName();
@@ -155,34 +172,8 @@ public final class ShardingTableRuleStatementChecker {
defaultDatabaseShardingStrategyConfig, defaultTableShardingStrategyConfig, checkedConfig.getDefaultShardingColumn()));
}
- private static void checkDataSources(final String databaseName, final Collection<AbstractTableRuleSegment> rules, final ShardingSphereDatabase database) {
- Collection<String> requiredDataSource = getRequiredDataSources(rules);
- Collection<String> notExistedDataSources = database.getResourceMetaData().getNotExistedDataSources(requiredDataSource);
- Collection<String> logicDataSources = getLogicDataSources(database);
- notExistedDataSources.removeIf(logicDataSources::contains);
- ShardingSpherePreconditions.checkState(notExistedDataSources.isEmpty(), () -> new MissingRequiredStorageUnitsException(databaseName, notExistedDataSources));
- }
-
- private static Collection<String> getLogicDataSources(final ShardingSphereDatabase database) {
- return database.getRuleMetaData().findRules(DataSourceContainedRule.class).stream()
- .map(each -> each.getDataSourceMapper().keySet()).flatMap(Collection::stream).collect(Collectors.toCollection(LinkedHashSet::new));
- }
-
- private static Collection<String> getRequiredDataSources(final Collection<AbstractTableRuleSegment> rules) {
- return rules.stream().map(AbstractTableRuleSegment::getDataSourceNodes).flatMap(Collection::stream)
- .map(ShardingTableRuleStatementChecker::parseDateSource).map(ShardingTableRuleStatementChecker::getDataSourceNames).flatMap(Collection::stream).collect(Collectors.toList());
- }
-
- private static Collection<String> parseDateSource(final String dateSource) {
- return new InlineExpressionParser(dateSource).splitAndEvaluate();
- }
-
- private static Collection<String> getDataSourceNames(final Collection<String> actualDataNodes) {
- Collection<String> result = new HashSet<>();
- for (String each : actualDataNodes) {
- result.add(isValidDataNode(each) ? new DataNode(each).getDataSourceName() : each);
- }
- return result;
+ private static Map<String, List<AbstractTableRuleSegment>> groupingByClassType(final Collection<AbstractTableRuleSegment> rules) {
+ return rules.stream().collect(Collectors.groupingBy(each -> each.getClass().getSimpleName()));
}
private static Collection<String> getDataSourceNames(final Collection<ShardingTableRuleConfiguration> tableRuleConfigs,
@@ -203,10 +194,154 @@ public final class ShardingTableRuleStatementChecker {
return new InlineExpressionParser(shardingTableRuleConfig.getActualDataNodes()).splitAndEvaluate().stream().map(each -> new DataNode(each).getDataSourceName()).collect(Collectors.toList());
}
+ private static Collection<String> getDataSourceNames(final Collection<String> actualDataNodes) {
+ Collection<String> result = new HashSet<>();
+ for (String each : actualDataNodes) {
+ result.add(isValidDataNode(each) ? new DataNode(each).getDataSourceName() : each);
+ }
+ return result;
+ }
+
private static boolean isValidDataNode(final String dataNodeStr) {
return dataNodeStr.contains(DELIMITER) && 2 == Splitter.on(DELIMITER).omitEmptyStrings().splitToList(dataNodeStr).size();
}
+ private static Map<String, TableRule> createTableRules(final Collection<ShardingTableRuleConfiguration> tableRuleConfigs, final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig,
+ final Collection<String> dataSourceNames) {
+ return tableRuleConfigs.stream().map(each -> new TableRule(each, dataSourceNames, getDefaultGenerateKeyColumn(defaultKeyGenerateStrategyConfig)))
+ .collect(Collectors.toMap(each -> each.getLogicTable().toLowerCase(), Function.identity(), (oldValue, currentValue) -> oldValue, LinkedHashMap::new));
+ }
+
+ private static String getDefaultGenerateKeyColumn(final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig) {
+ return Optional.ofNullable(defaultKeyGenerateStrategyConfig).map(KeyGenerateStrategyConfiguration::getColumn).orElse(null);
+ }
+
+ private static Map<String, TableRule> createAutoTableRules(final Collection<ShardingAutoTableRuleConfiguration> autoTableRuleConfigs, final Map<String, ShardingAlgorithm> shardingAlgorithms,
+ final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig, final Collection<String> dataSourceNames) {
+ return autoTableRuleConfigs.stream().map(each -> createAutoTableRule(defaultKeyGenerateStrategyConfig, each, shardingAlgorithms, dataSourceNames))
+ .collect(Collectors.toMap(each -> each.getLogicTable().toLowerCase(), Function.identity(), (oldValue, currentValue) -> oldValue, LinkedHashMap::new));
+ }
+
+ private static TableRule createAutoTableRule(final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig, final ShardingAutoTableRuleConfiguration autoTableRuleConfig,
+ final Map<String, ShardingAlgorithm> shardingAlgorithms, final Collection<String> dataSourceNames) {
+ ShardingAlgorithm shardingAlgorithm = shardingAlgorithms.get(autoTableRuleConfig.getShardingStrategy().getShardingAlgorithmName());
+ ShardingSpherePreconditions.checkState(shardingAlgorithm instanceof ShardingAutoTableAlgorithm,
+ () -> new ShardingAlgorithmClassImplementationException(autoTableRuleConfig.getShardingStrategy().getShardingAlgorithmName(), ShardingAutoTableAlgorithm.class));
+ return new TableRule(autoTableRuleConfig, dataSourceNames, (ShardingAutoTableAlgorithm) shardingAlgorithm, getDefaultGenerateKeyColumn(defaultKeyGenerateStrategyConfig));
+ }
+
+ private static Collection<String> createBroadcastTables(final Collection<String> broadcastTables) {
+ Collection<String> result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+ result.addAll(broadcastTables);
+ return result;
+ }
+
+ private static boolean isValidBindingTableConfiguration(final Map<String, TableRule> tableRules, final BindingTableCheckedConfiguration checkedConfig) {
+ for (ShardingTableReferenceRuleConfiguration each : checkedConfig.getBindingTableGroups()) {
+ Collection<String> bindingTables = Splitter.on(",").trimResults().splitToList(each.getReference().toLowerCase());
+ if (bindingTables.size() <= 1) {
+ return false;
+ }
+ Iterator<String> iterator = bindingTables.iterator();
+ TableRule sampleTableRule = getTableRule(iterator.next(), checkedConfig.getDataSourceNames(), tableRules, checkedConfig.getBroadcastTables());
+ while (iterator.hasNext()) {
+ TableRule tableRule = getTableRule(iterator.next(), checkedConfig.getDataSourceNames(), tableRules, checkedConfig.getBroadcastTables());
+ if (!isValidActualDataSourceName(sampleTableRule, tableRule) || !isValidActualTableName(sampleTableRule, tableRule)) {
+ return false;
+ }
+ if (isInvalidShardingAlgorithm(sampleTableRule, tableRule, true, checkedConfig) || isInvalidShardingAlgorithm(sampleTableRule, tableRule, false, checkedConfig)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static TableRule getTableRule(final String logicTableName, final Collection<String> dataSourceNames, final Map<String, TableRule> tableRules, final Collection<String> broadcastTables) {
+ TableRule result = tableRules.get(logicTableName);
+ if (null != result) {
+ return result;
+ }
+ if (broadcastTables.contains(logicTableName)) {
+ return new TableRule(dataSourceNames, logicTableName);
+ }
+ throw new ShardingTableRuleNotFoundException(Collections.singleton(logicTableName));
+ }
+
+ private static boolean isValidActualDataSourceName(final TableRule sampleTableRule, final TableRule tableRule) {
+ return sampleTableRule.getActualDataSourceNames().equals(tableRule.getActualDataSourceNames());
+ }
+
+ private static boolean isValidActualTableName(final TableRule sampleTableRule, final TableRule tableRule) {
+ for (String each : sampleTableRule.getActualDataSourceNames()) {
+ Collection<String> sampleActualTableNames =
+ sampleTableRule.getActualTableNames(each).stream().map(actualTableName -> actualTableName.replace(sampleTableRule.getTableDataNode().getPrefix(), "")).collect(Collectors.toSet());
+ Collection<String> actualTableNames =
+ tableRule.getActualTableNames(each).stream().map(optional -> optional.replace(tableRule.getTableDataNode().getPrefix(), "")).collect(Collectors.toSet());
+ if (!sampleActualTableNames.equals(actualTableNames)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean isInvalidShardingAlgorithm(final TableRule sampleTableRule, final TableRule tableRule, final boolean databaseAlgorithm,
+ final BindingTableCheckedConfiguration checkedConfig) {
+ return !getAlgorithmExpression(sampleTableRule, databaseAlgorithm, checkedConfig).equals(getAlgorithmExpression(tableRule, databaseAlgorithm, checkedConfig));
+ }
+
+ private static Optional<String> getAlgorithmExpression(final TableRule tableRule, final boolean databaseAlgorithm, final BindingTableCheckedConfiguration checkedConfig) {
+ ShardingStrategyConfiguration shardingStrategyConfig = databaseAlgorithm
+ ? null == tableRule.getDatabaseShardingStrategyConfig() ? checkedConfig.getDefaultDatabaseShardingStrategyConfig() : tableRule.getDatabaseShardingStrategyConfig()
+ : null == tableRule.getTableShardingStrategyConfig() ? checkedConfig.getDefaultTableShardingStrategyConfig() : tableRule.getTableShardingStrategyConfig();
+ ShardingAlgorithm shardingAlgorithm = checkedConfig.getShardingAlgorithms().get(shardingStrategyConfig.getShardingAlgorithmName());
+ String dataNodePrefix = databaseAlgorithm ? tableRule.getDataSourceDataNode().getPrefix() : tableRule.getTableDataNode().getPrefix();
+ String shardingColumn = getShardingColumn(shardingStrategyConfig, checkedConfig.getDefaultShardingColumn());
+ return null == shardingAlgorithm ? Optional.empty() : shardingAlgorithm.getAlgorithmStructure(dataNodePrefix, shardingColumn);
+ }
+
+ private static String getShardingColumn(final ShardingStrategyConfiguration shardingStrategyConfig, final String defaultShardingColumn) {
+ String shardingColumn = defaultShardingColumn;
+ if (shardingStrategyConfig instanceof ComplexShardingStrategyConfiguration) {
+ shardingColumn = ((ComplexShardingStrategyConfiguration) shardingStrategyConfig).getShardingColumns();
+ }
+ if (shardingStrategyConfig instanceof StandardShardingStrategyConfiguration) {
+ shardingColumn = ((StandardShardingStrategyConfiguration) shardingStrategyConfig).getShardingColumn();
+ }
+ return null == shardingColumn ? "" : shardingColumn;
+ }
+
+ private static void checkDataSources(final String databaseName, final Collection<AbstractTableRuleSegment> rules, final ShardingSphereDatabase database) {
+ Collection<String> requiredDataSource = getRequiredDataSources(rules);
+ Collection<String> notExistedDataSources = database.getResourceMetaData().getNotExistedDataSources(requiredDataSource);
+ Collection<String> logicDataSources = getLogicDataSources(database);
+ notExistedDataSources.removeIf(logicDataSources::contains);
+ ShardingSpherePreconditions.checkState(notExistedDataSources.isEmpty(), () -> new MissingRequiredStorageUnitsException(databaseName, notExistedDataSources));
+ }
+
+ private static Collection<String> getRequiredDataSources(final ShardingRuleConfiguration config) {
+ Collection<String> result = new LinkedHashSet<>();
+ result.addAll(config.getAutoTables().stream().map(ShardingAutoTableRuleConfiguration::getActualDataSources)
+ .map(each -> Splitter.on(",").trimResults().splitToList(each)).flatMap(Collection::stream).collect(Collectors.toSet()));
+ result.addAll(config.getTables().stream().map(each -> new InlineExpressionParser(each.getActualDataNodes()).splitAndEvaluate())
+ .flatMap(Collection::stream).distinct().map(each -> new DataNode(each).getDataSourceName()).collect(Collectors.toSet()));
+ return result;
+ }
+
+ private static <T extends AbstractTableRuleSegment> Collection<String> getRequiredDataSources(final Collection<T> rules) {
+ return rules.stream().map(AbstractTableRuleSegment::getDataSourceNodes).flatMap(Collection::stream)
+ .map(ShardingTableRuleStatementChecker::parseDateSource).map(ShardingTableRuleStatementChecker::getDataSourceNames).flatMap(Collection::stream).collect(Collectors.toList());
+ }
+
+ private static Collection<String> parseDateSource(final String dateSource) {
+ return new InlineExpressionParser(dateSource).splitAndEvaluate();
+ }
+
+ private static Collection<String> getLogicDataSources(final ShardingSphereDatabase database) {
+ return database.getRuleMetaData().findRules(DataSourceContainedRule.class).stream()
+ .map(each -> each.getDataSourceMapper().keySet()).flatMap(Collection::stream).collect(Collectors.toCollection(LinkedHashSet::new));
+ }
+
private static void checkTables(final String databaseName, final Collection<AbstractTableRuleSegment> rules, final ShardingRuleConfiguration currentRuleConfig, final boolean isCreate,
final boolean ifNotExists) {
Collection<String> requiredTables = rules.stream().map(AbstractTableRuleSegment::getLogicTable).collect(Collectors.toList());
@@ -302,38 +437,67 @@ public final class ShardingTableRuleStatementChecker {
private static void checkStrategy(final String databaseName, final Collection<TableRuleSegment> rules) {
for (TableRuleSegment each : rules) {
Optional<ShardingStrategySegment> databaseStrategySegment = Optional.ofNullable(each.getDatabaseStrategySegment());
- if (databaseStrategySegment.isPresent() && !databaseStrategySegment.get().getType().equalsIgnoreCase("none")) {
- AlgorithmSegment databaseShardingAlgorithm = databaseStrategySegment.get().getShardingAlgorithm();
- if (null != databaseShardingAlgorithm) {
- ShardingAlgorithm shardingAlgorithm = TypedSPILoader.getService(ShardingAlgorithm.class, databaseShardingAlgorithm.getName(), databaseShardingAlgorithm.getProps());
- ShardingSpherePreconditions.checkState(!(shardingAlgorithm instanceof ShardingAutoTableAlgorithm),
- () -> new InvalidAlgorithmConfigurationException("sharding", shardingAlgorithm.getType(),
- String.format("auto sharding algorithm cannot be used to create a table in Table mode `%s`", each.getLogicTable())));
+ if (databaseStrategySegment.isPresent()) {
+ if (databaseStrategySegment.get().getType().equalsIgnoreCase("none")) {
+ Collection<String> requiredDataSources = getRequiredDataSources(rules);
+ ShardingSpherePreconditions.checkState(1 == requiredDataSources.size(),
+ () -> new InvalidShardingStrategyConfigurationException("database", databaseStrategySegment.get().getType(), "strategy does not match data nodes"));
+ } else {
+ AlgorithmSegment databaseShardingAlgorithm = databaseStrategySegment.get().getShardingAlgorithm();
+ checkDatabaseShardingAlgorithm(databaseName, each, databaseShardingAlgorithm);
}
- ShardingSpherePreconditions.checkState(!isInvalidStrategy(each.getDatabaseStrategySegment()),
- () -> new InvalidAlgorithmConfigurationException(databaseName, null == databaseShardingAlgorithm ? null : databaseShardingAlgorithm.getName()));
}
Optional<ShardingStrategySegment> tableStrategySegment = Optional.ofNullable(each.getTableStrategySegment());
- if (tableStrategySegment.isPresent() && !tableStrategySegment.get().getType().equalsIgnoreCase("none")) {
- AlgorithmSegment tableShardingAlgorithm = tableStrategySegment.get().getShardingAlgorithm();
- if (null != tableShardingAlgorithm) {
- ShardingAlgorithm shardingAlgorithm = TypedSPILoader.getService(ShardingAlgorithm.class, tableShardingAlgorithm.getName(), tableShardingAlgorithm.getProps());
- ShardingSpherePreconditions.checkState(!(shardingAlgorithm instanceof ShardingAutoTableAlgorithm),
- () -> new InvalidAlgorithmConfigurationException("sharding", shardingAlgorithm.getType(),
- String.format("auto sharding algorithm cannot be used to create a table in Table mode `%s`", each.getLogicTable())));
+ if (tableStrategySegment.isPresent()) {
+ if (tableStrategySegment.get().getType().equalsIgnoreCase("none")) {
+ Collection<String> requiredTables = getRequiredTables(rules);
+ ShardingSpherePreconditions.checkState(1 == requiredTables.size(),
+ () -> new InvalidShardingStrategyConfigurationException("table", tableStrategySegment.get().getType(), "strategy does not match data nodes"));
+ } else {
+ AlgorithmSegment tableShardingAlgorithm = tableStrategySegment.get().getShardingAlgorithm();
+ checkTableShardingAlgorithm(databaseName, each, tableShardingAlgorithm);
}
- ShardingSpherePreconditions.checkState(!isInvalidStrategy(each.getTableStrategySegment()),
- () -> new InvalidAlgorithmConfigurationException(databaseName, null == tableShardingAlgorithm ? null : tableShardingAlgorithm.getName()));
}
}
}
- private static boolean isInvalidStrategy(final ShardingStrategySegment shardingStrategySegment) {
- return !ShardingStrategyType.getValueOf(shardingStrategySegment.getType()).isValid(shardingStrategySegment.getShardingColumn()) || null == shardingStrategySegment.getShardingAlgorithm();
+ private static void checkDatabaseShardingAlgorithm(final String databaseName, final TableRuleSegment each, final AlgorithmSegment databaseShardingAlgorithm) {
+ if (null != databaseShardingAlgorithm) {
+ ShardingAlgorithm shardingAlgorithm = TypedSPILoader.getService(ShardingAlgorithm.class, databaseShardingAlgorithm.getName(), databaseShardingAlgorithm.getProps());
+ ShardingSpherePreconditions.checkState(!(shardingAlgorithm instanceof ShardingAutoTableAlgorithm),
+ () -> new InvalidAlgorithmConfigurationException("sharding", shardingAlgorithm.getType(),
+ String.format("auto sharding algorithm cannot be used to create a table in Table mode `%s`", each.getLogicTable())));
+ }
+ ShardingSpherePreconditions.checkState(isValidStrategy(each.getDatabaseStrategySegment()),
+ () -> new InvalidAlgorithmConfigurationException(databaseName, null == databaseShardingAlgorithm ? null : databaseShardingAlgorithm.getName()));
}
- private static Map<String, List<AbstractTableRuleSegment>> groupingByClassType(final Collection<AbstractTableRuleSegment> rules) {
- return rules.stream().collect(Collectors.groupingBy(each -> each.getClass().getSimpleName()));
+ private static void checkTableShardingAlgorithm(final String databaseName, final TableRuleSegment each, final AlgorithmSegment tableShardingAlgorithm) {
+ if (null != tableShardingAlgorithm) {
+ ShardingAlgorithm shardingAlgorithm = TypedSPILoader.getService(ShardingAlgorithm.class, tableShardingAlgorithm.getName(), tableShardingAlgorithm.getProps());
+ ShardingSpherePreconditions.checkState(!(shardingAlgorithm instanceof ShardingAutoTableAlgorithm),
+ () -> new InvalidAlgorithmConfigurationException("sharding", shardingAlgorithm.getType(),
+ String.format("auto sharding algorithm cannot be used to create a table in Table mode `%s`", each.getLogicTable())));
+ }
+ ShardingSpherePreconditions.checkState(isValidStrategy(each.getTableStrategySegment()),
+ () -> new InvalidAlgorithmConfigurationException(databaseName, null == tableShardingAlgorithm ? null : tableShardingAlgorithm.getName()));
+ }
+
+ private static boolean isValidStrategy(final ShardingStrategySegment shardingStrategySegment) {
+ return ShardingStrategyType.getValueOf(shardingStrategySegment.getType()).isValid(shardingStrategySegment.getShardingColumn()) && null != shardingStrategySegment.getShardingAlgorithm();
+ }
+
+ private static <T extends AbstractTableRuleSegment> Collection<String> getRequiredTables(final Collection<T> rules) {
+ return rules.stream().map(AbstractTableRuleSegment::getDataSourceNodes).flatMap(Collection::stream)
+ .map(ShardingTableRuleStatementChecker::parseDateSource).map(ShardingTableRuleStatementChecker::getTableNames).flatMap(Collection::stream).collect(Collectors.toList());
+ }
+
+ private static Collection<String> getTableNames(final Collection<String> actualDataNodes) {
+ Collection<String> result = new HashSet<>();
+ for (String each : actualDataNodes) {
+ result.add(isValidDataNode(each) ? new DataNode(each).getTableName() : each);
+ }
+ return result;
}
private static void checkBindingTableRules(final Collection<AbstractTableRuleSegment> rules, final ShardingRuleConfiguration currentRuleConfig) {
@@ -353,141 +517,18 @@ public final class ShardingTableRuleStatementChecker {
ShardingRuleConfiguration toBeCheckedRuleConfig = createToBeCheckedShardingRuleConfiguration(currentRuleConfig);
removeRuleConfiguration(toBeCheckedRuleConfig, toBeAlteredRuleConfig);
addRuleConfiguration(toBeCheckedRuleConfig, toBeAlteredRuleConfig);
- Collection<String> dataSourceNames = getRequiredDataSource(toBeCheckedRuleConfig);
- dataSourceNames.addAll(getRequiredDataSource(toBeAlteredRuleConfig));
+ Collection<String> dataSourceNames = getRequiredDataSources(toBeCheckedRuleConfig);
+ dataSourceNames.addAll(getRequiredDataSources(toBeAlteredRuleConfig));
ShardingSpherePreconditions.checkState(check(toBeCheckedRuleConfig, dataSourceNames),
() -> new InvalidRuleConfigurationException("sharding table", toBeAlteredLogicTableNames, Collections.singleton("invalid binding table configuration.")));
}
- private static ShardingRuleConfiguration createToBeCheckedShardingRuleConfiguration(final ShardingRuleConfiguration currentRuleConfig) {
- ShardingRuleConfiguration result = new ShardingRuleConfiguration();
- result.setTables(new LinkedList<>(currentRuleConfig.getTables()));
- result.setAutoTables(new LinkedList<>(currentRuleConfig.getAutoTables()));
- result.setBindingTableGroups(new LinkedList<>(currentRuleConfig.getBindingTableGroups()));
- result.setBroadcastTables(new LinkedList<>(currentRuleConfig.getBroadcastTables()));
- result.setDefaultTableShardingStrategy(currentRuleConfig.getDefaultTableShardingStrategy());
- result.setDefaultDatabaseShardingStrategy(currentRuleConfig.getDefaultDatabaseShardingStrategy());
- result.setDefaultKeyGenerateStrategy(currentRuleConfig.getDefaultKeyGenerateStrategy());
- result.setDefaultShardingColumn(currentRuleConfig.getDefaultShardingColumn());
- result.setShardingAlgorithms(new LinkedHashMap<>(currentRuleConfig.getShardingAlgorithms()));
- result.setKeyGenerators(new LinkedHashMap<>(currentRuleConfig.getKeyGenerators()));
- result.setAuditors(new LinkedHashMap<>(currentRuleConfig.getAuditors()));
- return result;
- }
-
- private static Collection<String> getRequiredDataSource(final ShardingRuleConfiguration config) {
+ private static Collection<String> getCurrentBindingTables(final ShardingRuleConfiguration currentRuleConfig) {
Collection<String> result = new LinkedHashSet<>();
- result.addAll(config.getAutoTables().stream().map(ShardingAutoTableRuleConfiguration::getActualDataSources)
- .map(each -> Splitter.on(",").trimResults().splitToList(each)).flatMap(Collection::stream).collect(Collectors.toSet()));
- result.addAll(config.getTables().stream().map(each -> new InlineExpressionParser(each.getActualDataNodes()).splitAndEvaluate())
- .flatMap(Collection::stream).distinct().map(each -> new DataNode(each).getDataSourceName()).collect(Collectors.toSet()));
- return result;
- }
-
- private static boolean isValidBindingTableConfiguration(final Map<String, TableRule> tableRules, final BindingTableCheckedConfiguration checkedConfig) {
- for (ShardingTableReferenceRuleConfiguration each : checkedConfig.getBindingTableGroups()) {
- Collection<String> bindingTables = Splitter.on(",").trimResults().splitToList(each.getReference().toLowerCase());
- if (bindingTables.size() <= 1) {
- return false;
- }
- Iterator<String> iterator = bindingTables.iterator();
- TableRule sampleTableRule = getTableRule(iterator.next(), checkedConfig.getDataSourceNames(), tableRules, checkedConfig.getBroadcastTables());
- while (iterator.hasNext()) {
- TableRule tableRule = getTableRule(iterator.next(), checkedConfig.getDataSourceNames(), tableRules, checkedConfig.getBroadcastTables());
- if (!isValidActualDataSourceName(sampleTableRule, tableRule) || !isValidActualTableName(sampleTableRule, tableRule)) {
- return false;
- }
- if (!isValidShardingAlgorithm(sampleTableRule, tableRule, true, checkedConfig) || !isValidShardingAlgorithm(sampleTableRule, tableRule, false, checkedConfig)) {
- return false;
- }
- }
- }
- return true;
- }
-
- private static boolean isValidActualDataSourceName(final TableRule sampleTableRule, final TableRule tableRule) {
- return sampleTableRule.getActualDataSourceNames().equals(tableRule.getActualDataSourceNames());
- }
-
- private static boolean isValidActualTableName(final TableRule sampleTableRule, final TableRule tableRule) {
- for (String each : sampleTableRule.getActualDataSourceNames()) {
- Collection<String> sampleActualTableNames =
- sampleTableRule.getActualTableNames(each).stream().map(actualTableName -> actualTableName.replace(sampleTableRule.getTableDataNode().getPrefix(), "")).collect(Collectors.toSet());
- Collection<String> actualTableNames =
- tableRule.getActualTableNames(each).stream().map(optional -> optional.replace(tableRule.getTableDataNode().getPrefix(), "")).collect(Collectors.toSet());
- if (!sampleActualTableNames.equals(actualTableNames)) {
- return false;
- }
- }
- return true;
- }
-
- private static boolean isValidShardingAlgorithm(final TableRule sampleTableRule, final TableRule tableRule, final boolean databaseAlgorithm, final BindingTableCheckedConfiguration checkedConfig) {
- return getAlgorithmExpression(sampleTableRule, databaseAlgorithm, checkedConfig).equals(getAlgorithmExpression(tableRule, databaseAlgorithm, checkedConfig));
- }
-
- private static Optional<String> getAlgorithmExpression(final TableRule tableRule, final boolean databaseAlgorithm, final BindingTableCheckedConfiguration checkedConfig) {
- ShardingStrategyConfiguration shardingStrategyConfig = databaseAlgorithm
- ? null == tableRule.getDatabaseShardingStrategyConfig() ? checkedConfig.getDefaultDatabaseShardingStrategyConfig() : tableRule.getDatabaseShardingStrategyConfig()
- : null == tableRule.getTableShardingStrategyConfig() ? checkedConfig.getDefaultTableShardingStrategyConfig() : tableRule.getTableShardingStrategyConfig();
- ShardingAlgorithm shardingAlgorithm = checkedConfig.getShardingAlgorithms().get(shardingStrategyConfig.getShardingAlgorithmName());
- String dataNodePrefix = databaseAlgorithm ? tableRule.getDataSourceDataNode().getPrefix() : tableRule.getTableDataNode().getPrefix();
- String shardingColumn = getShardingColumn(shardingStrategyConfig, checkedConfig.getDefaultShardingColumn());
- return null == shardingAlgorithm ? Optional.empty() : shardingAlgorithm.getAlgorithmStructure(dataNodePrefix, shardingColumn);
- }
-
- private static String getShardingColumn(final ShardingStrategyConfiguration shardingStrategyConfig, final String defaultShardingColumn) {
- String shardingColumn = defaultShardingColumn;
- if (shardingStrategyConfig instanceof ComplexShardingStrategyConfiguration) {
- shardingColumn = ((ComplexShardingStrategyConfiguration) shardingStrategyConfig).getShardingColumns();
- }
- if (shardingStrategyConfig instanceof StandardShardingStrategyConfiguration) {
- shardingColumn = ((StandardShardingStrategyConfiguration) shardingStrategyConfig).getShardingColumn();
- }
- return null == shardingColumn ? "" : shardingColumn;
- }
-
- private static TableRule getTableRule(final String logicTableName, final Collection<String> dataSourceNames, final Map<String, TableRule> tableRules, final Collection<String> broadcastTables) {
- TableRule result = tableRules.get(logicTableName);
- if (null != result) {
- return result;
- }
- if (broadcastTables.contains(logicTableName)) {
- return new TableRule(dataSourceNames, logicTableName);
- }
- throw new ShardingTableRuleNotFoundException(Collections.singleton(logicTableName));
- }
-
- private static Collection<String> createBroadcastTables(final Collection<String> broadcastTables) {
- Collection<String> result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
- result.addAll(broadcastTables);
+ currentRuleConfig.getBindingTableGroups().forEach(each -> result.addAll(Splitter.on(",").trimResults().splitToList(each.getReference())));
return result;
}
- private static Map<String, TableRule> createAutoTableRules(final Collection<ShardingAutoTableRuleConfiguration> autoTableRuleConfigs, final Map<String, ShardingAlgorithm> shardingAlgorithms,
- final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig, final Collection<String> dataSourceNames) {
- return autoTableRuleConfigs.stream().map(each -> createAutoTableRule(defaultKeyGenerateStrategyConfig, each, shardingAlgorithms, dataSourceNames))
- .collect(Collectors.toMap(each -> each.getLogicTable().toLowerCase(), Function.identity(), (oldValue, currentValue) -> oldValue, LinkedHashMap::new));
- }
-
- private static TableRule createAutoTableRule(final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig, final ShardingAutoTableRuleConfiguration autoTableRuleConfig,
- final Map<String, ShardingAlgorithm> shardingAlgorithms, final Collection<String> dataSourceNames) {
- ShardingAlgorithm shardingAlgorithm = shardingAlgorithms.get(autoTableRuleConfig.getShardingStrategy().getShardingAlgorithmName());
- ShardingSpherePreconditions.checkState(shardingAlgorithm instanceof ShardingAutoTableAlgorithm,
- () -> new ShardingAlgorithmClassImplementationException(autoTableRuleConfig.getShardingStrategy().getShardingAlgorithmName(), ShardingAutoTableAlgorithm.class));
- return new TableRule(autoTableRuleConfig, dataSourceNames, (ShardingAutoTableAlgorithm) shardingAlgorithm, getDefaultGenerateKeyColumn(defaultKeyGenerateStrategyConfig));
- }
-
- private static Map<String, TableRule> createTableRules(final Collection<ShardingTableRuleConfiguration> tableRuleConfigs, final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig,
- final Collection<String> dataSourceNames) {
- return tableRuleConfigs.stream().map(each -> new TableRule(each, dataSourceNames, getDefaultGenerateKeyColumn(defaultKeyGenerateStrategyConfig)))
- .collect(Collectors.toMap(each -> each.getLogicTable().toLowerCase(), Function.identity(), (oldValue, currentValue) -> oldValue, LinkedHashMap::new));
- }
-
- private static String getDefaultGenerateKeyColumn(final KeyGenerateStrategyConfiguration defaultKeyGenerateStrategyConfig) {
- return Optional.ofNullable(defaultKeyGenerateStrategyConfig).map(KeyGenerateStrategyConfiguration::getColumn).orElse(null);
- }
-
private static void removeRuleConfiguration(final ShardingRuleConfiguration currentRuleConfig, final ShardingRuleConfiguration toBeAlteredRuleConfig) {
Collection<String> toBeAlteredLogicTableNames = getAlteredLogicalTableNames(toBeAlteredRuleConfig);
toBeAlteredLogicTableNames.forEach(each -> {
@@ -508,10 +549,4 @@ public final class ShardingTableRuleStatementChecker {
result.addAll(toBeAlteredRuleConfig.getAutoTables().stream().map(ShardingAutoTableRuleConfiguration::getLogicTable).collect(Collectors.toList()));
return result;
}
-
- private static Collection<String> getCurrentBindingTables(final ShardingRuleConfiguration currentRuleConfig) {
- Collection<String> result = new LinkedHashSet<>();
- currentRuleConfig.getBindingTableGroups().forEach(each -> result.addAll(Splitter.on(",").trimResults().splitToList(each.getReference())));
- return result;
- }
}
diff --git a/features/sharding/distsql/handler/src/test/java/org/apache/shardingsphere/sharding/distsql/checker/ShardingRuleStatementCheckerTest.java b/features/sharding/distsql/handler/src/test/java/org/apache/shardingsphere/sharding/distsql/checker/ShardingRuleStatementCheckerTest.java
index c2721efd586..f9c922607f9 100644
--- a/features/sharding/distsql/handler/src/test/java/org/apache/shardingsphere/sharding/distsql/checker/ShardingRuleStatementCheckerTest.java
+++ b/features/sharding/distsql/handler/src/test/java/org/apache/shardingsphere/sharding/distsql/checker/ShardingRuleStatementCheckerTest.java
@@ -18,6 +18,7 @@
package org.apache.shardingsphere.sharding.distsql.checker;
import org.apache.shardingsphere.distsql.handler.exception.algorithm.InvalidAlgorithmConfigurationException;
+import org.apache.shardingsphere.sharding.exception.strategy.InvalidShardingStrategyConfigurationException;
import org.apache.shardingsphere.distsql.handler.exception.rule.DuplicateRuleException;
import org.apache.shardingsphere.distsql.handler.exception.rule.MissingRequiredRuleException;
import org.apache.shardingsphere.distsql.handler.exception.storageunit.MissingRequiredStorageUnitsException;
@@ -269,7 +270,14 @@ class ShardingRuleStatementCheckerTest {
}
@Test
- void assertCheckerTableRuleWithNoneStrategyTypeSuccess() {
+ void assertCheckTableRuleWithNoneStrategyTypeThrows() {
+ Collection<AbstractTableRuleSegment> rules = new LinkedList<>();
+ rules.add(createWrongTableRuleWithNoneTypeStrategy());
+ assertThrows(InvalidShardingStrategyConfigurationException.class, () -> ShardingTableRuleStatementChecker.checkCreation(database, rules, false, shardingRuleConfig));
+ }
+
+ @Test
+ void assertCheckTableRuleWithNoneStrategyTypeSuccess() {
Collection<AbstractTableRuleSegment> rules = new LinkedList<>();
rules.add(createCompleteTableRuleWithNoneTypeStrategy());
ShardingTableRuleStatementChecker.checkCreation(database, rules, false, shardingRuleConfig);
@@ -314,12 +322,21 @@ class ShardingRuleStatementCheckerTest {
return result;
}
- private TableRuleSegment createCompleteTableRuleWithNoneTypeStrategy() {
+ private TableRuleSegment createWrongTableRuleWithNoneTypeStrategy() {
Properties props = new Properties();
KeyGenerateStrategySegment keyGenerator = new KeyGenerateStrategySegment("product_id", new AlgorithmSegment("DISTSQL.FIXTURE", props));
TableRuleSegment result = new TableRuleSegment("t_product_1", Collections.singletonList("ds_${0..1}.t_order${0..1}"), keyGenerator, null);
+ result.setDatabaseStrategySegment(new ShardingStrategySegment("none", null, null));
result.setTableStrategySegment(new ShardingStrategySegment("none", null, null));
+ return result;
+ }
+
+ private TableRuleSegment createCompleteTableRuleWithNoneTypeStrategy() {
+ Properties props = PropertiesBuilder.build(new Property("algorithm-expression", "t_order_${order_id % 2}"));
+ KeyGenerateStrategySegment keyGenerator = new KeyGenerateStrategySegment("product_id", new AlgorithmSegment("DISTSQL.FIXTURE", props));
+ TableRuleSegment result = new TableRuleSegment("t_product_1", Collections.singletonList("ds_0.t_order${0..1}"), keyGenerator, null);
result.setDatabaseStrategySegment(new ShardingStrategySegment("none", null, null));
+ result.setTableStrategySegment(new ShardingStrategySegment("standard", "order_id", new AlgorithmSegment("inline", props)));
return result;
}
}
diff --git a/features/sharding/distsql/handler/src/test/java/org/apache/shardingsphere/sharding/distsql/update/CreateShardingTableRuleStatementUpdaterTest.java b/features/sharding/distsql/handler/src/test/java/org/apache/shardingsphere/sharding/distsql/update/CreateShardingTableRuleStatementUpdaterTest.java
index 7a1bd79c1c1..683de397c93 100644
--- a/features/sharding/distsql/handler/src/test/java/org/apache/shardingsphere/sharding/distsql/update/CreateShardingTableRuleStatementUpdaterTest.java
+++ b/features/sharding/distsql/handler/src/test/java/org/apache/shardingsphere/sharding/distsql/update/CreateShardingTableRuleStatementUpdaterTest.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.sharding.distsql.update;
import lombok.SneakyThrows;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
import org.apache.shardingsphere.distsql.handler.exception.DistSQLException;
+import org.apache.shardingsphere.sharding.exception.strategy.InvalidShardingStrategyConfigurationException;
import org.apache.shardingsphere.distsql.parser.engine.spi.FeaturedDistSQLStatementParserFacade;
import org.apache.shardingsphere.distsql.parser.segment.AlgorithmSegment;
import org.apache.shardingsphere.distsql.parser.statement.DistSQLStatement;
@@ -154,6 +155,50 @@ class CreateShardingTableRuleStatementUpdaterTest {
assertThrows(DistSQLException.class, () -> updater.checkSQLStatement(database, distSQLStatement, null));
}
+ @Test
+ void assertCheckCreateShardingStatementWithNoneDatabaseStrategy() {
+ String sql = "CREATE SHARDING TABLE RULE t_order("
+ + "DATANODES('ds_0.t_order_${0..1}'),"
+ + "DATABASE_STRATEGY(TYPE='NONE'),"
+ + "TABLE_STRATEGY(TYPE='standard',SHARDING_COLUMN=order_id,SHARDING_ALGORITHM(TYPE(NAME='inline',PROPERTIES('algorithm-expression'='t_order_${order_id % 2}'))))"
+ + ");";
+ CreateShardingTableRuleStatement distSQLStatement = (CreateShardingTableRuleStatement) getDistSQLStatement(sql);
+ updater.checkSQLStatement(database, distSQLStatement, null);
+ }
+
+ @Test
+ void assertCheckCreateShardingStatementWithNoneDatabaseStrategyThrows() {
+ String sql = "CREATE SHARDING TABLE RULE t_order("
+ + "DATANODES('ds_${0..1}.t_order_${0..1}'),"
+ + "DATABASE_STRATEGY(TYPE='NONE'),"
+ + "TABLE_STRATEGY(TYPE='standard',SHARDING_COLUMN=order_id,SHARDING_ALGORITHM(TYPE(NAME='inline',PROPERTIES('algorithm-expression'='t_order_${order_id % 2}'))))"
+ + ");";
+ CreateShardingTableRuleStatement distSQLStatement = (CreateShardingTableRuleStatement) getDistSQLStatement(sql);
+ assertThrows(InvalidShardingStrategyConfigurationException.class, () -> updater.checkSQLStatement(database, distSQLStatement, null));
+ }
+
+ @Test
+ void assertCheckCreateShardingStatementWithNoneTableStrategy() {
+ String sql = "CREATE SHARDING TABLE RULE t_order("
+ + "DATANODES('ds_${0..1}.t_order_0'),"
+ + "DATABASE_STRATEGY(TYPE='standard',SHARDING_COLUMN=user_id,SHARDING_ALGORITHM(TYPE(NAME='inline',PROPERTIES('algorithm-expression'='ds_${user_id % 2}')))),"
+ + "TABLE_STRATEGY(TYPE='NONE')"
+ + ");";
+ CreateShardingTableRuleStatement distSQLStatement = (CreateShardingTableRuleStatement) getDistSQLStatement(sql);
+ updater.checkSQLStatement(database, distSQLStatement, null);
+ }
+
+ @Test
+ void assertCheckCreateShardingStatementWithNoneTableStrategyThrows() {
+ String sql = "CREATE SHARDING TABLE RULE t_order("
+ + "DATANODES('ds_${0..1}.t_order_${0..1}'),"
+ + "DATABASE_STRATEGY(TYPE='standard',SHARDING_COLUMN=user_id,SHARDING_ALGORITHM(TYPE(NAME='inline',PROPERTIES('algorithm-expression'='ds_${user_id % 2}')))),"
+ + "TABLE_STRATEGY(TYPE='NONE')"
+ + ");";
+ CreateShardingTableRuleStatement distSQLStatement = (CreateShardingTableRuleStatement) getDistSQLStatement(sql);
+ assertThrows(InvalidShardingStrategyConfigurationException.class, () -> updater.checkSQLStatement(database, distSQLStatement, null));
+ }
+
@Test
void assertUpdateWithIfNotExistsStatement() {
Collection<AbstractTableRuleSegment> segments = new LinkedList<>();