This is an automated email from the ASF dual-hosted git repository. starocean999 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push: new 65077c90649 [Enhancement] (nereids)implement showClustersCommand in nereids (#49672) 65077c90649 is described below commit 65077c90649f9653ed05dbd86cdea29b71e24f1e Author: Sridhar R Manikarnike <sridhar.n...@gmail.com> AuthorDate: Thu Apr 3 19:29:53 2025 +0530 [Enhancement] (nereids)implement showClustersCommand in nereids (#49672) Issue Number: close #42780 --- .../antlr4/org/apache/doris/nereids/DorisParser.g4 | 4 +- .../doris/nereids/parser/LogicalPlanBuilder.java | 8 ++ .../apache/doris/nereids/trees/plans/PlanType.java | 1 + .../trees/plans/commands/ShowClustersCommand.java | 158 +++++++++++++++++++++ .../trees/plans/visitor/CommandVisitor.java | 5 + .../show/test_show_clusters_command.groovy | 27 ++++ 6 files changed, 201 insertions(+), 2 deletions(-) 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 359e4312147..7c7c5ca674e 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 @@ -330,7 +330,8 @@ supportedShowStatement | SHOW DATABASE databaseId=INTEGER_VALUE #showDatabaseId | SHOW TABLE tableId=INTEGER_VALUE #showTableId | SHOW TRASH (ON backend=STRING_LITERAL)? #showTrash - | SHOW statementScope? STATUS #showStatus + | SHOW (CLUSTERS | (COMPUTE GROUPS)) #showClusters + | SHOW statementScope? STATUS #showStatus | SHOW WHITELIST #showWhitelist | SHOW TABLETS BELONG tabletIds+=INTEGER_VALUE (COMMA tabletIds+=INTEGER_VALUE)* #showTabletsBelong @@ -425,7 +426,6 @@ unsupportedShowStatement | (FROM tableName=multipartIdentifier (ALL VERBOSE?)?))? #showQueryStats | SHOW BUILD INDEX ((FROM | IN) database=multipartIdentifier)? wildWhere? sortClause? limitClause? #showBuildIndex - | SHOW (CLUSTERS | (COMPUTE GROUPS)) #showClusters | SHOW REPLICA STATUS FROM baseTableRef wildWhere? #showReplicaStatus | SHOW COPY ((FROM | IN) database=multipartIdentifier)? whereClause? sortClause? limitClause? #showCopy 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 1177f5f1ed2..f21f70f3026 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 @@ -303,6 +303,7 @@ import org.apache.doris.nereids.DorisParser.ShowBackendsContext; import org.apache.doris.nereids.DorisParser.ShowBackupContext; import org.apache.doris.nereids.DorisParser.ShowBrokerContext; import org.apache.doris.nereids.DorisParser.ShowCharsetContext; +import org.apache.doris.nereids.DorisParser.ShowClustersContext; import org.apache.doris.nereids.DorisParser.ShowCollationContext; import org.apache.doris.nereids.DorisParser.ShowColumnHistogramStatsContext; import org.apache.doris.nereids.DorisParser.ShowConfigContext; @@ -622,6 +623,7 @@ import org.apache.doris.nereids.trees.plans.commands.ShowBackupCommand; import org.apache.doris.nereids.trees.plans.commands.ShowBrokerCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCatalogCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCharsetCommand; +import org.apache.doris.nereids.trees.plans.commands.ShowClustersCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCollationCommand; import org.apache.doris.nereids.trees.plans.commands.ShowColumnHistogramStatsCommand; import org.apache.doris.nereids.trees.plans.commands.ShowConfigCommand; @@ -6397,6 +6399,12 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { return new DropExpiredStatsCommand(); } + @Override + public LogicalPlan visitShowClusters(ShowClustersContext ctx) { + boolean showComputeGroups = ctx.COMPUTE() != null; + return new ShowClustersCommand(showComputeGroups); + } + @Override public LogicalPlan visitAlterTableStats(DorisParser.AlterTableStatsContext ctx) { TableNameInfo tableNameInfo = new TableNameInfo(visitMultipartIdentifier(ctx.name)); 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 c850dfa26ef..1eebfcd236e 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 @@ -228,6 +228,7 @@ public enum PlanType { SHOW_BROKER_COMMAND, SHOW_CATALOG_COMMAND, SHOW_CHARSET_COMMAND, + SHOW_CLUSTERS_COMMAND, SHOW_COLLATION_COMMAND, SHOW_COLUMN_HISTOGRAM, SHOW_CONFIG_COMMAND, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowClustersCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowClustersCommand.java new file mode 100644 index 00000000000..27b1d20f1d2 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowClustersCommand.java @@ -0,0 +1,158 @@ +// 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.CompoundPredicate.Operator; +import org.apache.doris.analysis.ResourceTypeEnum; +import org.apache.doris.catalog.Column; +import org.apache.doris.catalog.Env; +import org.apache.doris.catalog.ScalarType; +import org.apache.doris.cloud.qe.ComputeGroupException; +import org.apache.doris.cloud.system.CloudSystemInfoService; +import org.apache.doris.cluster.ClusterNamespace; +import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.Config; +import org.apache.doris.common.ErrorCode; +import org.apache.doris.common.ErrorReport; +import org.apache.doris.mysql.privilege.Auth; +import org.apache.doris.mysql.privilege.PrivBitSet; +import org.apache.doris.mysql.privilege.PrivPredicate; +import org.apache.doris.mysql.privilege.Privilege; +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.ShowResultSetMetaData; +import org.apache.doris.qe.StmtExecutor; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * Represents the command for SHOW CLUSTERS. + */ +public class ShowClustersCommand extends ShowCommand { + public static final ImmutableList<String> CLUSTER_TITLE_NAMES = new ImmutableList.Builder<String>() + .add("cluster").add("is_current").add("users").add("backend_num").build(); + + public static final ImmutableList<String> COMPUTE_GROUP_TITLE_NAMES = new ImmutableList.Builder<String>() + .add("Name").add("IsCurrent").add("Users").add("BackendNum").build(); + + private static final Logger LOG = LogManager.getLogger(ShowClustersCommand.class); + private final boolean isComputeGroup; + + public ShowClustersCommand(boolean isComputeGroup) { + super(PlanType.SHOW_CLUSTERS_COMMAND); + this.isComputeGroup = isComputeGroup; + } + + private void validate(ConnectContext ctx) throws AnalysisException { + if (Config.isNotCloudMode()) { + // just user admin + if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get().getCurrentUserIdentity(), + PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV, Privilege.NODE_PRIV), Operator.OR))) { + ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN"); + } + } + } + + @Override + public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exception { + validate(ctx); + final List<List<String>> rows = Lists.newArrayList(); + if (!Config.isCloudMode()) { + ErrorReport.reportAnalysisException(ErrorCode.ERR_NOT_CLOUD_MODE); + return new ShowResultSet(getMetaData(), rows); + } + + List<String> clusterNames = null; + clusterNames = ((CloudSystemInfoService) Env.getCurrentSystemInfo()).getCloudClusterNames(); + + final Set<String> clusterNameSet = Sets.newTreeSet(); + clusterNameSet.addAll(clusterNames); + + for (String clusterName : clusterNameSet) { + ArrayList<String> row = Lists.newArrayList(clusterName); + // current_used, users + if (!Env.getCurrentEnv().getAccessManager() + .checkCloudPriv(ConnectContext.get().getCurrentUserIdentity(), clusterName, + PrivPredicate.USAGE, ResourceTypeEnum.CLUSTER)) { + continue; + } + String clusterNameFromCtx = ""; + try { + clusterNameFromCtx = ctx.getCloudCluster(); + } catch (ComputeGroupException e) { + LOG.warn("failed to get cluster name", e); + } + row.add(clusterName.equals(clusterNameFromCtx) ? "TRUE" : "FALSE"); + List<String> users = Env.getCurrentEnv().getAuth().getCloudClusterUsers(clusterName); + // non-root do not display root information + if (!Auth.ROOT_USER.equals(ctx.getQualifiedUser())) { + users.remove(Auth.ROOT_USER); + } + // common user, not admin + if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ctx.getCurrentUserIdentity(), + PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV), Operator.OR))) { + users.removeIf(user -> !user.equals(ClusterNamespace.getNameFromFullName(ctx.getQualifiedUser()))); + } + + String result = Joiner.on(", ").join(users); + row.add(result); + int backendNum = ((CloudSystemInfoService) Env.getCurrentEnv().getCurrentSystemInfo()) + .getBackendsByClusterName(clusterName).size(); + row.add(String.valueOf(backendNum)); + rows.add(row); + } + + return new ShowResultSet(getMetaData(), rows); + } + + @Override + public <R, C> R accept(PlanVisitor<R, C> visitor, C context) { + return visitor.visitShowClustersCommand(this, context); + } + + /** + * getMetaData() + */ + public ShowResultSetMetaData getMetaData() { + ShowResultSetMetaData.Builder builder = ShowResultSetMetaData.builder(); + + ImmutableList<String> titleNames = null; + if (isComputeGroup) { + titleNames = COMPUTE_GROUP_TITLE_NAMES; + } else { + titleNames = CLUSTER_TITLE_NAMES; + } + + for (String title : titleNames) { + builder.addColumn(new Column(title, ScalarType.createVarchar(128))); + } + return builder.build(); + } +} + 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 c7c038a4f8c..d39297fdca2 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 @@ -114,6 +114,7 @@ import org.apache.doris.nereids.trees.plans.commands.ShowBackupCommand; import org.apache.doris.nereids.trees.plans.commands.ShowBrokerCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCatalogCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCharsetCommand; +import org.apache.doris.nereids.trees.plans.commands.ShowClustersCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCollationCommand; import org.apache.doris.nereids.trees.plans.commands.ShowColumnHistogramStatsCommand; import org.apache.doris.nereids.trees.plans.commands.ShowConfigCommand; @@ -826,6 +827,10 @@ public interface CommandVisitor<R, C> { return visitCommand(showConvertLSCCommand, context); } + default R visitShowClustersCommand(ShowClustersCommand showClustersCommand, C context) { + return visitCommand(showClustersCommand, context); + } + default R visitSwitchCommand(SwitchCommand switchCommand, C context) { return visitCommand(switchCommand, context); } diff --git a/regression-test/suites/nereids_p0/show/test_show_clusters_command.groovy b/regression-test/suites/nereids_p0/show/test_show_clusters_command.groovy new file mode 100644 index 00000000000..a47e6f1b2b0 --- /dev/null +++ b/regression-test/suites/nereids_p0/show/test_show_clusters_command.groovy @@ -0,0 +1,27 @@ +// 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_clusters_command", "nereids_p0") { + if (!cloudMode) + return; + + // SHOW CLUSTERS + checkNereidsExecute """SHOW CLUSTERS""" + + // SHOW COMPUTE GROUPS + checkNereidsExecute """SHOW COMPUTE GROUPS""" +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org