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 09cfca191e1 [feat](Nereids)  support refresh catalog command (#43449)
09cfca191e1 is described below

commit 09cfca191e18c5ae6d71e2130b7c3cd76b9c1031
Author: Petrichor <31833513+vinle...@users.noreply.github.com>
AuthorDate: Tue Nov 19 16:56:31 2024 +0800

    [feat](Nereids)  support refresh catalog command (#43449)
    
    
    Issue Number: close # https://github.com/apache/doris/issues/42580
---
 .../antlr4/org/apache/doris/nereids/DorisParser.g4 |   6 +-
 .../org/apache/doris/catalog/RefreshManager.java   |   6 +-
 .../doris/nereids/parser/LogicalPlanBuilder.java   |  14 +++
 .../apache/doris/nereids/trees/plans/PlanType.java |   1 +
 .../commands/refresh/RefreshCatalogCommand.java    | 128 +++++++++++++++++++++
 .../trees/plans/visitor/CommandVisitor.java        |   5 +
 .../test_nereids_refresh_catalog.out               |  63 ++++++++++
 .../test_nereids_refresh_catalog.groovy            |  70 +++++++++++
 8 files changed, 289 insertions(+), 4 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 734be9fa51d..c9958e68641 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
@@ -55,6 +55,7 @@ statementBase
     | supportedDropStatement            #supportedDropStatementAlias
     | supportedSetStatement             #supportedSetStatementAlias
     | supportedUnsetStatement           #supportedUnsetStatementAlias
+    | supportedRefreshStatement         #supportedRefreshStatementAlias
     | supportedShowStatement            #supportedShowStatementAlias
     | unsupportedStatement              #unsupported
     | supportedRecoverStatement         #supportedRecoverStatementAlias
@@ -418,10 +419,13 @@ channelDescription
         partitionSpec? columnList=identifierList?
     ;
 
+supportedRefreshStatement
+    : REFRESH CATALOG name=identifier propertyClause?                          
     #refreshCatalog
+    ;
+
 unsupportedRefreshStatement
     : REFRESH TABLE name=multipartIdentifier                                   
     #refreshTable
     | REFRESH DATABASE name=multipartIdentifier propertyClause?                
     #refreshDatabase
-    | REFRESH CATALOG name=identifier propertyClause?                          
     #refreshCatalog
     | REFRESH LDAP (ALL | (FOR user=identifierOrText))                         
     #refreshLdap
     ;
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/RefreshManager.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/RefreshManager.java
index 52694e5a5bd..e421cc1475c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/RefreshManager.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/RefreshManager.java
@@ -32,8 +32,8 @@ import org.apache.doris.datasource.ExternalObjectLog;
 import org.apache.doris.datasource.ExternalTable;
 import org.apache.doris.datasource.InternalCatalog;
 import org.apache.doris.datasource.hive.HMSExternalTable;
+import 
org.apache.doris.nereids.trees.plans.commands.refresh.RefreshCatalogCommand;
 import org.apache.doris.persist.OperationType;
-import org.apache.doris.qe.DdlExecutor;
 
 import com.google.common.collect.Maps;
 import org.apache.logging.log4j.LogManager;
@@ -284,9 +284,9 @@ public class RefreshManager {
                          * {@link 
org.apache.doris.analysis.RefreshCatalogStmt#analyze(Analyzer)} is ok,
                          * because the default value of invalidCache is true.
                          * */
-                        RefreshCatalogStmt refreshCatalogStmt = new 
RefreshCatalogStmt(catalogName, null);
+                        RefreshCatalogCommand refreshCatalogCommand = new 
RefreshCatalogCommand(catalogName, null);
                         try {
-                            DdlExecutor.execute(Env.getCurrentEnv(), 
refreshCatalogStmt);
+                            refreshCatalogCommand.handleRefreshCatalog();
                         } catch (Exception e) {
                             LOG.warn("failed to refresh catalog {}", 
catalogName, e);
                         }
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 064e9568ac2..6fc011d6926 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
@@ -163,6 +163,7 @@ import org.apache.doris.nereids.DorisParser.QueryContext;
 import org.apache.doris.nereids.DorisParser.QueryOrganizationContext;
 import org.apache.doris.nereids.DorisParser.QueryTermContext;
 import org.apache.doris.nereids.DorisParser.RecoverDatabaseContext;
+import org.apache.doris.nereids.DorisParser.RefreshCatalogContext;
 import org.apache.doris.nereids.DorisParser.RefreshMTMVContext;
 import org.apache.doris.nereids.DorisParser.RefreshMethodContext;
 import org.apache.doris.nereids.DorisParser.RefreshScheduleContext;
@@ -513,6 +514,7 @@ import 
org.apache.doris.nereids.trees.plans.commands.info.TableNameInfo;
 import 
org.apache.doris.nereids.trees.plans.commands.insert.BatchInsertIntoTableCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.insert.InsertIntoTableCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.insert.InsertOverwriteTableCommand;
+import 
org.apache.doris.nereids.trees.plans.commands.refresh.RefreshCatalogCommand;
 import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
 import org.apache.doris.nereids.trees.plans.logical.LogicalCTE;
 import org.apache.doris.nereids.trees.plans.logical.LogicalExcept;
@@ -4050,6 +4052,17 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
     }
 
     @Override
+
+    public Object visitRefreshCatalog(RefreshCatalogContext ctx) {
+        if (ctx.name != null) {
+            String catalogName = ctx.name.getText();
+            Map<String, String> properties = ctx.propertyClause() != null
+                    ? 
Maps.newHashMap(visitPropertyClause(ctx.propertyClause())) : Maps.newHashMap();
+            return new RefreshCatalogCommand(catalogName, properties);
+        }
+        throw new AnalysisException("catalog name can not be null");
+    }
+
     public LogicalPlan visitShowLastInsert(ShowLastInsertContext ctx) {
         return new ShowLastInsertCommand();
     }
@@ -4061,6 +4074,7 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
             partitionId = Long.parseLong(ctx.partitionId.getText());
         }
         return new ShowPartitionIdCommand(partitionId);
+
     }
 
     @Override
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 55c73c11a81..e255ac32621 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
@@ -174,6 +174,7 @@ public enum PlanType {
     SET_TRANSACTION_COMMAND,
     SET_USER_PROPERTIES_COMMAND,
     SET_DEFAULT_STORAGE_VAULT_COMMAND,
+    REFRESH_CATALOG_COMMAND,
     PREPARED_COMMAND,
     EXECUTE_COMMAND,
     SHOW_BACKENDS_COMMAND,
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/refresh/RefreshCatalogCommand.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/refresh/RefreshCatalogCommand.java
new file mode 100644
index 00000000000..7b643303819
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/refresh/RefreshCatalogCommand.java
@@ -0,0 +1,128 @@
+// 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.common.util.Util;
+import org.apache.doris.datasource.CatalogIf;
+import org.apache.doris.datasource.CatalogLog;
+import org.apache.doris.datasource.ExternalCatalog;
+import org.apache.doris.datasource.InternalCatalog;
+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.visitor.PlanVisitor;
+import org.apache.doris.persist.OperationType;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.qe.StmtExecutor;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.Map;
+
+/**
+ * Manually refresh the catalog metadata.
+ */
+public class RefreshCatalogCommand extends Command implements ForwardWithSync {
+    private static final Logger LOG = 
LogManager.getLogger(RefreshCatalogCommand.class);
+    private static final String INVALID_CACHE = "invalid_cache";
+    private final String catalogName;
+    private Map<String, String> properties;
+    private boolean invalidCache = true;
+
+    public RefreshCatalogCommand(String catalogName, Map<String, String> 
properties) {
+        super(PlanType.REFRESH_CATALOG_COMMAND);
+        this.catalogName = catalogName;
+        this.properties = properties;
+    }
+
+    private void validate() throws AnalysisException {
+        Util.checkCatalogAllRules(catalogName);
+        if (catalogName.equals(InternalCatalog.INTERNAL_CATALOG_NAME)) {
+            throw new AnalysisException("Internal catalog name can't be 
refresh.");
+        }
+
+        if (!Env.getCurrentEnv().getAccessManager().checkCtlPriv(
+                ConnectContext.get(), catalogName, PrivPredicate.SHOW)) {
+            
ErrorReport.reportAnalysisException(ErrorCode.ERR_CATALOG_ACCESS_DENIED_ERROR,
+                    PrivPredicate.SHOW.getPrivs().toString(), catalogName);
+        }
+
+        if (properties != null) {
+            // Set to false only if user set the property 
"invalid_cache"="false"
+            invalidCache = !(properties.get(INVALID_CACHE) != null && 
properties.get(INVALID_CACHE)
+                    .equalsIgnoreCase("false"));
+        }
+
+    }
+
+    private void refreshCatalogInternal(CatalogIf catalog) {
+        if (!catalogName.equals(InternalCatalog.INTERNAL_CATALOG_NAME)) {
+            ((ExternalCatalog) catalog).onRefreshCache(invalidCache);
+            LOG.info("refresh catalog {} with invalidCache {}", catalogName, 
invalidCache);
+        }
+    }
+
+    /**
+     * refresh catalog
+     */
+    public void handleRefreshCatalog() throws AnalysisException {
+        CatalogIf catalog = 
Env.getCurrentEnv().getCatalogMgr().getCatalogOrAnalysisException(catalogName);
+        CatalogLog log = new CatalogLog();
+        log.setCatalogId(catalog.getId());
+        log.setInvalidCache(invalidCache);
+        refreshCatalogInternal(catalog);
+        
Env.getCurrentEnv().getEditLog().logCatalogLog(OperationType.OP_REFRESH_CATALOG,
 log);
+    }
+
+    @Override
+    public void run(ConnectContext ctx, StmtExecutor executor) throws 
Exception {
+        validate();
+        handleRefreshCatalog();
+    }
+
+    @Override
+    public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
+        return visitor.visitRefreshCatalogCommand(this, context);
+    }
+
+    @Override
+    public StmtType stmtType() {
+        return StmtType.REFRESH;
+    }
+
+    /**
+     * return sql expression of this command
+     *
+     * @return sql command
+     */
+    public String toSql() {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("REFRESH CATALOG ")
+                .append("`")
+                .append(catalogName)
+                .append("`");
+        return stringBuilder.toString();
+    }
+}
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 2ffdcc767ab..117c42b7bfc 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
@@ -77,6 +77,7 @@ import 
org.apache.doris.nereids.trees.plans.commands.UpdateCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.insert.BatchInsertIntoTableCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.insert.InsertIntoTableCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.insert.InsertOverwriteTableCommand;
+import 
org.apache.doris.nereids.trees.plans.commands.refresh.RefreshCatalogCommand;
 
 /** CommandVisitor. */
 public interface CommandVisitor<R, C> {
@@ -255,6 +256,10 @@ public interface CommandVisitor<R, C> {
         return visitCommand(setDefaultStorageVaultCommand, context);
     }
 
+    default R visitRefreshCatalogCommand(RefreshCatalogCommand 
refreshCatalogCommand, C context) {
+        return visitCommand(refreshCatalogCommand, context);
+    }
+
     default R visitShowLastInsertCommand(ShowLastInsertCommand 
showLastInsertCommand, C context) {
         return visitCommand(showLastInsertCommand, 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
new file mode 100644
index 00000000000..89b47bbe4eb
--- /dev/null
+++ 
b/regression-test/data/external_table_p0/nereids_commands/test_nereids_refresh_catalog.out
@@ -0,0 +1,63 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !sql --
+DORIS
+Doris
+doris
+doris_test
+information_schema
+init_db
+mysql
+show_test_do_not_modify
+
+-- !ex_tb0_where --
+111
+
+-- !ex_tb0 --
+111    abc
+112    abd
+113    abe
+114    abf
+115    abg
+
+-- !sql --
+DORIS
+Doris
+doris
+doris_test
+information_schema
+init_db
+mysql
+show_test_do_not_modify
+
+-- !sql --
+DORIS
+Doris
+doris
+doris_test
+information_schema
+init_db
+mysql
+new_mysql_db
+show_test_do_not_modify
+
+-- !sql --
+DORIS
+Doris
+doris
+doris_test
+information_schema
+init_db
+mysql
+new_mysql_db
+show_test_do_not_modify
+
+-- !sql --
+DORIS
+Doris
+doris
+doris_test
+information_schema
+init_db
+mysql
+show_test_do_not_modify
+
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
new file mode 100644
index 00000000000..f74f78a3709
--- /dev/null
+++ 
b/regression-test/suites/external_table_p0/nereids_commands/test_nereids_refresh_catalog.groovy
@@ -0,0 +1,70 @@
+// 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_refresh_catalog", 
"p0,external,mysql,external_docker,external_docker_mysql") {
+    String enabled = context.config.otherConfigs.get("enableJdbcTest")
+    String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
+    String s3_endpoint = getS3Endpoint()
+    String bucket = getS3BucketName()
+    String driver_url = 
"https://${bucket}.${s3_endpoint}/regression/jdbc_driver/mysql-connector-java-8.0.25.jar";
+    if (enabled != null && enabled.equalsIgnoreCase("true")) {
+        String catalog_name = "refresh_catalog_mysql_catalog_nereids";
+        String internal_db_name = "regression_test_jdbc_catalog_p0";
+        String ex_db_name = "doris_test";
+        String mysql_port = context.config.otherConfigs.get("mysql_57_port");
+        String ex_tb0 = "ex_tb0";
+        String new_mysql_db = "new_mysql_db";
+
+        sql """drop catalog if exists ${catalog_name} """
+
+           sql """set enable_nereids_planner=true;"""
+           sql """set enable_fallback_to_original_planner=false;"""
+
+        sql """create catalog if not exists ${catalog_name} properties(
+            "type"="jdbc",
+            "user"="root",
+            "password"="123456",
+            "jdbc_url" = 
"jdbc:mysql://${externalEnvIp}:${mysql_port}/doris_test?useSSL=false",
+            "driver_url" = "${driver_url}",
+            "driver_class" = "com.mysql.cj.jdbc.Driver"
+        );"""
+
+        sql """switch ${catalog_name}"""
+        sql """CALL EXECUTE_STMT("${catalog_name}", "drop database if exists 
${new_mysql_db}");"""
+
+        qt_sql """show databases;"""
+        sql """ use ${ex_db_name}"""
+
+        qt_ex_tb0_where """select id from ${ex_tb0} where id = 111;"""
+        order_qt_ex_tb0  """ select id, name from ${ex_tb0} order by id; """
+        // create database in mysql
+        sql """CALL EXECUTE_STMT("${catalog_name}", "create database  
${new_mysql_db} ;");"""
+        qt_sql """show databases;"""
+        checkNereidsExecute("refresh catalog ${catalog_name} ;")
+        qt_sql """show databases;"""
+
+        checkNereidsExecute("refresh catalog ${catalog_name} properties 
('invalid_cache'='true');")
+
+        sql """CALL EXECUTE_STMT("${catalog_name}", "drop database if exists 
${new_mysql_db} ;");"""
+        qt_sql """show databases;"""
+
+        checkNereidsExecute("refresh catalog ${catalog_name} properties 
('invalid_cache'='true');")
+        qt_sql """show databases;"""
+
+        sql """ drop catalog if exists ${catalog_name} ;"""
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to