apache / apache/datafusion

`avg` over a decimal with a negative scale panics with "attempt to divide by zero"

Open Beginner friendly
#24,898 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
9.3k
Forks
2.4k
Avg merge
3d 7h
Merged PRs (30d)
344

Description

### Describe the bug

`DecimalAverager::try_new` (`datafusion/functions-aggregate-common/src/utils.rs`) computes `10^sum_scale` and `10^target_scale` with `pow_wrapping(scale as u32)`. For a negative scale the exponent wraps to a huge value and the wrapped power is 0. `DecimalAverager::avg` then evaluates `target_mul.div_wrapping(sum_mul)` with `sum_mul == 0` and panics.

All four decimal widths are affected (`Decimal32`, `Decimal64`, `Decimal128`, `Decimal256`); the plain aggregate, the grouped aggregate and `avg(DISTINCT ...)` all go through the same helper.

### To Reproduce

```sql
SELECT avg(x) FROM (VALUES (arrow_cast(1, 'Decimal128(10, -2)'))) t(x);
```

```text
thread 'main' panicked at library/core/src/num/mod.rs:475:5:
attempt to divide by zero
```

(`arrow_array::arithmetic::div_wrapping` called from `DecimalAverager::avg`, `datafusion/functions-aggregate-common/src/utils.rs`.)

### Expected behavior

`avg` of `100` and `200` at scale -2 (i.e. 10 000 and 20 000) returns `15000.00` as `Decimal128(14, 2)`, the type `Avg::return_type` already declares for that input.

### Additional context

The two factors are only ever used as the ratio `10^(target_scale - sum_scale)`, which is a plain non-negative exponent whenever the target scale is not smaller than the input scale (already enforced).

Found while running a corpus of extreme-value literals against a debug build of `datafusion-cli`.

Contributor guide

Open the contributing guide

Research direction

Start in datafusion/functions-aggregate-common/src/utils.rs with DecimalAverager::try_new and DecimalAverager::avg, then reproduce the failure using the provided SQL query. Trace how negative scales produce the two power factors, and verify that decimal averages return the expected value without panicking for all four decimal widths and the plain, grouped, and DISTINCT aggregate paths.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, sql
Domain
databases
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.