matrixorigin / matrixorigin/matrixone
[Bug]: DECIMAL256 SUM persists values beyond its declared precision
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
## Description
`SUM(DECIMAL(65,0))` can produce and persist a 66-digit value even though the expression and destination column are both declared `DECIMAL(65,0)`, MatrixOne's maximum public Decimal precision.
The declared precision is not enforced during aggregation, CTAS, or `INSERT ... SELECT`, so a column can contain a value outside its own SQL type domain.
## Environment
- MatrixOne: latest official `main`, commit `07fdd4ae0f80f287b93fc4b525fd296d5617abc7`
- Deployment: local standalone launch (isolated Log/TN/CN ports and data directory)
## Reproduction
```sql
create table src(d decimal(65,0));
insert into src values
(99999999999999999999999999999999999999999999999999999999999999999),
(1);
select cast(sum(d) as char), length(cast(sum(d) as char)) from src;
create table dst as select sum(d) s from src;
show create table dst;
select cast(s as char), length(cast(s as char)) from dst;
create table explicit_dst(s decimal(65,0));
insert into explicit_dst select sum(d) from src;
select cast(s as char), length(cast(s as char)) from explicit_dst;
```
## Actual behavior
All three paths return/store:
```text
100000000000000000000000000000000000000000000000000000000000000000
```
which contains 66 digits. `SHOW CREATE TABLE dst` still reports `s DECIMAL(65,0)`.
The negative mirror stores the 66-digit magnitude with a minus sign as well. Results reproduced identically in 3/3 fresh runs.
## Expected behavior
Because the exact result exceeds the declared maximum precision, the aggregate or assignment must return a Decimal out-of-range error. A `DECIMAL(65,0)` column must not persist a 66-digit magnitude.
## Controls
- signed/unsigned integer and `BIT(64)` SUM/AVG widen correctly and remain consistent across DOP 1/8 and resident/spill paths;
- valid in-range `DECIMAL(65,0)` sums remain exact;
- comparison confirms the returned sum is greater than the maximum legal `DECIMAL(65,0)` value, rather than a formatting artifact.
## Code-path analysis
`SumReturnType` in `pkg/sql/colexec/aggexec/sumavg2.go` declares every Decimal256 SUM as `DECIMAL(65, input_scale)`. Accumulation uses `Decimal256.Add256`, whose overflow check covers the physical 256-bit integer container, not the public 65-digit SQL precision. CTAS and assignment then preserve the out-of-domain payload without a width check.
## Related but distinct
- #28585 tracks failure to widen `DECIMAL(38)` SUM into Decimal256 for representable results.
- This report starts with an already-Decimal256 `DECIMAL(65)` input and concerns failure to enforce the maximum declared result precision.
## Suggested regression coverage
- positive and negative precision-65 overflow by one digit;
- ordinary/grouped/window/DISTINCT SUM, DOP 1/>1, partial/final, and spill;
- CTAS and `INSERT ... SELECT` into explicit Decimal destinations;
- near-boundary in-range controls.
## Duplicate search
Open and closed issues were searched for Decimal256 SUM overflow, `DECIMAL(65,0)`, 66-digit values, CTAS, and declared precision. Existing #28584/#28585 concern Decimal128 widening rather than this Decimal256 domain violation.
Contributor guide
Assessment
This issue has not been assessed yet.