This is an automated email from the ASF dual-hosted git repository. jianglongtao pushed a commit to branch fix-33341 in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
commit a668c3cb401c6330d024d1b4a80447cb39043bb6 Author: RaigorJiang <[email protected]> AuthorDate: Mon Jul 22 09:59:38 2024 +0800 Pick #32044, Check privilege when register or alter storage unit --- .../core/advice/SQLParseCountAdviceTest.java | 2 +- ...ion.java => StorageUnitsValidateException.java} | 8 +- .../DataSourcePoolPropertiesValidator.java | 35 +++++-- .../DataSourcePoolPropertiesValidatorTest.java | 2 +- .../checker/DialectDatabaseEnvironmentChecker.java | 27 ++--- .../database/core/checker/PrivilegeCheckType.java | 17 +--- .../CheckDatabaseEnvironmentFailedException.java | 22 ++-- .../MissingRequiredPrivilegeException.java | 20 ++-- .../checker/MySQLDatabaseEnvironmentChecker.java | 112 +++++++++++++++++++++ .../metadata/data/loader/MySQLMetaDataLoader.java | 3 +- ....core.checker.DialectDatabaseEnvironmentChecker | 18 ++++ .../rdl/resource/AlterStorageUnitExecutor.java | 13 ++- .../rdl/resource/RegisterStorageUnitExecutor.java | 11 +- .../DistSQLDataSourcePoolPropertiesValidator.java | 21 +++- .../rdl/resource/AlterStorageUnitExecutorTest.java | 5 +- .../resource/RegisterStorageUnitExecutorTest.java | 5 +- .../transaction/util/AutoCommitUtilsTest.java | 9 +- .../engine/src/main/antlr4/imports/Keyword.g4 | 4 + .../engine/src/main/antlr4/imports/RDLStatement.g4 | 16 ++- .../core/kernel/KernelDistSQLStatementVisitor.java | 15 ++- .../unit/type/AlterStorageUnitStatement.java | 2 + .../unit/type/RegisterStorageUnitStatement.java | 2 + 22 files changed, 285 insertions(+), 84 deletions(-) diff --git a/agent/plugins/metrics/core/src/test/java/org/apache/shardingsphere/agent/plugin/metrics/core/advice/SQLParseCountAdviceTest.java b/agent/plugins/metrics/core/src/test/java/org/apache/shardingsphere/agent/plugin/metrics/core/advice/SQLParseCountAdviceTest.java index ffc6d334589..b6f74cb6063 100644 --- a/agent/plugins/metrics/core/src/test/java/org/apache/shardingsphere/agent/plugin/metrics/core/advice/SQLParseCountAdviceTest.java +++ b/agent/plugins/metrics/core/src/test/java/org/apache/shardingsphere/agent/plugin/metrics/core/advice/SQLParseCountAdviceTest.java @@ -102,7 +102,7 @@ class SQLParseCountAdviceTest { @Test void assertParseRDL() { - assertParse(new RegisterStorageUnitStatement(false, Collections.emptyList()), "RDL=1"); + assertParse(new RegisterStorageUnitStatement(false, Collections.emptyList(), Collections.emptySet()), "RDL=1"); } @Test diff --git a/infra/common/src/main/java/org/apache/shardingsphere/infra/exception/kernel/metadata/resource/storageunit/StorageUnitsConnectException.java b/infra/common/src/main/java/org/apache/shardingsphere/infra/exception/kernel/metadata/resource/storageunit/StorageUnitsValidateException.java similarity index 82% rename from infra/common/src/main/java/org/apache/shardingsphere/infra/exception/kernel/metadata/resource/storageunit/StorageUnitsConnectException.java rename to infra/common/src/main/java/org/apache/shardingsphere/infra/exception/kernel/metadata/resource/storageunit/StorageUnitsValidateException.java index 95cdd19514e..80ccacc50ab 100644 --- a/infra/common/src/main/java/org/apache/shardingsphere/infra/exception/kernel/metadata/resource/storageunit/StorageUnitsConnectException.java +++ b/infra/common/src/main/java/org/apache/shardingsphere/infra/exception/kernel/metadata/resource/storageunit/StorageUnitsValidateException.java @@ -24,14 +24,14 @@ import java.util.Map; import java.util.stream.Collectors; /** - * Storage units connect exception. + * Storage units validate exception. */ -public final class StorageUnitsConnectException extends ResourceDefinitionException { +public final class StorageUnitsValidateException extends ResourceDefinitionException { private static final long serialVersionUID = 1824912697040264268L; - public StorageUnitsConnectException(final Map<String, Exception> causes) { - super(XOpenSQLState.CONNECTION_EXCEPTION, 10, "Storage units can not connect, error messages are: %s.", causes.entrySet().stream().map(entry -> String.format( + public StorageUnitsValidateException(final Map<String, Exception> causes) { + super(XOpenSQLState.CONNECTION_EXCEPTION, 10, "Storage units validate error, messages are: %s.", causes.entrySet().stream().map(entry -> String.format( "Storage unit name: '%s', error message is: %s", entry.getKey(), entry.getValue().getMessage())).collect(Collectors.joining(System.lineSeparator()))); } } diff --git a/infra/data-source-pool/core/src/main/java/org/apache/shardingsphere/infra/datasource/pool/props/validator/DataSourcePoolPropertiesValidator.java b/infra/data-source-pool/core/src/main/java/org/apache/shardingsphere/infra/datasource/pool/props/validator/DataSourcePoolPropertiesValidator.java index d936cb0fc10..c2ae0a408fc 100644 --- a/infra/data-source-pool/core/src/main/java/org/apache/shardingsphere/infra/datasource/pool/props/validator/DataSourcePoolPropertiesValidator.java +++ b/infra/data-source-pool/core/src/main/java/org/apache/shardingsphere/infra/datasource/pool/props/validator/DataSourcePoolPropertiesValidator.java @@ -19,6 +19,11 @@ package org.apache.shardingsphere.infra.datasource.pool.props.validator; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.apache.shardingsphere.infra.database.core.checker.DialectDatabaseEnvironmentChecker; +import org.apache.shardingsphere.infra.database.core.checker.PrivilegeCheckType; +import org.apache.shardingsphere.infra.database.core.spi.DatabaseTypedSPILoader; +import org.apache.shardingsphere.infra.database.core.type.DatabaseType; +import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeFactory; import org.apache.shardingsphere.infra.datasource.pool.creator.DataSourcePoolCreator; import org.apache.shardingsphere.infra.datasource.pool.destroyer.DataSourcePoolDestroyer; import org.apache.shardingsphere.infra.datasource.pool.props.domain.DataSourcePoolProperties; @@ -27,9 +32,11 @@ import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; +import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; /** * Data source pool properties validator. @@ -39,16 +46,17 @@ public final class DataSourcePoolPropertiesValidator { /** * Validate data source pool properties map. - * + * * @param propsMap data source pool properties map + * @param expectedPrivileges excepted privileges * @return data source name and exception map */ - public static Map<String, Exception> validate(final Map<String, DataSourcePoolProperties> propsMap) { - Map<String, Exception> result = new LinkedHashMap<>(); + public static Map<String, Exception> validate(final Map<String, DataSourcePoolProperties> propsMap, final Collection<PrivilegeCheckType> expectedPrivileges) { + Map<String, Exception> result = new LinkedHashMap<>(propsMap.size(), 1F); for (Entry<String, DataSourcePoolProperties> entry : propsMap.entrySet()) { try { validateProperties(entry.getKey(), entry.getValue()); - validateConnection(entry.getKey(), entry.getValue()); + validateConnection(entry.getKey(), entry.getValue(), expectedPrivileges); } catch (final InvalidDataSourcePoolPropertiesException ex) { result.put(entry.getKey(), ex); } @@ -64,11 +72,16 @@ public final class DataSourcePoolPropertiesValidator { } } - private static void validateConnection(final String dataSourceName, final DataSourcePoolProperties props) throws InvalidDataSourcePoolPropertiesException { + private static void validateConnection(final String dataSourceName, final DataSourcePoolProperties props, + final Collection<PrivilegeCheckType> expectedPrivileges) throws InvalidDataSourcePoolPropertiesException { DataSource dataSource = null; try { dataSource = DataSourcePoolCreator.create(props); - checkFailFast(dataSource); + if (expectedPrivileges.isEmpty() || expectedPrivileges.contains(PrivilegeCheckType.NONE)) { + checkFailFast(dataSource); + return; + } + checkPrivileges(dataSource, props, expectedPrivileges); // CHECKSTYLE:OFF } catch (final SQLException | RuntimeException ex) { // CHECKSTYLE:ON @@ -87,4 +100,14 @@ public final class DataSourcePoolPropertiesValidator { // CHECKSTYLE:ON } } + + private static void checkPrivileges(final DataSource dataSource, final DataSourcePoolProperties props, final Collection<PrivilegeCheckType> expectedPrivileges) { + DatabaseType databaseType = DatabaseTypeFactory.get((String) props.getConnectionPropertySynonyms().getStandardProperties().get("url")); + Optional<DialectDatabaseEnvironmentChecker> checker = DatabaseTypedSPILoader.findService(DialectDatabaseEnvironmentChecker.class, databaseType); + if (checker.isPresent()) { + for (PrivilegeCheckType each : expectedPrivileges) { + checker.get().checkPrivilege(dataSource, each); + } + } + } } diff --git a/infra/data-source-pool/core/src/test/java/org/apache/shardingsphere/infra/datasource/pool/props/validator/DataSourcePoolPropertiesValidatorTest.java b/infra/data-source-pool/core/src/test/java/org/apache/shardingsphere/infra/datasource/pool/props/validator/DataSourcePoolPropertiesValidatorTest.java index 548c50901f8..cdbaae15bff 100644 --- a/infra/data-source-pool/core/src/test/java/org/apache/shardingsphere/infra/datasource/pool/props/validator/DataSourcePoolPropertiesValidatorTest.java +++ b/infra/data-source-pool/core/src/test/java/org/apache/shardingsphere/infra/datasource/pool/props/validator/DataSourcePoolPropertiesValidatorTest.java @@ -37,6 +37,6 @@ class DataSourcePoolPropertiesValidatorTest { @Test void assertValidate() { assertTrue(DataSourcePoolPropertiesValidator.validate( - Collections.singletonMap("name", new DataSourcePoolProperties(HikariDataSource.class.getName(), Collections.singletonMap("jdbcUrl", "jdbc:mock")))).isEmpty()); + Collections.singletonMap("name", new DataSourcePoolProperties(HikariDataSource.class.getName(), Collections.singletonMap("jdbcUrl", "jdbc:mock"))), Collections.emptySet()).isEmpty()); } } diff --git a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/checker/DialectDatabaseEnvironmentChecker.java similarity index 57% copy from parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java copy to infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/checker/DialectDatabaseEnvironmentChecker.java index 84795ad9340..84cc9724e19 100644 --- a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java +++ b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/checker/DialectDatabaseEnvironmentChecker.java @@ -15,23 +15,24 @@ * limitations under the License. */ -package org.apache.shardingsphere.distsql.statement.rdl.resource.unit.type; +package org.apache.shardingsphere.infra.database.core.checker; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.apache.shardingsphere.distsql.segment.DataSourceSegment; -import org.apache.shardingsphere.distsql.statement.rdl.resource.unit.StorageUnitDefinitionStatement; +import org.apache.shardingsphere.infra.database.core.spi.DatabaseTypedSPI; +import org.apache.shardingsphere.infra.spi.annotation.SingletonSPI; -import java.util.Collection; +import javax.sql.DataSource; /** - * Register storage unit statement. + * Dialect database environment checker. */ -@RequiredArgsConstructor -@Getter -public final class RegisterStorageUnitStatement extends StorageUnitDefinitionStatement { +@SingletonSPI +public interface DialectDatabaseEnvironmentChecker extends DatabaseTypedSPI { - private final boolean ifNotExists; - - private final Collection<DataSourceSegment> storageUnits; + /** + * Check user privileges. + * + * @param dataSource data source to be checked + * @param privilegeCheckType privilege check type + */ + void checkPrivilege(DataSource dataSource, PrivilegeCheckType privilegeCheckType); } diff --git a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/AlterStorageUnitStatement.java b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/checker/PrivilegeCheckType.java similarity index 59% copy from parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/AlterStorageUnitStatement.java copy to infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/checker/PrivilegeCheckType.java index 7a26c867c4d..8ce96c4b468 100644 --- a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/AlterStorageUnitStatement.java +++ b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/checker/PrivilegeCheckType.java @@ -15,21 +15,12 @@ * limitations under the License. */ -package org.apache.shardingsphere.distsql.statement.rdl.resource.unit.type; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.apache.shardingsphere.distsql.segment.DataSourceSegment; -import org.apache.shardingsphere.distsql.statement.rdl.resource.unit.StorageUnitDefinitionStatement; - -import java.util.Collection; +package org.apache.shardingsphere.infra.database.core.checker; /** - * Alter storage unit statement. + * Privilege check type. */ -@RequiredArgsConstructor -@Getter -public final class AlterStorageUnitStatement extends StorageUnitDefinitionStatement { +public enum PrivilegeCheckType { - private final Collection<DataSourceSegment> storageUnits; + NONE, PIPELINE, SELECT, XA } diff --git a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/exception/CheckDatabaseEnvironmentFailedException.java similarity index 54% copy from parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java copy to infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/exception/CheckDatabaseEnvironmentFailedException.java index 84795ad9340..ffa2387a35d 100644 --- a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java +++ b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/exception/CheckDatabaseEnvironmentFailedException.java @@ -15,23 +15,21 @@ * limitations under the License. */ -package org.apache.shardingsphere.distsql.statement.rdl.resource.unit.type; +package org.apache.shardingsphere.infra.database.core.exception; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.apache.shardingsphere.distsql.segment.DataSourceSegment; -import org.apache.shardingsphere.distsql.statement.rdl.resource.unit.StorageUnitDefinitionStatement; +import org.apache.shardingsphere.infra.exception.core.external.sql.sqlstate.XOpenSQLState; +import org.apache.shardingsphere.infra.exception.core.external.sql.type.kernel.category.MetaDataSQLException; -import java.util.Collection; +import java.sql.SQLException; /** - * Register storage unit statement. + * Check database environment failed exception. */ -@RequiredArgsConstructor -@Getter -public final class RegisterStorageUnitStatement extends StorageUnitDefinitionStatement { +public final class CheckDatabaseEnvironmentFailedException extends MetaDataSQLException { - private final boolean ifNotExists; + private static final long serialVersionUID = 3913140870320566898L; - private final Collection<DataSourceSegment> storageUnits; + public CheckDatabaseEnvironmentFailedException(final SQLException cause) { + super(XOpenSQLState.CONNECTION_EXCEPTION, 5, "Check database environment failed", cause); + } } diff --git a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/exception/MissingRequiredPrivilegeException.java similarity index 56% copy from parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java copy to infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/exception/MissingRequiredPrivilegeException.java index 84795ad9340..0acc5b92c75 100644 --- a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java +++ b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/exception/MissingRequiredPrivilegeException.java @@ -15,23 +15,21 @@ * limitations under the License. */ -package org.apache.shardingsphere.distsql.statement.rdl.resource.unit.type; +package org.apache.shardingsphere.infra.database.core.exception; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.apache.shardingsphere.distsql.segment.DataSourceSegment; -import org.apache.shardingsphere.distsql.statement.rdl.resource.unit.StorageUnitDefinitionStatement; +import org.apache.shardingsphere.infra.exception.core.external.sql.sqlstate.XOpenSQLState; +import org.apache.shardingsphere.infra.exception.core.external.sql.type.kernel.category.MetaDataSQLException; import java.util.Collection; /** - * Register storage unit statement. + * Missing required privilege exception. */ -@RequiredArgsConstructor -@Getter -public final class RegisterStorageUnitStatement extends StorageUnitDefinitionStatement { +public final class MissingRequiredPrivilegeException extends MetaDataSQLException { - private final boolean ifNotExists; + private static final long serialVersionUID = 3755362278200749857L; - private final Collection<DataSourceSegment> storageUnits; + public MissingRequiredPrivilegeException(final Collection<String> privileges) { + super(XOpenSQLState.PRIVILEGE_NOT_GRANTED, 6, "Missing required privilege(s) `%s`", privileges); + } } diff --git a/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/checker/MySQLDatabaseEnvironmentChecker.java b/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/checker/MySQLDatabaseEnvironmentChecker.java new file mode 100644 index 00000000000..358071b6a3d --- /dev/null +++ b/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/checker/MySQLDatabaseEnvironmentChecker.java @@ -0,0 +1,112 @@ +/* + * 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.infra.database.mysql.checker; + +import org.apache.shardingsphere.infra.database.core.checker.DialectDatabaseEnvironmentChecker; +import org.apache.shardingsphere.infra.database.core.checker.PrivilegeCheckType; +import org.apache.shardingsphere.infra.database.core.exception.CheckDatabaseEnvironmentFailedException; +import org.apache.shardingsphere.infra.database.core.exception.MissingRequiredPrivilegeException; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumMap; +import java.util.Map; + +/** + * Database environment checker for MySQL. + */ +public final class MySQLDatabaseEnvironmentChecker implements DialectDatabaseEnvironmentChecker { + + private static final String SHOW_GRANTS_SQL = "SHOW GRANTS"; + + private static final int MYSQL_MAJOR_VERSION_8 = 8; + + // BINLOG MONITOR is a synonym for REPLICATION CLIENT for MariaDB + private static final String[][] PIPELINE_REQUIRED_PRIVILEGES = + {{"ALL PRIVILEGES", "ON *.*"}, {"REPLICATION SLAVE", "REPLICATION CLIENT", "ON *.*"}, {"REPLICATION SLAVE", "BINLOG MONITOR", "ON *.*"}}; + + private static final String[][] XA_REQUIRED_PRIVILEGES = {{"ALL PRIVILEGES", "ON *.*"}, {"XA_RECOVER_ADMIN", "ON *.*"}}; + + private static final Map<PrivilegeCheckType, Collection<String>> REQUIRED_PRIVILEGES_FOR_MESSAGE = new EnumMap<>(PrivilegeCheckType.class); + + static { + REQUIRED_PRIVILEGES_FOR_MESSAGE.put(PrivilegeCheckType.PIPELINE, Arrays.asList("REPLICATION SLAVE", "REPLICATION CLIENT")); + REQUIRED_PRIVILEGES_FOR_MESSAGE.put(PrivilegeCheckType.SELECT, Collections.singleton("SELECT ON DATABASE")); + REQUIRED_PRIVILEGES_FOR_MESSAGE.put(PrivilegeCheckType.XA, Collections.singleton("XA_RECOVER_ADMIN")); + } + + @Override + public void checkPrivilege(final DataSource dataSource, final PrivilegeCheckType privilegeCheckType) { + try (Connection connection = dataSource.getConnection()) { + if (PrivilegeCheckType.XA == privilegeCheckType && MYSQL_MAJOR_VERSION_8 != connection.getMetaData().getDatabaseMajorVersion()) { + return; + } + checkPrivilege(connection, privilegeCheckType); + } catch (final SQLException ex) { + throw new CheckDatabaseEnvironmentFailedException(ex); + } + } + + private void checkPrivilege(final Connection connection, final PrivilegeCheckType privilegeCheckType) { + try ( + PreparedStatement preparedStatement = connection.prepareStatement(SHOW_GRANTS_SQL); + ResultSet resultSet = preparedStatement.executeQuery()) { + while (resultSet.next()) { + String privilege = resultSet.getString(1).toUpperCase(); + if (matchPrivileges(privilege, getRequiredPrivileges(connection, privilegeCheckType))) { + return; + } + } + } catch (final SQLException ex) { + throw new CheckDatabaseEnvironmentFailedException(ex); + } + throw new MissingRequiredPrivilegeException(REQUIRED_PRIVILEGES_FOR_MESSAGE.get(privilegeCheckType)); + } + + private String[][] getRequiredPrivileges(final Connection connection, final PrivilegeCheckType privilegeCheckType) throws SQLException { + switch (privilegeCheckType) { + case PIPELINE: + return PIPELINE_REQUIRED_PRIVILEGES; + case SELECT: + return getSelectRequiredPrivilege(connection); + case XA: + return XA_REQUIRED_PRIVILEGES; + default: + return new String[0][0]; + } + } + + private String[][] getSelectRequiredPrivilege(final Connection connection) throws SQLException { + return new String[][]{{"ALL PRIVILEGES", "ON *.*"}, {"SELECT", "ON *.*"}, {"SELECT", String.format("ON `%s`.*", connection.getCatalog()).toUpperCase()}}; + } + + private boolean matchPrivileges(final String grantedPrivileges, final String[][] requiredPrivileges) { + return Arrays.stream(requiredPrivileges).anyMatch(each -> Arrays.stream(each).allMatch(grantedPrivileges::contains)); + } + + @Override + public String getDatabaseType() { + return "MySQL"; + } +} diff --git a/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/metadata/data/loader/MySQLMetaDataLoader.java b/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/metadata/data/loader/MySQLMetaDataLoader.java index 223d712d939..748f04d32cf 100644 --- a/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/metadata/data/loader/MySQLMetaDataLoader.java +++ b/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/metadata/data/loader/MySQLMetaDataLoader.java @@ -69,8 +69,7 @@ public final class MySQLMetaDataLoader implements DialectMetaDataLoader { public Collection<SchemaMetaData> load(final MetaDataLoaderMaterial material) throws SQLException { Collection<TableMetaData> tableMetaDataList = new LinkedList<>(); Map<String, Collection<ColumnMetaData>> columnMetaDataMap = loadColumnMetaDataMap(material.getDataSource(), material.getActualTableNames()); - Collection<String> viewNames = loadViewNames(material.getDataSource(), columnMetaDataMap.keySet()); - Map<String, Collection<IndexMetaData>> indexMetaDataMap = columnMetaDataMap.isEmpty() ? Collections.emptyMap() : loadIndexMetaData(material.getDataSource(), columnMetaDataMap.keySet()); + Collection<String> viewNames = columnMetaDataMap.isEmpty() ? Collections.emptySet() : loadViewNames(material.getDataSource(), columnMetaDataMap.keySet()); Map<String, Collection<IndexMetaData>> indexMetaDataMap = columnMetaDataMap.isEmpty() ? Collections.emptyMap() : loadIndexMetaData(material.getDataSource(), columnMetaDataMap.keySet()); Map<String, Collection<ConstraintMetaData>> constraintMetaDataMap = columnMetaDataMap.isEmpty() ? Collections.emptyMap() : loadConstraintMetaDataMap(material.getDataSource(), columnMetaDataMap.keySet()); for (Entry<String, Collection<ColumnMetaData>> entry : columnMetaDataMap.entrySet()) { diff --git a/infra/database/type/mysql/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.database.core.checker.DialectDatabaseEnvironmentChecker b/infra/database/type/mysql/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.database.core.checker.DialectDatabaseEnvironmentChecker new file mode 100644 index 00000000000..631900c3ccc --- /dev/null +++ b/infra/database/type/mysql/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.database.core.checker.DialectDatabaseEnvironmentChecker @@ -0,0 +1,18 @@ +# +# 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. +# + +org.apache.shardingsphere.infra.database.mysql.checker.MySQLDatabaseEnvironmentChecker diff --git a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/AlterStorageUnitExecutor.java b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/AlterStorageUnitExecutor.java index 4f70b7c0e49..11f5fabffcf 100644 --- a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/AlterStorageUnitExecutor.java +++ b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/AlterStorageUnitExecutor.java @@ -27,6 +27,7 @@ import org.apache.shardingsphere.distsql.segment.HostnameAndPortBasedDataSourceS import org.apache.shardingsphere.distsql.segment.URLBasedDataSourceSegment; import org.apache.shardingsphere.distsql.segment.converter.DataSourceSegmentsConverter; import org.apache.shardingsphere.distsql.statement.rdl.resource.unit.type.AlterStorageUnitStatement; +import org.apache.shardingsphere.infra.database.core.checker.PrivilegeCheckType; import org.apache.shardingsphere.infra.database.core.connector.ConnectionProperties; import org.apache.shardingsphere.infra.database.core.connector.url.JdbcUrl; import org.apache.shardingsphere.infra.database.core.connector.url.StandardJdbcUrlParser; @@ -35,8 +36,8 @@ import org.apache.shardingsphere.infra.exception.core.ShardingSpherePrecondition import org.apache.shardingsphere.infra.exception.core.external.ShardingSphereExternalException; import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.AlterStorageUnitConnectionInfoException; import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.DuplicateStorageUnitException; -import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.StorageUnitsOperateException; import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.MissingRequiredStorageUnitsException; +import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.StorageUnitsOperateException; 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; @@ -63,7 +64,7 @@ public final class AlterStorageUnitExecutor implements DistSQLUpdateExecutor<Alt public void executeUpdate(final AlterStorageUnitStatement sqlStatement, final ContextManager contextManager) { checkBefore(sqlStatement); Map<String, DataSourcePoolProperties> propsMap = DataSourceSegmentsConverter.convert(database.getProtocolType(), sqlStatement.getStorageUnits()); - validateHandler.validate(propsMap); + validateHandler.validate(propsMap, getExpectedPrivileges(sqlStatement)); try { contextManager.getInstanceContext().getModeContextManager().alterStorageUnits(database.getName(), propsMap); } catch (final SQLException | ShardingSphereExternalException ex) { @@ -112,6 +113,14 @@ public final class AlterStorageUnitExecutor implements DistSQLUpdateExecutor<Alt return Objects.equals(hostName, connectionProps.getHostname()) && Objects.equals(port, String.valueOf(connectionProps.getPort())) && Objects.equals(database, connectionProps.getCatalog()); } + private Collection<PrivilegeCheckType> getExpectedPrivileges(final AlterStorageUnitStatement sqlStatement) { + Collection<PrivilegeCheckType> result = sqlStatement.getExpectedPrivileges().stream().map(each -> PrivilegeCheckType.valueOf(each.toUpperCase())).collect(Collectors.toSet()); + if (result.isEmpty()) { + result.add(PrivilegeCheckType.SELECT); + } + return result; + } + @Override public Class<AlterStorageUnitStatement> getType() { return AlterStorageUnitStatement.class; diff --git a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/RegisterStorageUnitExecutor.java b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/RegisterStorageUnitExecutor.java index 3b4e820b969..f343abba791 100644 --- a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/RegisterStorageUnitExecutor.java +++ b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/RegisterStorageUnitExecutor.java @@ -25,6 +25,7 @@ import org.apache.shardingsphere.distsql.handler.validate.DistSQLDataSourcePoolP import org.apache.shardingsphere.distsql.segment.DataSourceSegment; import org.apache.shardingsphere.distsql.segment.converter.DataSourceSegmentsConverter; import org.apache.shardingsphere.distsql.statement.rdl.resource.unit.type.RegisterStorageUnitStatement; +import org.apache.shardingsphere.infra.database.core.checker.PrivilegeCheckType; import org.apache.shardingsphere.infra.datasource.pool.props.domain.DataSourcePoolProperties; import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions; import org.apache.shardingsphere.infra.exception.core.external.ShardingSphereExternalException; @@ -65,7 +66,7 @@ public final class RegisterStorageUnitExecutor implements DistSQLUpdateExecutor< if (propsMap.isEmpty()) { return; } - validateHandler.validate(propsMap); + validateHandler.validate(propsMap, getExpectedPrivileges(sqlStatement)); try { contextManager.getInstanceContext().getModeContextManager().registerStorageUnits(database.getName(), propsMap); } catch (final SQLException | ShardingSphereExternalException ex) { @@ -109,6 +110,14 @@ public final class RegisterStorageUnitExecutor implements DistSQLUpdateExecutor< return database.getRuleMetaData().getAttributes(DataSourceMapperRuleAttribute.class).stream().flatMap(each -> each.getDataSourceMapper().keySet().stream()).collect(Collectors.toList()); } + private Collection<PrivilegeCheckType> getExpectedPrivileges(final RegisterStorageUnitStatement sqlStatement) { + Collection<PrivilegeCheckType> result = sqlStatement.getExpectedPrivileges().stream().map(each -> PrivilegeCheckType.valueOf(each.toUpperCase())).collect(Collectors.toSet()); + if (result.isEmpty()) { + result.add(PrivilegeCheckType.SELECT); + } + return result; + } + @Override public Class<RegisterStorageUnitStatement> getType() { return RegisterStorageUnitStatement.class; diff --git a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/validate/DistSQLDataSourcePoolPropertiesValidator.java b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/validate/DistSQLDataSourcePoolPropertiesValidator.java index 55e755c69e0..8c1f9ecfd08 100644 --- a/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/validate/DistSQLDataSourcePoolPropertiesValidator.java +++ b/infra/distsql-handler/src/main/java/org/apache/shardingsphere/distsql/handler/validate/DistSQLDataSourcePoolPropertiesValidator.java @@ -17,11 +17,14 @@ package org.apache.shardingsphere.distsql.handler.validate; +import org.apache.shardingsphere.infra.database.core.checker.PrivilegeCheckType; import org.apache.shardingsphere.infra.datasource.pool.props.domain.DataSourcePoolProperties; import org.apache.shardingsphere.infra.datasource.pool.props.validator.DataSourcePoolPropertiesValidator; import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions; -import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.StorageUnitsConnectException; +import org.apache.shardingsphere.infra.exception.kernel.metadata.resource.storageunit.StorageUnitsValidateException; +import java.util.Collection; +import java.util.Collections; import java.util.Map; /** @@ -31,11 +34,21 @@ public final class DistSQLDataSourcePoolPropertiesValidator { /** * Validate data source properties map. - * + * * @param propsMap data source pool properties map */ public void validate(final Map<String, DataSourcePoolProperties> propsMap) { - Map<String, Exception> exceptions = DataSourcePoolPropertiesValidator.validate(propsMap); - ShardingSpherePreconditions.checkState(exceptions.isEmpty(), () -> new StorageUnitsConnectException(exceptions)); + validate(propsMap, Collections.emptySet()); + } + + /** + * Validate data source properties map. + * + * @param propsMap data source pool properties map + * @param expectedPrivileges expected privileges + */ + public void validate(final Map<String, DataSourcePoolProperties> propsMap, final Collection<PrivilegeCheckType> expectedPrivileges) { + Map<String, Exception> exceptions = DataSourcePoolPropertiesValidator.validate(propsMap, expectedPrivileges); + ShardingSpherePreconditions.checkState(exceptions.isEmpty(), () -> new StorageUnitsValidateException(exceptions)); } } diff --git a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/AlterStorageUnitExecutorTest.java b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/AlterStorageUnitExecutorTest.java index 1d2a5f9c46c..c9c47ae891d 100644 --- a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/AlterStorageUnitExecutorTest.java +++ b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/AlterStorageUnitExecutorTest.java @@ -103,13 +103,14 @@ class AlterStorageUnitExecutorTest { } private AlterStorageUnitStatement createAlterStorageUnitStatement(final String resourceName) { - return new AlterStorageUnitStatement(Collections.singleton(new URLBasedDataSourceSegment(resourceName, "jdbc:mysql://127.0.0.1:3306/ds_0", "root", "", new Properties()))); + return new AlterStorageUnitStatement(Collections.singleton(new URLBasedDataSourceSegment(resourceName, "jdbc:mysql://127.0.0.1:3306/ds_0", "root", "", new Properties())), + Collections.emptySet()); } private AlterStorageUnitStatement createAlterStorageUnitStatementWithDuplicateStorageUnitNames() { return new AlterStorageUnitStatement(Arrays.asList( new HostnameAndPortBasedDataSourceSegment("ds_0", "127.0.0.1", "3306", "ds_0", "root", "", new Properties()), - new URLBasedDataSourceSegment("ds_0", "jdbc:mysql://127.0.0.1:3306/ds_1", "root", "", new Properties()))); + new URLBasedDataSourceSegment("ds_0", "jdbc:mysql://127.0.0.1:3306/ds_1", "root", "", new Properties())), Collections.emptySet()); } private ConnectionProperties mockConnectionProperties(final String catalog) { diff --git a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/RegisterStorageUnitExecutorTest.java b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/RegisterStorageUnitExecutorTest.java index fffdbfe5a3f..e06efe08be8 100644 --- a/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/RegisterStorageUnitExecutorTest.java +++ b/infra/distsql-handler/src/test/java/org/apache/shardingsphere/distsql/handler/executor/rdl/resource/RegisterStorageUnitExecutorTest.java @@ -91,12 +91,13 @@ class RegisterStorageUnitExecutorTest { } private RegisterStorageUnitStatement createRegisterStorageUnitStatement() { - return new RegisterStorageUnitStatement(false, Collections.singleton(new URLBasedDataSourceSegment("ds_0", "jdbc:mysql://127.0.0.1:3306/test0", "root", "", new Properties()))); + return new RegisterStorageUnitStatement(false, Collections.singleton(new URLBasedDataSourceSegment("ds_0", "jdbc:mysql://127.0.0.1:3306/test0", "root", "", new Properties())), + Collections.emptySet()); } private RegisterStorageUnitStatement createRegisterStorageUnitStatementWithDuplicateStorageUnitNames() { return new RegisterStorageUnitStatement(false, Arrays.asList( new HostnameAndPortBasedDataSourceSegment("ds_0", "127.0.0.1", "3306", "ds_0", "root", "", new Properties()), - new URLBasedDataSourceSegment("ds_0", "jdbc:mysql://127.0.0.1:3306/ds_1", "root", "", new Properties()))); + new URLBasedDataSourceSegment("ds_0", "jdbc:mysql://127.0.0.1:3306/ds_1", "root", "", new Properties())), Collections.emptySet()); } } diff --git a/kernel/transaction/core/src/test/java/org/apache/shardingsphere/transaction/util/AutoCommitUtilsTest.java b/kernel/transaction/core/src/test/java/org/apache/shardingsphere/transaction/util/AutoCommitUtilsTest.java index 151f4aa73af..6cd7b6fcba6 100644 --- a/kernel/transaction/core/src/test/java/org/apache/shardingsphere/transaction/util/AutoCommitUtilsTest.java +++ b/kernel/transaction/core/src/test/java/org/apache/shardingsphere/transaction/util/AutoCommitUtilsTest.java @@ -19,18 +19,15 @@ package org.apache.shardingsphere.transaction.util; import org.apache.shardingsphere.distsql.statement.rdl.resource.unit.type.RegisterStorageUnitStatement; import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment; -import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment; import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement; -import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.ddl.MySQLCreateTableStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLInsertStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLSelectStatement; import org.junit.jupiter.api.Test; -import java.util.LinkedList; - import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; class AutoCommitUtilsTest { @@ -38,7 +35,7 @@ class AutoCommitUtilsTest { void assertNeedOpenTransactionForSelectStatement() { SelectStatement selectStatement = new MySQLSelectStatement(); assertFalse(AutoCommitUtils.needOpenTransaction(selectStatement)); - selectStatement.setFrom(new SimpleTableSegment(new TableNameSegment(0, 5, new IdentifierValue("foo")))); + selectStatement.setFrom(mock(SimpleTableSegment.class)); assertTrue(AutoCommitUtils.needOpenTransaction(selectStatement)); } @@ -50,6 +47,6 @@ class AutoCommitUtilsTest { @Test void assertNeedOpenTransactionForOtherStatement() { - assertFalse(AutoCommitUtils.needOpenTransaction(new RegisterStorageUnitStatement(false, new LinkedList<>()))); + assertFalse(AutoCommitUtils.needOpenTransaction(mock(RegisterStorageUnitStatement.class))); } } diff --git a/parser/distsql/engine/src/main/antlr4/imports/Keyword.g4 b/parser/distsql/engine/src/main/antlr4/imports/Keyword.g4 index e2bdb512195..6f096e6417f 100644 --- a/parser/distsql/engine/src/main/antlr4/imports/Keyword.g4 +++ b/parser/distsql/engine/src/main/antlr4/imports/Keyword.g4 @@ -346,3 +346,7 @@ ALGORITHM FORCE : F O R C E ; + +CHECK_PRIVILEGES + : C H E C K UL_ P R I V I L E G E S + ; diff --git a/parser/distsql/engine/src/main/antlr4/imports/RDLStatement.g4 b/parser/distsql/engine/src/main/antlr4/imports/RDLStatement.g4 index 418dd843b7c..5dfb4f7a0bd 100644 --- a/parser/distsql/engine/src/main/antlr4/imports/RDLStatement.g4 +++ b/parser/distsql/engine/src/main/antlr4/imports/RDLStatement.g4 @@ -20,17 +20,21 @@ grammar RDLStatement; import BaseRule; registerStorageUnit - : REGISTER STORAGE UNIT ifNotExists? storageUnitDefinition (COMMA_ storageUnitDefinition)* + : REGISTER STORAGE UNIT ifNotExists? storageUnitsDefinition (COMMA_ checkPrivileges)? ; alterStorageUnit - : ALTER STORAGE UNIT storageUnitDefinition (COMMA_ storageUnitDefinition)* + : ALTER STORAGE UNIT storageUnitsDefinition (COMMA_ checkPrivileges)? ; unregisterStorageUnit : UNREGISTER STORAGE UNIT ifExists? storageUnitName (COMMA_ storageUnitName)* ignoreTables? ; +storageUnitsDefinition + : storageUnitDefinition (COMMA_ storageUnitDefinition)* + ; + storageUnitDefinition : storageUnitName LP_ (simpleSource | urlSource) COMMA_ USER EQ_ user (COMMA_ PASSWORD EQ_ password)? (COMMA_ propertiesDefinition)? RP_ ; @@ -80,3 +84,11 @@ ifExists ifNotExists : IF NOT EXISTS ; + +checkPrivileges + : CHECK_PRIVILEGES EQ_ privilegeType (COMMA_ privilegeType)* + ; + +privilegeType + : IDENTIFIER_ + ; diff --git a/parser/distsql/engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/kernel/KernelDistSQLStatementVisitor.java b/parser/distsql/engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/kernel/KernelDistSQLStatementVisitor.java index 0ecce27e2da..67f09b2f851 100644 --- a/parser/distsql/engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/kernel/KernelDistSQLStatementVisitor.java +++ b/parser/distsql/engine/src/main/java/org/apache/shardingsphere/distsql/parser/core/kernel/KernelDistSQLStatementVisitor.java @@ -22,6 +22,7 @@ import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementBa import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.AlgorithmDefinitionContext; import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.AlterComputeNodeContext; import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.AlterStorageUnitContext; +import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.CheckPrivilegesContext; import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.ConvertYamlConfigurationContext; import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.DatabaseNameContext; import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.DisableComputeNodeContext; @@ -58,6 +59,7 @@ import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementPa import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.ShowStorageUnitsContext; import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.ShowTableMetadataContext; import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.StorageUnitDefinitionContext; +import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.StorageUnitsDefinitionContext; import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.UnlabelComputeNodeContext; import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.UnlockClusterContext; import org.apache.shardingsphere.distsql.parser.autogen.KernelDistSQLStatementParser.UnregisterStorageUnitContext; @@ -100,6 +102,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.Identifi import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.StringLiteralValue; import java.util.Collection; +import java.util.Collections; import java.util.Objects; import java.util.Properties; import java.util.stream.Collectors; @@ -111,12 +114,20 @@ public final class KernelDistSQLStatementVisitor extends KernelDistSQLStatementB @Override public ASTNode visitRegisterStorageUnit(final RegisterStorageUnitContext ctx) { - return new RegisterStorageUnitStatement(null != ctx.ifNotExists(), ctx.storageUnitDefinition().stream().map(each -> (DataSourceSegment) visit(each)).collect(Collectors.toList())); + return new RegisterStorageUnitStatement(null != ctx.ifNotExists(), getStorageUnits(ctx.storageUnitsDefinition()), getExpectedPrivileges(ctx.checkPrivileges())); } @Override public ASTNode visitAlterStorageUnit(final AlterStorageUnitContext ctx) { - return new AlterStorageUnitStatement(ctx.storageUnitDefinition().stream().map(each -> (DataSourceSegment) visit(each)).collect(Collectors.toList())); + return new AlterStorageUnitStatement(getStorageUnits(ctx.storageUnitsDefinition()), getExpectedPrivileges(ctx.checkPrivileges())); + } + + private Collection<DataSourceSegment> getStorageUnits(final StorageUnitsDefinitionContext ctx) { + return ctx.storageUnitDefinition().stream().map(each -> (DataSourceSegment) visit(each)).collect(Collectors.toList()); + } + + private Collection<String> getExpectedPrivileges(final CheckPrivilegesContext ctx) { + return null == ctx ? Collections.emptySet() : ctx.privilegeType().stream().map(this::getIdentifierValue).collect(Collectors.toSet()); } @Override diff --git a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/AlterStorageUnitStatement.java b/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/AlterStorageUnitStatement.java index 7a26c867c4d..0bf3cb2f506 100644 --- a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/AlterStorageUnitStatement.java +++ b/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/AlterStorageUnitStatement.java @@ -32,4 +32,6 @@ import java.util.Collection; public final class AlterStorageUnitStatement extends StorageUnitDefinitionStatement { private final Collection<DataSourceSegment> storageUnits; + + private final Collection<String> expectedPrivileges; } diff --git a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java b/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java index 84795ad9340..90418b0d600 100644 --- a/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java +++ b/parser/distsql/statement/src/main/java/org/apache/shardingsphere/distsql/statement/rdl/resource/unit/type/RegisterStorageUnitStatement.java @@ -34,4 +34,6 @@ public final class RegisterStorageUnitStatement extends StorageUnitDefinitionSta private final boolean ifNotExists; private final Collection<DataSourceSegment> storageUnits; + + private final Collection<String> expectedPrivileges; }
