Range-check a UInt64 constant converted to DateTime - #118367
Range-check a UInt64 constant converted to DateTime#118367alexey-milovidov wants to merge 1 commit into
UInt64 constant converted to DateTime#118367Conversation
A `DateTime` stores a `UInt32`, so a `UInt64` constant that does not fit it
cannot equal any value of the column. The conversion took such a constant
unchanged - `UInt64` is the canonical `Field` type of `DateTime`, so it looked
like nothing had to be done - and the column insertion downstream truncated it
modulo 2^32:
SELECT count() FROM t WHERE dt = toUInt64(4294967296); -- 0
SELECT count() FROM t WHERE dt IN (toUInt64(4294967296)); -- 1: matched the epoch row
SELECT count() FROM t WHERE dt NOT IN (toUInt64(4294967296)); -- 2: a row lost
At default settings the disjunction rewrite turns an `OR` chain of equalities
into `IN`, so a `WHERE` in which every comparison is individually false returned
every row the constants wrapped onto.
The `Date`, `Date32` and `Time` branches next to it already range-check for the
same reason; `DateTime` now does too. A constant outside the range is excluded
from a set, as an out-of-range integer for a numeric column already was, and the
`values` table function rejects it the way it rejects one for `Date` or `UInt8`.
Closes: #117244
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
TL;DR: the fix itself looks right and fail-safe on every consumer I traced (set members get excluded exactly,
Happy to file the |

A
DateTimestores aUInt32, so aUInt64constant that does not fit it cannot equal any value of the column. The conversion took such a constant unchanged -UInt64is the canonicalFieldtype ofDateTime, so it looked like nothing had to be done - and the column insertion downstream truncated it modulo 2^32:The
Date,Date32andTimebranches next to it already range-check for the same reason;DateTimenow does too. A constant outside the range is excluded from a set, as an out-of-range integer for a numeric column already was.One note on the
valuespath: the issue asks forvalues('x DateTime', toUInt64(4294967296))to produce whatCASTproduces (a wrapped2106-02-07 06:28:15). It now raisesARGUMENT_OUT_OF_BOUNDinstead, which is what that path already does forDate,Date32and evenUInt8-values('x UInt8', toUInt64(256))has always been an error whileCASTwraps. Rejecting it keepsDateTimeconsistent with every other type there.Closes: #117244
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
Fixed a
UInt64constant that does not fitUInt32matching an unrelated row of aDateTimecolumn inIN(and in anORchain of equalities, which is rewritten intoIN): the constant was truncated modulo 2^32 instead of being excluded from the set.Workflow [PR]
Sync PR [sync-upstream/pr/118367]