diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/RefreshTableMetaDataExecutor.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/RefreshTableMetaDataExecutor.java index 2d0ecfd4159e7..c94dc4e7a0325 100644 --- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/RefreshTableMetaDataExecutor.java +++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/RefreshTableMetaDataExecutor.java @@ -19,12 +19,14 @@ import lombok.Setter; import org.apache.shardingsphere.distsql.handler.aware.DistSQLExecutorDatabaseAware; -import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.EmptyStorageUnitException; -import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.MissingRequiredStorageUnitsException; import org.apache.shardingsphere.distsql.handler.engine.update.DistSQLUpdateExecutor; import org.apache.shardingsphere.distsql.statement.ral.updatable.RefreshTableMetaDataStatement; import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry; import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions; +import org.apache.shardingsphere.infra.exception.kernel.metadata.SchemaNotFoundException; +import org.apache.shardingsphere.infra.exception.kernel.metadata.TableNotFoundException; +import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.EmptyStorageUnitException; +import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.MissingRequiredStorageUnitsException; import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit; import org.apache.shardingsphere.mode.manager.ContextManager; @@ -43,8 +45,8 @@ public final class RefreshTableMetaDataExecutor implements DistSQLUpdateExecutor @Override public void executeUpdate(final RefreshTableMetaDataStatement sqlStatement, final ContextManager contextManager) throws SQLException { - checkStorageUnit(contextManager.getStorageUnits(database.getName()), sqlStatement); String schemaName = getSchemaName(sqlStatement); + checkBeforeUpdate(sqlStatement, schemaName); if (sqlStatement.getStorageUnitName().isPresent()) { if (sqlStatement.getTableName().isPresent()) { contextManager.reloadTable(database, schemaName, sqlStatement.getStorageUnitName().get(), sqlStatement.getTableName().get()); @@ -60,6 +62,16 @@ public void executeUpdate(final RefreshTableMetaDataStatement sqlStatement, fina } } + private String getSchemaName(final RefreshTableMetaDataStatement sqlStatement) { + return sqlStatement.getSchemaName().isPresent() ? sqlStatement.getSchemaName().get() : new DatabaseTypeRegistry(database.getProtocolType()).getDefaultSchemaName(database.getName()); + } + + private void checkBeforeUpdate(final RefreshTableMetaDataStatement sqlStatement, final String schemaName) { + checkStorageUnit(database.getResourceMetaData().getStorageUnits(), sqlStatement); + checkSchema(schemaName); + checkTable(sqlStatement, schemaName); + } + private void checkStorageUnit(final Map storageUnits, final RefreshTableMetaDataStatement sqlStatement) { ShardingSpherePreconditions.checkNotEmpty(storageUnits, () -> new EmptyStorageUnitException(database.getName())); if (sqlStatement.getStorageUnitName().isPresent()) { @@ -68,8 +80,15 @@ private void checkStorageUnit(final Map storageUnits, final } } - private String getSchemaName(final RefreshTableMetaDataStatement sqlStatement) { - return sqlStatement.getSchemaName().isPresent() ? sqlStatement.getSchemaName().get() : new DatabaseTypeRegistry(database.getProtocolType()).getDefaultSchemaName(database.getName()); + private void checkSchema(final String schemaName) { + ShardingSpherePreconditions.checkState(database.containsSchema(schemaName), () -> new SchemaNotFoundException(schemaName)); + } + + private void checkTable(final RefreshTableMetaDataStatement sqlStatement, final String schemaName) { + if (sqlStatement.getTableName().isPresent()) { + String tableName = sqlStatement.getTableName().get(); + ShardingSpherePreconditions.checkState(database.getSchema(schemaName).containsTable(tableName), () -> new TableNotFoundException(tableName)); + } } @Override diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/DistSQLUpdateBackendHandlerTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/DistSQLUpdateBackendHandlerTest.java index 0e6a9d9bb364b..e22e7a1a61922 100644 --- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/DistSQLUpdateBackendHandlerTest.java +++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/DistSQLUpdateBackendHandlerTest.java @@ -19,9 +19,14 @@ import org.apache.shardingsphere.distsql.statement.ral.updatable.RefreshTableMetaDataStatement; import org.apache.shardingsphere.infra.database.core.type.DatabaseType; +import org.apache.shardingsphere.infra.exception.kernel.metadata.SchemaNotFoundException; +import org.apache.shardingsphere.infra.exception.kernel.metadata.TableNotFoundException; import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.EmptyStorageUnitException; import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.MissingRequiredStorageUnitsException; import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; +import org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData; +import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit; +import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema; import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader; import org.apache.shardingsphere.mode.manager.ContextManager; import org.apache.shardingsphere.proxy.backend.context.ProxyContext; @@ -30,8 +35,11 @@ import org.apache.shardingsphere.proxy.backend.session.ConnectionSession; import org.apache.shardingsphere.test.mock.AutoMockExtension; import org.apache.shardingsphere.test.mock.StaticMockSettings; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Answers; +import org.mockito.Mock; import java.sql.SQLException; import java.util.Collections; @@ -39,7 +47,7 @@ import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -49,29 +57,62 @@ class DistSQLUpdateBackendHandlerTest { private final DatabaseType databaseType = TypedSPILoader.getService(DatabaseType.class, "FIXTURE"); - @Test - void assertEmptyResource() { - ContextManager contextManager = mock(ContextManager.class, RETURNS_DEEP_STUBS); + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private ContextManager contextManager; + + @BeforeEach + void setUp() { when(ProxyContext.getInstance().getContextManager()).thenReturn(contextManager); - when(contextManager.getStorageUnits("foo_db")).thenReturn(Collections.emptyMap()); - when(contextManager.getDatabase("foo_db")).thenReturn(new ShardingSphereDatabase("foo_db", mock(), mock(), mock(), Collections.emptyList())); + } + + @Test + void assertEmptyStorageUnit() { + when(contextManager.getDatabase("foo_db")).thenReturn(new ShardingSphereDatabase("foo_db", databaseType, mock(), mock(), Collections.emptyList())); DistSQLUpdateBackendHandler backendHandler = new DistSQLUpdateBackendHandler(new RefreshTableMetaDataStatement(), mockConnectionSession("foo_db")); assertThrows(EmptyStorageUnitException.class, backendHandler::execute); } @Test - void assertMissingRequiredResources() { - ContextManager contextManager = mock(ContextManager.class, RETURNS_DEEP_STUBS); - when(ProxyContext.getInstance().getContextManager()).thenReturn(contextManager); + void assertMissingRequiredStorageUnit() { + ResourceMetaData resourceMetaData = mock(ResourceMetaData.class); + when(resourceMetaData.getStorageUnits()).thenReturn(Collections.singletonMap("ds_0", mock(StorageUnit.class))); + when(contextManager.getDatabase("foo_db")).thenReturn(new ShardingSphereDatabase("foo_db", databaseType, resourceMetaData, mock(), Collections.emptyList())); DistSQLUpdateBackendHandler backendHandler = new DistSQLUpdateBackendHandler(new RefreshTableMetaDataStatement("t_order", "ds_1", null), mockConnectionSession("foo_db")); assertThrows(MissingRequiredStorageUnitsException.class, backendHandler::execute); } + @Test + void assertSchemaNotFound() { + ResourceMetaData resourceMetaData = mock(ResourceMetaData.class); + when(resourceMetaData.getStorageUnits()).thenReturn(Collections.singletonMap("ds_0", mock(StorageUnit.class))); + when(contextManager.getDatabase("foo_db")).thenReturn(new ShardingSphereDatabase("foo_db", databaseType, resourceMetaData, mock(), Collections.emptyList())); + DistSQLUpdateBackendHandler backendHandler = new DistSQLUpdateBackendHandler(new RefreshTableMetaDataStatement("t_order", "ds_0", "bar_db"), mockConnectionSession("foo_db")); + assertThrows(SchemaNotFoundException.class, backendHandler::execute); + } + + @Test + void assertTableNotFound() { + ResourceMetaData resourceMetaData = mock(ResourceMetaData.class); + when(resourceMetaData.getStorageUnits()).thenReturn(Collections.singletonMap("ds_0", mock(StorageUnit.class))); + ShardingSphereSchema schema = mock(ShardingSphereSchema.class); + ShardingSphereDatabase database = mock(ShardingSphereDatabase.class); + when(database.containsSchema("foo_db")).thenReturn(true); + when(database.getSchema("foo_db")).thenReturn(schema); + when(database.getResourceMetaData()).thenReturn(resourceMetaData); + when(contextManager.getDatabase("foo_db")).thenReturn(database); + DistSQLUpdateBackendHandler backendHandler = new DistSQLUpdateBackendHandler(new RefreshTableMetaDataStatement("t_order", "ds_0", "foo_db"), mockConnectionSession("foo_db")); + assertThrows(TableNotFoundException.class, backendHandler::execute); + } + @Test void assertUpdate() throws SQLException { - ContextManager contextManager = mock(ContextManager.class, RETURNS_DEEP_STUBS); - when(ProxyContext.getInstance().getContextManager()).thenReturn(contextManager); - when(contextManager.getDatabase("foo_db")).thenReturn(new ShardingSphereDatabase("foo_db", databaseType, mock(), mock(), Collections.emptyList())); + ResourceMetaData resourceMetaData = mock(ResourceMetaData.class); + when(resourceMetaData.getStorageUnits()).thenReturn(Collections.singletonMap("ds_0", mock(StorageUnit.class))); + ShardingSphereDatabase database = mock(ShardingSphereDatabase.class); + when(database.containsSchema(any())).thenReturn(true); + when(database.getProtocolType()).thenReturn(databaseType); + when(database.getResourceMetaData()).thenReturn(resourceMetaData); + when(contextManager.getDatabase("foo_db")).thenReturn(database); ResponseHeader actual = new DistSQLUpdateBackendHandler(new RefreshTableMetaDataStatement(), mockConnectionSession("foo_db")).execute(); assertThat(actual, instanceOf(UpdateResponseHeader.class)); }