From eef5f6ecd8f0034e3d84c2a3839e39fd2baddc87 Mon Sep 17 00:00:00 2001 From: yx-keith Date: Thu, 6 Mar 2025 17:22:11 +0800 Subject: [PATCH] implement dropCached/Expired/StatsCommand in nereids --- .../org/apache/doris/nereids/DorisParser.g4 | 13 +- .../nereids/parser/LogicalPlanBuilder.java | 33 ++++ .../doris/nereids/trees/plans/PlanType.java | 7 +- .../commands/DropCachedStatsCommand.java | 99 +++++++++++ .../commands/DropExpiredStatsCommand.java | 50 ++++++ .../plans/commands/DropStatsCommand.java | 165 ++++++++++++++++++ .../trees/plans/visitor/CommandVisitor.java | 15 ++ .../doris/statistics/AnalysisManager.java | 32 ++++ .../statistics/StatisticsRepository.java | 2 +- 9 files changed, 404 insertions(+), 12 deletions(-) create mode 100644 fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropCachedStatsCommand.java create mode 100644 fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropExpiredStatsCommand.java create mode 100644 fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropStatsCommand.java 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 9a819baaf0a84d..e65552b28e2f6a 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 @@ -737,19 +737,14 @@ supportedStatsStatement (WITH analyzeProperties)* propertyClause? #analyzeDatabase | ANALYZE TABLE name=multipartIdentifier partitionSpec? columns=identifierList? (WITH analyzeProperties)* propertyClause? #analyzeTable - ; - -unsupportedStatsStatement - : ALTER TABLE name=multipartIdentifier SET STATS - LEFT_PAREN propertyItemList RIGHT_PAREN partitionSpec? #alterTableStats - | ALTER TABLE name=multipartIdentifier (INDEX indexName=identifier)? - MODIFY COLUMN columnName=identifier - SET STATS LEFT_PAREN propertyItemList RIGHT_PAREN partitionSpec? #alterColumnStats | DROP STATS tableName=multipartIdentifier columns=identifierList? partitionSpec? #dropStats | DROP CACHED STATS tableName=multipartIdentifier #dropCachedStats | DROP EXPIRED STATS #dropExpiredStats - | DROP ANALYZE JOB INTEGER_VALUE #dropAanalyzeJob + ; + +unsupportedStatsStatement + : DROP ANALYZE JOB INTEGER_VALUE #dropAanalyzeJob | KILL ANALYZE jobId=INTEGER_VALUE #killAnalyzeJob | SHOW TABLE STATS tableName=multipartIdentifier partitionSpec? columnList=identifierList? #showTableStats 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 5129c0991a51c5..0afd320eff3e43 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 @@ -26,6 +26,7 @@ import org.apache.doris.analysis.DbName; import org.apache.doris.analysis.EncryptKeyName; import org.apache.doris.analysis.FunctionName; +import org.apache.doris.analysis.PartitionNames; import org.apache.doris.analysis.PassVar; import org.apache.doris.analysis.SetType; import org.apache.doris.analysis.StorageBackend; @@ -560,12 +561,14 @@ import org.apache.doris.nereids.trees.plans.commands.DeleteFromCommand; import org.apache.doris.nereids.trees.plans.commands.DeleteFromUsingCommand; import org.apache.doris.nereids.trees.plans.commands.DescribeCommand; +import org.apache.doris.nereids.trees.plans.commands.DropCachedStatsCommand; import org.apache.doris.nereids.trees.plans.commands.DropCatalogCommand; import org.apache.doris.nereids.trees.plans.commands.DropCatalogRecycleBinCommand; import org.apache.doris.nereids.trees.plans.commands.DropCatalogRecycleBinCommand.IdType; import org.apache.doris.nereids.trees.plans.commands.DropConstraintCommand; import org.apache.doris.nereids.trees.plans.commands.DropDatabaseCommand; import org.apache.doris.nereids.trees.plans.commands.DropEncryptkeyCommand; +import org.apache.doris.nereids.trees.plans.commands.DropExpiredStatsCommand; import org.apache.doris.nereids.trees.plans.commands.DropFileCommand; import org.apache.doris.nereids.trees.plans.commands.DropFunctionCommand; import org.apache.doris.nereids.trees.plans.commands.DropJobCommand; @@ -574,6 +577,7 @@ import org.apache.doris.nereids.trees.plans.commands.DropRepositoryCommand; import org.apache.doris.nereids.trees.plans.commands.DropRoleCommand; import org.apache.doris.nereids.trees.plans.commands.DropSqlBlockRuleCommand; +import org.apache.doris.nereids.trees.plans.commands.DropStatsCommand; import org.apache.doris.nereids.trees.plans.commands.DropStoragePolicyCommand; import org.apache.doris.nereids.trees.plans.commands.DropTableCommand; import org.apache.doris.nereids.trees.plans.commands.DropUserCommand; @@ -840,6 +844,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -6092,5 +6097,33 @@ public LogicalPlan visitDescribeTableValuedFunction(DorisParser.DescribeTableVal } return new DescribeCommand(tableValuedFunctionRef); } + + @Override + public LogicalPlan visitDropStats(DorisParser.DropStatsContext ctx) { + TableNameInfo tableNameInfo = new TableNameInfo(visitMultipartIdentifier(ctx.tableName)); + + Set columnNames = new HashSet<>(); + if (ctx.identifierList() != null) { + columnNames.addAll(visitIdentifierList(ctx.identifierList())); + } + + PartitionNames partitionNames = null; + if (ctx.partitionSpec() != null) { + Pair> partitionSpec = visitPartitionSpec(ctx.partitionSpec()); + partitionNames = new PartitionNames(partitionSpec.first, partitionSpec.second); + } + return new DropStatsCommand(tableNameInfo, columnNames, partitionNames); + } + + @Override + public LogicalPlan visitDropCachedStats(DorisParser.DropCachedStatsContext ctx) { + TableNameInfo tableNameInfo = new TableNameInfo(visitMultipartIdentifier(ctx.tableName)); + return new DropCachedStatsCommand(tableNameInfo); + } + + @Override + public LogicalPlan visitDropExpiredStats(DorisParser.DropExpiredStatsContext ctx) { + return new DropExpiredStatsCommand(); + } } 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 f6a3997dd0fa15..cd2950cc72f470 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 @@ -310,5 +310,8 @@ public enum PlanType { ALTER_SYSTEM_SET_LOAD_ERRORS_HU, ALTER_SYSTEM_MODIFY_BACKEND, ALTER_SYSTEM_MODIFY_FRONTEND_OR_BACKEND_HOSTNAME, - ALTER_SYSTEM_RENAME_COMPUTE_GROUP -} + ALTER_SYSTEM_RENAME_COMPUTE_GROUP, + DROP_STATS_COMMAND, + DROP_CACHED_STATS_COMMAND, + DROP_EXPIRED_STATS_COMMAND + } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropCachedStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropCachedStatsCommand.java new file mode 100644 index 00000000000000..be90f1a55bd61d --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropCachedStatsCommand.java @@ -0,0 +1,99 @@ +// 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.DatabaseIf; +import org.apache.doris.catalog.Env; +import org.apache.doris.catalog.TableIf; +import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.ErrorCode; +import org.apache.doris.common.ErrorReport; +import org.apache.doris.common.UserException; +import org.apache.doris.datasource.CatalogIf; +import org.apache.doris.mysql.privilege.PrivPredicate; +import org.apache.doris.nereids.trees.plans.PlanType; +import org.apache.doris.nereids.trees.plans.commands.info.TableNameInfo; +import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.StmtExecutor; + +/** + * Manually drop cached statistics for table and its mv. + *

+ * syntax: + * DROP CACHED STATS TableName; + */ +public class DropCachedStatsCommand extends DropCommand { + private final TableNameInfo tableNameInfo; + private long catalogId; + private long dbId; + private long tblId; + + public DropCachedStatsCommand(TableNameInfo tableNameInfo) { + super(PlanType.DROP_CACHED_STATS_COMMAND); + this.tableNameInfo = tableNameInfo; + } + + @Override + public void doRun(ConnectContext ctx, StmtExecutor executor) throws Exception { + validate(ctx); + ctx.getEnv().getAnalysisManager().dropCachedStats(catalogId, dbId, tblId); + } + + private void validate(ConnectContext ctx) throws UserException { + if (tableNameInfo == null) { + throw new UserException("Should specify a valid table name."); + } + tableNameInfo.analyze(ctx); + String catalogName = tableNameInfo.getCtl(); + String dbName = tableNameInfo.getDb(); + String tblName = tableNameInfo.getTbl(); + CatalogIf catalog = ctx.getEnv().getCatalogMgr().getCatalogOrAnalysisException(tableNameInfo.getCtl()); + DatabaseIf db = catalog.getDbOrAnalysisException(dbName); + TableIf table = db.getTableOrAnalysisException(tblName); + tblId = table.getId(); + dbId = db.getId(); + catalogId = catalog.getId(); + // check permission + checkAnalyzePriv(catalogName, db.getFullName(), table.getName()); + } + + private void checkAnalyzePriv(String catalogName, String dbName, String tblName) throws AnalysisException { + if (!Env.getCurrentEnv().getAccessManager() + .checkTblPriv(ConnectContext.get(), catalogName, dbName, tblName, + PrivPredicate.DROP)) { + ErrorReport.reportAnalysisException( + ErrorCode.ERR_TABLEACCESS_DENIED_ERROR, + "DROP", + ConnectContext.get().getQualifiedUser(), + ConnectContext.get().getRemoteIP(), + dbName + "." + tblName); + } + } + + @Override + public R accept(PlanVisitor visitor, C context) { + return visitor.visitDropCachedStatsCommand(this, context); + } + + @Override + public StmtType stmtType() { + return StmtType.DROP; + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropExpiredStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropExpiredStatsCommand.java new file mode 100644 index 00000000000000..6eeb39ae7eec2f --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropExpiredStatsCommand.java @@ -0,0 +1,50 @@ +// 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.nereids.trees.plans.PlanType; +import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.StmtExecutor; + +/** + * DropExpiredStatsCommand + */ + +public class DropExpiredStatsCommand extends DropCommand { + + public DropExpiredStatsCommand() { + super(PlanType.DROP_EXPIRED_STATS_COMMAND); + } + + @Override + public void doRun(ConnectContext ctx, StmtExecutor executor) throws Exception { + ctx.getEnv().getAnalysisManager().dropExpiredStats(); + } + + @Override + public R accept(PlanVisitor visitor, C context) { + return visitor.visitDropExpiredStatsCommand(this, context); + } + + @Override + public StmtType stmtType() { + return StmtType.DROP; + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropStatsCommand.java new file mode 100644 index 00000000000000..c93322a340a903 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropStatsCommand.java @@ -0,0 +1,165 @@ +// 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.PartitionNames; +import org.apache.doris.analysis.StmtType; +import org.apache.doris.catalog.DatabaseIf; +import org.apache.doris.catalog.Env; +import org.apache.doris.catalog.TableIf; +import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.ErrorCode; +import org.apache.doris.common.ErrorReport; +import org.apache.doris.common.UserException; +import org.apache.doris.datasource.CatalogIf; +import org.apache.doris.mysql.privilege.PrivPredicate; +import org.apache.doris.nereids.trees.plans.PlanType; +import org.apache.doris.nereids.trees.plans.commands.info.TableNameInfo; +import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.StmtExecutor; + +import java.util.Set; + +/** + * Manually drop statistics for tables or partitions. + * Table or partition can be specified, if neither is specified, + * all statistics under the current database will be deleted. + *

+ * syntax: + * DROP [EXPIRED] STATS [TableName [PARTITIONS(partitionNames)]]; + */ +public class DropStatsCommand extends DropCommand { + + public static final int MAX_IN_ELEMENT_TO_DELETE = 100; + private final TableNameInfo tableNameInfo; + private final Set columnNames; + private final PartitionNames opPartitionNames; + private boolean isAllColumns; + private long catalogId; + private long dbId; + private long tblId; + + public DropStatsCommand(TableNameInfo tableNameInfo, + Set columnNames, + PartitionNames opPartitionNames) { + super(PlanType.DROP_STATS_COMMAND); + this.tableNameInfo = tableNameInfo; + this.columnNames = columnNames; + this.opPartitionNames = opPartitionNames; + } + + public long getCatalogId() { + return catalogId; + } + + public long getDbId() { + return dbId; + } + + public long getTblId() { + return tblId; + } + + public PartitionNames getOpPartitionNames() { + return opPartitionNames; + } + + public Set getColumnNames() { + return columnNames; + } + + public boolean isAllColumns() { + return isAllColumns; + } + + @Override + public void doRun(ConnectContext ctx, StmtExecutor executor) throws Exception { + validate(ctx); + ctx.getEnv().getAnalysisManager().dropStats(this); + } + + private void validate(ConnectContext ctx) throws UserException { + if (!ConnectContext.get().getSessionVariable().enableStats) { + throw new UserException("Analyze function is forbidden, you should add `enable_stats=true`" + + "in your FE conf file"); + } + + if (tableNameInfo == null) { + throw new UserException("Should specify a valid table name."); + } + tableNameInfo.analyze(ctx); + String catalogName = tableNameInfo.getCtl(); + String dbName = tableNameInfo.getDb(); + String tblName = tableNameInfo.getTbl(); + CatalogIf catalog = ctx.getEnv().getCatalogMgr().getCatalogOrAnalysisException(tableNameInfo.getCtl()); + DatabaseIf db = catalog.getDbOrAnalysisException(dbName); + TableIf table = db.getTableOrAnalysisException(tblName); + tblId = table.getId(); + dbId = db.getId(); + catalogId = catalog.getId(); + // check permission + checkAnalyzePriv(catalogName, db.getFullName(), table.getName()); + // check columnNames + if (columnNames != null) { + if (columnNames.size() > MAX_IN_ELEMENT_TO_DELETE) { + throw new UserException("Can't delete more that " + MAX_IN_ELEMENT_TO_DELETE + " columns at one time."); + } + isAllColumns = false; + for (String cName : columnNames) { + if (table.getColumn(cName) == null) { + ErrorReport.reportAnalysisException( + ErrorCode.ERR_WRONG_COLUMN_NAME, + "DROP", + ConnectContext.get().getQualifiedUser(), + ConnectContext.get().getRemoteIP(), + cName); + } + } + } else { + isAllColumns = true; + } + if (opPartitionNames != null && opPartitionNames.getPartitionNames() != null + && opPartitionNames.getPartitionNames().size() > MAX_IN_ELEMENT_TO_DELETE) { + throw new UserException("Can't delete more that " + MAX_IN_ELEMENT_TO_DELETE + " partitions at one time"); + } + } + + private void checkAnalyzePriv(String catalogName, String dbName, String tblName) throws AnalysisException { + if (!Env.getCurrentEnv().getAccessManager() + .checkTblPriv(ConnectContext.get(), catalogName, dbName, tblName, + PrivPredicate.DROP)) { + ErrorReport.reportAnalysisException( + ErrorCode.ERR_TABLEACCESS_DENIED_ERROR, + "DROP", + ConnectContext.get().getQualifiedUser(), + ConnectContext.get().getRemoteIP(), + dbName + "." + tblName); + } + } + + @Override + public R accept(PlanVisitor visitor, C context) { + return visitor.visitDropStatsCommand(this, context); + } + + @Override + public StmtType stmtType() { + return StmtType.DROP; + } +} 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 c1c805c4d24d65..7de59b241ecaca 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 @@ -62,11 +62,13 @@ import org.apache.doris.nereids.trees.plans.commands.DeleteFromCommand; import org.apache.doris.nereids.trees.plans.commands.DeleteFromUsingCommand; import org.apache.doris.nereids.trees.plans.commands.DescribeCommand; +import org.apache.doris.nereids.trees.plans.commands.DropCachedStatsCommand; import org.apache.doris.nereids.trees.plans.commands.DropCatalogCommand; import org.apache.doris.nereids.trees.plans.commands.DropCatalogRecycleBinCommand; import org.apache.doris.nereids.trees.plans.commands.DropConstraintCommand; import org.apache.doris.nereids.trees.plans.commands.DropDatabaseCommand; import org.apache.doris.nereids.trees.plans.commands.DropEncryptkeyCommand; +import org.apache.doris.nereids.trees.plans.commands.DropExpiredStatsCommand; import org.apache.doris.nereids.trees.plans.commands.DropFileCommand; import org.apache.doris.nereids.trees.plans.commands.DropFunctionCommand; import org.apache.doris.nereids.trees.plans.commands.DropJobCommand; @@ -75,6 +77,7 @@ import org.apache.doris.nereids.trees.plans.commands.DropRepositoryCommand; import org.apache.doris.nereids.trees.plans.commands.DropRoleCommand; import org.apache.doris.nereids.trees.plans.commands.DropSqlBlockRuleCommand; +import org.apache.doris.nereids.trees.plans.commands.DropStatsCommand; import org.apache.doris.nereids.trees.plans.commands.DropStoragePolicyCommand; import org.apache.doris.nereids.trees.plans.commands.DropTableCommand; import org.apache.doris.nereids.trees.plans.commands.DropUserCommand; @@ -834,4 +837,16 @@ default R visitDescribeCommand(DescribeCommand describeCommand, C context) { default R visitShowTableCommand(ShowTableCommand showTableCommand, C context) { return visitCommand(showTableCommand, context); } + + default R visitDropStatsCommand(DropStatsCommand dropStatsCommand, C context) { + return visitCommand(dropStatsCommand, context); + } + + default R visitDropCachedStatsCommand(DropCachedStatsCommand dropCachedStatsCommand, C context) { + return visitCommand(dropCachedStatsCommand, context); + } + + default R visitDropExpiredStatsCommand(DropExpiredStatsCommand dropExpiredStatsCommand, C context) { + return visitCommand(dropExpiredStatsCommand, context); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisManager.java b/fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisManager.java index 989d694dd4810d..fdea930a3773bf 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisManager.java +++ b/fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisManager.java @@ -61,6 +61,7 @@ import org.apache.doris.nereids.trees.plans.commands.AnalyzeDatabaseCommand; import org.apache.doris.nereids.trees.plans.commands.AnalyzeTableCommand; import org.apache.doris.nereids.trees.plans.commands.info.TableNameInfo; +import org.apache.doris.nereids.trees.plans.commands.DropStatsCommand; import org.apache.doris.persist.AnalyzeDeletionLog; import org.apache.doris.persist.TableStatsDeletionLog; import org.apache.doris.persist.gson.GsonUtils; @@ -853,6 +854,37 @@ private ThreadPoolExecutor createThreadPoolForSyncAnalyze() { StatisticsUtil.getAnalyzeTimeout())); } + public void dropStats(DropStatsCommand dropStatsCommand) throws DdlException { + TableStatsMeta tableStats = findTableStatsStatus(dropStatsCommand.getTblId()); + if (tableStats == null) { + return; + } + Set cols = dropStatsCommand.getColumnNames(); + PartitionNames partitionNames = dropStatsCommand.getOpPartitionNames(); + long catalogId = dropStatsCommand.getCatalogId(); + long dbId = dropStatsCommand.getDbId(); + long tblId = dropStatsCommand.getTblId(); + TableIf table = StatisticsUtil.findTable(catalogId, dbId, tblId); + // Remove tableMetaStats if drop whole table stats. + if ((cols == null || cols.isEmpty()) && (!table.isPartitionedTable() || partitionNames == null + || partitionNames.isStar() || partitionNames.getPartitionNames() == null)) { + removeTableStats(tblId); + Env.getCurrentEnv().getEditLog().logDeleteTableStats(new TableStatsDeletionLog(tblId)); + } + invalidateLocalStats(catalogId, dbId, tblId, cols, tableStats, partitionNames); + // Drop stats ddl is master only operation. + Set partitions = null; + if (partitionNames != null && !partitionNames.isStar() && partitionNames.getPartitionNames() != null) { + partitions = new HashSet<>(partitionNames.getPartitionNames()); + } + invalidateRemoteStats(catalogId, dbId, tblId, cols, partitions, false); + StatisticsRepository.dropStatistics(catalogId, dbId, tblId, cols, partitions); + } + + public void dropExpiredStats() { + Env.getCurrentEnv().getStatisticsCleaner().clear(); + } + public void dropCachedStats(DropCachedStatsStmt stmt) { long catalogId = stmt.getCatalogIdId(); long dbId = stmt.getDbId(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsRepository.java b/fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsRepository.java index beac03a53a70f2..b6f0c069c84b71 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsRepository.java +++ b/fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsRepository.java @@ -217,7 +217,7 @@ private static String constructId(Object... params) { public static void dropStatistics( long ctlId, long dbId, long tblId, Set colNames, Set partNames) throws DdlException { - if (colNames == null && partNames == null) { + if ((colNames == null || colNames.isEmpty()) && partNames == null) { executeDropStatisticsAllColumnSql(ctlId, dbId, tblId); } else { dropStatisticsByColAndPartitionName(ctlId, dbId, tblId, colNames, partNames);