This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.0 by this push:
new 6cd317ae584 branch-4.0: [fix](parser) Fix FROM DUAL incorrectly
matching table names starting with dual #59003 (#59021)
6cd317ae584 is described below
commit 6cd317ae584420fb5a3bd7edd4510e70bdddf5eb
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Wed Dec 17 16:02:12 2025 +0800
branch-4.0: [fix](parser) Fix FROM DUAL incorrectly matching table names
starting with dual #59003 (#59021)
Cherry-picked from #59003
Co-authored-by: zy-kkk <[email protected]>
---
.../antlr4/org/apache/doris/nereids/DorisLexer.g4 | 3 ---
.../antlr4/org/apache/doris/nereids/DorisParser.g4 | 3 ++-
.../doris/nereids/parser/LogicalPlanBuilder.java | 13 +++++-----
regression-test/data/query_p0/dual/dual.out | 15 +++++++++++
regression-test/suites/query_p0/dual/dual.groovy | 30 ++++++++++++++++++++++
5 files changed, 54 insertions(+), 10 deletions(-)
diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
index 8cf376907f0..414d2d5043a 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
@@ -714,9 +714,6 @@ BRACKETED_COMMENT
;
-FROM_DUAL
- : 'FROM' WS+ 'DUAL' -> channel(HIDDEN);
-
WS
: [ \r\n\t]+ -> channel(HIDDEN)
;
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 2f895bc8cbd..ae2103dbd8c 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
@@ -1253,7 +1253,8 @@ whereClause
;
fromClause
- : FROM relations
+ : FROM DUAL #fromDual
+ | FROM relations #fromRelations
;
// For PL-SQL
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 72f7ce3d99c..eaeca5669f3 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
@@ -217,7 +217,8 @@ import org.apache.doris.nereids.DorisParser.ExportContext;
import org.apache.doris.nereids.DorisParser.ExpressionWithEofContext;
import org.apache.doris.nereids.DorisParser.ExpressionWithOrderContext;
import org.apache.doris.nereids.DorisParser.FixedPartitionDefContext;
-import org.apache.doris.nereids.DorisParser.FromClauseContext;
+import org.apache.doris.nereids.DorisParser.FromDualContext;
+import org.apache.doris.nereids.DorisParser.FromRelationsContext;
import org.apache.doris.nereids.DorisParser.FunctionArgumentsContext;
import org.apache.doris.nereids.DorisParser.FunctionIdentifierContext;
import org.apache.doris.nereids.DorisParser.GroupConcatContext;
@@ -1878,8 +1879,8 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
)
);
query = withTableAlias(query, ctx.tableAlias());
- if (ctx.fromClause() != null) {
- query = withRelations(query,
ctx.fromClause().relations().relation());
+ if (ctx.fromClause() instanceof FromRelationsContext) {
+ query = withRelations(query, ((FromRelationsContext)
ctx.fromClause()).relations().relation());
}
query = withFilter(query, Optional.ofNullable(ctx.whereClause()));
String tableAlias = null;
@@ -2479,11 +2480,11 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
SelectClauseContext selectCtx = ctx.selectClause();
LogicalPlan selectPlan;
LogicalPlan relation;
- if (ctx.fromClause() == null) {
+ if (ctx.fromClause() == null || ctx.fromClause() instanceof
FromDualContext) {
relation = new
LogicalOneRowRelation(StatementScopeIdGenerator.newRelationId(),
ImmutableList.of(new Alias(Literal.of(0))));
} else {
- relation = visitFromClause(ctx.fromClause());
+ relation = visitFromRelations((FromRelationsContext)
ctx.fromClause());
}
if (ctx.intoClause() != null &&
!ConnectContext.get().isRunProcedure()) {
throw new ParseException("Only procedure supports insert into
variables", selectCtx);
@@ -3616,7 +3617,7 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
}
@Override
- public LogicalPlan visitFromClause(FromClauseContext ctx) {
+ public LogicalPlan visitFromRelations(FromRelationsContext ctx) {
return ParserUtils.withOrigin(ctx, () ->
visitRelations(ctx.relations()));
}
diff --git a/regression-test/data/query_p0/dual/dual.out
b/regression-test/data/query_p0/dual/dual.out
index fee517f8f2c..fa14b5f70a7 100644
--- a/regression-test/data/query_p0/dual/dual.out
+++ b/regression-test/data/query_p0/dual/dual.out
@@ -63,6 +63,21 @@
-- !sql --
1
+-- !sql --
+1 2
+
+-- !sql --
+2
+
+-- !sql --
+1
+
+-- !sql --
+1
+
+-- !sql --
+3
+
-- !sql --
1
1
diff --git a/regression-test/suites/query_p0/dual/dual.groovy
b/regression-test/suites/query_p0/dual/dual.groovy
index 868fdce895b..373b6c108f9 100644
--- a/regression-test/suites/query_p0/dual/dual.groovy
+++ b/regression-test/suites/query_p0/dual/dual.groovy
@@ -42,6 +42,36 @@ suite('dual') {
qt_sql 'select a from (select 1 as a from dual union all select 2 as a
from dual) u'
qt_sql 'select row_number() over (order by 1) from dual;'
+ // Test CTE with name starting with 'dual' - should not be confused with
FROM DUAL
+ qt_sql '''
+ with dualtbl as (
+ select 1 as col1, 2 as col2
+ )
+ select col1, col2 from dualtbl
+ '''
+
+ qt_sql '''
+ with dualtbl as (
+ select 1 as a
+ ),
+ dual2 as (
+ select a + 1 as b from dualtbl
+ )
+ select * from dual2
+ '''
+
+ // Test subquery alias starting with 'dual'
+ qt_sql 'select * from (select 1 as x) dualtbl'
+ qt_sql 'select dualtbl.x from (select 1 as x) dualtbl'
+
+ // Multiple CTEs referencing each other with dual-prefix names
+ qt_sql '''
+ with duala as (select 1 as v),
+ dualb as (select v + 1 as v from duala),
+ dualc as (select v + 1 as v from dualb)
+ select * from dualc
+ '''
+
// Dropping and creating a table named 'dual' to test behavior when dual
is a real table
sql 'drop table if exists `dual`'
sql '''
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]