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 3595fd35a5750e..948b0d5599f86d 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 @@ -196,6 +196,7 @@ supportedDropStatement ; supportedShowStatement + : SHOW (GLOBAL | SESSION | LOCAL)? VARIABLES wildWhere? #showVariables | SHOW AUTHORS #showAuthors | SHOW LAST INSERT #showLastInsert @@ -220,6 +221,8 @@ supportedShowStatement | SHOW FRONTENDS name=identifier? #showFrontends | SHOW TABLE tableId=INTEGER_VALUE #showTableId | SHOW WHITELIST #showWhitelist + | SHOW TABLETS BELONG + tabletIds+=INTEGER_VALUE (COMMA tabletIds+=INTEGER_VALUE)* #showTabletsBelong ; unsupportedOtherStatement @@ -296,8 +299,6 @@ unsupportedShowStatement | SHOW TEMPORARY? PARTITIONS FROM tableName=multipartIdentifier wildWhere? sortClause? limitClause? #showPartitions | SHOW TABLET tabletId=INTEGER_VALUE #showTabletId - | SHOW TABLETS BELONG - tabletIds+=INTEGER_VALUE (COMMA tabletIds+=INTEGER_VALUE)* #showTabletBelong | SHOW TABLETS FROM tableName=multipartIdentifier partitionSpec? wildWhere? sortClause? limitClause? #showTabletsFromTable | SHOW PROPERTY (FOR user=identifierOrText)? wildWhere? #showUserProperties 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 257cf5d3309499..6b5e0b129c07e8 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 @@ -220,6 +220,7 @@ import org.apache.doris.nereids.DorisParser.ShowSqlBlockRuleContext; import org.apache.doris.nereids.DorisParser.ShowStorageEnginesContext; import org.apache.doris.nereids.DorisParser.ShowTableIdContext; +import org.apache.doris.nereids.DorisParser.ShowTabletsBelongContext; import org.apache.doris.nereids.DorisParser.ShowVariablesContext; import org.apache.doris.nereids.DorisParser.ShowViewContext; import org.apache.doris.nereids.DorisParser.ShowWhitelistContext; @@ -474,6 +475,7 @@ 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.ShowTableIdCommand; +import org.apache.doris.nereids.trees.plans.commands.ShowTabletsBelongCommand; import org.apache.doris.nereids.trees.plans.commands.ShowVariablesCommand; import org.apache.doris.nereids.trees.plans.commands.ShowViewCommand; import org.apache.doris.nereids.trees.plans.commands.ShowWhiteListCommand; @@ -4259,4 +4261,13 @@ public LogicalPlan visitShowTableId(ShowTableIdContext ctx) { public LogicalPlan visitShowPrivileges(ShowPrivilegesContext ctx) { return new ShowPrivilegesCommand(); } + + @Override + public LogicalPlan visitShowTabletsBelong(ShowTabletsBelongContext ctx) { + List tabletIdLists = new ArrayList<>(); + ctx.tabletIds.stream().forEach(tabletToken -> { + tabletIdLists.add(Long.parseLong(tabletToken.getText())); + }); + return new ShowTabletsBelongCommand(tabletIdLists); + } } 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 de80cffa1f3068..06a32bb31020c7 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 @@ -198,6 +198,7 @@ public enum PlanType { SHOW_AUTHORS_COMMAND, SHOW_VIEW_COMMAND, SHOW_WHITE_LIST_COMMAND, + SHOW_TABLETS_BELONG_COMMAND, RECOVER_DATABASE_COMMAND, RECOVER_TABLE_COMMAND, RECOVER_PARTITION_COMMAND, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletsBelongCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletsBelongCommand.java new file mode 100644 index 00000000000000..2243e60868f988 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletsBelongCommand.java @@ -0,0 +1,154 @@ +// 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.RedirectStatus; +import org.apache.doris.catalog.Column; +import org.apache.doris.catalog.Database; +import org.apache.doris.catalog.Env; +import org.apache.doris.catalog.OlapTable; +import org.apache.doris.catalog.ScalarType; +import org.apache.doris.catalog.Table; +import org.apache.doris.catalog.TabletInvertedIndex; +import org.apache.doris.catalog.TabletMeta; +import org.apache.doris.common.ErrorCode; +import org.apache.doris.common.ErrorReport; +import org.apache.doris.common.Pair; +import org.apache.doris.common.util.DebugUtil; +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.ShowResultSetMetaData; +import org.apache.doris.qe.StmtExecutor; + +import com.google.common.collect.ImmutableList; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * show tablet belong command + */ +public class ShowTabletsBelongCommand extends ShowCommand { + private static final ImmutableList TITLE_NAMES = new ImmutableList.Builder() + .add("DbName") + .add("TableName") + .add("TableSize") + .add("PartitionNum") + .add("BucketNum") + .add("ReplicaCount") + .add("TabletIds") + .build(); + private final List tabletIds; + + /** + * constructor + */ + public ShowTabletsBelongCommand(List tabletIds) { + super(PlanType.SHOW_TABLETS_BELONG_COMMAND); + this.tabletIds = tabletIds; + } + + public ShowResultSetMetaData getMetaData() { + ShowResultSetMetaData.Builder builder = ShowResultSetMetaData.builder(); + for (String title : TITLE_NAMES) { + builder.addColumn(new Column(title, ScalarType.createVarchar(128))); + } + return builder.build(); + } + + @Override + public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exception { + //validation logic + // check auth + if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.ADMIN)) { + ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, + PrivPredicate.ADMIN.getPrivs().toString()); + } + if (tabletIds == null || tabletIds.isEmpty()) { + throw new Exception("Please supply at least one tablet id"); + } + + // main logic. + List> rows = new ArrayList<>(); + Env env = Env.getCurrentEnv(); + TabletInvertedIndex invertedIndex = Env.getCurrentInvertedIndex(); + Map> tableToTabletIdsMap = new HashMap<>(); + for (long tabletId : tabletIds) { + TabletMeta tabletMeta = invertedIndex.getTabletMeta(tabletId); + if (tabletMeta == null) { + continue; + } + Database db = env.getInternalCatalog().getDbNullable(tabletMeta.getDbId()); + if (db == null) { + continue; + } + long tableId = tabletMeta.getTableId(); + Table table = db.getTableNullable(tableId); + if (table == null) { + continue; + } + + if (!tableToTabletIdsMap.containsKey(tableId)) { + tableToTabletIdsMap.put(tableId, new HashSet<>()); + } + tableToTabletIdsMap.get(tableId).add(tabletId); + } + + for (long tableId : tableToTabletIdsMap.keySet()) { + Table table = env.getInternalCatalog().getTableByTableId(tableId); + List line = new ArrayList<>(); + line.add(table.getDatabase().getFullName()); + line.add(table.getName()); + + OlapTable olapTable = (OlapTable) table; + Pair tableSizePair = DebugUtil.getByteUint((long) olapTable.getDataSize()); + String readableSize = DebugUtil.DECIMAL_FORMAT_SCALE_3.format(tableSizePair.first) + " " + + tableSizePair.second; + line.add(readableSize); + line.add(new Long(olapTable.getPartitionNum()).toString()); + int totalBucketNum = 0; + Set partitionNamesSet = table.getPartitionNames(); + for (String partitionName : partitionNamesSet) { + totalBucketNum += table.getPartition(partitionName).getDistributionInfo().getBucketNum(); + } + line.add(new Long(totalBucketNum).toString()); + line.add(new Long(olapTable.getReplicaCount()).toString()); + line.add(tableToTabletIdsMap.get(tableId).toString()); + + rows.add(line); + } + return new ShowResultSet(getMetaData(), rows); + } + + @Override + public R accept(PlanVisitor visitor, C context) { + return visitor.visitShowTabletsBelongCommand(this, context); + } + + @Override + public RedirectStatus toRedirectStatus() { + return RedirectStatus.FORWARD_NO_SYNC; + } +} 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 4af2ec8c328123..5b77c5b5be019e 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 @@ -74,6 +74,7 @@ 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.ShowTableIdCommand; +import org.apache.doris.nereids.trees.plans.commands.ShowTabletsBelongCommand; import org.apache.doris.nereids.trees.plans.commands.ShowVariablesCommand; import org.apache.doris.nereids.trees.plans.commands.ShowViewCommand; import org.apache.doris.nereids.trees.plans.commands.ShowWhiteListCommand; @@ -363,4 +364,8 @@ default R visitShowTableIdCommand(ShowTableIdCommand showTableIdCommand, C conte default R visitShowPrivilegesCommand(ShowPrivilegesCommand showPrivilegesCommand, C context) { return visitCommand(showPrivilegesCommand, context); } + + default R visitShowTabletsBelongCommand(ShowTabletsBelongCommand showTabletBelongCommand, C context) { + return visitCommand(showTabletBelongCommand, context); + } } diff --git a/regression-test/suites/auth_call/test_show_tablet_auth.groovy b/regression-test/suites/auth_call/test_show_tablet_auth.groovy index 03f8ed58a8ed40..d071dcae074dec 100644 --- a/regression-test/suites/auth_call/test_show_tablet_auth.groovy +++ b/regression-test/suites/auth_call/test_show_tablet_auth.groovy @@ -78,6 +78,9 @@ suite("test_show_tablet_auth","p0,auth_call") { def tablet_res = sql """SHOW TABLET ${res[0][0]}""" assertTrue(tablet_res.size() == 1) + + checkNereidsExecute("SHOW TABLETS BELONG ${res[0][0]}") + checkNereidsExecute("SHOW TABLETS BELONG 100,101") tablet_res = sql """SHOW TABLETS BELONG ${res[0][0]}""" assertTrue(tablet_res.size() == 1)