This is an automated email from the ASF dual-hosted git repository.

morrysnow pushed a commit to branch branch-3.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-3.1 by this push:
     new ede0dfc1210 branch-3.1: [fix](cloud) Add more prompt information when 
compute group is invalid #56946 (#58225)
ede0dfc1210 is described below

commit ede0dfc1210118d73699d9e9e2994623a4b6432e
Author: deardeng <[email protected]>
AuthorDate: Tue Nov 25 12:10:12 2025 +0800

    branch-3.1: [fix](cloud) Add more prompt information when compute group is 
invalid #56946 (#58225)
    
    cherry pick from #56946
---
 .../doris/cloud/load/CloudBrokerLoadJob.java       |  6 +-
 .../apache/doris/cloud/qe/CloudCoordinator.java    |  7 +--
 .../doris/datasource/jdbc/JdbcExternalCatalog.java |  9 ++-
 .../java/org/apache/doris/qe/ConnectContext.java   | 69 +++++++++++++++++++++-
 .../java/org/apache/doris/qe/StmtExecutor.java     |  8 ++-
 .../resource/computegroup/ComputeGroupMgr.java     | 47 +++++++++++++++
 .../ExternalFileTableValuedFunction.java           |  9 ++-
 .../tablefunction/NumbersTableValuedFunction.java  |  9 ++-
 .../multi_cluster/test_no_cluster_hits.groovy      | 34 +++++++++--
 9 files changed, 182 insertions(+), 16 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/load/CloudBrokerLoadJob.java 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/load/CloudBrokerLoadJob.java
index 2cbfc57c833..8c10f6e963c 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/load/CloudBrokerLoadJob.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/load/CloudBrokerLoadJob.java
@@ -46,6 +46,7 @@ import org.apache.doris.qe.Coordinator;
 import org.apache.doris.qe.OriginStatement;
 import org.apache.doris.qe.QeProcessorImpl;
 import org.apache.doris.qe.StmtExecutor;
+import org.apache.doris.resource.computegroup.ComputeGroupMgr;
 import org.apache.doris.system.Backend;
 import org.apache.doris.thrift.TStatusCode;
 import org.apache.doris.thrift.TUniqueId;
@@ -111,8 +112,9 @@ public class CloudBrokerLoadJob extends BrokerLoadJob {
                     ((CloudSystemInfoService) 
Env.getCurrentSystemInfo()).getCloudClusterIdByName(clusterName);
             }
             if (Strings.isNullOrEmpty(this.cloudClusterId)) {
-                LOG.warn("cluster id is empty, cluster name {}", clusterName);
-                throw new MetaNotFoundException("cluster id is empty, cluster 
name: " + clusterName);
+                LOG.warn("can not find compute group: {}", clusterName);
+                String computeGroupHints = 
ComputeGroupMgr.computeGroupNotFoundPromptMsg(clusterName);
+                throw new MetaNotFoundException(computeGroupHints);
             }
             sessionVariables.put(CLOUD_CLUSTER_ID, this.cloudClusterId);
         }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/qe/CloudCoordinator.java 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/qe/CloudCoordinator.java
index 2a69e84352d..c051b35103c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/cloud/qe/CloudCoordinator.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/cloud/qe/CloudCoordinator.java
@@ -29,6 +29,7 @@ import org.apache.doris.planner.Planner;
 import org.apache.doris.planner.ScanNode;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.qe.Coordinator;
+import org.apache.doris.resource.computegroup.ComputeGroupMgr;
 import org.apache.doris.thrift.TUniqueId;
 
 import com.google.common.base.Strings;
@@ -86,10 +87,8 @@ public class CloudCoordinator extends Coordinator {
 
         if (idToBackend == null || idToBackend.isEmpty()) {
             LOG.warn("no available backends, idToBackend {}", idToBackend);
-            String clusterName = ConnectContext.get() != null
-                    ? ConnectContext.get().getCloudCluster() : "ctx empty cant 
get clusterName";
-            throw new UserException("no available backends, the cluster maybe 
not be set or been dropped clusterName = "
-                + clusterName);
+            String computeGroupHints = 
ComputeGroupMgr.computeGroupNotFoundPromptMsg(cluster);
+            throw new UserException(computeGroupHints);
         }
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
index 642242be419..d852b9df554 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
@@ -23,6 +23,7 @@ import org.apache.doris.catalog.JdbcResource;
 import org.apache.doris.catalog.JdbcTable;
 import org.apache.doris.catalog.TableIf.TableType;
 import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.Config;
 import org.apache.doris.common.DdlException;
 import org.apache.doris.common.FeConstants;
 import org.apache.doris.datasource.CatalogProperty;
@@ -40,6 +41,7 @@ import 
org.apache.doris.datasource.mapping.JdbcIdentifierMapping;
 import org.apache.doris.proto.InternalService;
 import org.apache.doris.proto.InternalService.PJdbcTestConnectionRequest;
 import org.apache.doris.proto.InternalService.PJdbcTestConnectionResult;
+import org.apache.doris.resource.computegroup.ComputeGroupMgr;
 import org.apache.doris.rpc.BackendServiceProxy;
 import org.apache.doris.rpc.RpcException;
 import org.apache.doris.system.Backend;
@@ -411,7 +413,12 @@ public class JdbcExternalCatalog extends ExternalCatalog {
             throw new DdlException(e.getMessage());
         }
         if (aliveBe == null) {
-            throw new DdlException("Test BE Connection to JDBC Failed: No 
Alive backends");
+            String computeGroupHints = "";
+            if (Config.isCloudMode()) {
+                // null: computeGroupNotFoundPromptMsg select cluster for hint 
msg
+                computeGroupHints = 
ComputeGroupMgr.computeGroupNotFoundPromptMsg(null);
+            }
+            throw new DdlException("Test BE Connection to JDBC Failed: No 
Alive backends" + computeGroupHints);
         }
         TNetworkAddress address = new TNetworkAddress(aliveBe.getHost(), 
aliveBe.getBrpcPort());
         try {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java
index d6888cf6caa..f8a1678bf42 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java
@@ -41,6 +41,7 @@ import org.apache.doris.common.Config;
 import org.apache.doris.common.DdlException;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.FeConstants;
+import org.apache.doris.common.Pair;
 import org.apache.doris.common.Status;
 import org.apache.doris.common.UserException;
 import org.apache.doris.common.util.DebugUtil;
@@ -1391,6 +1392,30 @@ public class ConnectContext {
 
         String cluster = null;
         String choseWay = null;
+        // 1 get cluster from session
+        String sessionCluster = getSessionVariable().getCloudCluster();
+        if (!Strings.isNullOrEmpty(sessionCluster)) {
+            choseWay = "use session";
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("finally set context compute group name {} for user 
{} with chose way '{}'",
+                        sessionCluster, getCurrentUserIdentity(), choseWay);
+            }
+            return sessionCluster;
+        }
+
+        // 2 get cluster from user
+        String userPropCluster = getDefaultCloudClusterFromUser(true);
+        if (!StringUtils.isEmpty(userPropCluster)) {
+            choseWay = "user property";
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("finally set context compute group name {} for user 
{} with chose way '{}'", userPropCluster,
+                        getCurrentUserIdentity(), choseWay);
+            }
+            return userPropCluster;
+        }
+
+        // 3 get cluster from a cached variable in connect context
+        // this value comes from a cluster selection policy
         if (!Strings.isNullOrEmpty(this.cloudCluster)) {
             cluster = this.cloudCluster;
             choseWay = "use context cluster";
@@ -1429,7 +1454,49 @@ public class ConnectContext {
         return cluster;
     }
 
-    // TODO implement this function
+    private String getDefaultCloudClusterFromUser(boolean checkExist) {
+        String defaultCluster = 
Env.getCurrentEnv().getAuth().getDefaultCloudCluster(getQualifiedUser());
+        if (Strings.isNullOrEmpty(defaultCluster)) {
+            return null;
+        }
+        if (!checkExist) {
+            // default cluster may be dropped.
+            return defaultCluster;
+        }
+
+        // Validate cluster existence
+        List<String> cloudClusterNames = ((CloudSystemInfoService) 
Env.getCurrentSystemInfo()).getCloudClusterNames();
+        if (cloudClusterNames.contains(defaultCluster)) {
+            return defaultCluster;
+        }
+        LOG.warn("default compute group {} of user {} is invalid, all cluster: 
{}", defaultCluster,
+                getQualifiedUser(), cloudClusterNames);
+        return null;
+    }
+
+    // for log use, compute group name and the way to get it
+    // the way may be context policy, session, default compute group from user
+    public static Pair<String, String> computeGroupFromHintMsg() {
+        String clusterName = "";
+        try {
+            if (ConnectContext.get() != null) {
+                clusterName = ConnectContext.get().getCloudCluster();
+            }
+        } catch (Exception e) {
+            clusterName = "ctx empty cant get clusterName";
+
+        }
+        String fromSession = 
ConnectContext.get().getSessionVariable().getCloudCluster();
+        String fromDefaultComputeGroup = 
ConnectContext.get().getDefaultCloudClusterFromUser(false);
+        String clusterFrom = "context policy";
+        if (clusterName.equalsIgnoreCase(fromSession)) {
+            clusterFrom = "session variable";
+        } else if (clusterName.equalsIgnoreCase(fromDefaultComputeGroup)) {
+            clusterFrom = "default compute group from user";
+        }
+        return Pair.of(clusterName, clusterFrom);
+    }
+
     public String getDefaultCloudCluster() {
         List<String> cloudClusterNames = ((CloudSystemInfoService) 
Env.getCurrentSystemInfo()).getCloudClusterNames();
         String defaultCluster = 
Env.getCurrentEnv().getAuth().getDefaultCloudCluster(getQualifiedUser());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
index 3383651f779..fedf66289b8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
@@ -188,6 +188,7 @@ import org.apache.doris.qe.cache.Cache;
 import org.apache.doris.qe.cache.CacheAnalyzer;
 import org.apache.doris.qe.cache.CacheAnalyzer.CacheMode;
 import org.apache.doris.qe.cache.SqlCache;
+import org.apache.doris.resource.computegroup.ComputeGroupMgr;
 import org.apache.doris.rewrite.ExprRewriter;
 import org.apache.doris.rewrite.mvrewrite.MVSelectFailedException;
 import org.apache.doris.rpc.BackendServiceProxy;
@@ -2096,7 +2097,12 @@ public class StmtExecutor {
             }
         }
         if (address == null) {
-            throw new AnalysisException("No Alive backends");
+            String computeGroupHints = "";
+            if (Config.isCloudMode()) {
+                // null: computeGroupNotFoundPromptMsg select cluster for hint 
msg
+                computeGroupHints = 
ComputeGroupMgr.computeGroupNotFoundPromptMsg(null);
+            }
+            throw new AnalysisException("No Alive backends" + 
computeGroupHints);
         }
 
         // 5. send rpc to BE
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/resource/computegroup/ComputeGroupMgr.java
 
b/fe/fe-core/src/main/java/org/apache/doris/resource/computegroup/ComputeGroupMgr.java
new file mode 100644
index 00000000000..569e9b8f3f2
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/resource/computegroup/ComputeGroupMgr.java
@@ -0,0 +1,47 @@
+// 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.resource.computegroup;
+
+import org.apache.doris.common.Pair;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.system.SystemInfoService;
+
+public class ComputeGroupMgr {
+
+    private SystemInfoService systemInfoService;
+
+    public ComputeGroupMgr(SystemInfoService systemInfoService) {
+        this.systemInfoService = systemInfoService;
+    }
+
+    public static String computeGroupNotFoundPromptMsg(String 
physicalClusterName) {
+        StringBuilder sb = new StringBuilder();
+        Pair<String, String> computeGroupInfos = 
ConnectContext.computeGroupFromHintMsg();
+        sb.append(" Unable to find the compute group: ");
+        sb.append("<");
+        if (physicalClusterName == null) {
+            sb.append(computeGroupInfos.first);
+        } else {
+            sb.append(physicalClusterName);
+        }
+        sb.append(">");
+        sb.append(". Please check if the compute group has been deleted. how 
this compute group is selected: ");
+        sb.append(computeGroupInfos.second);
+        return sb.toString();
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/ExternalFileTableValuedFunction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/ExternalFileTableValuedFunction.java
index 9f9f769c780..e67d695bd8e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/ExternalFileTableValuedFunction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/ExternalFileTableValuedFunction.java
@@ -32,6 +32,7 @@ import org.apache.doris.catalog.StructType;
 import org.apache.doris.catalog.Table;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.Config;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.Pair;
 import org.apache.doris.common.UserException;
@@ -57,6 +58,7 @@ import org.apache.doris.proto.Types.PTypeDesc;
 import org.apache.doris.proto.Types.PTypeNode;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.qe.SessionVariable;
+import org.apache.doris.resource.computegroup.ComputeGroupMgr;
 import org.apache.doris.rpc.BackendServiceProxy;
 import org.apache.doris.rpc.RpcException;
 import org.apache.doris.system.Backend;
@@ -234,7 +236,12 @@ public abstract class ExternalFileTableValuedFunction 
extends TableValuedFunctio
         columns = Lists.newArrayList();
         Backend be = getBackend();
         if (be == null) {
-            throw new AnalysisException("No Alive backends");
+            String computeGroupHints = "";
+            if (Config.isCloudMode()) {
+                // null: computeGroupNotFoundPromptMsg select cluster for hint 
msg
+                computeGroupHints = 
ComputeGroupMgr.computeGroupNotFoundPromptMsg(null);
+            }
+            throw new AnalysisException("No Alive backends" + 
computeGroupHints);
         }
 
         if (fileFormatProperties.getFileFormatType() == 
TFileFormatType.FORMAT_WAL) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/NumbersTableValuedFunction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/NumbersTableValuedFunction.java
index b40658e4796..e3486123ddb 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/NumbersTableValuedFunction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/NumbersTableValuedFunction.java
@@ -21,6 +21,8 @@ import org.apache.doris.catalog.Column;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.PrimitiveType;
 import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.Config;
+import org.apache.doris.resource.computegroup.ComputeGroupMgr;
 import org.apache.doris.system.Backend;
 import org.apache.doris.thrift.TDataGenFunctionName;
 import org.apache.doris.thrift.TDataGenScanRange;
@@ -122,7 +124,12 @@ public class NumbersTableValuedFunction extends 
DataGenTableValuedFunction {
             }
         }
         if (backendList.isEmpty()) {
-            throw new AnalysisException("No Alive backends");
+            String computeGroupHints = "";
+            if (Config.isCloudMode()) {
+                // null: computeGroupNotFoundPromptMsg select cluster for hint 
msg
+                computeGroupHints = 
ComputeGroupMgr.computeGroupNotFoundPromptMsg(null);
+            }
+            throw new AnalysisException("No Alive backends" + 
computeGroupHints);
         }
 
         Collections.shuffle(backendList);
diff --git 
a/regression-test/suites/cloud_p0/multi_cluster/test_no_cluster_hits.groovy 
b/regression-test/suites/cloud_p0/multi_cluster/test_no_cluster_hits.groovy
index 82a77ecb368..41c1ad21ed5 100644
--- a/regression-test/suites/cloud_p0/multi_cluster/test_no_cluster_hits.groovy
+++ b/regression-test/suites/cloud_p0/multi_cluster/test_no_cluster_hits.groovy
@@ -134,6 +134,7 @@ suite('test_no_cluster_hits', 'multi_cluster, docker') {
             assertTrue(e.getMessage().contains("ComputeGroupException: 
CURRENT_USER_NO_AUTH_TO_USE_COMPUTE_GROUP"))
             assertTrue(e.getMessage().contains("set default compute group 
failed"))
         } 
+        sql """SET PROPERTY FOR 'root' 'default_cloud_cluster' = 
${currentCluster.cluster}"""
 
         // no cluster
         def tag = getCloudBeTagByName(currentCluster.cluster)
@@ -153,14 +154,37 @@ suite('test_no_cluster_hits', 'multi_cluster, docker') {
             result.size() == 0
         }
 
+        cluster.addBackend(1, "testCluster")
+
         try {
-            // errCode = 2, detailMessage = The current compute group 
compute_cluster is not registered in the system
-            sql """
-                select * from $table
-            """
+            // test root's default cluster invalid
+            connectInDocker('root', '') {
+                sql """insert into $table values (3, 3)"""
+            }
+        } catch (Exception e) {
+            logger.info("exception: {}", e.getMessage())
+            assertTrue(e.getMessage().contains("Unable to find the compute 
group: <compute_cluster>"))
+        } 
+
+        try {
+            connectInDocker('root', '') {
+                sql """select * from $table"""
+            }
         } catch (Exception e) {
             logger.info("exception: {}", e.getMessage())
-            assertTrue(e.getMessage().contains("The current compute group 
compute_cluster is not registered in the system"))
+            assertTrue(e.getMessage().contains("Unable to find the compute 
group: <compute_cluster>"))
         } 
+
+
+        try {
+            // test tvf
+            connectInDocker('root', '') {
+                sql """select * from numbers("number" = "100")"""
+            }
+        } catch (Exception e) {
+            logger.info("exception: {}", e.getMessage())
+            assertTrue(e.getMessage().contains("how this compute group is 
selected: default compute group from user"))
+        }
+        
     }
 }


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

Reply via email to