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

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


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new 38b0dbcff56 branch-4.1: [fix](fe) Fix NereidsCoordinator not created 
in proxy flow due to missing parsedStatement on StatementContext #64363 (#64437)
38b0dbcff56 is described below

commit 38b0dbcff56fd2611d06749a6a9e2dbc5df7880a
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Mon Jun 15 13:48:29 2026 +0800

    branch-4.1: [fix](fe) Fix NereidsCoordinator not created in proxy flow due 
to missing parsedStatement on StatementContext #64363 (#64437)
    
    Cherry-picked from #64363
    
    Co-authored-by: starocean999 <[email protected]>
---
 .../java/org/apache/doris/qe/StmtExecutor.java     | 10 ++++++
 .../java/org/apache/doris/qe/StmtExecutorTest.java | 38 ++++++++++++++++++++++
 2 files changed, 48 insertions(+)

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 da70264331c..6de5d241c60 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
@@ -882,6 +882,16 @@ public class StmtExecutor {
             }
             parsedStmt = statements.get(originStmt.idx);
         }
+        // In the proxy flow (multi-FE forwarding), the StatementContext is 
created fresh
+        // without a parsedStatement. Propagate it so that downstream code like
+        // canUseNereidsDistributePlanner can correctly identify the Nereids 
execution
+        // context, ensuring EnvFactory creates a NereidsCoordinator instead 
of a legacy
+        // Coordinator (which would fail with "fragment has no children").
+        // Only do this when isProxy is true, because other code paths like
+        // executeInternalQuery() rely on legacy Coordinator behavior with 
mock backends.
+        if (isProxy) {
+            this.context.getStatementContext().setParsedStatement(parsedStmt);
+        }
     }
 
     public void finalizeQuery() {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/qe/StmtExecutorTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/qe/StmtExecutorTest.java
index 3e3f4ba9d49..c778c965f6d 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/qe/StmtExecutorTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/qe/StmtExecutorTest.java
@@ -301,4 +301,42 @@ public class StmtExecutorTest extends TestWithFeService {
 
         Mockito.verify(resultFileSink).setDeleteExistingFiles(false);
     }
+
+    @Test
+    public void testParseByNereidsSetsParsedStatementOnStatementContext() 
throws Exception {
+        // This test verifies the fix for a bug in multi-FE environments where
+        // parseByNereids() did not propagate the parsed statement to the
+        // StatementContext. In the proxy flow (e.g., when a follower FE 
forwards
+        // a query to the master FE), the StmtExecutor is created via the proxy
+        // constructor which creates a fresh StatementContext without a
+        // parsedStatement. Without the fix, 
statementContext.getParsedStatement()
+        // remains null, causing 
SessionVariable.canUseNereidsDistributePlanner()
+        // to return false, which leads EnvFactory.createCoordinator() to 
create
+        // a legacy Coordinator instead of NereidsCoordinator, resulting in
+        // "fragment has no children" error.
+
+        // Simulate the proxy flow: StmtExecutor(ConnectContext, 
OriginStatement, boolean isProxy)
+        StmtExecutor executor = new StmtExecutor(connectContext,
+                new OriginStatement("select 1", 0), true);
+
+        // Before parsing, statementContext should exist but parsedStatement 
should be null
+        Assertions.assertNotNull(connectContext.getStatementContext());
+        
Assertions.assertNull(connectContext.getStatementContext().getParsedStatement(),
+                "ParsedStatement should be null before parseByNereids() in 
proxy flow");
+
+        // Trigger parseByNereids via reflection (it's private)
+        Method parseByNereidsMethod = 
StmtExecutor.class.getDeclaredMethod("parseByNereids");
+        parseByNereidsMethod.setAccessible(true);
+        parseByNereidsMethod.invoke(executor);
+
+        // After parsing, parsedStatement should be set on the StatementContext
+        org.apache.doris.analysis.StatementBase parsedStatement
+                = connectContext.getStatementContext().getParsedStatement();
+        Assertions.assertNotNull(parsedStatement,
+                "ParsedStatement should not be null after parseByNereids() in 
proxy flow");
+        Assertions.assertTrue(
+                parsedStatement instanceof 
org.apache.doris.nereids.glue.LogicalPlanAdapter,
+                "ParsedStatement should be a LogicalPlanAdapter after 
parseByNereids(), but was: "
+                        + (parsedStatement == null ? "null" : 
parsedStatement.getClass().getName()));
+    }
 }


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

Reply via email to