diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ArithmeticExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ArithmeticExpr.java index 3df32f0ae9..1a962680e2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ArithmeticExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ArithmeticExpr.java @@ -505,7 +505,7 @@ public class ArithmeticExpr extends Expr { if (((ScalarType) type).getScalarScale() != ((ScalarType) children.get(1).type).getScalarScale()) { castChild(type, 1); } - } else if (op == Operator.DIVIDE && t1TargetType.isDecimalV3()) { + } else if (op == Operator.DIVIDE && (t1TargetType.isDecimalV3())) { int leftPrecision = t1Precision + t2Scale + Config.div_precision_increment; int leftScale = t1Scale + t2Scale + Config.div_precision_increment; if (leftPrecision > ScalarType.MAX_DECIMAL128_PRECISION) { @@ -515,7 +515,15 @@ public class ArithmeticExpr extends Expr { type = castBinaryOp(Type.DOUBLE); break; } - castChild(ScalarType.createDecimalV3Type(leftPrecision, leftScale), 0); + Expr child = getChild(0); + if (child instanceof DecimalLiteral) { + DecimalLiteral literalChild = (DecimalLiteral) child; + Expr newChild = literalChild + .castToDecimalV3ByDivde(ScalarType.createDecimalV3Type(leftPrecision, leftScale)); + setChild(0, newChild); + } else { + castChild(ScalarType.createDecimalV3Type(leftPrecision, leftScale), 0); + } } else if (op == Operator.MOD) { // TODO use max int part + max scale of two operands as result type // because BE require the result and operands types are the exact the same decimalv3 type diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java index 8cc25b9b27..be93975efb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java @@ -63,6 +63,8 @@ public class CastExpr extends Expr { // True if this cast does not change the type. private boolean noOp = false; + private boolean notFold = false; + private static final Map, Function.NullableMode> TYPE_NULLABLE_MODE; static { @@ -582,5 +584,13 @@ public class CastExpr extends Expr { public String getStringValueForArray() { return children.get(0).getStringValueForArray(); } + + public void setNotFold(boolean notFold) { + this.notFold = notFold; + } + + public boolean isNotFold() { + return this.notFold; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java index 81fe2bf755..47e98e1142 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java @@ -384,6 +384,13 @@ public class DecimalLiteral extends LiteralExpr { return super.uncheckedCastTo(targetType); } + public Expr castToDecimalV3ByDivde(Type targetType) { + // onlye use in DecimalLiteral divide DecimalV3 + CastExpr expr = new CastExpr(targetType, this); + expr.setNotFold(true); + return expr; + } + @Override public int hashCode() { return 31 * super.hashCode() + Objects.hashCode(value); diff --git a/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java b/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java index dcc0bede70..8b65597812 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java +++ b/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java @@ -109,6 +109,9 @@ public class FoldConstantsRule implements ExprRewriteRule { // cast-to-types and that can lead to query failures, e.g., CTAS if (expr instanceof CastExpr) { CastExpr castExpr = (CastExpr) expr; + if (castExpr.isNotFold()) { + return castExpr; + } if (castExpr.getChild(0) instanceof NullLiteral) { return castExpr.getChild(0); } diff --git a/regression-test/data/correctness/test_cast_as_decimalv3.out b/regression-test/data/correctness/test_cast_as_decimalv3.out index 2e7ab315b3..9032acc1ee 100644 --- a/regression-test/data/correctness/test_cast_as_decimalv3.out +++ b/regression-test/data/correctness/test_cast_as_decimalv3.out @@ -1,9 +1,14 @@ -- This file is automatically generated. You should know what you did if you want to edit this -- !select1 -- -0.333333333333333333333333 -0.250000000000000000000000 -0.200000000000000000000000 +0.333333 +0.250000 +0.200000 -- !select2 -- 0.333333 +-- !select3 -- +0.33333 +0.25000 +0.20000 + diff --git a/regression-test/suites/correctness/test_cast_as_decimalv3.groovy b/regression-test/suites/correctness/test_cast_as_decimalv3.groovy index 6bf346ad87..b7e4998a23 100644 --- a/regression-test/suites/correctness/test_cast_as_decimalv3.groovy +++ b/regression-test/suites/correctness/test_cast_as_decimalv3.groovy @@ -47,4 +47,7 @@ suite("test_cast_as_decimalv3") { qt_select2 """ select cast(1 as DECIMALV3(5, 2)) / cast(3 as DECIMALV3(5, 2)) """ + qt_select3 """ + select 1.0 / val from divtest order by id + """ } \ No newline at end of file