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();
+    }
+}

Reply via email to