From a578dbba57e131dcf89ba4fe3872d6e1bb0a66d8 Mon Sep 17 00:00:00 2001 From: morrySnow Date: Mon, 25 May 2026 18:08:16 +0800 Subject: [PATCH] [fix](parser) isNull should under primaryExpression related PR #14967 #15163 --- .../org/apache/doris/nereids/DorisParser.g4 | 8 +++---- .../nereids/parser/LogicalPlanBuilder.java | 4 ++-- .../nereids/parser/NereidsParserTest.java | 24 +++++++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) 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 7c251b2a61b452..78d8d978c6a626 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 @@ -1634,8 +1634,6 @@ lambdaExpression booleanExpression : LOGICALNOT booleanExpression #logicalNot | EXISTS LEFT_PAREN query RIGHT_PAREN #exist - | (ISNULL | IS_NULL_PRED) LEFT_PAREN valueExpression RIGHT_PAREN #isnull - | IS_NOT_NULL_PRED LEFT_PAREN valueExpression RIGHT_PAREN #is_not_null_pred | valueExpression predicate? #predicated | NOT booleanExpression #logicalNot | left=booleanExpression operator=(AND | LOGICALAND) right=booleanExpression #logicalBinary @@ -1689,8 +1687,8 @@ primaryExpression | CASE whenClause+ (ELSE elseExpression=expression)? END #searchedCase | CASE value=expression whenClause+ (ELSE elseExpression=expression)? END #simpleCase | name=CAST LEFT_PAREN expression AS castDataType RIGHT_PAREN #cast - | name=TRY_CAST LEFT_PAREN expression AS castDataType RIGHT_PAREN #tryCast - | DEFAULT LEFT_PAREN qualifiedName RIGHT_PAREN #defaultValue + | name=TRY_CAST LEFT_PAREN expression AS castDataType RIGHT_PAREN #tryCast + | DEFAULT LEFT_PAREN qualifiedName RIGHT_PAREN #defaultValue | constant #constantDefault | interval #intervalLiteral | ASTERISK (exceptOrReplace)* #star @@ -1712,6 +1710,8 @@ primaryExpression | (SUBSTR | SUBSTRING | MID) LEFT_PAREN expression FROM expression (FOR expression)? RIGHT_PAREN #substring | POSITION LEFT_PAREN expression IN expression RIGHT_PAREN #position + | (ISNULL | IS_NULL_PRED) LEFT_PAREN expression RIGHT_PAREN #isnull + | IS_NOT_NULL_PRED LEFT_PAREN expression RIGHT_PAREN #is_not_null_pred | functionCallExpression #functionCall | value=primaryExpression LEFT_BRACKET index=valueExpression RIGHT_BRACKET #elementAt | value=primaryExpression LEFT_BRACKET begin=valueExpression 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 2938d9efb7b487..1751bf90e13b73 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 @@ -5138,12 +5138,12 @@ public Expression visitExist(ExistContext context) { @Override public Expression visitIsnull(IsnullContext context) { - return ParserUtils.withOrigin(context, () -> new IsNull(typedVisit(context.valueExpression()))); + return ParserUtils.withOrigin(context, () -> new IsNull(typedVisit(context.expression()))); } @Override public Expression visitIs_not_null_pred(Is_not_null_predContext context) { - return ParserUtils.withOrigin(context, () -> new Not(new IsNull(typedVisit(context.valueExpression())))); + return ParserUtils.withOrigin(context, () -> new Not(new IsNull(typedVisit(context.expression())))); } public List withInList(PredicateContext ctx) { diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java index 0a8abb2c356017..247facf6b64b8a 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java @@ -30,7 +30,10 @@ import org.apache.doris.nereids.exceptions.SyntaxParseException; import org.apache.doris.nereids.glue.LogicalPlanAdapter; import org.apache.doris.nereids.trees.expressions.Cast; +import org.apache.doris.nereids.trees.expressions.EqualTo; import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.IsNull; +import org.apache.doris.nereids.trees.expressions.Not; import org.apache.doris.nereids.trees.expressions.OrderExpression; import org.apache.doris.nereids.trees.expressions.functions.generator.Unnest; import org.apache.doris.nereids.trees.expressions.literal.DecimalLiteral; @@ -1631,4 +1634,25 @@ public void testUpdateWithOrderByAndLimit() { plan = nereidsParser.parseSingle(sql); Assertions.assertInstanceOf(UpdateCommand.class, plan); } + + @Test + public void testIsNullAndIsNotNullExpression() { + NereidsParser nereidsParser = new NereidsParser(); + String sql = "ISNULL(X) = 1"; + Expression expression = nereidsParser.parseExpression(sql); + + Assertions.assertInstanceOf(EqualTo.class, expression); + Assertions.assertInstanceOf(IsNull.class, expression.child(0)); + + sql = "IS_NULL_PRED(X) = 1"; + expression = nereidsParser.parseExpression(sql); + Assertions.assertInstanceOf(EqualTo.class, expression); + Assertions.assertInstanceOf(IsNull.class, expression.child(0)); + + sql = "IS_NOT_NULL_PRED(X) = 1"; + expression = nereidsParser.parseExpression(sql); + Assertions.assertInstanceOf(EqualTo.class, expression); + Assertions.assertInstanceOf(Not.class, expression.child(0)); + Assertions.assertInstanceOf(IsNull.class, expression.child(0).child(0)); + } }