This is an automated email from the ASF dual-hosted git repository.
terrymanu 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 08369e3cc2d Fix Single table schema availability handling (#39621)
08369e3cc2d is described below
commit 08369e3cc2d27b5ae167f302f624d63f35923590
Author: Liang Zhang <[email protected]>
AuthorDate: Fri Aug 28 12:33:19 2026 +0800
Fix Single table schema availability handling (#39621)
* Fix Single table schema availability handling
* Fix Single table schema availability handling
---
.../single/datanode/SingleTableDataNodeLoader.java | 8 ++--
.../SingleRuleConfigurationDecorator.java | 11 +++++-
.../SingleMutableDataNodeRuleAttribute.java | 17 +++++++-
.../single/util/SingleTableLoadUtils.java | 4 +-
.../datanode/SingleTableDataNodeLoaderTest.java | 32 +++++++++++++++
.../SingleRuleConfigurationDecoratorTest.java | 46 +++++++++++++---------
.../SingleMutableDataNodeRuleAttributeTest.java | 5 ++-
.../single/util/SingleTableLoadUtilsTest.java | 18 +++++++--
.../handler/update/LoadSingleTableExecutor.java | 30 ++++++++------
.../handler/update/UnloadSingleTableExecutor.java | 4 +-
.../update/LoadSingleTableExecutorTest.java | 36 ++++++++++++-----
.../update/UnloadSingleTableExecutorTest.java | 28 ++++++++++---
12 files changed, 177 insertions(+), 62 deletions(-)
diff --git
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/datanode/SingleTableDataNodeLoader.java
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/datanode/SingleTableDataNodeLoader.java
index ae251323eb7..e7afaa1b412 100644
---
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/datanode/SingleTableDataNodeLoader.java
+++
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/datanode/SingleTableDataNodeLoader.java
@@ -198,7 +198,9 @@ public final class SingleTableDataNodeLoader {
if (null == configuredTablesForDataSource) {
continue;
}
- if
(configuredTablesForDataSource.containsKey(SingleTableConstants.ASTERISK)) {
+ Collection<String> configuredTablesForAllSchemas =
configuredTablesForDataSource.get(SingleTableConstants.ASTERISK);
+ if (null != configuredTablesForAllSchemas
+ &&
(configuredTablesForAllSchemas.contains(SingleTableConstants.ASTERISK) ||
configuredTablesForAllSchemas.contains(each.getTableName()))) {
result.add(each);
continue;
}
@@ -224,9 +226,9 @@ public final class SingleTableDataNodeLoader {
DatabaseType databaseType =
validStorageTypes.getOrDefault(parsedDataNode.getDataSourceName(),
protocolType);
DataNode dataNode = new DataNode(databaseName, databaseType, each);
Map<String, Collection<String>> schemaTables =
result.getOrDefault(dataNode.getDataSourceName(), new LinkedHashMap<>());
- Collection<String> tables =
schemaTables.getOrDefault(dataNode.getSchemaName(), new LinkedList<>());
+ Collection<String> tables =
schemaTables.computeIfAbsent(dataNode.getSchemaName(),
+ ignored ->
SingleTableConstants.ASTERISK.equals(dataNode.getSchemaName()) ? new
CaseInsensitiveSet<>() : new LinkedHashSet<>());
tables.add(dataNode.getTableName());
- schemaTables.putIfAbsent(dataNode.getSchemaName(), tables);
result.putIfAbsent(dataNode.getDataSourceName(), schemaTables);
}
return result;
diff --git
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/decorator/SingleRuleConfigurationDecorator.java
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/decorator/SingleRuleConfigurationDecorator.java
index 10923e140e1..c1924895a75 100644
---
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/decorator/SingleRuleConfigurationDecorator.java
+++
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/decorator/SingleRuleConfigurationDecorator.java
@@ -159,7 +159,7 @@ public final class SingleRuleConfigurationDecorator
implements RuleConfiguration
if (expectedDataNodes.containsKey(entry.getKey())) {
DataNode dataNode = expectedDataNodes.get(entry.getKey());
String tableNodeStr = getTableNodeString(isSchemaAvailable,
physicalDataNode);
-
ShardingSpherePreconditions.checkState(physicalDataNode.equals(dataNode),
+
ShardingSpherePreconditions.checkState(isMatchedDataNode(isSchemaAvailable,
physicalDataNode, dataNode),
() -> new
InvalidSingleRuleConfigurationException(String.format("Single table `%s` is
found that does not match %s", tableNodeStr,
getTableNodeString(isSchemaAvailable,
dataNode))));
result.add(tableNodeStr);
@@ -175,13 +175,20 @@ public final class SingleRuleConfigurationDecorator
implements RuleConfiguration
ShardingSpherePreconditions.checkContainsKey(actualDataNodes,
each.getTableName(), () -> new
SingleTableNotFoundException(getTableNodeString(isSchemaAvailable, each)));
DataNode actualDataNode =
actualDataNodes.get(each.getTableName()).iterator().next();
String tableNodeStr = getTableNodeString(isSchemaAvailable,
actualDataNode);
-
ShardingSpherePreconditions.checkState(actualDataNode.equals(each), () -> new
InvalidSingleRuleConfigurationException(
+
ShardingSpherePreconditions.checkState(isMatchedDataNode(isSchemaAvailable,
actualDataNode, each), () -> new InvalidSingleRuleConfigurationException(
String.format("Single table '%s' is found that does not
match %s", tableNodeStr, getTableNodeString(isSchemaAvailable, each))));
result.add(tableNodeStr);
}
return result;
}
+ private boolean isMatchedDataNode(final boolean isSchemaAvailable, final
DataNode actualDataNode, final DataNode configuredDataNode) {
+ if (isSchemaAvailable ||
!SingleTableConstants.ASTERISK.equals(configuredDataNode.getSchemaName())) {
+ return actualDataNode.equals(configuredDataNode);
+ }
+ return
actualDataNode.getDataSourceName().equals(configuredDataNode.getDataSourceName())
&& actualDataNode.getTableName().equals(configuredDataNode.getTableName());
+ }
+
@Override
public Class<SingleRuleConfiguration> getType() {
return SingleRuleConfiguration.class;
diff --git
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/rule/attribute/SingleMutableDataNodeRuleAttribute.java
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/rule/attribute/SingleMutableDataNodeRuleAttribute.java
index 191283b35d5..8825c562242 100644
---
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/rule/attribute/SingleMutableDataNodeRuleAttribute.java
+++
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/rule/attribute/SingleMutableDataNodeRuleAttribute.java
@@ -100,12 +100,23 @@ public final class SingleMutableDataNodeRuleAttribute
implements MutableDataNode
if (null == dataNodes) {
continue;
}
+ Collection<String> removedDataNodeStrings = new LinkedList<>();
Iterator<DataNode> iterator = dataNodes.iterator();
while (iterator.hasNext()) {
DataNode dataNode = iterator.next();
if (schemaNames.contains(dataNode.getSchemaName())) {
iterator.remove();
-
configuration.getTables().remove(SingleTableLoadUtils.getDataNodeString(protocolType,
dataNode.getDataSourceName(), dataNode.getSchemaName(), each));
+ removedDataNodeStrings.add(getDataNodeString(dataNode,
each));
+ }
+ }
+ if (!removedDataNodeStrings.isEmpty()) {
+ Collection<String> retainedDataNodeStrings = new
LinkedHashSet<>(dataNodes.size(), 1F);
+ for (DataNode dataNode : dataNodes) {
+ retainedDataNodeStrings.add(getDataNodeString(dataNode,
each));
+ }
+ removedDataNodeStrings.removeAll(retainedDataNodeStrings);
+ for (String removedDataNodeString : removedDataNodeStrings) {
+ configuration.getTables().remove(removedDataNodeString);
}
}
if (dataNodes.isEmpty()) {
@@ -115,6 +126,10 @@ public final class SingleMutableDataNodeRuleAttribute
implements MutableDataNode
}
}
+ private String getDataNodeString(final DataNode dataNode, final String
tableName) {
+ return SingleTableLoadUtils.getDataNodeString(protocolType,
dataNode.getDataSourceName(), dataNode.getSchemaName(), tableName);
+ }
+
@SuppressWarnings("CollectionWithoutInitialCapacity")
@Override
public Optional<DataNode> findTableDataNode(final String schemaName, final
String tableName) {
diff --git
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/util/SingleTableLoadUtils.java
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/util/SingleTableLoadUtils.java
index c9782810ec7..a66121a4f57 100644
---
a/kernel/single/core/src/main/java/org/apache/shardingsphere/single/util/SingleTableLoadUtils.java
+++
b/kernel/single/core/src/main/java/org/apache/shardingsphere/single/util/SingleTableLoadUtils.java
@@ -132,7 +132,7 @@ public final class SingleTableLoadUtils {
*/
public static String getAllTablesNodeStrFromDataSource(final DatabaseType
databaseType, final String dataSourceName, final String schemaName) {
DialectDatabaseMetaData dialectDatabaseMetaData = new
DatabaseTypeRegistry(databaseType).getDialectDatabaseMetaData();
- return
dialectDatabaseMetaData.getSchemaOption().getDefaultSchema().isPresent()
+ return dialectDatabaseMetaData.getSchemaOption().isSchemaAvailable()
? formatDataNode(dataSourceName, schemaName,
SingleTableConstants.ASTERISK)
: formatDataNode(dataSourceName,
SingleTableConstants.ASTERISK);
}
@@ -148,7 +148,7 @@ public final class SingleTableLoadUtils {
*/
public static String getDataNodeString(final DatabaseType databaseType,
final String dataSourceName, final String schemaName, final String tableName) {
DialectDatabaseMetaData dialectDatabaseMetaData = new
DatabaseTypeRegistry(databaseType).getDialectDatabaseMetaData();
- return
dialectDatabaseMetaData.getSchemaOption().getDefaultSchema().isPresent() ?
formatDataNode(dataSourceName, schemaName, tableName) :
formatDataNode(dataSourceName, tableName);
+ return dialectDatabaseMetaData.getSchemaOption().isSchemaAvailable() ?
formatDataNode(dataSourceName, schemaName, tableName) :
formatDataNode(dataSourceName, tableName);
}
private static String formatDataNode(final String dataSourceName, final
String tableName) {
diff --git
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/datanode/SingleTableDataNodeLoaderTest.java
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/datanode/SingleTableDataNodeLoaderTest.java
index cad0aad5812..48a71137868 100644
---
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/datanode/SingleTableDataNodeLoaderTest.java
+++
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/datanode/SingleTableDataNodeLoaderTest.java
@@ -19,7 +19,9 @@ package org.apache.shardingsphere.single.datanode;
import ch.qos.logback.classic.Level;
import
org.apache.shardingsphere.database.connector.core.metadata.data.loader.type.SchemaMetaDataLoader;
+import
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.DialectDatabaseMetaData;
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeRegistry;
import org.apache.shardingsphere.infra.database.DatabaseTypeEngine;
import org.apache.shardingsphere.infra.datanode.DataNode;
import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
@@ -51,6 +53,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Optional;
import java.util.TreeSet;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -60,6 +63,9 @@ import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyCollection;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mockConstruction;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
@@ -171,6 +177,32 @@ class SingleTableDataNodeLoaderTest {
assertThat(actual.get("foo_tbl2").iterator().next().getDataSourceName(),
is("foo_ds"));
}
+ @Test
+ void assertLoadExactTablesWhenSchemaIsUnavailable() throws SQLException {
+ Map<String, Collection<String>> fooSchemaTableNames = new
LinkedHashMap<>(2, 1F);
+ fooSchemaTableNames.put("bar_schema",
Collections.singleton("FOO_TBL1"));
+ fooSchemaTableNames.put("dbo", Collections.singleton("foo_tbl2"));
+ Map<String, Collection<String>> barSchemaTableNames =
Collections.singletonMap("dbo", Arrays.asList("bar_tbl1", "bar_tbl2"));
+ DialectDatabaseMetaData dialectDatabaseMetaData =
mock(DialectDatabaseMetaData.class, RETURNS_DEEP_STUBS);
+
when(dialectDatabaseMetaData.getSchemaOption().getDefaultSchema()).thenReturn(Optional.of("dbo"));
+
when(dialectDatabaseMetaData.getSchemaOption().isSchemaAvailable()).thenReturn(false);
+ try (
+ MockedStatic<DatabaseTypeEngine> databaseTypeEngine =
mockStatic(DatabaseTypeEngine.class);
+ MockedConstruction<DatabaseTypeRegistry> ignoredRegistry =
mockConstruction(DatabaseTypeRegistry.class, (mock, context) -> {
+
when(mock.getDialectDatabaseMetaData()).thenReturn(dialectDatabaseMetaData);
+ });
+ MockedConstruction<SchemaMetaDataLoader> ignored =
mockConstruction(SchemaMetaDataLoader.class, (mock, context) -> {
+ when(mock.loadSchemaTableNames(anyString(),
any(DataSource.class), anyCollection(), anyCollection()))
+ .thenAnswer(invocation ->
dataSourceMap.get("foo_ds") == invocation.getArgument(1) ? fooSchemaTableNames
: barSchemaTableNames);
+ })) {
+ databaseTypeEngine.when(() ->
DatabaseTypeEngine.getStorageType(dataSourceMap.get("foo_ds"))).thenReturn(databaseType);
+ databaseTypeEngine.when(() ->
DatabaseTypeEngine.getStorageType(dataSourceMap.get("bar_ds"))).thenReturn(databaseType);
+ Map<String, Collection<DataNode>> actual =
SingleTableDataNodeLoader.load(
+ "foo_db", databaseType, dataSourceMap,
Collections.emptyList(), Arrays.asList("foo_ds.foo_tbl1", "bar_ds.*"));
+ assertThat(new TreeSet<>(actual.keySet()), is(new
TreeSet<>(Arrays.asList("FOO_TBL1", "bar_tbl1", "bar_tbl2"))));
+ }
+ }
+
@Test
void assertLoadWithSameTableInDifferentSchemas() {
Collection<String> configuredTables =
Collections.singleton("foo_ds.target_schema.same_tbl");
diff --git
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/decorator/SingleRuleConfigurationDecoratorTest.java
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/decorator/SingleRuleConfigurationDecoratorTest.java
index ab85ebfd9cb..5e3e52615c2 100644
---
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/decorator/SingleRuleConfigurationDecoratorTest.java
+++
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/decorator/SingleRuleConfigurationDecoratorTest.java
@@ -133,16 +133,20 @@ class SingleRuleConfigurationDecoratorTest {
@Test
void assertDecorateThrowsWhenSpecifiedTableMismatch() {
- DataNode dataNode = new DataNode("bar_ds", "foo_schema", "t_order");
- Map<String, Collection<DataNode>> actualDataNodes =
Collections.singletonMap(dataNode.getTableName(),
Collections.singleton(dataNode));
- Collection<String> splitTables =
Collections.singletonList("*.foo_schema.t_order");
- Collection<DataNode> configuredDataNodes = Collections.singleton(new
DataNode("foo_ds", "foo_schema", "t_order"));
+ Map<String, Collection<DataNode>> actualDataNodes = new
LinkedHashMap<>(2, 1F);
+ actualDataNodes.put("expanded_tbl", Collections.singleton(new
DataNode("expand_ds", "foo_schema", "expanded_tbl")));
+ actualDataNodes.put("t_order", Collections.singleton(new
DataNode("foo_ds", "bar_schema", "t_order")));
+ Collection<String> splitTables =
Arrays.asList("expand_ds.foo_schema.*", "foo_ds.foo_schema.t_order");
+ Collection<DataNode> configuredDataNodes = Arrays.asList(
+ new DataNode("expand_ds", "foo_schema",
SingleTableConstants.ASTERISK), new DataNode("foo_ds", "foo_schema",
"t_order"));
when(SingleTableDataNodeLoader.load(anyString(), anyMap(),
anyCollection(), anyCollection(), anyMap())).thenReturn(actualDataNodes);
mockSplitAndConvert(splitTables, configuredDataNodes,
Collections.emptyList(), Collections.emptyList());
Map<String, DataSource> dataSources =
Collections.singletonMap("foo_ds", mock(DataSource.class));
- SingleRuleConfiguration ruleConfig = new
SingleRuleConfiguration(Collections.singletonList("*.foo_schema.t_order"),
null);
- assertThrows(InvalidSingleRuleConfigurationException.class,
- () -> decorator.decorate("foo_db", dataSources,
Collections.singleton(mock(ShardingSphereRule.class, RETURNS_DEEP_STUBS)),
ruleConfig));
+ SingleRuleConfiguration ruleConfig = new
SingleRuleConfiguration(splitTables, null);
+ try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaRegistry(true)) {
+ assertThrows(InvalidSingleRuleConfigurationException.class,
+ () -> decorator.decorate("foo_db", dataSources,
Collections.singleton(mock(ShardingSphereRule.class, RETURNS_DEEP_STUBS)),
ruleConfig));
+ }
}
@Test
@@ -150,17 +154,19 @@ class SingleRuleConfigurationDecoratorTest {
Map<String, Collection<DataNode>> actualDataNodes = new
LinkedHashMap<>(3, 1F);
actualDataNodes.put("feature_tbl", Collections.singleton(new
DataNode("skip_ds", "foo_schema", "feature_tbl")));
actualDataNodes.put("expanded_tbl", Collections.singleton(new
DataNode("expand_ds", "foo_schema", "expanded_tbl")));
- actualDataNodes.put("matched_tbl", Collections.singleton(new
DataNode("bar_ds", "foo_schema", "matched_tbl")));
+ actualDataNodes.put("matched_tbl", Collections.singleton(new
DataNode("bar_ds", "dbo", "matched_tbl")));
when(SingleTableDataNodeLoader.load(anyString(), anyMap(),
anyCollection(), anyCollection(), anyMap())).thenReturn(actualDataNodes);
- Collection<String> splitTables = Arrays.asList("expand_ds.*",
"bar_ds.bar_tbl");
+ Collection<String> splitTables = Arrays.asList("expand_ds.*",
"bar_ds.matched_tbl");
Collection<DataNode> configuredDataNodes = Arrays.asList(
- new DataNode("expand_ds", "foo_schema",
SingleTableConstants.ASTERISK),
- new DataNode("bar_ds", "foo_schema", "matched_tbl"));
+ new DataNode("expand_ds", SingleTableConstants.ASTERISK,
SingleTableConstants.ASTERISK),
+ new DataNode("bar_ds", SingleTableConstants.ASTERISK,
"matched_tbl"));
mockSplitAndConvert(splitTables, configuredDataNodes,
Collections.emptyList(), Collections.singleton("feature_tbl"));
- SingleRuleConfiguration ruleConfig = new
SingleRuleConfiguration(Arrays.asList("expand_ds.*", "bar_ds.bar_tbl"), null);
+ SingleRuleConfiguration ruleConfig = new
SingleRuleConfiguration(splitTables, null);
Map<String, DataSource> dataSources =
Collections.singletonMap("foo_ds", mock(DataSource.class));
- assertThat(decorator.decorate("foo_db", dataSources,
Collections.singleton(mock(ShardingSphereRule.class, RETURNS_DEEP_STUBS)),
ruleConfig).getTables(),
- contains("expand_ds.expanded_tbl", "bar_ds.matched_tbl"));
+ try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaRegistry(false)) {
+ assertThat(decorator.decorate("foo_db", dataSources,
Collections.singleton(mock(ShardingSphereRule.class, RETURNS_DEEP_STUBS)),
ruleConfig).getTables(),
+ contains("expand_ds.expanded_tbl", "bar_ds.matched_tbl"));
+ }
}
@Test
@@ -184,17 +190,19 @@ class SingleRuleConfigurationDecoratorTest {
@Test
void assertDecorateThrowsWhenExpandedNodeMismatch() {
Collection<String> emptyTables = Collections.emptySet();
- Map<String, Collection<DataNode>> actualDataNodes =
Collections.singletonMap("t_order", Collections.singleton(new
DataNode("other_ds", "foo_schema", "t_order")));
+ Map<String, Collection<DataNode>> actualDataNodes =
Collections.singletonMap("t_order", Collections.singleton(new
DataNode("other_ds", "dbo", "t_order")));
when(SingleTableDataNodeLoader.load(anyString(), anyMap(),
anyCollection(), anyCollection(), anyMap())).thenReturn(actualDataNodes);
Collection<String> splitTables = Arrays.asList("expand_ds.*",
"expand_ds.t_order");
Collection<DataNode> configuredDataNodes = Arrays.asList(
- new DataNode("expand_ds", "foo_schema",
SingleTableConstants.ASTERISK),
- new DataNode("expand_ds", "foo_schema", "t_order"));
+ new DataNode("expand_ds", SingleTableConstants.ASTERISK,
SingleTableConstants.ASTERISK),
+ new DataNode("expand_ds", SingleTableConstants.ASTERISK,
"t_order"));
mockSplitAndConvert(splitTables, configuredDataNodes, emptyTables,
emptyTables);
SingleRuleConfiguration ruleConfig = new
SingleRuleConfiguration(Arrays.asList("expand_ds.*", "expand_ds.t_order"),
null);
Map<String, DataSource> dataSources =
Collections.singletonMap("foo_ds", mock(DataSource.class));
- assertThrows(InvalidSingleRuleConfigurationException.class,
- () -> decorator.decorate("foo_db", dataSources,
Collections.singleton(mock(ShardingSphereRule.class, RETURNS_DEEP_STUBS)),
ruleConfig));
+ try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaRegistry(false)) {
+ assertThrows(InvalidSingleRuleConfigurationException.class,
+ () -> decorator.decorate("foo_db", dataSources,
Collections.singleton(mock(ShardingSphereRule.class, RETURNS_DEEP_STUBS)),
ruleConfig));
+ }
}
@Test
diff --git
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/rule/attribute/SingleMutableDataNodeRuleAttributeTest.java
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/rule/attribute/SingleMutableDataNodeRuleAttributeTest.java
index f1a05e91523..27128f3ab46 100644
---
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/rule/attribute/SingleMutableDataNodeRuleAttributeTest.java
+++
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/rule/attribute/SingleMutableDataNodeRuleAttributeTest.java
@@ -105,7 +105,7 @@ class SingleMutableDataNodeRuleAttributeTest {
@MethodSource("removeWithSchemaNamesArguments")
void assertRemoveWithSchemaNames(final String name, final
Collection<DataNode> initialDataNodes, final Collection<String> schemaNames,
final int expectedDataNodeCount, final
Collection<String> expectedTables, final boolean expectedTableInMap, final
boolean expectedLogicTableExists) {
- SingleRuleConfiguration configuration = new
SingleRuleConfiguration(new
LinkedList<>(createDataNodeStrings(initialDataNodes)), null);
+ SingleRuleConfiguration configuration = new
SingleRuleConfiguration(new LinkedList<>(new
LinkedHashSet<>(createDataNodeStrings(initialDataNodes))), null);
Map<String, Collection<DataNode>> singleTableDataNodes =
createSingleTableDataNodes(initialDataNodes);
SingleTableMapperRuleAttribute tableMapperRuleAttribute = new
SingleTableMapperRuleAttribute(singleTableDataNodes.values());
SingleMutableDataNodeRuleAttribute ruleAttribute =
createRuleAttribute(configuration, Collections.singleton("foo_ds"),
singleTableDataNodes, tableMapperRuleAttribute);
@@ -194,6 +194,7 @@ class SingleMutableDataNodeRuleAttributeTest {
private static Stream<Arguments> removeWithSchemaNamesArguments() {
DataNode fooDataNode = new DataNode("foo_ds", "foo_schema", "foo_tbl");
DataNode barDataNode = new DataNode("foo_ds", "bar_schema", "foo_tbl");
+ DataNode otherDataSourceNode = new DataNode("bar_ds", "bar_schema",
"foo_tbl");
return Stream.of(
Arguments.of("keep data node when schema not matched",
Collections.singleton(fooDataNode), Collections.singleton("baz_schema"), 1,
Collections.singleton(SingleTableLoadUtils.getDataNodeString(DATABASE_TYPE,
"foo_ds", "foo_schema", "foo_tbl")), true, true),
@@ -201,6 +202,8 @@ class SingleMutableDataNodeRuleAttributeTest {
Collections.singleton(SingleTableLoadUtils.getDataNodeString(DATABASE_TYPE,
"foo_ds", "foo_schema", "foo_tbl")), true, true),
Arguments.of("remove matched schema and keep others",
Arrays.asList(fooDataNode, barDataNode), Collections.singleton("foo_schema"), 1,
Collections.singleton(SingleTableLoadUtils.getDataNodeString(DATABASE_TYPE,
"foo_ds", "bar_schema", "foo_tbl")), true, true),
+ Arguments.of("remove matched schema and keep another data
source", Arrays.asList(fooDataNode, otherDataSourceNode),
Collections.singleton("foo_schema"), 1,
+
Collections.singleton(SingleTableLoadUtils.getDataNodeString(DATABASE_TYPE,
"bar_ds", "bar_schema", "foo_tbl")), true, true),
Arguments.of("remove all matched schemas",
Collections.singleton(fooDataNode), Collections.singleton("foo_schema"), 0,
Collections.emptyList(), false, false));
}
diff --git
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/util/SingleTableLoadUtilsTest.java
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/util/SingleTableLoadUtilsTest.java
index f646959551b..873c6ec4b28 100644
---
a/kernel/single/core/src/test/java/org/apache/shardingsphere/single/util/SingleTableLoadUtilsTest.java
+++
b/kernel/single/core/src/test/java/org/apache/shardingsphere/single/util/SingleTableLoadUtilsTest.java
@@ -100,11 +100,20 @@ class SingleTableLoadUtilsTest {
@Test
void assertGetAllTablesNodeStrWithSchema() {
- try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaRegistry()) {
+ try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaRegistry(true)) {
assertThat(SingleTableLoadUtils.getAllTablesNodeStr(databaseType),
is("*.*.*"));
}
}
+ @Test
+ void assertFormatBySchemaAvailabilityWhenDefaultSchemaExists() {
+ try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaRegistry(false)) {
+ assertThat(SingleTableLoadUtils.getAllTablesNodeStr(databaseType),
is("*.*.*"));
+
assertThat(SingleTableLoadUtils.getAllTablesNodeStrFromDataSource(databaseType,
"foo_ds", "foo_schema"), is("foo_ds.*"));
+ assertThat(SingleTableLoadUtils.getDataNodeString(databaseType,
"foo_ds", "foo_schema", "foo_tbl"), is("foo_ds.foo_tbl"));
+ }
+ }
+
@Test
void assertGetAllTablesNodeStrFromDataSource() {
assertThat(SingleTableLoadUtils.getAllTablesNodeStrFromDataSource(databaseType,
"foo_ds", "foo_schema"), is("foo_ds.*"));
@@ -112,7 +121,7 @@ class SingleTableLoadUtilsTest {
@Test
void assertGetAllTablesNodeStrFromDataSourceWithSchema() {
- try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaRegistry()) {
+ try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaRegistry(true)) {
assertThat(SingleTableLoadUtils.getAllTablesNodeStrFromDataSource(databaseType,
"foo_ds", "foo_schema"), is("foo_ds.foo_schema.*"));
}
}
@@ -124,14 +133,15 @@ class SingleTableLoadUtilsTest {
@Test
void assertGetDataNodeStringWithSchema() {
- try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaRegistry()) {
+ try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaRegistry(true)) {
assertThat(SingleTableLoadUtils.getDataNodeString(databaseType,
"foo_ds", "foo_schema", "foo_tbl"), is("foo_ds.foo_schema.foo_tbl"));
}
}
- private MockedConstruction<DatabaseTypeRegistry> mockSchemaRegistry() {
+ private MockedConstruction<DatabaseTypeRegistry> mockSchemaRegistry(final
boolean schemaAvailable) {
DialectDatabaseMetaData dialectDatabaseMetaData =
mock(DialectDatabaseMetaData.class, RETURNS_DEEP_STUBS);
when(dialectDatabaseMetaData.getSchemaOption().getDefaultSchema()).thenReturn(Optional.of("foo_schema"));
+
when(dialectDatabaseMetaData.getSchemaOption().isSchemaAvailable()).thenReturn(schemaAvailable);
return mockConstruction(DatabaseTypeRegistry.class, (mock, context) ->
when(mock.getDialectDatabaseMetaData()).thenReturn(dialectDatabaseMetaData));
}
diff --git
a/kernel/single/distsql/handler/src/main/java/org/apache/shardingsphere/single/distsql/handler/update/LoadSingleTableExecutor.java
b/kernel/single/distsql/handler/src/main/java/org/apache/shardingsphere/single/distsql/handler/update/LoadSingleTableExecutor.java
index f9fc406687b..75768397294 100644
---
a/kernel/single/distsql/handler/src/main/java/org/apache/shardingsphere/single/distsql/handler/update/LoadSingleTableExecutor.java
+++
b/kernel/single/distsql/handler/src/main/java/org/apache/shardingsphere/single/distsql/handler/update/LoadSingleTableExecutor.java
@@ -68,9 +68,12 @@ public final class LoadSingleTableExecutor implements
DatabaseRuleCreateExecutor
database.checkStorageUnitsExisted(storageUnitNames);
}
String defaultSchemaName = database.getDefaultSchemaName();
- checkShouldNotExistLogicTables(sqlStatement, defaultSchemaName);
+ DialectDatabaseMetaData dialectDatabaseMetaData = new
DatabaseTypeRegistry(database.getProtocolType()).getDialectDatabaseMetaData();
+ boolean isSchemaAvailable =
dialectDatabaseMetaData.getSchemaOption().isSchemaAvailable();
+ checkShouldNotExistLogicTables(sqlStatement, defaultSchemaName,
isSchemaAvailable);
if (!storageUnitNames.isEmpty()) {
- checkShouldExistActualTables(sqlStatement, storageUnitNames,
defaultSchemaName);
+ boolean isSchemaWildcard = !isSchemaAvailable &&
dialectDatabaseMetaData.getSchemaOption().getDefaultSchema().isPresent();
+ checkShouldExistActualTables(sqlStatement, storageUnitNames,
defaultSchemaName, isSchemaWildcard);
}
}
@@ -78,24 +81,22 @@ public final class LoadSingleTableExecutor implements
DatabaseRuleCreateExecutor
return
sqlStatement.getTables().stream().map(SingleTableSegment::getStorageUnitName).filter(each
-> !SingleTableConstants.ASTERISK.equals(each)).collect(Collectors.toSet());
}
- private void checkShouldNotExistLogicTables(final LoadSingleTableStatement
sqlStatement, final String defaultSchemaName) {
+ private void checkShouldNotExistLogicTables(final LoadSingleTableStatement
sqlStatement, final String defaultSchemaName, final boolean isSchemaAvailable) {
Collection<SingleTableSegment> tableSegments =
sqlStatement.getTables();
- DialectDatabaseMetaData dialectDatabaseMetaData = new
DatabaseTypeRegistry(database.getProtocolType()).getDialectDatabaseMetaData();
- boolean isSchemaSupportedDatabaseType =
dialectDatabaseMetaData.getSchemaOption().getDefaultSchema().isPresent();
ShardingSphereSchema schema = database.getSchema(defaultSchemaName);
for (SingleTableSegment each : tableSegments) {
- checkTableNodeFormat(isSchemaSupportedDatabaseType, each);
+ checkTableNodeFormat(isSchemaAvailable, each);
if (!SingleTableConstants.ASTERISK.equals(each.getTableName())) {
ShardingSpherePreconditions.checkState(!schema.containsTable(each.getTableName()),
() -> new TableExistsException(each.getTableName()));
}
}
}
- private void checkTableNodeFormat(final boolean
isSchemaSupportedDatabaseType, final SingleTableSegment singleTableSegment) {
+ private void checkTableNodeFormat(final boolean isSchemaAvailable, final
SingleTableSegment singleTableSegment) {
if
(SingleTableConstants.ALL_TABLES.equals(singleTableSegment.toString()) ||
SingleTableConstants.ALL_SCHEMA_TABLES.equals(singleTableSegment.toString())) {
return;
}
- if (isSchemaSupportedDatabaseType) {
+ if (isSchemaAvailable) {
ShardingSpherePreconditions.checkState(singleTableSegment.getSchemaName().isPresent(),
() -> new
InvalidDataNodeFormatException(singleTableSegment.toString(), "Current database
is schema required, please use format `db.schema.table`"));
} else {
@@ -104,7 +105,8 @@ public final class LoadSingleTableExecutor implements
DatabaseRuleCreateExecutor
}
}
- private void checkShouldExistActualTables(final LoadSingleTableStatement
sqlStatement, final Collection<String> storageUnitNames, final String
defaultSchemaName) {
+ private void checkShouldExistActualTables(final LoadSingleTableStatement
sqlStatement, final Collection<String> storageUnitNames, final String
defaultSchemaName,
+ final boolean isSchemaWildcard) {
Map<String, DataSource> dataSourceMap =
database.getResourceMetaData().getStorageUnits().entrySet()
.stream().collect(Collectors.toMap(Entry::getKey, entry ->
entry.getValue().getDataSource()));
Map<String, DataSource> aggregatedDataSourceMap =
PhysicalDataSourceAggregator.getAggregatedDataSources(dataSourceMap,
database.getRuleMetaData().getRules());
@@ -122,10 +124,12 @@ public final class LoadSingleTableExecutor implements
DatabaseRuleCreateExecutor
() -> new TableNotFoundException(tableName,
storageUnitName));
DatabaseType storageUnitDatabaseType =
storageUnitDatabaseTypes.get(storageUnitName);
Map<String, Collection<String>> schemaTableNames =
actualTableNodes.get(storageUnitName);
- Collection<String> actualTableNames =
each.getSchemaName().map(schemaName ->
schemaTableNames.getOrDefault(schemaName, Collections.emptySet()))
- .orElseGet(() ->
getDefaultSchemaTableNames(schemaTableNames, defaultSchemaName,
storageUnitName, storageUnitDatabaseType,
- aggregatedDataSourceMap.get(storageUnitName),
schemaPolicies));
-
ShardingSpherePreconditions.checkState(actualTableNames.contains(tableName), ()
-> new TableNotFoundException(tableName, storageUnitName));
+ boolean tableExists = each.getSchemaName().map(schemaName ->
schemaTableNames.getOrDefault(schemaName,
Collections.emptySet()).contains(tableName))
+ .orElseGet(() -> isSchemaWildcard
+ ?
schemaTableNames.values().stream().anyMatch(tableNames ->
tableNames.contains(tableName))
+ : getDefaultSchemaTableNames(schemaTableNames,
defaultSchemaName, storageUnitName, storageUnitDatabaseType,
+
aggregatedDataSourceMap.get(storageUnitName),
schemaPolicies).contains(tableName));
+ ShardingSpherePreconditions.checkState(tableExists, () -> new
TableNotFoundException(tableName, storageUnitName));
}
}
}
diff --git
a/kernel/single/distsql/handler/src/main/java/org/apache/shardingsphere/single/distsql/handler/update/UnloadSingleTableExecutor.java
b/kernel/single/distsql/handler/src/main/java/org/apache/shardingsphere/single/distsql/handler/update/UnloadSingleTableExecutor.java
index a788dc92b2b..2134cc036d4 100644
---
a/kernel/single/distsql/handler/src/main/java/org/apache/shardingsphere/single/distsql/handler/update/UnloadSingleTableExecutor.java
+++
b/kernel/single/distsql/handler/src/main/java/org/apache/shardingsphere/single/distsql/handler/update/UnloadSingleTableExecutor.java
@@ -34,6 +34,7 @@ import
org.apache.shardingsphere.single.config.SingleRuleConfiguration;
import
org.apache.shardingsphere.single.distsql.statement.rdl.UnloadSingleTableStatement;
import org.apache.shardingsphere.single.exception.SingleTableNotFoundException;
import org.apache.shardingsphere.single.rule.SingleRule;
+import org.apache.shardingsphere.single.util.SingleTableLoadUtils;
import java.util.Collection;
import java.util.Collections;
@@ -86,7 +87,8 @@ public final class UnloadSingleTableExecutor implements
DatabaseRuleAlterExecuto
private void checkTableRuleExist(final String databaseName, final
DatabaseType databaseType, final Collection<DataNode> dataNodes, final String
tableName) {
ShardingSpherePreconditions.checkNotEmpty(dataNodes, () -> new
MissingRequiredRuleException("Single", databaseName, tableName));
DataNode dataNode = dataNodes.iterator().next();
-
ShardingSpherePreconditions.checkContains(rule.getConfiguration().getTables(),
dataNode.format(databaseType), () -> new MissingRequiredRuleException("Single",
databaseName, tableName));
+ String dataNodeString =
SingleTableLoadUtils.getDataNodeString(databaseType,
dataNode.getDataSourceName(), dataNode.getSchemaName(),
dataNode.getTableName());
+
ShardingSpherePreconditions.checkContains(rule.getConfiguration().getTables(),
dataNodeString, () -> new MissingRequiredRuleException("Single", databaseName,
tableName));
}
@Override
diff --git
a/kernel/single/distsql/handler/src/test/java/org/apache/shardingsphere/single/distsql/handler/update/LoadSingleTableExecutorTest.java
b/kernel/single/distsql/handler/src/test/java/org/apache/shardingsphere/single/distsql/handler/update/LoadSingleTableExecutorTest.java
index 610ed7eb3c3..e1017b4788c 100644
---
a/kernel/single/distsql/handler/src/test/java/org/apache/shardingsphere/single/distsql/handler/update/LoadSingleTableExecutorTest.java
+++
b/kernel/single/distsql/handler/src/test/java/org/apache/shardingsphere/single/distsql/handler/update/LoadSingleTableExecutorTest.java
@@ -96,16 +96,16 @@ class LoadSingleTableExecutorTest {
@ParameterizedTest(name = "{0}")
@MethodSource("assertCheckBeforeUpdateWithPreValidationFailureArguments")
- void assertCheckBeforeUpdateWithPreValidationFailure(final String name,
final boolean schemaSupported, final SingleTableSegment tableSegment,
+ void assertCheckBeforeUpdateWithPreValidationFailure(final String name,
final boolean schemaAvailable, final SingleTableSegment tableSegment,
final boolean
tableExists, final Class<? extends RuntimeException> expectedException) {
prepareStorageUnits();
- prepareSchema(tableExists, schemaSupported ? "foo_schema" : "foo_db");
- if (schemaSupported) {
+ prepareSchema(tableExists, schemaAvailable ? "foo_schema" : "foo_db");
+ if (schemaAvailable) {
when(database.getDefaultSchemaName()).thenReturn("foo_schema");
}
LoadSingleTableStatement sqlStatement = new
LoadSingleTableStatement(Collections.singleton(tableSegment));
- if (schemaSupported) {
- try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaSupportedDatabaseTypeRegistry()) {
+ if (schemaAvailable) {
+ try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaDatabaseTypeRegistry(true)) {
assertThrows(expectedException, () ->
executor.checkBeforeUpdate(sqlStatement));
}
} else {
@@ -132,7 +132,7 @@ class LoadSingleTableExecutorTest {
void assertCheckBeforeUpdateWithSchemaSupportedDatabaseType() {
prepareActualTableValidationScenario(Collections.singletonMap("foo_ds", new
MockedDataSource()), Collections.singletonMap("foo_schema",
Collections.singleton("foo_tbl")));
LoadSingleTableStatement sqlStatement = new
LoadSingleTableStatement(Arrays.asList(new SingleTableSegment("foo_ds",
"foo_schema", "foo_tbl"), new SingleTableSegment("*", "*")));
- try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaSupportedDatabaseTypeRegistry()) {
+ try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaDatabaseTypeRegistry(true)) {
when(database.getDefaultSchemaName()).thenReturn("foo_schema");
prepareSchema(false, "foo_schema");
assertDoesNotThrow(() -> executor.checkBeforeUpdate(sqlStatement));
@@ -146,11 +146,27 @@ class LoadSingleTableExecutorTest {
assertDoesNotThrow(() -> executor.checkBeforeUpdate(new
LoadSingleTableStatement(Collections.singletonList(new
SingleTableSegment("foo_ds", "foo_tbl")))));
}
+ @Test
+ void assertCheckBeforeUpdateRejectsNonDefaultSchemaWhenSchemaUnavailable()
{
+
when(DatabaseTypeEngine.getStorageType(any(DataSource.class))).thenReturn(TypedSPILoader.getService(DatabaseType.class,
"MySQL"));
+
prepareActualTableValidationScenario(Collections.singletonMap("foo_ds", new
MockedDataSource()), Collections.singletonMap("bar_schema",
Collections.singleton("foo_tbl")));
+ assertThrows(TableNotFoundException.class,
+ () -> executor.checkBeforeUpdate(new
LoadSingleTableStatement(Collections.singletonList(new
SingleTableSegment("foo_ds", "foo_tbl")))));
+ }
+
+ @Test
+ void assertCheckBeforeUpdateWithDefaultSchemaWhenSchemaUnavailable() {
+
prepareActualTableValidationScenario(Collections.singletonMap("foo_ds", new
MockedDataSource()), Collections.singletonMap("bar_schema",
Collections.singleton("foo_tbl")));
+ try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaDatabaseTypeRegistry(false)) {
+ assertDoesNotThrow(() -> executor.checkBeforeUpdate(new
LoadSingleTableStatement(Collections.singletonList(new
SingleTableSegment("foo_ds", "foo_tbl")))));
+ }
+ }
+
@Test
void
assertCheckBeforeUpdateWithExplicitSchemaAndDifferentProtocolAndStorageTypes() {
when(DatabaseTypeEngine.getStorageType(any(DataSource.class))).thenReturn(TypedSPILoader.getService(DatabaseType.class,
"MySQL"));
prepareActualTableValidationScenario(Collections.singletonMap("foo_ds", new
MockedDataSource()), Collections.singletonMap("foo_schema",
Collections.singleton("foo_tbl")));
- try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaSupportedDatabaseTypeRegistry()) {
+ try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaDatabaseTypeRegistry(true)) {
assertDoesNotThrow(() -> executor.checkBeforeUpdate(new
LoadSingleTableStatement(Collections.singletonList(new
SingleTableSegment("foo_ds", "foo_schema", "foo_tbl")))));
}
}
@@ -159,7 +175,7 @@ class LoadSingleTableExecutorTest {
void
assertCheckBeforeUpdateWithMismatchedExplicitSchemaAndDifferentProtocolAndStorageTypes()
{
when(DatabaseTypeEngine.getStorageType(any(DataSource.class))).thenReturn(TypedSPILoader.getService(DatabaseType.class,
"MySQL"));
prepareActualTableValidationScenario(Collections.singletonMap("foo_ds", new
MockedDataSource()), Collections.singletonMap("FOO_SCHEMA",
Collections.singleton("foo_tbl")));
- try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaSupportedDatabaseTypeRegistry()) {
+ try (MockedConstruction<DatabaseTypeRegistry> ignored =
mockSchemaDatabaseTypeRegistry(true)) {
assertThrows(TableNotFoundException.class,
() -> executor.checkBeforeUpdate(new
LoadSingleTableStatement(Collections.singletonList(new
SingleTableSegment("foo_ds", "foo_schema", "foo_tbl")))));
}
@@ -214,11 +230,11 @@ class LoadSingleTableExecutorTest {
}
}
- private MockedConstruction<DatabaseTypeRegistry>
mockSchemaSupportedDatabaseTypeRegistry() {
+ private MockedConstruction<DatabaseTypeRegistry>
mockSchemaDatabaseTypeRegistry(final boolean schemaAvailable) {
DialectDatabaseMetaData dialectDatabaseMetaData =
mock(DialectDatabaseMetaData.class, RETURNS_DEEP_STUBS);
when(dialectDatabaseMetaData.getSchemaOption().getDefaultSchema()).thenReturn(Optional.of("foo_schema"));
+
when(dialectDatabaseMetaData.getSchemaOption().isSchemaAvailable()).thenReturn(schemaAvailable);
return mockConstruction(DatabaseTypeRegistry.class, (mock, context) ->
{
- when(mock.getDefaultSchemaName("foo_db")).thenReturn("foo_schema");
when(mock.getDialectDatabaseMetaData()).thenReturn(dialectDatabaseMetaData);
});
}
diff --git
a/kernel/single/distsql/handler/src/test/java/org/apache/shardingsphere/single/distsql/handler/update/UnloadSingleTableExecutorTest.java
b/kernel/single/distsql/handler/src/test/java/org/apache/shardingsphere/single/distsql/handler/update/UnloadSingleTableExecutorTest.java
index 6545e5e7817..66b594faf8c 100644
---
a/kernel/single/distsql/handler/src/test/java/org/apache/shardingsphere/single/distsql/handler/update/UnloadSingleTableExecutorTest.java
+++
b/kernel/single/distsql/handler/src/test/java/org/apache/shardingsphere/single/distsql/handler/update/UnloadSingleTableExecutorTest.java
@@ -17,7 +17,9 @@
package org.apache.shardingsphere.single.distsql.handler.update;
+import
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.DialectDatabaseMetaData;
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeRegistry;
import
org.apache.shardingsphere.database.exception.core.exception.syntax.table.NoSuchTableException;
import
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.DatabaseRuleDefinitionExecutor;
import org.apache.shardingsphere.infra.datanode.DataNode;
@@ -41,6 +43,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Mock;
+import org.mockito.MockedConstruction;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
@@ -63,7 +66,9 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
@@ -108,10 +113,17 @@ class UnloadSingleTableExecutorTest {
@ParameterizedTest(name = "{0}")
@MethodSource("assertCheckBeforeUpdateWithSuccessArguments")
- void assertCheckBeforeUpdate(final String name, final
UnloadSingleTableStatement sqlStatement, final Collection<String> allTables,
+ void assertCheckBeforeUpdate(final String name, final boolean
schemaAvailable, final UnloadSingleTableStatement sqlStatement, final
Collection<String> allTables,
final Collection<String> singleTables, final
Map<String, Collection<DataNode>> tableDataNodes, final Collection<String>
configuredTables) {
prepareCheckBeforeUpdateContext(allTables, singleTables,
tableDataNodes, configuredTables);
- assertDoesNotThrow(() -> executor.checkBeforeUpdate(sqlStatement));
+ DialectDatabaseMetaData dialectDatabaseMetaData =
mock(DialectDatabaseMetaData.class, RETURNS_DEEP_STUBS);
+
when(dialectDatabaseMetaData.getSchemaOption().getDefaultSchema()).thenReturn(Optional.of("foo_schema"));
+
when(dialectDatabaseMetaData.getSchemaOption().isSchemaAvailable()).thenReturn(schemaAvailable);
+ try (
+ MockedConstruction<DatabaseTypeRegistry> ignored =
mockConstruction(
+ DatabaseTypeRegistry.class, (mock, context) ->
when(mock.getDialectDatabaseMetaData()).thenReturn(dialectDatabaseMetaData))) {
+ assertDoesNotThrow(() -> executor.checkBeforeUpdate(sqlStatement));
+ }
}
@Test
@@ -179,13 +191,17 @@ class UnloadSingleTableExecutorTest {
Map<String, Collection<DataNode>> multipleTableNodes = new
HashMap<>(2, 1F);
multipleTableNodes.put("foo_tbl", Collections.singleton(new
DataNode("foo_ds.foo_tbl")));
multipleTableNodes.put("bar_tbl", Collections.singleton(new
DataNode("foo_ds.foo_schema.bar_tbl")));
+ Map<String, Collection<DataNode>> schemaTableNodes = new HashMap<>(1,
1F);
+ schemaTableNodes.put("foo_tbl", Collections.singleton(new
DataNode("foo_ds.foo_schema.foo_tbl")));
return Stream.of(
- Arguments.of("unload all tables bypasses table checks", new
UnloadSingleTableStatement(true, Collections.emptyList()),
+ Arguments.of("unload all tables bypasses table checks", false,
new UnloadSingleTableStatement(true, Collections.emptyList()),
Collections.emptyList(), Collections.emptyList(),
Collections.emptyMap(), Collections.emptyList()),
- Arguments.of("valid single table passes checks", new
UnloadSingleTableStatement(false, Collections.singletonList("foo_tbl")),
+ Arguments.of("valid single table passes checks", false, new
UnloadSingleTableStatement(false, Collections.singletonList("foo_tbl")),
Collections.singleton("foo_tbl"),
Collections.singleton("foo_tbl"), singleTableNodes,
Collections.singleton("foo_ds.foo_tbl")),
- Arguments.of("valid multiple tables pass checks", new
UnloadSingleTableStatement(false, Arrays.asList("foo_tbl", "bar_tbl")),
- Arrays.asList("foo_tbl", "bar_tbl"),
Arrays.asList("foo_tbl", "bar_tbl"), multipleTableNodes,
Arrays.asList("foo_ds.foo_tbl", "foo_ds.bar_tbl")));
+ Arguments.of("valid multiple tables pass checks", false, new
UnloadSingleTableStatement(false, Arrays.asList("foo_tbl", "bar_tbl")),
+ Arrays.asList("foo_tbl", "bar_tbl"),
Arrays.asList("foo_tbl", "bar_tbl"), multipleTableNodes,
Arrays.asList("foo_ds.foo_tbl", "foo_ds.bar_tbl")),
+ Arguments.of("valid schema table passes checks", true, new
UnloadSingleTableStatement(false, Collections.singletonList("foo_tbl")),
+ Collections.singleton("foo_tbl"),
Collections.singleton("foo_tbl"), schemaTableNodes,
Collections.singleton("foo_ds.foo_schema.foo_tbl")));
}
private static Stream<Arguments>
assertBuildToBeAlteredRuleConfigurationArguments() {