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]