Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ public static Expression divideDouble(DoubleLiteral first, DoubleLiteral second)
*/
@ExecFunction(name = "divide")
public static Expression divideDecimal(DecimalLiteral first, DecimalLiteral second) {
if (first.getValue().compareTo(BigDecimal.ZERO) == 0) {
if (second.getValue().compareTo(BigDecimal.ZERO) == 0) {
return new NullLiteral(first.getDataType());
}
BigDecimal result = first.getValue().divide(second.getValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,27 @@ void testFoldString() {
}, "soundex only supports ASCII");
}

@Test
void testFoldDivideDecimalV2() {
executor = new ExpressionRuleExecutor(ImmutableList.of(
bottomUp(FoldConstantRuleOnFE.VISITOR_INSTANCE)
));
// 0 / 5 over DecimalV2 literals must fold to decimal 0 through the full FoldConstantRuleOnFE
// dispatch (which selects NumericArithmetic.divideDecimal), not NULL.
Divide divide = new Divide(new DecimalLiteral(new BigDecimal(0)), new DecimalLiteral(new BigDecimal(5)));
Expression rewritten = executor.rewrite(divide, context);
Assertions.assertFalse(rewritten instanceof NullLiteral, "0 / 5 must not fold to NULL, got " + rewritten);
Assertions.assertTrue(rewritten instanceof DecimalLiteral,
"0 / 5 should fold to a decimal literal, got " + rewritten);
Assertions.assertEquals(0, ((DecimalLiteral) rewritten).getValue().compareTo(BigDecimal.ZERO),
"0 / 5 should fold to 0");

// 5 / 0 over DecimalV2 literals must fold to NULL (Doris/MySQL divide-by-zero semantics).
divide = new Divide(new DecimalLiteral(new BigDecimal(5)), new DecimalLiteral(new BigDecimal(0)));
rewritten = executor.rewrite(divide, context);
Assertions.assertTrue(rewritten instanceof NullLiteral, "5 / 0 should fold to NULL, got " + rewritten);
}

@Test
void testleFoldNumeric() {
executor = new ExpressionRuleExecutor(ImmutableList.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@

package org.apache.doris.nereids.trees.expressions.functions.executable;

import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
import org.apache.doris.nereids.trees.expressions.literal.DecimalLiteral;
import org.apache.doris.nereids.trees.expressions.literal.DecimalV3Literal;
import org.apache.doris.nereids.trees.expressions.literal.DoubleLiteral;
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
import org.apache.doris.nereids.types.DecimalV2Type;
import org.apache.doris.nereids.types.DecimalV3Type;

Expand All @@ -47,6 +49,29 @@ public void testDecimalV2Abs() {
Assertions.assertEquals(DecimalV2Type.createDecimalV2Type(10, 0), result.getDataType());
}

@Test
public void testDivideDecimalZeroNumerator() {
// 0 / 5 must fold to decimal 0, not NULL. The zero-guard must check the
// denominator (second), not the numerator (first).
DecimalLiteral zero = new DecimalLiteral(DecimalV2Type.createDecimalV2Type(10, 0), new BigDecimal(0));
DecimalLiteral five = new DecimalLiteral(DecimalV2Type.createDecimalV2Type(10, 0), new BigDecimal(5));
Expression result = NumericArithmetic.divideDecimal(zero, five);
Assertions.assertTrue(result instanceof DecimalLiteral,
"0 / 5 should fold to a decimal, but got " + result);
Assertions.assertEquals(0, ((DecimalLiteral) result).getValue().compareTo(BigDecimal.ZERO),
"0 / 5 should fold to 0");
}

@Test
public void testDivideDecimalZeroDenominator() {
// 5 / 0 must fold to NULL (SQL divide-by-zero semantics), not throw.
DecimalLiteral five = new DecimalLiteral(DecimalV2Type.createDecimalV2Type(10, 0), new BigDecimal(5));
DecimalLiteral zero = new DecimalLiteral(DecimalV2Type.createDecimalV2Type(10, 0), new BigDecimal(0));
Expression result = NumericArithmetic.divideDecimal(five, zero);
Assertions.assertTrue(result instanceof NullLiteral,
"5 / 0 should fold to NULL, but got " + result);
}

@Test
public void testSignBit() {
Assertions.assertEquals(BooleanLiteral.FALSE, NumericArithmetic.signbit(new DoubleLiteral(0.0)));
Expand Down
Loading