diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 index 1b1e218a9581462..6ed144924bcd863 100644 --- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 +++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 @@ -225,7 +225,8 @@ supportedShowStatement | SHOW VIEW (FROM |IN) tableName=multipartIdentifier ((FROM | IN) database=identifier)? #showView - | SHOW PLUGINS #showPlugins + | SHOW PLUGINS #showPlugins + | SHOW STORAGE (VAULT | VAULTS) #showStorageVault | SHOW REPOSITORIES #showRepositories | SHOW BRIEF? CREATE TABLE name=multipartIdentifier #showCreateTable | SHOW ROLES #showRoles @@ -285,8 +286,7 @@ lockTable unsupportedShowStatement : SHOW ROW POLICY (FOR (userIdentify | (ROLE role=identifier)))? #showRowPolicy | SHOW STORAGE POLICY (USING (FOR policy=identifierOrText)?)? #showStoragePolicy - | SHOW STAGES #showStages - | SHOW STORAGE (VAULT | VAULTS) #showStorageVault + | SHOW STAGES #showStages | SHOW CREATE REPOSITORY FOR identifier #showCreateRepository | SHOW OPEN TABLES ((FROM | IN) database=multipartIdentifier)? wildWhere? #showOpenTables | SHOW TABLE STATUS ((FROM | IN) database=multipartIdentifier)? wildWhere? #showTableStatus diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java index 2db26dc15011f0d..b024a440ea5ddff 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java @@ -251,6 +251,7 @@ import org.apache.doris.nereids.DorisParser.ShowSmallFilesContext; import org.apache.doris.nereids.DorisParser.ShowSqlBlockRuleContext; import org.apache.doris.nereids.DorisParser.ShowStorageEnginesContext; +import org.apache.doris.nereids.DorisParser.ShowStorageVaultContext; import org.apache.doris.nereids.DorisParser.ShowTableIdContext; import org.apache.doris.nereids.DorisParser.ShowTabletsBelongContext; import org.apache.doris.nereids.DorisParser.ShowTriggersContext; @@ -536,6 +537,7 @@ import org.apache.doris.nereids.trees.plans.commands.ShowSmallFilesCommand; import org.apache.doris.nereids.trees.plans.commands.ShowSqlBlockRuleCommand; import org.apache.doris.nereids.trees.plans.commands.ShowStorageEnginesCommand; +import org.apache.doris.nereids.trees.plans.commands.ShowStorageVaultCommand; import org.apache.doris.nereids.trees.plans.commands.ShowTableIdCommand; import org.apache.doris.nereids.trees.plans.commands.ShowTabletsBelongCommand; import org.apache.doris.nereids.trees.plans.commands.ShowTriggersCommand; @@ -4308,6 +4310,11 @@ public SetTransactionCommand visitSetTransaction(SetTransactionContext ctx) { return new SetTransactionCommand(); } + @Override + public LogicalPlan visitShowStorageVault(ShowStorageVaultContext ctx) { + return new ShowStorageVaultCommand(); + } + @Override public SetUserPropertiesCommand visitSetUserProperties(SetUserPropertiesContext ctx) { String user = ctx.user != null ? stripQuotes(ctx.user.getText()) : null; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java index 8f474ea395f8890..95f27b90014ddff 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java @@ -218,6 +218,7 @@ public enum PlanType { SHOW_ROLE_COMMAND, SHOW_SMALL_FILES_COMMAND, SHOW_STORAGE_ENGINES_COMMAND, + SHOW_STORAGE_VAULT_COMMAND, SHOW_TABLE_ID_COMMAND, SHOW_TRIGGERS_COMMAND, SHOW_VARIABLES_COMMAND, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowStorageVaultCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowStorageVaultCommand.java new file mode 100644 index 000000000000000..80b2d7302b0b66d --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowStorageVaultCommand.java @@ -0,0 +1,90 @@ +// 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.doris.nereids.trees.plans.commands; + +import org.apache.doris.analysis.UserIdentity; +import org.apache.doris.catalog.Env; +import org.apache.doris.catalog.StorageVault; +import org.apache.doris.cloud.catalog.CloudEnv; +import org.apache.doris.cloud.proto.Cloud; +import org.apache.doris.cloud.rpc.MetaServiceProxy; +import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.Config; +import org.apache.doris.common.FeConstants; +import org.apache.doris.mysql.privilege.Auth; +import org.apache.doris.mysql.privilege.PrivPredicate; +import org.apache.doris.nereids.trees.plans.PlanType; +import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.ShowResultSet; +import org.apache.doris.qe.StmtExecutor; +import org.apache.doris.rpc.RpcException; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Represents the command for SHOW STORAGE VAULT or SHOW STORAGE VAULTS. + */ +public class ShowStorageVaultCommand extends ShowCommand { + + public ShowStorageVaultCommand() { + super(PlanType.SHOW_STORAGE_VAULT_COMMAND); + } + + private void validate() throws AnalysisException { + if (Config.isNotCloudMode()) { + throw new AnalysisException("Storage Vault is only supported for cloud mode"); + } + if (!FeConstants.runningUnitTest) { + // In legacy cloud mode, some s3 back-ended storage does need to use storage vault. + if (!((CloudEnv) Env.getCurrentEnv()).getEnableStorageVault()) { + throw new AnalysisException("Your cloud instance doesn't support storage vault"); + } + } + } + + @Override + public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exception { + validate(); + // [vault name, vault id, vault properties, isDefault] + List> rows; + try { + Cloud.GetObjStoreInfoResponse resp = MetaServiceProxy.getInstance() + .getObjStoreInfo(Cloud.GetObjStoreInfoRequest.newBuilder().build()); + Auth auth = Env.getCurrentEnv().getAuth(); + UserIdentity user = ctx.getCurrentUserIdentity(); + rows = resp.getStorageVaultList().stream() + .filter(storageVault -> auth.checkStorageVaultPriv(user, storageVault.getName(), + PrivPredicate.USAGE)) + .map(StorageVault::convertToShowStorageVaultProperties) + .collect(Collectors.toList()); + if (resp.hasDefaultStorageVaultId()) { + StorageVault.setDefaultVaultToShowVaultResult(rows, resp.getDefaultStorageVaultId()); + } + } catch (RpcException e) { + throw new AnalysisException(e.getMessage()); + } + return new ShowResultSet(StorageVault.STORAGE_VAULT_META_DATA, rows); + } + + @Override + public R accept(PlanVisitor visitor, C context) { + return visitor.visitShowStorageVaultCommand(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java index c00c0ef90ca0186..c3b49a75162bf21 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java @@ -99,6 +99,7 @@ import org.apache.doris.nereids.trees.plans.commands.ShowSmallFilesCommand; import org.apache.doris.nereids.trees.plans.commands.ShowSqlBlockRuleCommand; import org.apache.doris.nereids.trees.plans.commands.ShowStorageEnginesCommand; +import org.apache.doris.nereids.trees.plans.commands.ShowStorageVaultCommand; import org.apache.doris.nereids.trees.plans.commands.ShowTableIdCommand; import org.apache.doris.nereids.trees.plans.commands.ShowTabletsBelongCommand; import org.apache.doris.nereids.trees.plans.commands.ShowTriggersCommand; @@ -224,6 +225,10 @@ default R visitResumeMTMVCommand(ResumeMTMVCommand resumeMTMVCommand, C context) return visitCommand(resumeMTMVCommand, context); } + default R visitShowStorageVaultCommand(ShowStorageVaultCommand showStorageVaultCommand, C context) { + return visitCommand(showStorageVaultCommand, context); + } + default R visitShowCreateMTMVCommand(ShowCreateMTMVCommand showCreateMTMVCommand, C context) { return visitCommand(showCreateMTMVCommand, context); } diff --git a/regression-test/suites/nereids_p0/show/test_show_storage_vault_command.groovy b/regression-test/suites/nereids_p0/show/test_show_storage_vault_command.groovy new file mode 100644 index 000000000000000..4a41c8ef34de0b0 --- /dev/null +++ b/regression-test/suites/nereids_p0/show/test_show_storage_vault_command.groovy @@ -0,0 +1,32 @@ +// 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. + +suite("test_show_storage_vault_command", "query,storage_vault,cloud") { + try { + // Execute the SHOW STORAGE VAULT command and verify the output + checkNereidsExecute("SHOW STORAGE VAULT") + String tmp = sql """SHOW STORAGE VAULT""" + log.info("Result of Show Vault is ", tmp) + + // Execute the SHOW STORAGE VAULTS command and verify the output + checkNereidsExecute("SHOW STORAGE VAULTS") + } catch (Exception e) { + // Log any exceptions that occur during testing + log.error("Failed to execute SHOW STORAGE VAULT command", e) + throw e + } +}