cockroachdb / cockroachdb/cockroach
sql/opt: NormalizeCmpTimeZoneFunction silently masks "exceeds supported timestamp bounds" errors
- Dominant language
- Go
- Stars
- 32.5k
- Forks
- 4.1k
- PR merge metrics
- PR metrics pending
Description
**Describe the problem**
The `NormalizeCmpTimeZoneFunction` (and its `NormalizeCmpTimeZoneFunctionTZ`
sibling) normalization rule rewrites a predicate of the form
`timezone(zone, ts) op const` into `ts op (timezone-shifted const)`,
hoisting the per-row `timezone(...)` call out so the comparison can use a
constant on the right-hand side. When the per-row evaluation of
`timezone(zone, ts)` would push the value past the supported `TIMESTAMP`
bound (`294276-12-31 23:59:59.999999`), the rewrite silently suppresses the
bounds error and returns a result that the original expression could not
have produced.
This is the same class of bug as #125751 — predicate rewrites that ignore
runtime evaluation errors — but for a different rule and a different error
class (timestamp bounds vs. float precision). #125751 does not mention this
rule.
**To Reproduce**
Setup:
```sql
CREATE TABLE t (ts TIMESTAMP);
INSERT INTO t VALUES ('294276-12-31 23:59:59.999999'); -- upper TIMESTAMP bound
```
With the rule disabled, per-row evaluation errors as expected:
```sql
SET disable_optimizer_rules = 'NormalizeCmpTimeZoneFunction';
SELECT timezone('America/Denver', ts) >= '2020-06-01 12:35:55-07' FROM t;
```
```
ERROR: timestamp "294277-01-01T06:59:59Z" exceeds supported timestamp bounds
```
With the rule enabled (default), the query silently succeeds:
```sql
SET disable_optimizer_rules = '';
SELECT timezone('America/Denver', ts) >= '2020-06-01 12:35:55-07' FROM t;
```
```
?column?
------------
true
(1 row)
```
`EXPLAIN (OPT)` confirms the rewrite:
- Rule enabled: `ts >= '2020-06-01 13:35:55'` (no `timezone(...)` call).
- Rule disabled: `timezone('America/Denver', ts) >= '2020-06-01 12:35:55-07'`.
**Expected behavior**
If a per-row evaluation of `timezone(zone, ts)` would error with
\"timestamp exceeds supported timestamp bounds\", the query should error
regardless of whether the optimizer chooses to rewrite the predicate. The
rewrite is only valid when the two plans agree on success-and-error
behavior across all input rows.
**Actual behavior**
With the rule enabled (the default), the rewritten plan never evaluates
`timezone(zone, ts)` per row, so the bounds check is bypassed and the
query returns `true` for the boundary row.
**Additional context**
How it was found: a per-rule differential testing harness for the
optimizer's normalization rules. For each query in the rules' hand-written
testdata, run with the rule enabled and again with
`SET disable_optimizer_rules = ''`. Any divergence in the result
set is a candidate correctness bug. Random boundary-aware data populated
by `randgen.PopulateTableWithRandData` (which inserts upper-bound
`TIMESTAMP` values) caused the bounds-error case to surface for this
rule in the `pkg/sql/opt/norm/testdata/rules/comp` corpus.
A self-contained regression check, as a logictest stanza appended to
`pkg/sql/logictest/testdata/logic_test/timestamp` — fails on master,
will pass once the rule is patched:
```text
subtest regression_normalize_cmp_timezone_bounds
statement ok
CREATE TABLE timezone_bounds_t (ts TIMESTAMP)
statement ok
INSERT INTO timezone_bounds_t VALUES ('294276-12-31 23:59:59.999999')
# Sanity check: with the rule disabled, per-row evaluation errors as
# expected on the boundary row.
statement ok
SET disable_optimizer_rules = 'NormalizeCmpTimeZoneFunction'
query error exceeds supported timestamp bounds
SELECT timezone('America/Denver', ts) >= '2020-06-01 12:35:55-07' FROM timezone_bounds_t
statement ok
SET disable_optimizer_rules = ''
# With the rule enabled (default), the rewrite must not silently mask
# the bounds error.
query error exceeds supported timestamp bounds
SELECT timezone('America/Denver', ts) >= '2020-06-01 12:35:55-07' FROM timezone_bounds_t
statement ok
DROP TABLE timezone_bounds_t
subtest end
```
Related: #125751 — `sql: optimizer folds away constants in arithmetic
equality comparisons` — same class of bug for `NormalizeCmpPlusConst` /
`NormalizeCmpConstMinus` and float precision rather than timestamp bounds.
Jira issue: CRDB-63328
Contributor guide
Assessment
This issue has not been assessed yet.