[Bug] DECIMALV2 constant folding: 0 / x folds to NULL instead of 0 (divideDecimal checks wrong operand)
- Dominant language
- Java
- Stars
- 15.9k
- Forks
- 3.9k
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 520
Description
### Search before asking
- [x] I had searched in the [issues](https://github.com/apache/doris/issues) and found no similar issues.
### Version
master (Nereids fold-constant `divideDecimal`).
### What's Wrong?
`NumericArithmetic.divideDecimal` (the DECIMALV2 constant-folding `divide` function) guards against division by zero by checking the **numerator** (`first`) instead of the **denominator** (`second`):
```java
public static Expression divideDecimal(DecimalLiteral first, DecimalLiteral second) {
if (first.getValue().compareTo(BigDecimal.ZERO) == 0) { // wrong operand
return new NullLiteral(first.getDataType());
}
BigDecimal result = first.getValue().divide(second.getValue());
return new DecimalLiteral(result);
}
```
When both operands are constant DECIMALV2 literals (so the fold-constant rule invokes `divideDecimal`):
- `0 / x` folds to **NULL** instead of `0` — a silent wrong result.
- `x / 0` skips the guard and calls `BigDecimal.divide(ZERO)`, throwing `ArithmeticException`. This is caught by `ExpressionEvaluator.invoke` and the expression is left unfolded (BE then evaluates it, returning NULL), so it is not a crash, but the FE folding path is incorrect.
The sibling functions `divideDouble` and `divideDecimalV3` both correctly check `second`.
### What You Expected?
`0 / x` should fold to `0`. Division by zero should return NULL (Doris/MySQL semantics), consistent with `divideDouble` and `divideDecimalV3`.
### How to Reproduce?
Constant-fold a DECIMALV2 division whose numerator literal is `0`, with both operands constant DECIMALV2 literals so the Nereids fold-constant rule dispatches to `divideDecimal`. The folded result is NULL where it should be 0.
### Anything Else?
Fix proposed in PR #64675.
### Are you willing to submit PR?
- [x] Yes I am willing to submit a PR!
Contributor guide
Research direction
Start in NumericArithmetic.divideDecimal and compare its operand check with divideDouble and divideDecimalV3. Trace the Nereids constant-folding path for DECIMALV2 literals, then verify that 0 divided by a nonzero value folds to 0 and division by zero produces NULL without an ArithmeticException escaping the folding path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- database
- Issue type
- Bug
- Difficulty
- 1/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100