Skip to content

Commit aed82bf

Browse files
LiBinfengYour Name
authored andcommitted
[Fix](Nereids) fix floor/round/ceil/truncate functions type compute precision problem (#43422)
- Problem function like ```select floor(300.343, 2)``` precision should be 5 and scale should be 2, but now is (6, 2) after compute precision, but after folding const on fe, it changed to (5, 2) but upper level of plan still expect the output of child to be (6, 2). So it would rise an exception when executing. - How it was fixed fix folding constant precision of floor/round/ceil/truncate functions from (5, 2) to (6, 2) in upper case - Notion when second value is negative and it absolute value >= precision - value, it can not be expressed in fe which result is zero with decimal type (3, 0). like 000. So just let it go back and no using folding constant by fe. - Related PR: #40744 - Release note Fix floor/round/ceil functions precision problem in folding constant
1 parent fbf81f4 commit aed82bf

File tree

2 files changed

+39
-20
lines changed

2 files changed

+39
-20
lines changed

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmetic.java

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -694,20 +694,25 @@ private static Expression checkOutputBoundary(Literal input) {
694694
return input;
695695
}
696696

697+
private static Expression castDecimalV3Literal(DecimalV3Literal literal, int precision) {
698+
return new DecimalV3Literal(DecimalV3Type.createDecimalV3Type(precision, literal.getValue().scale()),
699+
literal.getValue());
700+
}
701+
697702
/**
698703
* round
699704
*/
700705
@ExecFunction(name = "round")
701706
public static Expression round(DecimalV3Literal first) {
702-
return first.round(0);
707+
return castDecimalV3Literal(first.round(0), first.getValue().precision());
703708
}
704709

705710
/**
706711
* round
707712
*/
708713
@ExecFunction(name = "round")
709714
public static Expression round(DecimalV3Literal first, IntegerLiteral second) {
710-
return first.round(second.getValue());
715+
return castDecimalV3Literal(first.round(second.getValue()), first.getValue().precision());
711716
}
712717

713718
/**
@@ -733,15 +738,15 @@ public static Expression round(DoubleLiteral first, IntegerLiteral second) {
733738
*/
734739
@ExecFunction(name = "ceil")
735740
public static Expression ceil(DecimalV3Literal first) {
736-
return first.roundCeiling(0);
741+
return castDecimalV3Literal(first.roundCeiling(0), first.getValue().precision());
737742
}
738743

739744
/**
740745
* ceil
741746
*/
742747
@ExecFunction(name = "ceil")
743748
public static Expression ceil(DecimalV3Literal first, IntegerLiteral second) {
744-
return first.roundCeiling(second.getValue());
749+
return castDecimalV3Literal(first.roundCeiling(second.getValue()), first.getValue().precision());
745750
}
746751

747752
/**
@@ -767,15 +772,15 @@ public static Expression ceil(DoubleLiteral first, IntegerLiteral second) {
767772
*/
768773
@ExecFunction(name = "floor")
769774
public static Expression floor(DecimalV3Literal first) {
770-
return first.roundFloor(0);
775+
return castDecimalV3Literal(first.roundFloor(0), first.getValue().precision());
771776
}
772777

773778
/**
774779
* floor
775780
*/
776781
@ExecFunction(name = "floor")
777782
public static Expression floor(DecimalV3Literal first, IntegerLiteral second) {
778-
return first.roundFloor(second.getValue());
783+
return castDecimalV3Literal(first.roundFloor(second.getValue()), first.getValue().precision());
779784
}
780785

781786
/**
@@ -1136,21 +1141,10 @@ public static Expression mathE() {
11361141
public static Expression truncate(DecimalV3Literal first, IntegerLiteral second) {
11371142
if (first.getValue().compareTo(BigDecimal.ZERO) == 0) {
11381143
return first;
1144+
} else if (first.getValue().compareTo(BigDecimal.ZERO) < 0) {
1145+
return castDecimalV3Literal(first.roundCeiling(second.getValue()), first.getValue().precision());
11391146
} else {
1140-
if (first.getValue().scale() < second.getValue()) {
1141-
return first;
1142-
}
1143-
if (second.getValue() < 0) {
1144-
double factor = Math.pow(10, Math.abs(second.getValue()));
1145-
return new DecimalV3Literal(
1146-
DecimalV3Type.createDecimalV3Type(first.getValue().precision(), 0),
1147-
BigDecimal.valueOf(Math.floor(first.getDouble() / factor) * factor));
1148-
}
1149-
if (first.getValue().compareTo(BigDecimal.ZERO) == -1) {
1150-
return first.roundCeiling(second.getValue());
1151-
} else {
1152-
return first.roundFloor(second.getValue());
1153-
}
1147+
return castDecimalV3Literal(first.roundFloor(second.getValue()), first.getValue().precision());
11541148
}
11551149
}
11561150

regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_numeric_arithmatic.groovy

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,4 +409,29 @@ test {
409409

410410
//Additional cases for Xor, Conv, and other mathematical functions
411411
testFoldConst("SELECT CONV(-10, 10, 2) AS conv_invalid_base") //Conv with negative input (may be undefined)
412+
413+
// fix floor/ceil/round function return type with DecimalV3 input
414+
testFoldConst("with cte as (select floor(300.343) order by 1 limit 1) select * from cte")
415+
testFoldConst("with cte as (select round(300.343) order by 1 limit 1) select * from cte")
416+
testFoldConst("with cte as (select ceil(300.343) order by 1 limit 1) select * from cte")
417+
418+
testFoldConst("with cte as (select floor(300.343, 2) order by 1 limit 1) select * from cte")
419+
testFoldConst("with cte as (select round(300.343, 2) order by 1 limit 1) select * from cte")
420+
testFoldConst("with cte as (select ceil(300.343, 2) order by 1 limit 1) select * from cte")
421+
testFoldConst("with cte as (select truncate(300.343, 2) order by 1 limit 1) select * from cte")
422+
423+
testFoldConst("with cte as (select floor(300.343, 0) order by 1 limit 1) select * from cte")
424+
testFoldConst("with cte as (select round(300.343, 0) order by 1 limit 1) select * from cte")
425+
testFoldConst("with cte as (select ceil(300.343, 0) order by 1 limit 1) select * from cte")
426+
testFoldConst("with cte as (select truncate(300.343, 0) order by 1 limit 1) select * from cte")
427+
428+
testFoldConst("with cte as (select floor(300.343, -1) order by 1 limit 1) select * from cte")
429+
testFoldConst("with cte as (select round(300.343, -1) order by 1 limit 1) select * from cte")
430+
testFoldConst("with cte as (select ceil(300.343, -1) order by 1 limit 1) select * from cte")
431+
testFoldConst("with cte as (select truncate(300.343, -1) order by 1 limit 1) select * from cte")
432+
433+
testFoldConst("with cte as (select floor(300.343, -4) order by 1 limit 1) select * from cte")
434+
testFoldConst("with cte as (select round(300.343, -4) order by 1 limit 1) select * from cte")
435+
testFoldConst("with cte as (select ceil(300.343, -4) order by 1 limit 1) select * from cte")
436+
testFoldConst("with cte as (select truncate(300.343, -4) order by 1 limit 1) select * from cte")
412437
}

0 commit comments

Comments
 (0)