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 14a01734e08 [feat](nereids)support refresh table command (#45546)
14a01734e08 is described below

commit 14a01734e08cc81c47e323df8ea8fc5048386d73
Author: Petrichor <[email protected]>
AuthorDate: Thu Dec 19 11:36:12 2024 +0800

    [feat](nereids)support refresh table command (#45546)
    
    Issue Number: close https://github.com/apache/doris/issues/42578
---
 .../antlr4/org/apache/doris/nereids/DorisParser.g4 |  4 +-
 .../doris/nereids/parser/LogicalPlanBuilder.java   | 14 ++++
 .../apache/doris/nereids/trees/plans/PlanType.java |  1 +
 .../commands/refresh/RefreshTableCommand.java      | 84 ++++++++++++++++++++++
 .../trees/plans/visitor/CommandVisitor.java        |  5 ++
 .../test_nereids_refresh_catalog.out               | 21 ++++++
 .../test_nereids_refresh_catalog.groovy            | 18 +++++
 7 files changed, 145 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 64ff9209bfe..ad884eefee1 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
@@ -457,6 +457,7 @@ channelDescription
 supportedRefreshStatement
     : REFRESH CATALOG name=identifier propertyClause?                          
     #refreshCatalog
     | REFRESH DATABASE name=multipartIdentifier propertyClause?                
     #refreshDatabase
+    | REFRESH TABLE name=multipartIdentifier                                   
     #refreshTable
     ;
 
 supportedCleanStatement
@@ -464,8 +465,7 @@ supportedCleanStatement
     ;
 
 unsupportedRefreshStatement
-    : REFRESH TABLE name=multipartIdentifier                                   
     #refreshTable
-    | REFRESH LDAP (ALL | (FOR user=identifierOrText))                         
     #refreshLdap
+    : REFRESH LDAP (ALL | (FOR user=identifierOrText))                         
     #refreshLdap
     ;
 
 unsupportedCleanStatement
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 951c8b342d5..4c5d43cb4db 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
@@ -208,6 +208,7 @@ import 
org.apache.doris.nereids.DorisParser.RefreshDatabaseContext;
 import org.apache.doris.nereids.DorisParser.RefreshMTMVContext;
 import org.apache.doris.nereids.DorisParser.RefreshMethodContext;
 import org.apache.doris.nereids.DorisParser.RefreshScheduleContext;
+import org.apache.doris.nereids.DorisParser.RefreshTableContext;
 import org.apache.doris.nereids.DorisParser.RefreshTriggerContext;
 import org.apache.doris.nereids.DorisParser.RegularQuerySpecificationContext;
 import org.apache.doris.nereids.DorisParser.RelationContext;
@@ -670,6 +671,7 @@ import 
org.apache.doris.nereids.trees.plans.commands.load.LoadSequenceClause;
 import org.apache.doris.nereids.trees.plans.commands.load.LoadWhereClause;
 import 
org.apache.doris.nereids.trees.plans.commands.refresh.RefreshCatalogCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.refresh.RefreshDatabaseCommand;
+import 
org.apache.doris.nereids.trees.plans.commands.refresh.RefreshTableCommand;
 import org.apache.doris.nereids.trees.plans.commands.use.SwitchCommand;
 import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
 import org.apache.doris.nereids.trees.plans.logical.LogicalCTE;
@@ -4464,6 +4466,18 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
         throw new ParseException("Only one dot can be in the name: " + 
String.join(".", parts));
     }
 
+    @Override
+    public Object visitRefreshTable(RefreshTableContext ctx) {
+        List<String> parts = visitMultipartIdentifier(ctx.name);
+        int size = parts.size();
+        if (size == 0) {
+            throw new ParseException("table name can't be empty");
+        } else if (size <= 3) {
+            return new RefreshTableCommand(new TableNameInfo(parts));
+        }
+        throw new ParseException("Only one or two dot can be in the name: " + 
String.join(".", parts));
+    }
+
     @Override
     public LogicalPlan visitShowCreateRepository(ShowCreateRepositoryContext 
ctx) {
         return new ShowCreateRepositoryCommand(ctx.identifier().getText());
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 9ed408dfe05..0cec8c48caf 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
@@ -194,6 +194,7 @@ public enum PlanType {
     SET_DEFAULT_STORAGE_VAULT_COMMAND,
     REFRESH_CATALOG_COMMAND,
     REFRESH_DATABASE_COMMAND,
+    REFRESH_TABLE_COMMAND,
     PREPARED_COMMAND,
     EXECUTE_COMMAND,
     DROP_SQL_BLOCK_RULE_COMMAND,
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/refresh/RefreshTableCommand.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/refresh/RefreshTableCommand.java
new file mode 100644
index 00000000000..71d77ab22b3
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/refresh/RefreshTableCommand.java
@@ -0,0 +1,84 @@
+// 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.refresh;
+
+import org.apache.doris.analysis.StmtType;
+import org.apache.doris.catalog.Env;
+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.commands.Command;
+import org.apache.doris.nereids.trees.plans.commands.ForwardWithSync;
+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 org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * Refresh table command.
+ */
+public class RefreshTableCommand extends Command implements ForwardWithSync {
+    private static final Logger LOG = 
LogManager.getLogger(RefreshTableCommand.class);
+    private TableNameInfo tableNameInfo;
+
+    public RefreshTableCommand(TableNameInfo tableName) {
+        super(PlanType.REFRESH_TABLE_COMMAND);
+        this.tableNameInfo = tableName;
+    }
+
+    @Override
+    public void run(ConnectContext ctx, StmtExecutor executor) throws 
Exception {
+        tableNameInfo.analyze(ctx);
+        checkRefreshTableAccess();
+        // refresh table execute logic
+        Env.getCurrentEnv().getRefreshManager()
+                .refreshTable(tableNameInfo.getCtl(), tableNameInfo.getDb(), 
tableNameInfo.getTbl(), false);
+    }
+
+    @Override
+    public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
+        return visitor.visitRefreshTableCommand(this, context);
+    }
+
+    @Override
+    public StmtType stmtType() {
+        return StmtType.REFRESH;
+    }
+
+    /**
+     * check access.
+     */
+    private void checkRefreshTableAccess() throws AnalysisException {
+        if 
(!Env.getCurrentEnv().getAccessManager().checkTblPriv(ConnectContext.get(),
+                tableNameInfo.getCtl(), tableNameInfo.getDb(),
+                tableNameInfo.getTbl(), PrivPredicate.SHOW)) {
+            
ErrorReport.reportAnalysisException(ErrorCode.ERR_TABLE_ACCESS_DENIED_ERROR,
+                    PrivPredicate.SHOW.getPrivs().toString(), 
tableNameInfo.getTbl());
+        }
+    }
+
+    public String toSql() {
+        return "REFRESH TABLE " + tableNameInfo.toSql();
+    }
+
+}
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 eb764be57c0..f988055f0f6 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
@@ -144,6 +144,7 @@ import 
org.apache.doris.nereids.trees.plans.commands.insert.InsertOverwriteTable
 import 
org.apache.doris.nereids.trees.plans.commands.load.CreateRoutineLoadCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.refresh.RefreshCatalogCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.refresh.RefreshDatabaseCommand;
+import 
org.apache.doris.nereids.trees.plans.commands.refresh.RefreshTableCommand;
 import org.apache.doris.nereids.trees.plans.commands.use.SwitchCommand;
 
 /** CommandVisitor. */
@@ -415,6 +416,10 @@ public interface CommandVisitor<R, C> {
         return visitCommand(refreshDatabaseCommand, context);
     }
 
+    default R visitRefreshTableCommand(RefreshTableCommand 
refreshTableCommand, C context) {
+        return visitCommand(refreshTableCommand, context);
+    }
+
     default R visitShowBackendsCommand(ShowBackendsCommand 
showBackendsCommand, C context) {
         return visitCommand(showBackendsCommand, context);
     }
diff --git 
a/regression-test/data/external_table_p0/nereids_commands/test_nereids_refresh_catalog.out
 
b/regression-test/data/external_table_p0/nereids_commands/test_nereids_refresh_catalog.out
index c3f57d7ba81..66ca9363d71 100644
--- 
a/regression-test/data/external_table_p0/nereids_commands/test_nereids_refresh_catalog.out
+++ 
b/regression-test/data/external_table_p0/nereids_commands/test_nereids_refresh_catalog.out
@@ -54,6 +54,27 @@ new_mysql_table1
 new_mysql_table1
 new_mysql_table2
 
+-- !show_create_table --
+new_mysql_table2       CREATE TABLE `new_mysql_table2` (\n  `id` int NULL,\n  
`name` varchar(20) NULL\n) ENGINE=JDBC_EXTERNAL_TABLE;
+
+-- !preceding_refresh_table --
+new_mysql_table2       CREATE TABLE `new_mysql_table2` (\n  `id` int NULL,\n  
`name` varchar(20) NULL\n) ENGINE=JDBC_EXTERNAL_TABLE;
+
+-- !subsequent_refresh_table --
+new_mysql_table2       CREATE TABLE `new_mysql_table2` (\n  `id` int NULL,\n  
`name` varchar(20) NULL,\n  `new_column` int NULL\n) ENGINE=JDBC_EXTERNAL_TABLE;
+
+-- !preceding_refresh_table --
+new_mysql_table2       CREATE TABLE `new_mysql_table2` (\n  `id` int NULL,\n  
`name` varchar(20) NULL,\n  `new_column` int NULL\n) ENGINE=JDBC_EXTERNAL_TABLE;
+
+-- !subsequent_refresh_table --
+new_mysql_table2       CREATE TABLE `new_mysql_table2` (\n  `id` int NULL,\n  
`name` varchar(20) NULL,\n  `new_column` int NULL,\n  `new_column_1` int 
NULL\n) ENGINE=JDBC_EXTERNAL_TABLE;
+
+-- !preceding_refresh_table --
+new_mysql_table2       CREATE TABLE `new_mysql_table2` (\n  `id` int NULL,\n  
`name` varchar(20) NULL,\n  `new_column` int NULL,\n  `new_column_1` int 
NULL\n) ENGINE=JDBC_EXTERNAL_TABLE;
+
+-- !subsequent_refresh_table --
+new_mysql_table2       CREATE TABLE `new_mysql_table2` (\n  `id` int NULL,\n  
`name` varchar(20) NULL,\n  `new_column` int NULL,\n  `new_column_1` int 
NULL,\n  `new_column_2` int NULL\n) ENGINE=JDBC_EXTERNAL_TABLE;
+
 -- !preceding_drop_external_database --
 DORIS
 Doris
diff --git 
a/regression-test/suites/external_table_p0/nereids_commands/test_nereids_refresh_catalog.groovy
 
b/regression-test/suites/external_table_p0/nereids_commands/test_nereids_refresh_catalog.groovy
index 87dacd41425..8fbaa486610 100644
--- 
a/regression-test/suites/external_table_p0/nereids_commands/test_nereids_refresh_catalog.groovy
+++ 
b/regression-test/suites/external_table_p0/nereids_commands/test_nereids_refresh_catalog.groovy
@@ -75,6 +75,24 @@ suite("test_nereids_refresh_catalog", 
"p0,external,mysql,external_docker,externa
         checkNereidsExecute("refresh database ${catalog_name}.${new_mysql_db} 
;")
         qt_subsequent_refresh_database """show tables;"""
 
+        qt_show_create_table """show create table 
${new_mysql_db}.${new_mysql_table2};"""
+        // add a column in external table
+        sql """CALL EXECUTE_STMT("${catalog_name}", "alter table 
${new_mysql_db}.${new_mysql_table2} add new_column int;");"""
+        qt_preceding_refresh_table """show create table 
${new_mysql_db}.${new_mysql_table2};"""
+        //refresh table ctl.db.tb1
+        checkNereidsExecute("refresh table 
${catalog_name}.${new_mysql_db}.${new_mysql_table2} ;")
+        qt_subsequent_refresh_table """show create table 
${new_mysql_db}.${new_mysql_table2};"""
+        sql """CALL EXECUTE_STMT("${catalog_name}", "alter table 
${new_mysql_db}.${new_mysql_table2} add new_column_1 int;");"""
+        qt_preceding_refresh_table """show create table 
${new_mysql_db}.${new_mysql_table2};"""
+        // refresh table db.tbl
+        checkNereidsExecute("refresh table ${new_mysql_db}.${new_mysql_table2} 
;")
+        qt_subsequent_refresh_table """show create table 
${new_mysql_db}.${new_mysql_table2};"""
+        sql """CALL EXECUTE_STMT("${catalog_name}", "alter table 
${new_mysql_db}.${new_mysql_table2} add new_column_2 int;");"""
+        qt_preceding_refresh_table """show create table 
${new_mysql_db}.${new_mysql_table2};"""
+        //refresh table tbl1
+        checkNereidsExecute("refresh table ${new_mysql_table2};")
+        qt_subsequent_refresh_table """show create table 
${new_mysql_db}.${new_mysql_table2};"""
+
         sql """CALL EXECUTE_STMT("${catalog_name}", "drop database if exists 
${new_mysql_db} ;");"""
         qt_preceding_drop_external_database """show databases;"""
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to