ConstantOrderNormalizationRule reorders integer chains without a range check
- Dominant language
- C++
- Stars
- 41.5k
- Forks
- 3.8k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 515
Description
### What happens?
`ConstantOrderNormalizationRule` hoists the foldable leaves of a commutative integer chain to the front with no range check, so the chain is evaluated in an order the query did not write and an addition that fits raises an overflow error. It flips back under `disabled_optimizers = 'expression_rewriter'`.
### To Reproduce
```sql
CREATE TABLE t(a INTEGER, b INTEGER);
INSERT INTO t VALUES (2147483645, -2);
SET disabled_optimizers = 'expression_rewriter';
SELECT (a + 1) + (b + 2) FROM t;
SET disabled_optimizers = '';
SELECT (a + 1) + (b + 2) FROM t;
```
```
2147483646
Out of Range Error: Overflow in addition of INT32 (3 + 2147483645)!
```
PostgreSQL 17.11 gives `2147483646` and its plan keeps the written order.
With `explain_output = 'OPTIMIZED_ONLY'` the projection is `((3 + a) + b)`: the rule flattens the chain and moves the foldable leaves to the front, `ConstantFoldingRule` folds `1 + 2` into `3`, and `3 + a` is evaluated first, which overflows where the written order does not. The rule is registered at `src/optimizer/optimizer.cpp:50` and `ConstantFoldingRule` at `:51`.
### OS:
macOS 26.6.2, arm64 (Darwin 25.6.0)
### DuckDB Version:
v1.5.5
### DuckDB Client:
CLI
### Hardware:
Apple M5 Pro, 48 GB
### Full Name:
Ryan Lin
### Affiliation:
Student, University of Waterloo
### Did you include all relevant configuration (e.g., CPU architecture, Linux distribution) to reproduce the issue?
- [x] Yes, I have
### Did you include all code required to reproduce the issue?
- [x] Yes, I have
### Did you include all relevant data sets for reproducing the issue?
Not applicable - the reproduction does not require a data set
Contributor guide
Research direction
Reproduce the SQL example with and without expression_rewriter, then inspect the ConstantOrderNormalizationRule and ConstantFoldingRule registered in src/optimizer/optimizer.cpp:50-51. Trace how the integer chain becomes ((3 + a) + b), and add a regression test showing that the written-order result succeeds without an overflow.】【。
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, sql
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100