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

gavinchou 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 858332c72bf [fix] Preserve CurrentConnected in frontends() TVF (#61087)
858332c72bf is described below

commit 858332c72bfeea4391ad5a345842e5e3e3c56365
Author: deardeng <[email protected]>
AuthorDate: Fri Mar 20 01:07:40 2026 +0800

    [fix] Preserve CurrentConnected in frontends() TVF (#61087)
    
    Cause:
    - FRONTENDS() goes through metadata scan and may be generated on master
    FE.
    - In this path, currentConnectedFE context is not always preserved, so
    CurrentConnected falls back to master and WHERE CURRENTCONNECTED='Yes'
    always matches master.
    
    Fix:
    - Reuse TFrontendsMetadataParams.cluster_name as a pass-through slot to
    carry the FE host that accepted the client connection from TVF planning
    to metadata generation.
    - Populate this host in FrontendsTableValuedFunction#getMetaScanRange
    (prefer ConnectContext.currentConnectedFEIp, fallback to self host).
    - Read and apply it in MetadataGenerator#frontendsMetadataResult via
    FrontendsProcNode#getFrontendsInfo(env, infos, currentConnectedFeHost).
    - Add comments at write/read points to explain why cluster_name is
    reused for this pass-through.
    
    Verification:
    - FE UT: org.apache.doris.tablefunction.FrontendsTableValuedFunctionTest
---
 .../doris/common/proc/FrontendsProcNode.java       |  9 ++-
 .../FrontendsTableValuedFunction.java              |  8 +-
 .../doris/tablefunction/MetadataGenerator.java     |  4 +-
 .../FrontendsTableValuedFunctionTest.java          | 93 ++++++++++++++++++++++
 gensrc/thrift/PlanNodes.thrift                     |  1 +
 5 files changed, 112 insertions(+), 3 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/proc/FrontendsProcNode.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/proc/FrontendsProcNode.java
index a4c26b57af6..f83a49bf8bf 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/common/proc/FrontendsProcNode.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/common/proc/FrontendsProcNode.java
@@ -93,6 +93,10 @@ public class FrontendsProcNode implements ProcNodeInterface {
     }
 
     public static void getFrontendsInfo(Env env, List<List<String>> infos) {
+        getFrontendsInfo(env, infos, null);
+    }
+
+    public static void getFrontendsInfo(Env env, List<List<String>> infos, 
String currentConnectedFeHost) {
         InetSocketAddress master = null;
         try {
             master = env.getHaProtocol().getLeader();
@@ -109,7 +113,10 @@ public class FrontendsProcNode implements 
ProcNodeInterface {
         // Because the `show frontend` stmt maybe forwarded from other FE.
         // if we only get self node from currrent catalog, the 
"CurrentConnected" field will always points to Msater FE.
         String selfNode = Env.getCurrentEnv().getSelfNode().getHost();
-        if (ConnectContext.get() != null && 
!Strings.isNullOrEmpty(ConnectContext.get().getCurrentConnectedFEIp())) {
+        if (!Strings.isNullOrEmpty(currentConnectedFeHost)) {
+            selfNode = currentConnectedFeHost;
+        } else if (ConnectContext.get() != null
+                && 
!Strings.isNullOrEmpty(ConnectContext.get().getCurrentConnectedFEIp())) {
             selfNode = ConnectContext.get().getCurrentConnectedFEIp();
         }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsTableValuedFunction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsTableValuedFunction.java
index 79b61d33b28..05b709cd523 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsTableValuedFunction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsTableValuedFunction.java
@@ -30,6 +30,7 @@ import org.apache.doris.thrift.TFrontendsMetadataParams;
 import org.apache.doris.thrift.TMetaScanRange;
 import org.apache.doris.thrift.TMetadataType;
 
+import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
@@ -105,7 +106,12 @@ public class FrontendsTableValuedFunction extends 
MetadataTableValuedFunction {
         TMetaScanRange metaScanRange = new TMetaScanRange();
         metaScanRange.setMetadataType(TMetadataType.FRONTENDS);
         TFrontendsMetadataParams frontendsMetadataParams = new 
TFrontendsMetadataParams();
-        frontendsMetadataParams.setClusterName("");
+        String currentConnectedFe = 
Env.getCurrentEnv().getSelfNode().getHost();
+        if (ConnectContext.get() != null
+                && 
!Strings.isNullOrEmpty(ConnectContext.get().getCurrentConnectedFEIp())) {
+            currentConnectedFe = 
ConnectContext.get().getCurrentConnectedFEIp();
+        }
+        frontendsMetadataParams.setCurrentConnectedFeHost(currentConnectedFe);
         metaScanRange.setFrontendsParams(frontendsMetadataParams);
         return metaScanRange;
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java
 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java
index 97af4edbafc..9bddb165063 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java
@@ -94,6 +94,7 @@ import org.apache.doris.thrift.TBackendsMetadataParams;
 import org.apache.doris.thrift.TCell;
 import org.apache.doris.thrift.TFetchSchemaTableDataRequest;
 import org.apache.doris.thrift.TFetchSchemaTableDataResult;
+import org.apache.doris.thrift.TFrontendsMetadataParams;
 import org.apache.doris.thrift.THudiMetadataParams;
 import org.apache.doris.thrift.THudiQueryType;
 import org.apache.doris.thrift.TJobsMetadataParams;
@@ -552,11 +553,12 @@ public class MetadataGenerator {
             return errorResult("frontends metadata param is not set.");
         }
 
+        TFrontendsMetadataParams frontendsParam = 
params.getFrontendsMetadataParams();
         TFetchSchemaTableDataResult result = new TFetchSchemaTableDataResult();
 
         List<TRow> dataBatch = Lists.newArrayList();
         List<List<String>> infos = Lists.newArrayList();
-        FrontendsProcNode.getFrontendsInfo(Env.getCurrentEnv(), infos);
+        FrontendsProcNode.getFrontendsInfo(Env.getCurrentEnv(), infos, 
frontendsParam.getCurrentConnectedFeHost());
         for (List<String> info : infos) {
             TRow trow = new TRow();
             for (String item : info) {
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/tablefunction/FrontendsTableValuedFunctionTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/tablefunction/FrontendsTableValuedFunctionTest.java
new file mode 100644
index 00000000000..745bec1b302
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/tablefunction/FrontendsTableValuedFunctionTest.java
@@ -0,0 +1,93 @@
+// 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.tablefunction;
+
+import org.apache.doris.catalog.Env;
+import org.apache.doris.catalog.InfoSchemaDb;
+import org.apache.doris.datasource.InternalCatalog;
+import org.apache.doris.mysql.privilege.AccessControllerManager;
+import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.system.SystemInfoService.HostInfo;
+import org.apache.doris.thrift.TMetaScanRange;
+
+import mockit.Expectations;
+import mockit.Mocked;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+
+public class FrontendsTableValuedFunctionTest {
+    private static final String INTERNAL_CTL = 
InternalCatalog.INTERNAL_CATALOG_NAME;
+    private static final String INFO_DB = InfoSchemaDb.DATABASE_NAME;
+
+    @Mocked
+    private Env env;
+    @Mocked
+    private AccessControllerManager accessControllerManager;
+    @Mocked
+    private ConnectContext ctx;
+
+    private void mockContext(String selfHost, String currentConnectedFe) {
+        new Expectations() {
+            {
+                Env.getCurrentEnv();
+                minTimes = 0;
+                result = env;
+
+                env.getAccessManager();
+                minTimes = 0;
+                result = accessControllerManager;
+
+                ConnectContext.get();
+                minTimes = 0;
+                result = ctx;
+
+                accessControllerManager.checkDbPriv(ctx, INTERNAL_CTL, 
INFO_DB, PrivPredicate.SELECT);
+                minTimes = 0;
+                result = true;
+
+                env.getSelfNode();
+                minTimes = 0;
+                result = new HostInfo(selfHost, 9010);
+
+                ctx.getCurrentConnectedFEIp();
+                minTimes = 0;
+                result = currentConnectedFe;
+            }
+        };
+    }
+
+    @Test
+    public void testGetMetaScanRangeUseCurrentConnectedFe() throws Exception {
+        mockContext("self-fe-host", "connected-fe-host");
+        FrontendsTableValuedFunction tvf = new 
FrontendsTableValuedFunction(new HashMap<>());
+        TMetaScanRange range = tvf.getMetaScanRange(Collections.emptyList());
+        Assert.assertEquals("connected-fe-host", 
range.getFrontendsParams().getCurrentConnectedFeHost());
+    }
+
+    @Test
+    public void testGetMetaScanRangeFallbackToSelfNode() throws Exception {
+        mockContext("self-fe-host", "");
+        FrontendsTableValuedFunction tvf = new 
FrontendsTableValuedFunction(new HashMap<>());
+        TMetaScanRange range = tvf.getMetaScanRange(Collections.emptyList());
+        Assert.assertEquals("self-fe-host", 
range.getFrontendsParams().getCurrentConnectedFeHost());
+    }
+}
diff --git a/gensrc/thrift/PlanNodes.thrift b/gensrc/thrift/PlanNodes.thrift
index 64ad52267b3..4092ebff872 100644
--- a/gensrc/thrift/PlanNodes.thrift
+++ b/gensrc/thrift/PlanNodes.thrift
@@ -598,6 +598,7 @@ struct TBackendsMetadataParams {
 
 struct TFrontendsMetadataParams {
   1: optional string cluster_name
+  2: optional string current_connected_fe_host
 }
 
 struct TMaterializedViewsMetadataParams {


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

Reply via email to