Repository navigation
fix(model): compare date values in the query builder and dynamic finders as dates on SQLite - #4281
Conversation
…ers as dates on SQLite Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Peter Amiri <peter@alurium.com>
rev1-r1 review: head
|
… value
$unwrapDateLiteral() now changes a value only when it is exactly {ts 'yyyy-mm-dd HH:mm:ss[.f]'},
{d 'yyyy-mm-dd'} or {t 'HH:mm:ss[.f]'}; text such as {d 'abc'} stays verbatim. It still applies
to any column type, because SQLite date columns are often declared TEXT and are typed as strings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Peter Amiri <peter@alurium.com>
Wheels Test Results214 247 tests 210 150 ✅ 1h 3m 52s ⏱️ Results for commit f2c47dd. |
rev1-r1 re-review: head
|
Summary
A date passed to the query builder or a dynamic finder now compares as a date on SQLite.
The values in
where(column, operator, value),whereBetween(),whereIn()and dynamic finders (findOneByPublishedAt(date)) go through the adapter's$quoteValue(str), which takes a string. A CFML date object becomes its CFML literal there,{ts '2026-09-28 00:00:00'}, on Lucee, Adobe and BoxLang alike.2026-10-01 09:00:00, the formatsave()writes). It never matches, sowhere("publishedAt", ">=", someDate)silently returned no rows. A string literal in afindAll(where=...)worked.Change
Base.$quoteValue()first passes the value through a new$unwrapDateLiteral(). A value that is exactly a CFML date literal becomes the textsave()writes:{ts 'X'}X{d 'X'}X 00:00:00{t 'X'}1899-12-30 XThat is the same mapping the SQLite migrator applies to stored literals. Any other value is unchanged: a date written as a string, or text that merely looks like a literal, such as
{d 'abc'}or{ts 'not a date'}.Why there is no column-type check. The unwrap applies to any column type and relies only on the exact literal shape. SQLite date columns are often declared
TEXT(the core test schema'sc_o_r_e_profiles.dateofbirthis one), and Wheels types those asstring/cf_sql_varchar, while the same column on MySQL isdatetime/cf_sql_timestamp. A "date-like types only" check would leave the bug in place exactly where it bites. The only text that changes is a string that is exactly a CFML date literal, which in practice comes from a date object.Tests
model/QueryBuilderDateValueSpec(5 query checks plus 3 for$unwrapDateLiteral(): literal shapes, non-date text left verbatim, and{d 'abc'}quoted verbatim for a text column). Each creates its own rows from date objects in a year no fixture uses and rolls them back. It covers:where()with>=and<;whereBetween();whereIn();🤖 Generated with Claude Code