This is an automated email from the ASF dual-hosted git repository.

jianglongtao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new bee027d  [DistSQL]Add a check on whether the database is changed when 
alter resource (#15307)
bee027d is described below

commit bee027d3e30c9de20935289bd69c9695805017b6
Author: lanchengx <[email protected]>
AuthorDate: Wed Feb 9 18:30:11 2022 +0800

    [DistSQL]Add a check on whether the database is changed when alter resource 
(#15307)
    
    * Modifying the database is not allowed when modifying resources.
    
    * Use `DataSourceProperties` instead of `Datasource`.
    
    * Edit prompt.
    
    * Rename method.
    
    * Add judgment on host and port.
---
 .../rdl/resource/AlterResourceBackendHandler.java  | 34 ++++++++++++++++++++--
 .../resource/AlterResourceBackendHandlerTest.java  | 23 ++++++++++++++-
 2 files changed, 54 insertions(+), 3 deletions(-)

diff --git 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/resource/AlterResourceBackendHandler.java
 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/resource/AlterResourceBackendHandler.java
index e26a907..60abedb 100644
--- 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/resource/AlterResourceBackendHandler.java
+++ 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/resource/AlterResourceBackendHandler.java
@@ -20,9 +20,12 @@ package 
org.apache.shardingsphere.proxy.backend.text.distsql.rdl.resource;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.shardingsphere.distsql.parser.segment.DataSourceSegment;
 import 
org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterResourceStatement;
+import org.apache.shardingsphere.infra.database.metadata.url.JdbcUrl;
+import 
org.apache.shardingsphere.infra.database.metadata.url.StandardJdbcUrlParser;
+import org.apache.shardingsphere.infra.database.type.DatabaseType;
 import org.apache.shardingsphere.infra.datasource.props.DataSourceProperties;
+import 
org.apache.shardingsphere.infra.datasource.props.DataSourcePropertiesCreator;
 import 
org.apache.shardingsphere.infra.datasource.props.DataSourcePropertiesValidator;
-import org.apache.shardingsphere.infra.database.type.DatabaseType;
 import org.apache.shardingsphere.infra.distsql.exception.DistSQLException;
 import 
org.apache.shardingsphere.infra.distsql.exception.resource.DuplicateResourceException;
 import 
org.apache.shardingsphere.infra.distsql.exception.resource.InvalidResourcesException;
@@ -36,7 +39,10 @@ import 
org.apache.shardingsphere.proxy.backend.text.SchemaRequiredBackendHandler
 import javax.sql.DataSource;
 import java.sql.SQLException;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -69,10 +75,18 @@ public final class AlterResourceBackendHandler extends 
SchemaRequiredBackendHand
         return new UpdateResponseHeader(sqlStatement);
     }
     
-    private void checkSQLStatement(final String schemaName, final 
AlterResourceStatement sqlStatement) throws DuplicateResourceException, 
RequiredResourceMissedException {
+    private void checkSQLStatement(final String schemaName, final 
AlterResourceStatement sqlStatement) throws DistSQLException {
         Collection<String> toBeAlteredResourceNames = 
getToBeAlteredResourceNames(sqlStatement);
         checkToBeAlteredDuplicateResourceNames(toBeAlteredResourceNames);
         checkResourceNameExisted(schemaName, toBeAlteredResourceNames);
+        checkDatabase(schemaName, sqlStatement);
+    }
+    
+    private void checkDatabase(final String schemaName, final 
AlterResourceStatement sqlStatement) throws DistSQLException {
+        Map<String, DataSource> resources = 
ProxyContext.getInstance().getMetaData(schemaName).getResource().getDataSources();
+        Set<String> invalid = 
sqlStatement.getDataSources().stream().collect(Collectors.toMap(DataSourceSegment::getName,
 each -> each)).entrySet().stream()
+                .filter(each -> !isIdenticalDatabase(each.getValue(), 
resources.get(each.getKey()))).map(Entry::getKey).collect(Collectors.toSet());
+        DistSQLException.predictionThrow(invalid.isEmpty(), new 
InvalidResourcesException(Collections.singleton(String.format("Cannot alter the 
database of %s", invalid))));
     }
     
     private Collection<String> getToBeAlteredResourceNames(final 
AlterResourceStatement sqlStatement) {
@@ -97,4 +111,20 @@ public final class AlterResourceBackendHandler extends 
SchemaRequiredBackendHand
             throw new RequiredResourceMissedException(schemaName, 
notExistedResourceNames);
         }
     }
+    
+    private boolean isIdenticalDatabase(final DataSourceSegment segment, final 
DataSource dataSource) {
+        String hostName = segment.getHostname();
+        String port = segment.getPort();
+        String database = segment.getDatabase();
+        if (null != segment.getUrl() && (null == hostName || null == port || 
null == database)) {
+            JdbcUrl segmentJdbcUrl = new 
StandardJdbcUrlParser().parse(segment.getUrl());
+            hostName = segmentJdbcUrl.getHostname();
+            port = String.valueOf(segmentJdbcUrl.getPort());
+            database = segmentJdbcUrl.getDatabase();
+        }
+        DataSourceProperties dataSourceProperties = 
DataSourcePropertiesCreator.create(dataSource);
+        String url = 
String.valueOf(dataSourceProperties.getConnectionPropertySynonyms().getStandardProperties().get("url"));
+        JdbcUrl dataSourceJdbcUrl = new StandardJdbcUrlParser().parse(url);
+        return hostName.equals(dataSourceJdbcUrl.getHostname()) && 
port.equals(String.valueOf(dataSourceJdbcUrl.getPort())) && 
database.equals(dataSourceJdbcUrl.getDatabase());
+    }
 }
diff --git 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/resource/AlterResourceBackendHandlerTest.java
 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/resource/AlterResourceBackendHandlerTest.java
index 7c8c53b..4e29b63 100644
--- 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/resource/AlterResourceBackendHandlerTest.java
+++ 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/rdl/resource/AlterResourceBackendHandlerTest.java
@@ -17,12 +17,14 @@
 
 package org.apache.shardingsphere.proxy.backend.text.distsql.rdl.resource;
 
+import com.zaxxer.hikari.HikariDataSource;
 import org.apache.shardingsphere.distsql.parser.segment.DataSourceSegment;
 import 
org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterResourceStatement;
 import 
org.apache.shardingsphere.infra.datasource.props.DataSourcePropertiesValidator;
 import org.apache.shardingsphere.infra.database.type.dialect.MySQLDatabaseType;
 import org.apache.shardingsphere.infra.distsql.exception.DistSQLException;
 import 
org.apache.shardingsphere.infra.distsql.exception.resource.DuplicateResourceException;
+import 
org.apache.shardingsphere.infra.distsql.exception.resource.InvalidResourcesException;
 import 
org.apache.shardingsphere.infra.distsql.exception.resource.RequiredResourceMissedException;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import 
org.apache.shardingsphere.infra.metadata.resource.ShardingSphereResource;
@@ -93,7 +95,7 @@ public final class AlterResourceBackendHandlerTest {
         
when(metaDataContexts.getAllSchemaNames()).thenReturn(Collections.singleton("test_schema"));
         when(metaDataContexts.getMetaData("test_schema")).thenReturn(metaData);
         when(metaData.getResource()).thenReturn(resource);
-        
when(resource.getDataSources()).thenReturn(Collections.singletonMap("ds_0", 
dataSource));
+        
when(resource.getDataSources()).thenReturn(Collections.singletonMap("ds_0", 
mockHikariDataSource("ds_0")));
         ResponseHeader responseHeader = 
alterResourceBackendHandler.execute("test_schema", 
createAlterResourceStatement("ds_0"));
         assertTrue(responseHeader instanceof UpdateResponseHeader);
     }
@@ -115,6 +117,19 @@ public final class AlterResourceBackendHandlerTest {
         alterResourceBackendHandler.execute("test_schema", 
createAlterResourceStatement("not_existed"));
     }
     
+    @Test(expected = InvalidResourcesException.class)
+    public void assertExecuteWithAlterDatabase() throws Exception {
+        ContextManager contextManager = mock(ContextManager.class, 
RETURNS_DEEP_STUBS);
+        
when(contextManager.getMetaDataContexts()).thenReturn(metaDataContexts);
+        ProxyContext.getInstance().init(contextManager);
+        
when(metaDataContexts.getAllSchemaNames()).thenReturn(Collections.singleton("test_schema"));
+        when(metaDataContexts.getMetaData("test_schema")).thenReturn(metaData);
+        when(metaData.getResource()).thenReturn(resource);
+        
when(resource.getDataSources()).thenReturn(Collections.singletonMap("ds_0", 
mockHikariDataSource("ds_1")));
+        ResponseHeader responseHeader = 
alterResourceBackendHandler.execute("test_schema", 
createAlterResourceStatement("ds_0"));
+        assertTrue(responseHeader instanceof UpdateResponseHeader);
+    }
+    
     private AlterResourceStatement createAlterResourceStatement(final String 
resourceName) {
         return new AlterResourceStatement(Collections.singleton(new 
DataSourceSegment(resourceName, "jdbc:mysql://127.0.0.1:3306/ds_0", null, null, 
null, "root", "", new Properties())));
     }
@@ -125,4 +140,10 @@ public final class AlterResourceBackendHandlerTest {
         result.add(new DataSourceSegment("ds_0", 
"jdbc:mysql://127.0.0.1:3306/ds_1", null, null, null, "root", "", new 
Properties()));
         return new AlterResourceStatement(result);
     }
+    
+    private HikariDataSource mockHikariDataSource(final String database) {
+        HikariDataSource result = new HikariDataSource();
+        
result.setJdbcUrl(String.format("jdbc:mysql://127.0.0.1:3306/%s?serverTimezone=UTC&useSSL=false",
 database));
+        return result;
+    }
 }

Reply via email to