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 70fbed3025d Fix database lookup validation in migration and metadata
entry points (#40336)
70fbed3025d is described below
commit 70fbed3025dd29ce4f921b4aa1f9f70ab687d20b
Author: Liang Zhang <[email protected]>
AuthorDate: Thu Oct 22 19:06:36 2026 +0800
Fix database lookup validation in migration and metadata entry points
(#40336)
---
.../scenario/migration/api/MigrationJobAPI.java | 2 +-
.../migration/api/MigrationJobAPITest.java | 57 +++++++
.../storage/QualifiedDataSourceChangedHandler.java | 7 +-
.../QualifiedDataSourceChangedHandlerTest.java | 20 ++-
.../select/UnicastResourceShowExecutor.java | 5 +-
.../select/UnicastResourceShowExecutorTest.java | 165 +++++++++++++++++++++
6 files changed, 245 insertions(+), 11 deletions(-)
diff --git
a/kernel/data-pipeline/scenario/migration/core/src/main/java/org/apache/shardingsphere/data/pipeline/scenario/migration/api/MigrationJobAPI.java
b/kernel/data-pipeline/scenario/migration/core/src/main/java/org/apache/shardingsphere/data/pipeline/scenario/migration/api/MigrationJobAPI.java
index a7640709de5..72e3afe9204 100644
---
a/kernel/data-pipeline/scenario/migration/core/src/main/java/org/apache/shardingsphere/data/pipeline/scenario/migration/api/MigrationJobAPI.java
+++
b/kernel/data-pipeline/scenario/migration/core/src/main/java/org/apache/shardingsphere/data/pipeline/scenario/migration/api/MigrationJobAPI.java
@@ -317,7 +317,7 @@ public final class MigrationJobAPI implements
TransmissionJobAPI {
private void refreshTableMetadata(final String jobId, final String
databaseName) {
// TODO use origin database name for now. It can be reduce metadata
refresh scope after reloadDatabaseMetaData case-sensitive problem fixed.
ContextManager contextManager =
PipelineContextManager.getContext(PipelineJobIdUtils.parseContextKey(jobId));
- ShardingSphereDatabase database =
contextManager.getMetaDataContexts().getMetaData().getDatabase(databaseName);
+ ShardingSphereDatabase database =
contextManager.getDatabase(databaseName);
contextManager.reloadDatabase(database);
}
diff --git
a/kernel/data-pipeline/scenario/migration/core/src/test/java/org/apache/shardingsphere/data/pipeline/scenario/migration/api/MigrationJobAPITest.java
b/kernel/data-pipeline/scenario/migration/core/src/test/java/org/apache/shardingsphere/data/pipeline/scenario/migration/api/MigrationJobAPITest.java
index c208bdf925a..4c91deac28f 100644
---
a/kernel/data-pipeline/scenario/migration/core/src/test/java/org/apache/shardingsphere/data/pipeline/scenario/migration/api/MigrationJobAPITest.java
+++
b/kernel/data-pipeline/scenario/migration/core/src/test/java/org/apache/shardingsphere/data/pipeline/scenario/migration/api/MigrationJobAPITest.java
@@ -18,6 +18,7 @@
package org.apache.shardingsphere.data.pipeline.scenario.migration.api;
import org.apache.shardingsphere.data.pipeline.core.context.PipelineContextKey;
+import
org.apache.shardingsphere.data.pipeline.core.context.PipelineContextManager;
import
org.apache.shardingsphere.data.pipeline.core.datasource.PipelineDataSource;
import
org.apache.shardingsphere.data.pipeline.core.exception.param.PipelineInvalidParameterException;
import org.apache.shardingsphere.data.pipeline.core.job.api.PipelineAPIFactory;
@@ -29,9 +30,12 @@ import
org.apache.shardingsphere.data.pipeline.core.sqlbuilder.sql.PipelinePrepa
import
org.apache.shardingsphere.data.pipeline.scenario.migration.MigrationJobId;
import
org.apache.shardingsphere.data.pipeline.scenario.migration.config.MigrationJobConfiguration;
import
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
+import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
import org.apache.shardingsphere.infra.datanode.DataNode;
import org.apache.shardingsphere.infra.instance.metadata.InstanceType;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.metadata.identifier.DatabaseIdentifierContext;
+import org.apache.shardingsphere.mode.manager.ContextManager;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -39,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.Answers;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockedConstruction;
import org.mockito.MockedStatic;
@@ -55,9 +60,11 @@ import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.sameInstance;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockConstruction;
import static org.mockito.Mockito.mockStatic;
@@ -73,6 +80,9 @@ class MigrationJobAPITest {
@Mock
private PipelineJobManager jobManager;
+ @Mock
+ private PipelineJobConfigurationManager jobConfigManager;
+
@Mock
private PipelineDataSourcePersistService dataSourcePersistService;
@@ -82,6 +92,7 @@ class MigrationJobAPITest {
void setUp() throws ReflectiveOperationException {
jobAPI = new MigrationJobAPI();
Plugins.getMemberAccessor().set(MigrationJobAPI.class.getDeclaredField("jobManager"),
jobAPI, jobManager);
+
Plugins.getMemberAccessor().set(MigrationJobAPI.class.getDeclaredField("jobConfigManager"),
jobAPI, jobConfigManager);
Plugins.getMemberAccessor().set(MigrationJobAPI.class.getDeclaredField("dataSourcePersistService"),
jobAPI, dataSourcePersistService);
}
@@ -121,6 +132,52 @@ class MigrationJobAPITest {
verify(jobManager, never()).start(any());
}
+ @Test
+ void assertCommit() {
+ String jobId = PipelineJobIdUtils.marshal(new
MigrationJobId(contextKey, Collections.emptyList()));
+ String checkJobId = "foo_check_job";
+ MigrationJobConfiguration jobConfig =
mock(MigrationJobConfiguration.class);
+ when(jobConfig.getTargetDatabaseName()).thenReturn("foo_db");
+
when(jobConfigManager.getJobConfiguration(jobId)).thenReturn(jobConfig);
+ ContextManager contextManager = mock(ContextManager.class);
+ ShardingSphereDatabase database = mock(ShardingSphereDatabase.class);
+ when(contextManager.getDatabase("foo_db")).thenReturn(database);
+ try (
+ MockedStatic<PipelineAPIFactory> ignoredFactory =
mockStatic(PipelineAPIFactory.class, Answers.RETURNS_DEEP_STUBS);
+ MockedStatic<PipelineContextManager> ignoredContext =
mockStatic(PipelineContextManager.class)) {
+
when(PipelineAPIFactory.getPipelineGovernanceFacade(contextKey).getJobFacade().getCheck().listCheckJobIds(jobId)).thenReturn(Collections.singleton(checkJobId));
+
when(PipelineContextManager.getContext(contextKey)).thenReturn(contextManager);
+ jobAPI.commit(jobId);
+ InOrder inOrder = inOrder(jobManager, contextManager);
+ inOrder.verify(jobManager).stop(jobId);
+ inOrder.verify(jobManager).drop(checkJobId);
+ inOrder.verify(contextManager).getDatabase("foo_db");
+ inOrder.verify(contextManager).reloadDatabase(database);
+ inOrder.verify(jobManager).drop(jobId);
+ }
+ }
+
+ @Test
+ void assertCommitWithUnknownDatabase() {
+ String jobId = PipelineJobIdUtils.marshal(new
MigrationJobId(contextKey, Collections.emptyList()));
+ MigrationJobConfiguration jobConfig =
mock(MigrationJobConfiguration.class);
+ when(jobConfig.getTargetDatabaseName()).thenReturn("foo_db");
+
when(jobConfigManager.getJobConfiguration(jobId)).thenReturn(jobConfig);
+ ContextManager contextManager = mock(ContextManager.class);
+ UnknownDatabaseException expected = new
UnknownDatabaseException("foo_db");
+ when(contextManager.getDatabase("foo_db")).thenThrow(expected);
+ try (
+ MockedStatic<PipelineAPIFactory> ignoredFactory =
mockStatic(PipelineAPIFactory.class, Answers.RETURNS_DEEP_STUBS);
+ MockedStatic<PipelineContextManager> ignoredContext =
mockStatic(PipelineContextManager.class)) {
+
when(PipelineContextManager.getContext(contextKey)).thenReturn(contextManager);
+ UnknownDatabaseException actual =
assertThrows(UnknownDatabaseException.class, () -> jobAPI.commit(jobId));
+ assertThat(actual, sameInstance(expected));
+ verify(jobManager).stop(jobId);
+ verify(contextManager,
never()).reloadDatabase(any(ShardingSphereDatabase.class));
+ verify(jobManager, never()).drop(jobId);
+ }
+ }
+
@ParameterizedTest(name = "{0}")
@MethodSource("provideRollbackSchemas")
void assertRollbackNormalizesSchemaAndPreservesActualTable(final String
name, final String schemaName, final String expectedSchemaName) throws
SQLException {
diff --git
a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/handler/global/node/storage/QualifiedDataSourceChangedHandler.java
b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/handler/global/node/storage/QualifiedDataSourceChangedHandler.java
index d3e73dc6600..9ea86187c31 100644
---
a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/handler/global/node/storage/QualifiedDataSourceChangedHandler.java
+++
b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/handler/global/node/storage/QualifiedDataSourceChangedHandler.java
@@ -21,6 +21,7 @@ import com.google.common.base.Strings;
import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.metadata.database.schema.QualifiedDataSource;
import
org.apache.shardingsphere.infra.rule.attribute.datasource.StaticDataSourceRuleAttribute;
import
org.apache.shardingsphere.infra.state.datasource.qualified.QualifiedDataSourceState;
@@ -68,8 +69,8 @@ public final class QualifiedDataSourceChangedHandler
implements GlobalDataChange
}
private void handleQualifiedDataSourceStateChanged(final
ShardingSphereMetaData metaData, final QualifiedDataSource qualifiedDataSource,
final QualifiedDataSourceState state) {
-
ShardingSpherePreconditions.checkState(metaData.containsDatabase(qualifiedDataSource.getDatabaseName()),
() -> new UnknownDatabaseException(qualifiedDataSource.getDatabaseName()));
-
metaData.getDatabase(qualifiedDataSource.getDatabaseName()).getRuleMetaData().getAttributes(StaticDataSourceRuleAttribute.class)
- .forEach(each -> each.updateStatus(qualifiedDataSource,
state.getState()));
+ ShardingSphereDatabase database =
metaData.getDatabase(qualifiedDataSource.getDatabaseName());
+ ShardingSpherePreconditions.checkNotNull(database, () -> new
UnknownDatabaseException(qualifiedDataSource.getDatabaseName()));
+
database.getRuleMetaData().getAttributes(StaticDataSourceRuleAttribute.class).forEach(each
-> each.updateStatus(qualifiedDataSource, state.getState()));
}
}
diff --git
a/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/handler/global/node/storage/QualifiedDataSourceChangedHandlerTest.java
b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/handler/global/node/storage/QualifiedDataSourceChangedHandlerTest.java
index 71af39031fd..88511746af9 100644
---
a/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/handler/global/node/storage/QualifiedDataSourceChangedHandlerTest.java
+++
b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/handler/global/node/storage/QualifiedDataSourceChangedHandlerTest.java
@@ -17,6 +17,7 @@
package
org.apache.shardingsphere.mode.manager.cluster.dispatch.handler.global.node.storage;
+import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
import
org.apache.shardingsphere.infra.metadata.database.schema.QualifiedDataSource;
import
org.apache.shardingsphere.infra.rule.attribute.datasource.StaticDataSourceRuleAttribute;
import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader;
@@ -35,12 +36,14 @@ import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Collections;
-import static org.mockito.ArgumentMatchers.anyString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.refEq;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
@@ -60,18 +63,25 @@ class QualifiedDataSourceChangedHandlerTest {
@Test
void assertHandleWithEmptyValue() {
handler.handle(contextManager, new
DataChangedEvent("/nodes/qualified_data_sources/foo_db.foo_group.foo_ds", "",
Type.ADDED));
- verify(contextManager.getMetaDataContexts().getMetaData(),
never()).containsDatabase(anyString());
+ verifyNoInteractions(contextManager);
}
@Test
void assertHandleWithoutQualifiedDataSource() {
handler.handle(contextManager, new
DataChangedEvent("/nodes/qualified_data_sources", "state: DISABLED",
Type.ADDED));
- verify(contextManager.getMetaDataContexts().getMetaData(),
never()).containsDatabase(anyString());
+ verifyNoInteractions(contextManager);
+ }
+
+ @Test
+ void assertHandleWithUnknownDatabase() {
+
when(contextManager.getMetaDataContexts().getMetaData().getDatabase("foo_db")).thenReturn(null);
+ UnknownDatabaseException actual =
assertThrows(UnknownDatabaseException.class,
+ () -> handler.handle(contextManager, new
DataChangedEvent("/nodes/qualified_data_sources/foo_db.foo_group.foo_ds",
"state: DISABLED", Type.ADDED)));
+ assertThat(actual.getDatabaseName(), is("foo_db"));
}
@Test
void assertHandle() {
-
when(contextManager.getMetaDataContexts().getMetaData().containsDatabase("foo_db")).thenReturn(true);
StaticDataSourceRuleAttribute staticDataSourceRuleAttribute =
mock(StaticDataSourceRuleAttribute.class);
when(contextManager.getMetaDataContexts().getMetaData().getDatabase("foo_db").getRuleMetaData().getAttributes(StaticDataSourceRuleAttribute.class))
.thenReturn(Collections.singleton(staticDataSourceRuleAttribute));
diff --git
a/proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/select/UnicastResourceShowExecutor.java
b/proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/select/UnicastResourceShowExecutor.java
index 4d8cde486f3..78575882c2c 100644
---
a/proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/select/UnicastResourceShowExecutor.java
+++
b/proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/select/UnicastResourceShowExecutor.java
@@ -77,8 +77,9 @@ public final class UnicastResourceShowExecutor implements
DatabaseAdminQueryExec
public void execute(final ConnectionSession connectionSession, final
ShardingSphereMetaData metaData) throws SQLException {
String originDatabase = connectionSession.getUsedDatabaseName();
String databaseName = null == originDatabase ?
getFirstDatabaseName(metaData) : originDatabase;
-
ShardingSpherePreconditions.checkState(metaData.containsDatabase(databaseName),
() -> new UnknownDatabaseException(databaseName));
-
ShardingSpherePreconditions.checkState(metaData.getDatabase(databaseName).containsDataSource(),
() -> new EmptyStorageUnitException(databaseName));
+ ShardingSphereDatabase database = metaData.getDatabase(databaseName);
+ ShardingSpherePreconditions.checkNotNull(database, () -> new
UnknownDatabaseException(databaseName));
+ ShardingSpherePreconditions.checkState(database.containsDataSource(),
() -> new EmptyStorageUnitException(databaseName));
HintValueContext hintValueContext = SQLHintUtils.extractHint(sql);
try {
connectionSession.setCurrentDatabaseName(databaseName);
diff --git
a/proxy/backend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/select/UnicastResourceShowExecutorTest.java
b/proxy/backend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/select/UnicastResourceShowExecutorTest.java
new file mode 100644
index 00000000000..6ccfe12267a
--- /dev/null
+++
b/proxy/backend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/select/UnicastResourceShowExecutorTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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.proxy.backend.mysql.handler.admin.executor.select;
+
+import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.NoDatabaseSelectedException;
+import
org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
+import
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.binder.engine.SQLBindEngine;
+import
org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.EmptyStorageUnitException;
+import
org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResultMetaData;
+import org.apache.shardingsphere.infra.merge.result.MergedResult;
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.session.query.QueryContext;
+import
org.apache.shardingsphere.proxy.backend.connector.DatabaseProxyConnector;
+import
org.apache.shardingsphere.proxy.backend.connector.DatabaseProxyConnectorFactory;
+import org.apache.shardingsphere.proxy.backend.response.data.QueryResponseCell;
+import org.apache.shardingsphere.proxy.backend.response.data.QueryResponseRow;
+import
org.apache.shardingsphere.proxy.backend.response.header.query.QueryHeader;
+import
org.apache.shardingsphere.proxy.backend.response.header.query.QueryResponseHeader;
+import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
+import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
+import
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
+import
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockedConstruction;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.sameInstance;
+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.eq;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(DatabaseProxyConnectorFactory.class)
+class UnicastResourceShowExecutorTest {
+
+ @Mock
+ private ConnectionSession connectionSession;
+
+ @Mock
+ private ShardingSphereMetaData metaData;
+
+ @Mock
+ private DatabaseProxyConnector databaseProxyConnector;
+
+ private final SelectStatement sqlStatement = mock(SelectStatement.class);
+
+ @Test
+ void assertExecuteWithUnknownDatabase() {
+ when(connectionSession.getUsedDatabaseName()).thenReturn("foo_db");
+ UnknownDatabaseException actual =
assertThrows(UnknownDatabaseException.class,
+ () -> new UnicastResourceShowExecutor(sqlStatement, "SELECT
@@max_allowed_packet").execute(connectionSession, metaData));
+ assertThat(actual.getDatabaseName(), is("foo_db"));
+ }
+
+ @Test
+ void assertExecuteWithEmptyStorageUnits() {
+ when(connectionSession.getUsedDatabaseName()).thenReturn("foo_db");
+
when(metaData.getDatabase("foo_db")).thenReturn(mock(ShardingSphereDatabase.class));
+ EmptyStorageUnitException actual =
assertThrows(EmptyStorageUnitException.class,
+ () -> new UnicastResourceShowExecutor(sqlStatement, "SELECT
@@max_allowed_packet").execute(connectionSession, metaData));
+ assertThat(actual.getMessage(), is("There is no storage unit in
database 'foo_db'."));
+ }
+
+ @Test
+ void assertExecuteWithoutDatabases() {
+ assertThrows(NoDatabaseSelectedException.class, () -> new
UnicastResourceShowExecutor(sqlStatement, "SELECT
@@max_allowed_packet").execute(connectionSession, metaData));
+ }
+
+ @Test
+ void assertExecuteWithoutAvailableStorageUnits() {
+
when(metaData.getAllDatabases()).thenReturn(Collections.singleton(mock(ShardingSphereDatabase.class)));
+ EmptyStorageUnitException actual =
assertThrows(EmptyStorageUnitException.class,
+ () -> new UnicastResourceShowExecutor(sqlStatement, "SELECT
@@max_allowed_packet").execute(connectionSession, metaData));
+ assertThat(actual.getMessage(), is("There is no storage unit in any
database."));
+ }
+
+ @Test
+ void assertExecuteWithFirstAvailableDatabase() throws SQLException {
+ ShardingSphereDatabase firstDatabase =
mock(ShardingSphereDatabase.class);
+ when(firstDatabase.containsDataSource()).thenReturn(true);
+ when(firstDatabase.getName()).thenReturn("foo_db");
+
when(metaData.getAllDatabases()).thenReturn(Arrays.asList(mock(ShardingSphereDatabase.class),
firstDatabase));
+ when(metaData.getDatabase("foo_db")).thenReturn(firstDatabase);
+ SQLStatementContext sqlStatementContext =
mock(SQLStatementContext.class, RETURNS_DEEP_STUBS);
+
when(sqlStatementContext.getTablesContext().getDatabaseNames()).thenReturn(Collections.singletonList("foo_db"));
+
when(DatabaseProxyConnectorFactory.newInstance(any(QueryContext.class), any(),
eq(false))).thenReturn(databaseProxyConnector);
+ QueryHeader queryHeader = new QueryHeader("", "", "foo_label",
"foo_column", Types.VARCHAR, "VARCHAR", 100, 0, false, false, false, false);
+ when(databaseProxyConnector.execute()).thenReturn(new
QueryResponseHeader(Collections.singletonList(queryHeader)));
+ when(databaseProxyConnector.next()).thenReturn(true, false);
+ when(databaseProxyConnector.getRowData()).thenReturn(new
QueryResponseRow(Collections.singletonList(new QueryResponseCell(Types.VARCHAR,
"foo_value"))));
+ UnicastResourceShowExecutor executor = new
UnicastResourceShowExecutor(sqlStatement, "SELECT @@max_allowed_packet");
+ try (MockedConstruction<SQLBindEngine> ignored =
mockConstruction(SQLBindEngine.class, (mock, context) ->
when(mock.bind(sqlStatement)).thenReturn(sqlStatementContext))) {
+ executor.execute(connectionSession, metaData);
+ }
+ InOrder actualOrder = inOrder(connectionSession,
databaseProxyConnector);
+ actualOrder.verify(connectionSession).setCurrentDatabaseName("foo_db");
+ actualOrder.verify(databaseProxyConnector).execute();
+ actualOrder.verify(connectionSession).setCurrentDatabaseName(null);
+ actualOrder.verify(databaseProxyConnector).close();
+ MergedResult actual = executor.getMergedResult();
+ assertTrue(actual.next());
+ assertThat(actual.getValue(1, Object.class), is("foo_value"));
+ assertFalse(actual.next());
+ QueryResultMetaData actualMetaData = executor.getQueryResultMetaData();
+ assertThat(actualMetaData.getColumnCount(), is(1));
+ assertThat(actualMetaData.getColumnLabel(1), is("foo_label"));
+ assertThat(actualMetaData.getColumnName(1), is("foo_label"));
+ assertThat(actualMetaData.getColumnType(1), is(Types.VARCHAR));
+ }
+
+ @Test
+ void assertExecuteWithConnectorFailure() throws SQLException {
+ when(connectionSession.getUsedDatabaseName()).thenReturn("foo_db");
+ ShardingSphereDatabase database = mock(ShardingSphereDatabase.class);
+ when(database.containsDataSource()).thenReturn(true);
+ when(metaData.getDatabase("foo_db")).thenReturn(database);
+ SQLStatementContext sqlStatementContext =
mock(SQLStatementContext.class, RETURNS_DEEP_STUBS);
+
when(sqlStatementContext.getTablesContext().getDatabaseNames()).thenReturn(Collections.singletonList("foo_db"));
+
when(DatabaseProxyConnectorFactory.newInstance(any(QueryContext.class), any(),
eq(false))).thenReturn(databaseProxyConnector);
+ SQLException expected = new SQLException("foo_failure");
+ when(databaseProxyConnector.execute()).thenThrow(expected);
+ try (MockedConstruction<SQLBindEngine> ignored =
mockConstruction(SQLBindEngine.class, (mock, context) ->
when(mock.bind(sqlStatement)).thenReturn(sqlStatementContext))) {
+ SQLException actual = assertThrows(SQLException.class, () -> new
UnicastResourceShowExecutor(sqlStatement, "SELECT
@@max_allowed_packet").execute(connectionSession, metaData));
+ assertThat(actual, sameInstance(expected));
+ }
+ InOrder actualOrder = inOrder(connectionSession,
databaseProxyConnector);
+ actualOrder.verify(connectionSession).setCurrentDatabaseName("foo_db");
+ actualOrder.verify(databaseProxyConnector).execute();
+ actualOrder.verify(connectionSession).setCurrentDatabaseName("foo_db");
+ actualOrder.verify(databaseProxyConnector).close();
+ }
+}