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 6cd4010bdcb7688..ec6b5d5cc1cee6d 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 @@ -56,6 +56,7 @@ statementBase | supportedSetStatement #supportedSetStatementAlias | supportedUnsetStatement #supportedUnsetStatementAlias | unsupportedStatement #unsupported + | supportedAdminStatement #supportedAdminStatementAlias ; unsupportedStatement @@ -475,11 +476,14 @@ unsupportedAdminStatement | ADMIN SET TABLE name=multipartIdentifier PARTITION VERSION properties=propertyClause? #adminSetPartitionVersion | ADMIN DIAGNOSE TABLET tabletId=INTEGER_VALUE #adminDiagnoseTablet - | ADMIN SHOW TABLET STORAGE FORMAT VERBOSE? #adminShowTabletStorageFormat | ADMIN COPY TABLET tabletId=INTEGER_VALUE properties=propertyClause? #adminCopyTablet | ADMIN SET TABLE name=multipartIdentifier STATUS properties=propertyClause? #adminSetTableStatus ; +supportedAdminStatement + : ADMIN SHOW TABLET STORAGE FORMAT VERBOSE? #adminShowTabletStorageFormat + ; + baseTableRef : multipartIdentifier optScanParams? tableSnapshot? specifiedPartition? tabletList? tableAlias sample? relationHint? 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 1af48c8a5971c38..5760e5ea1f4ced7 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 @@ -46,6 +46,7 @@ import org.apache.doris.mtmv.MTMVRefreshTriggerInfo; import org.apache.doris.nereids.DorisParser; import org.apache.doris.nereids.DorisParser.AddConstraintContext; +import org.apache.doris.nereids.DorisParser.AdminShowTabletStorageFormatContext; import org.apache.doris.nereids.DorisParser.AggClauseContext; import org.apache.doris.nereids.DorisParser.AggStateDataTypeContext; import org.apache.doris.nereids.DorisParser.AliasQueryContext; @@ -423,6 +424,7 @@ import org.apache.doris.nereids.trees.plans.commands.ShowCreateMTMVCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCreateProcedureCommand; import org.apache.doris.nereids.trees.plans.commands.ShowProcedureStatusCommand; +import org.apache.doris.nereids.trees.plans.commands.ShowTabletStorageFormatCommand; import org.apache.doris.nereids.trees.plans.commands.UnsetDefaultStorageVaultCommand; import org.apache.doris.nereids.trees.plans.commands.UnsetVariableCommand; import org.apache.doris.nereids.trees.plans.commands.UnsupportedCommand; @@ -3999,4 +4001,10 @@ public SetUserPropertiesCommand visitSetUserProperties(SetUserPropertiesContext public SetDefaultStorageVaultCommand visitSetDefaultStorageVault(SetDefaultStorageVaultContext ctx) { return new SetDefaultStorageVaultCommand(stripQuotes(ctx.identifier().getText())); } + + @Override + public LogicalPlan visitAdminShowTabletStorageFormat(AdminShowTabletStorageFormatContext ctx) { + boolean verbose = ctx.VERBOSE() != null; + return new ShowTabletStorageFormatCommand(verbose); + } } 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 d7a219cc7e45193..429cc9e54a5c573 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 @@ -176,5 +176,6 @@ public enum PlanType { PREPARED_COMMAND, EXECUTE_COMMAND, SHOW_CONFIG_COMMAND, - REPLAY_COMMAND + REPLAY_COMMAND, + ADMIN_SHOW_TABLET_STORAGE_FORMAT_COMMAND } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletStorageFormatCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletStorageFormatCommand.java new file mode 100644 index 000000000000000..974c46747a12466 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletStorageFormatCommand.java @@ -0,0 +1,130 @@ +// 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.StmtType; +import org.apache.doris.catalog.Column; +import org.apache.doris.catalog.Env; +import org.apache.doris.catalog.ScalarType; +import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.ErrorCode; +import org.apache.doris.common.ErrorReport; +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 org.apache.doris.system.Backend; +import org.apache.doris.task.AgentClient; +import org.apache.doris.thrift.TCheckStorageFormatResult; + +import com.google.common.collect.Lists; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; + +/** + * admin show tablet storage format command + */ +public class ShowTabletStorageFormatCommand extends Command implements NoForward { + public static final Logger LOG = LogManager.getLogger(ShowTabletStorageFormatCommand.class); + private final boolean verbose; + + /** + * constructor + */ + public ShowTabletStorageFormatCommand(boolean verbose) { + super(PlanType.ADMIN_SHOW_TABLET_STORAGE_FORMAT_COMMAND); + this.verbose = verbose; + } + + /** + * get Meta for show + */ + public ShowResultSetMetaData getMetaData() { + ShowResultSetMetaData.Builder builder = ShowResultSetMetaData.builder(); + if (verbose) { + builder.addColumn(new Column("BackendId", ScalarType.createVarchar(30))) + .addColumn(new Column("TabletId", ScalarType.createVarchar(30))) + .addColumn(new Column("StorageFormat", ScalarType.createVarchar(30))); + } else { + builder.addColumn(new Column("BackendId", ScalarType.createVarchar(30))) + .addColumn(new Column("V1Count", ScalarType.createVarchar(30))) + .addColumn(new Column("V2Count", ScalarType.createVarchar(30))); + } + return builder.build(); + } + + @Override + public void run(ConnectContext ctx, StmtExecutor executor) throws Exception { + if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.ADMIN)) { + ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, + PrivPredicate.ADMIN.getPrivs().toString()); + } + + List> resultRowSet = Lists.newArrayList(); + for (Backend be : Env.getCurrentSystemInfo().getAllBackendsByAllCluster().values()) { + if (be.isQueryAvailable() && be.isLoadAvailable()) { + AgentClient client = new AgentClient(be.getHost(), be.getBePort()); + TCheckStorageFormatResult result = client.checkStorageFormat(); + if (result == null) { + throw new AnalysisException("get tablet data from backend: " + be.getId() + "error."); + } + if (verbose) { + for (long tabletId : result.getV1Tablets()) { + List row = new ArrayList<>(); + row.add(String.valueOf(be.getId())); + row.add(String.valueOf(tabletId)); + row.add("V1"); + resultRowSet.add(row); + } + for (long tabletId : result.getV2Tablets()) { + List row = new ArrayList<>(); + row.add(String.valueOf(be.getId())); + row.add(String.valueOf(tabletId)); + row.add("V2"); + resultRowSet.add(row); + } + } else { + List row = new ArrayList<>(); + row.add(String.valueOf(be.getId())); + row.add(String.valueOf(result.getV1Tablets().size())); + row.add(String.valueOf(result.getV2Tablets().size())); + resultRowSet.add(row); + } + } + } + ShowResultSetMetaData showMetaData = getMetaData(); + ShowResultSet resultSet = new ShowResultSet(showMetaData, resultRowSet); + executor.sendResultSet(resultSet); + } + + @Override + public R accept(PlanVisitor visitor, C context) { + return visitor.visitShowTabletStorageFormatCommand(this, context); + } + + @Override + public StmtType stmtType() { + return StmtType.SHOW; + } +} 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 814596bca31a91e..9343468c776a4a2 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 @@ -52,6 +52,7 @@ import org.apache.doris.nereids.trees.plans.commands.ShowCreateMTMVCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCreateProcedureCommand; import org.apache.doris.nereids.trees.plans.commands.ShowProcedureStatusCommand; +import org.apache.doris.nereids.trees.plans.commands.ShowTabletStorageFormatCommand; import org.apache.doris.nereids.trees.plans.commands.UnsetDefaultStorageVaultCommand; import org.apache.doris.nereids.trees.plans.commands.UnsetVariableCommand; import org.apache.doris.nereids.trees.plans.commands.UnsupportedCommand; @@ -232,4 +233,9 @@ default R visitSetUserPropertiesCommand(SetUserPropertiesCommand setUserProperti default R visitSetDefaultStorageVault(SetDefaultStorageVaultCommand setDefaultStorageVaultCommand, C context) { return visitCommand(setDefaultStorageVaultCommand, context); } + + default R visitShowTabletStorageFormatCommand(ShowTabletStorageFormatCommand showTabletStorageFormatCommand, + C context) { + return visitCommand(showTabletStorageFormatCommand, context); + } }