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 6c37a2b276b0dd..0cd32f3820fda4 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 @@ -508,6 +508,7 @@ supportedAdminStatement | ADMIN CLEAN TRASH (ON LEFT_PAREN backends+=STRING_LITERAL (COMMA backends+=STRING_LITERAL)* RIGHT_PAREN)? #adminCleanTrash + | ADMIN SET TABLE name=multipartIdentifier STATUS properties=propertyClause? #adminSetTableStatus ; supportedRecoverStatement @@ -528,7 +529,6 @@ unsupportedAdminStatement | ADMIN SET TABLE name=multipartIdentifier PARTITION VERSION properties=propertyClause? #adminSetPartitionVersion | ADMIN COPY TABLET tabletId=INTEGER_VALUE properties=propertyClause? #adminCopyTablet - | ADMIN SET TABLE name=multipartIdentifier STATUS properties=propertyClause? #adminSetTableStatus ; baseTableRef 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 a9ce9215d4d9be..68226f156c7f25 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 @@ -55,6 +55,7 @@ import org.apache.doris.nereids.DorisParser.AdminCompactTableContext; import org.apache.doris.nereids.DorisParser.AdminDiagnoseTabletContext; import org.apache.doris.nereids.DorisParser.AdminRebalanceDiskContext; +import org.apache.doris.nereids.DorisParser.AdminSetTableStatusContext; import org.apache.doris.nereids.DorisParser.AdminShowReplicaDistributionContext; import org.apache.doris.nereids.DorisParser.AdminShowReplicaStatusContext; import org.apache.doris.nereids.DorisParser.AdminShowTabletStorageFormatContext; @@ -491,6 +492,7 @@ import org.apache.doris.nereids.trees.plans.commands.AdminCleanTrashCommand; import org.apache.doris.nereids.trees.plans.commands.AdminCompactTableCommand; import org.apache.doris.nereids.trees.plans.commands.AdminRebalanceDiskCommand; +import org.apache.doris.nereids.trees.plans.commands.AdminSetTableStatusCommand; import org.apache.doris.nereids.trees.plans.commands.AdminShowReplicaStatusCommand; import org.apache.doris.nereids.trees.plans.commands.AlterCatalogCommentCommand; import org.apache.doris.nereids.trees.plans.commands.AlterMTMVCommand; @@ -4844,6 +4846,14 @@ public LogicalPlan visitShowCharset(ShowCharsetContext ctx) { return new ShowCharsetCommand(); } + @Override + public LogicalPlan visitAdminSetTableStatus(AdminSetTableStatusContext ctx) { + List dbTblNameParts = visitMultipartIdentifier(ctx.name); + Map properties = ctx.propertyClause() != null + ? Maps.newHashMap(visitPropertyClause(ctx.propertyClause())) : Maps.newHashMap(); + return new AdminSetTableStatusCommand(new TableNameInfo(dbTblNameParts), properties); + } + @Override public LogicalPlan visitShowFrontends(ShowFrontendsContext ctx) { String detail = (ctx.name != null) ? ctx.name.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 bfa0163e7d267e..6395f429db29de 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 @@ -201,6 +201,7 @@ public enum PlanType { DROP_USER_COMMAND, DROP_WORKLOAD_GROUP_NAME, DROP_WORKLOAD_POLICY_COMMAND, + ADMIN_SET_TABLE_STATUS_COMMAND, ALTER_CATALOG_COMMENT_COMMAND, ALTER_SQL_BLOCK_RULE_COMMAND, SHOW_BACKENDS_COMMAND, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminSetTableStatusCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminSetTableStatusCommand.java new file mode 100644 index 00000000000000..36c46c333468c7 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminSetTableStatusCommand.java @@ -0,0 +1,98 @@ +// 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.catalog.Env; +import org.apache.doris.catalog.OlapTable.OlapTableState; +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.common.util.Util; +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.Map; + +/** + * AdminSetTableStatusCommand + */ +public class AdminSetTableStatusCommand extends Command implements ForwardWithSync { + public static final String TABLE_STATE = "state"; + private final TableNameInfo tableNameInfo; + private final Map properties; + private OlapTableState tableState; + + /** + * constructor + */ + public AdminSetTableStatusCommand(TableNameInfo tableNameInfo, Map properties) { + super(PlanType.ADMIN_SET_TABLE_STATUS_COMMAND); + this.tableNameInfo = tableNameInfo; + this.properties = properties; + } + + @Override + public void run(ConnectContext ctx, StmtExecutor executor) throws Exception { + validate(ctx); + Env.getCurrentEnv().setTableStatusInternal(tableNameInfo.getDb(), tableNameInfo.getTbl(), tableState, false); + } + + private void validate(ConnectContext ctx) throws UserException { + // check auth + if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.ADMIN)) { + ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN"); + } + + tableNameInfo.analyze(ctx); + Util.prohibitExternalCatalog(tableNameInfo.getCtl(), this.getClass().getSimpleName()); + + checkProperties(); + } + + private void checkProperties() throws AnalysisException { + for (Map.Entry entry : properties.entrySet()) { + String key = entry.getKey(); + String val = entry.getValue(); + + if (key.equalsIgnoreCase(TABLE_STATE)) { + try { + tableState = OlapTableState.valueOf(val.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new AnalysisException("Invalid table state: " + val); + } + } else { + throw new AnalysisException("Unsupported property: " + key); + } + } + + if (tableState == null) { + throw new AnalysisException("Should add properties: STATE."); + } + } + + @Override + public R accept(PlanVisitor visitor, C context) { + return visitor.visitAdminSetTableStatusCommand(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 6efa58c1b8eb91..a9340894c33590 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 @@ -23,6 +23,7 @@ import org.apache.doris.nereids.trees.plans.commands.AdminCleanTrashCommand; import org.apache.doris.nereids.trees.plans.commands.AdminCompactTableCommand; import org.apache.doris.nereids.trees.plans.commands.AdminRebalanceDiskCommand; +import org.apache.doris.nereids.trees.plans.commands.AdminSetTableStatusCommand; import org.apache.doris.nereids.trees.plans.commands.AdminShowReplicaStatusCommand; import org.apache.doris.nereids.trees.plans.commands.AlterCatalogCommentCommand; import org.apache.doris.nereids.trees.plans.commands.AlterJobStatusCommand; @@ -236,6 +237,10 @@ default R visitAdminCleanTrashCommand(AdminCleanTrashCommand adminCleanTrashComm return visitCommand(adminCleanTrashCommand, context); } + default R visitAdminSetTableStatusCommand(AdminSetTableStatusCommand cmd, C context) { + return visitCommand(cmd, context); + } + default R visitDropConstraintCommand(DropConstraintCommand dropConstraintCommand, C context) { return visitCommand(dropConstraintCommand, context); } diff --git a/regression-test/suites/nereids_p0/ddl/admin/test_nereids_admin_set_tbl_status.groovy b/regression-test/suites/nereids_p0/ddl/admin/test_nereids_admin_set_tbl_status.groovy new file mode 100644 index 00000000000000..8e2a8b67aaed0f --- /dev/null +++ b/regression-test/suites/nereids_p0/ddl/admin/test_nereids_admin_set_tbl_status.groovy @@ -0,0 +1,49 @@ +// 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_nereids_admin_set_tbl_status") { + def tbName1 = "test_nereids_admin_set_tbl_status" + + try { + sql "DROP TABLE IF EXISTS ${tbName1}" + sql """ + CREATE TABLE IF NOT EXISTS ${tbName1} ( + k1 INT, + v1 INT, + v2 INT + ) + DUPLICATE KEY (k1) + DISTRIBUTED BY HASH(k1) BUCKETS 1 properties("replication_num" = "1", "light_schema_change" = "false", "disable_auto_compaction" = "true"); + """ + + // set table state to ROLLUP + checkNereidsExecute("ADMIN SET TABLE ${tbName1} STATUS PROPERTIES ('state' = 'rollup');") + // try alter table comment + test { + sql """ ALTER TABLE ${tbName1} MODIFY COMMENT 'test'; """ + exception "Table[test_nereids_admin_set_tbl_status]'s state(ROLLUP) is not NORMAL. Do not allow doing ALTER ops" + } + + // set table state to NORMAL + checkNereidsExecute("ADMIN SET TABLE ${tbName1} STATUS PROPERTIES ('state' = 'normal');") + // try alter table comment + sql """ ALTER TABLE ${tbName1} MODIFY COMMENT 'test'; """ + } finally { + // drop table + sql """ DROP TABLE ${tbName1} force""" + } +}