This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.2 by this push:
new 0ba9170608d branch-4.2: [fix](expr opt) Preserve cast boundaries
during arithmetic simplification #67733 (#70017)
0ba9170608d is described below
commit 0ba9170608df1faa61066a322cec0366d7600a43
Author: morrySnow <[email protected]>
AuthorDate: Tue Nov 3 17:00:35 2026 +0800
branch-4.2: [fix](expr opt) Preserve cast boundaries during arithmetic
simplification #67733 (#70017)
picked from master #67733
---
.../expression/rules/SimplifyArithmeticRule.java | 56 ++++------------------
.../expression/SimplifyArithmeticRuleTest.java | 13 +++++
.../sql/presto/scalar/timestamp/TestOperators.sql | 2 +-
3 files changed, 23 insertions(+), 48 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticRule.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticRule.java
index 6eea495e5cf..3076e36ec52 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticRule.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticRule.java
@@ -22,12 +22,10 @@ import
org.apache.doris.nereids.rules.expression.ExpressionPatternRuleFactory;
import org.apache.doris.nereids.rules.expression.ExpressionRuleType;
import org.apache.doris.nereids.trees.expressions.Add;
import org.apache.doris.nereids.trees.expressions.BinaryArithmetic;
-import org.apache.doris.nereids.trees.expressions.Cast;
import org.apache.doris.nereids.trees.expressions.Divide;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.Multiply;
import org.apache.doris.nereids.trees.expressions.Subtract;
-import org.apache.doris.nereids.types.DataType;
import org.apache.doris.nereids.util.TypeCoercionUtils;
import org.apache.doris.nereids.util.TypeUtils;
import org.apache.doris.nereids.util.Utils;
@@ -138,16 +136,13 @@ public class SimplifyArithmeticRule implements
ExpressionPatternRuleFactory {
// isAddOrSub: true for extract only "+" or "-" sub expressions, false for
extract only "*" or "/" sub expressions
private static List<Operand> flatten(Expression expr, boolean isAddOrSub) {
List<Operand> result = Lists.newArrayList();
- doFlatten(true, expr, isAddOrSub, result, Optional.empty());
+ doFlatten(true, expr, isAddOrSub, result);
return result;
}
// flag: true for '+' or '*', false for '-' or '/'
// isAddOrSub: true for extract only "+" or "-" sub expressions, false for
extract only "*" or "/" sub expressions
- private static void doFlatten(boolean flag, Expression expr, boolean
isAddOrSub, List<Operand> result,
- Optional<DataType> castType) {
- // cast (a * 10 as double) * (cast 20 as double)
- // => cast(a as double) * (cast 10 as double) * (cast 20 as double)
+ private static void doFlatten(boolean flag, Expression expr, boolean
isAddOrSub, List<Operand> result) {
BinaryArithmetic arithmetic = null;
Predicate<Expression> isPositiveArithmetic = isAddOrSub
? TypeUtils::isAdd : TypeUtils::isMultiply;
@@ -156,52 +151,20 @@ public class SimplifyArithmeticRule implements
ExpressionPatternRuleFactory {
Predicate<Expression> isPosNegArithmetic =
isPositiveArithmetic.or(isNegativeArithmetic);
if (isPosNegArithmetic.test(expr)) {
arithmetic = (BinaryArithmetic) expr;
- } else if (expr instanceof Cast && hasConstantOperand(expr,
isAddOrSub)) {
- Cast cast = (Cast) expr;
- if (isPosNegArithmetic.test(cast.child())) {
- arithmetic = (BinaryArithmetic) cast.child();
- castType = Optional.of(cast.getDataType());
- }
}
if (arithmetic != null) {
- doFlatten(flag, arithmetic.left(), isAddOrSub, result, castType);
+ doFlatten(flag, arithmetic.left(), isAddOrSub, result);
if (isNegativeArithmetic.test(arithmetic) && !flag) {
- doFlatten(true, arithmetic.right(), isAddOrSub, result,
castType);
+ doFlatten(true, arithmetic.right(), isAddOrSub, result);
} else if (isPositiveArithmetic.test(arithmetic) && !flag) {
- doFlatten(false, arithmetic.right(), isAddOrSub, result,
castType);
+ doFlatten(false, arithmetic.right(), isAddOrSub, result);
} else {
- doFlatten(!isNegativeArithmetic.test(arithmetic),
arithmetic.right(), isAddOrSub, result, castType);
+ doFlatten(!isNegativeArithmetic.test(arithmetic),
arithmetic.right(), isAddOrSub, result);
}
} else {
- if (castType.isPresent()) {
- result.add(Operand.of(flag,
TypeCoercionUtils.castIfNotSameType(expr, castType.get())));
- } else {
- result.add(Operand.of(flag, expr));
- }
- }
- }
-
- private static boolean hasConstantOperand(Expression expr, boolean
isAddOrSub) {
- if (expr.isConstant()) {
- return true;
- }
-
- Predicate<Expression> checkArithmetic = isAddOrSub
- ? TypeUtils::isAddOrSubtract : TypeUtils::isMultiplyOrDivide;
- BinaryArithmetic arithmetic = null;
- if (checkArithmetic.test(expr)) {
- arithmetic = (BinaryArithmetic) expr;
- } else if (expr instanceof Cast) {
- Cast cast = (Cast) expr;
- if (checkArithmetic.test(cast.child())) {
- arithmetic = (BinaryArithmetic) cast.child();
- }
- }
- if (arithmetic != null) {
- return hasConstantOperand(arithmetic.left(), isAddOrSub)
- || hasConstantOperand(arithmetic.right(), isAddOrSub);
- } else {
- return false;
+ // Keep non-arithmetic expressions atomic. In particular, moving a
cast to the
+ // operands can change rounding, overflow, error and null behavior.
+ result.add(Operand.of(flag, expr));
}
}
@@ -241,4 +204,3 @@ public class SimplifyArithmeticRule implements
ExpressionPatternRuleFactory {
}
}
}
-
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyArithmeticRuleTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyArithmeticRuleTest.java
index df14840f628..cb09906214b 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyArithmeticRuleTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyArithmeticRuleTest.java
@@ -95,6 +95,19 @@ class SimplifyArithmeticRuleTest extends
ExpressionRewriteTestHelper {
assertRewriteAfterSimplify("-IA / 2.0 * ((-IB - 1) - (3 + (IC + 4)))",
"(((0 - IA) / 2.0) * (((0 - IB) - 1) - (3 + (IC + 4))))");
}
+ @Test
+ void testPreserveCastAroundArithmetic() {
+ executor = new ExpressionRuleExecutor(ImmutableList.of(
+ bottomUp(SimplifyArithmeticRule.INSTANCE)
+ ));
+
+ String castExpression = "cast(LA - 9223372036854775800 as double) +
cast(0 as double)";
+ assertRewriteAfterSimplify(castExpression, castExpression);
+
+ String tryCastExpression = "try_cast(LA - 9223372036854775800 as
double) + cast(0 as double)";
+ assertRewriteAfterSimplify(tryCastExpression, tryCastExpression);
+ }
+
@Test
void testSimplifyArithmeticComparison() {
executor = new ExpressionRuleExecutor(ImmutableList.of(
diff --git
a/regression-test/suites/external_table_p0/dialect_compatible/sql/presto/scalar/timestamp/TestOperators.sql
b/regression-test/suites/external_table_p0/dialect_compatible/sql/presto/scalar/timestamp/TestOperators.sql
index 5a3d008a0e4..c8510432786 100644
---
a/regression-test/suites/external_table_p0/dialect_compatible/sql/presto/scalar/timestamp/TestOperators.sql
+++
b/regression-test/suites/external_table_p0/dialect_compatible/sql/presto/scalar/timestamp/TestOperators.sql
@@ -222,6 +222,7 @@ SELECT TIMESTAMP '2020-05-01 12:34:56.123456789' BETWEEN
TIMESTAMP '2020-05-01 1
SELECT TIMESTAMP '2020-05-01 12:34:56.1234567890' BETWEEN TIMESTAMP
'2020-05-01 12:34:56.1234567889' and TIMESTAMP '2020-05-01 12:34:56.1234567891';
SELECT TIMESTAMP '2020-05-01 12:34:56.12345678901' BETWEEN TIMESTAMP
'2020-05-01 12:34:56.1234567890' and TIMESTAMP '2020-05-01
12:34:56.12345678902';
SELECT TIMESTAMP '2020-05-01 12:34:56.123456789012' BETWEEN TIMESTAMP
'2020-05-01 12:34:56.123456789011' and TIMESTAMP '2020-05-01
12:34:56.123456789013';
+set debug_skip_fold_constant=true;
-- SELECT TIMESTAMP '2020-05-01 12:34:56' + INTERVAL '1.123' SECOND; # differ:
doris : None, presto : 2020-05-01 12:34:57.123
-- SELECT TIMESTAMP '2020-05-01 12:34:56.1' + INTERVAL '1.123' SECOND; #
differ: doris : None, presto : 2020-05-01 12:34:57.223
-- SELECT TIMESTAMP '2020-05-01 12:34:56.12' + INTERVAL '1.123' SECOND; #
differ: doris : None, presto : 2020-05-01 12:34:57.243
@@ -389,7 +390,6 @@ SELECT TIMESTAMP '2020-05-01 12:34:56.123456789012' BETWEEN
TIMESTAMP '2020-05-0
-- SELECT TIMESTAMP '2020-05-01 12:34:55.1111111111' - TIMESTAMP '2020-05-01
12:34:56.9999999999'; # differ: doris : -2, presto : -0 00:00:01.889
-- SELECT TIMESTAMP '2020-05-01 12:34:55.11111111111' - TIMESTAMP '2020-05-01
12:34:56.99999999999'; # differ: doris : -2, presto : -0 00:00:01.889
-- SELECT TIMESTAMP '2020-05-01 12:34:55.111111111111' - TIMESTAMP '2020-05-01
12:34:56.999999999999'; # differ: doris : -2, presto : -0 00:00:01.889
-set debug_skip_fold_constant=true;
SELECT TIMESTAMP '2020-05-01 12:34:56' = TIMESTAMP '2020-05-01 12:34:56';
SELECT TIMESTAMP '2020-05-01 12:34:56.1' = TIMESTAMP '2020-05-01 12:34:56.1';
SELECT TIMESTAMP '2020-05-01 12:34:56.12' = TIMESTAMP '2020-05-01 12:34:56.12';
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]