From 8ef34fdd19d06627fee4147c21fee4c08170686d Mon Sep 17 00:00:00 2001 From: ivin Date: Wed, 7 Jan 2026 17:39:26 +0800 Subject: [PATCH] [improve](syntax) compatiable with mysql MOD syntax (#58432) ### What problem does this PR solve? This PR improves compatibility with MySQL arithmetic expression syntax, allow user use `%` and `MOD` to represent modular semantics. Note that the `MOD` is a non-reserved keyword, can be used in arithmetic expressions, MOD function name or to represent aliases in as statements. before: ```sql SELECT 10 MOD 3 as mod; ERROR 1105 (HY000): errCode = 2, detailMessage = mismatched input '3' expecting {, ';'}(line 1, pos 19) ``` after: ```sql mysql> SELECT 10 MOD 3 as mod; +------+ | mod | +------+ | 1 | +------+ ``` Issue Number: close #xxx Related PR: #xxx Problem Summary: ### Release note None ### Check List (For Author) - Test - [x] Regression test - [ ] Unit Test - [ ] Manual test (add detailed scripts or steps below) - [ ] No need to test or manual test. Explain why: - [ ] This is a refactor/code format and no logic has been changed. - [ ] Previous test can cover this change. - [ ] No code files have been changed. - [ ] Other reason - Behavior changed: - [ ] No. - [ ] Yes. - Does this need documentation? - [ ] No. - [ ] Yes. ### Check List (For Reviewer who merge this PR) - [ ] Confirm the release note - [ ] Confirm test cases - [ ] Confirm document - [ ] Add branch pick label --- .../main/antlr4/org/apache/doris/nereids/DorisLexer.g4 | 1 + .../antlr4/org/apache/doris/nereids/DorisParser.g4 | 3 ++- .../doris/nereids/parser/LogicalPlanBuilder.java | 2 ++ .../nereids_p0/operator/test_arithmetic_operators.out | 10 ++++++++++ .../operator/test_arithmetic_operators.groovy | 3 +++ 5 files changed, 18 insertions(+), 1 deletion(-) 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 a8daa3eb89466d..e1cb6076a4a4b6 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 @@ -614,6 +614,7 @@ SUBTRACT: '-'; ASTERISK: '*'; SLASH: '/'; MOD: '%'; +MOD_ALT: 'MOD'; TILDE: '~'; AMPERSAND: '&'; LOGICALAND: '&&'; 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 11be1ad450517c..293599c648a0d8 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 @@ -1612,7 +1612,7 @@ valueExpression | operator=(SUBTRACT | PLUS | TILDE) valueExpression #arithmeticUnary // split arithmeticBinary from 1 to 5 due to they have different operator precedence | left=valueExpression operator=HAT right=valueExpression #arithmeticBinary - | left=valueExpression operator=(ASTERISK | SLASH | MOD | DIV) right=valueExpression #arithmeticBinary + | left=valueExpression operator=(ASTERISK | SLASH | MOD | MOD_ALT | DIV) right=valueExpression #arithmeticBinary | left=valueExpression operator=(PLUS | SUBTRACT) right=valueExpression #arithmeticBinary | left=valueExpression operator=AMPERSAND right=valueExpression #arithmeticBinary | left=valueExpression operator=PIPE right=valueExpression #arithmeticBinary @@ -2117,6 +2117,7 @@ nonReserved | MIN | MINUTE | MINUTES + | MOD_ALT | MODIFY | MONTH | MTMV 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 f769c0aace8823..2425f832617ffa 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 @@ -2999,6 +2999,8 @@ public Expression visitArithmeticBinary(ArithmeticBinaryContext ctx) { return new Divide(left, right); case DorisParser.MOD: return new Mod(left, right); + case DorisParser.MOD_ALT: + return new Mod(left, right); case DorisParser.PLUS: return new Add(left, right); case DorisParser.SUBTRACT: diff --git a/regression-test/data/nereids_p0/operator/test_arithmetic_operators.out b/regression-test/data/nereids_p0/operator/test_arithmetic_operators.out index 218d2376dddbcc..8e841fe2e54671 100644 --- a/regression-test/data/nereids_p0/operator/test_arithmetic_operators.out +++ b/regression-test/data/nereids_p0/operator/test_arithmetic_operators.out @@ -290,3 +290,13 @@ \N \N \N \N \N \N +-- !arith_op30 -- +0.123 0.1 0.3330001831054688 +1.500 0.2680000000000007 0.25 +0.325 1 0 + +-- !arith_op31 -- +0.123 0.1 0.3330001831054688 +1.500 0.2680000000000007 0.25 +0.325 1 0 + diff --git a/regression-test/suites/nereids_p0/operator/test_arithmetic_operators.groovy b/regression-test/suites/nereids_p0/operator/test_arithmetic_operators.groovy index 1cec22cbe4cbcb..3fbd15bd3bb60a 100644 --- a/regression-test/suites/nereids_p0/operator/test_arithmetic_operators.groovy +++ b/regression-test/suites/nereids_p0/operator/test_arithmetic_operators.groovy @@ -76,4 +76,7 @@ suite("test_arithmetic_operators", "query,p0") { qt_arith_op27 "select -10.2 / 0.0, -10.2 / 0, -10.2 % 0.0, -10.2 % 0" qt_arith_op28 "select k5 / 0, k8 / 0, k9 / 0 from ${tableName} order by k1,k2,k3,k4" qt_arith_op29 "select k5 % 0, k8 % 0, k9 % 0 from ${tableName} order by k1,k2,k3,k4" + + qt_arith_op30 "select k5 MOD 3, k8 mod 2, k9 Mod 1 from ${tableName} order by k1,k2,k3,k4" + qt_arith_op31 "select k5 MOD 3, MOD(k8, 2), (k9 MOD 1) as MOD from ${tableName} order by k1,k2,k3,k4" }