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