Skip to content

Bind SQLite timestamp parameters as the exact stored text#78

Draft
myieye wants to merge 2 commits into
mainfrom
fix/linq2db-timestamp-params
Draft

Bind SQLite timestamp parameters as the exact stored text#78
myieye wants to merge 2 commits into
mainfrom
fix/linq2db-timestamp-params

Conversation

@myieye

@myieye myieye commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

linq2db renders DateTime/DateTimeOffset parameters truncated to milliseconds while Microsoft.Data.Sqlite stores 7-digit TEXT and SQLite's strftime rounds — so timestamp comparisons via linq2db could misclassify rows. In lexbox this made WhereAfter via ToLinqToDB() match the target commit itself and delete it during snapshot regeneration (see sillsdev/languageforge-lexbox#2391).

  • DateTime/DateTimeOffset parameters now bind as the exact TEXT Microsoft.Data.Sqlite writes (yyyy-MM-dd HH:mm:ss.FFFFFFF, UTC), so both sides of a comparison normalize identically.
  • Remaining limitation (inherent, documented in code): linq2db wraps SQLite timestamp comparisons in strftime('...%f') on both sides — millisecond-grained, not configurable — so same-millisecond commits compare equal. Use EF where exact ordering matters (e.g. WhereAfter); OrderBy on a timestamp column is unaffected.
  • Tests: linq2db variant of the tick-scale filter test (millisecond and coarser scales), and a WhereAfter self-exclusion regression test seeded with sub-millisecond timestamps ≥ 0.5ms — both fail without the fix.

🤖 Generated with Claude Code

linq2db renders DateTime/DateTimeOffset parameters truncated to
milliseconds while Microsoft.Data.Sqlite stores 7-digit TEXT and
SQLite's strftime rounds to the nearest millisecond, so timestamp
comparisons could misclassify rows around the parameter value. In
lexbox this made WhereAfter via ToLinqToDB() classify the target
commit as after itself and delete it during snapshot regeneration.

Binding parameters as the exact stored text makes both sides of a
comparison normalize identically. linq2db comparisons remain
millisecond-grained (strftime '%f' wraps both sides), so exact
same-millisecond ordering still requires EF.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dc19c475-e287-4259-86d1-73cd5150f599

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/linq2db-timestamp-params

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

myieye added a commit to sillsdev/languageforge-lexbox that referenced this pull request Jul 7, 2026
linq2db renders timestamp parameters truncated to milliseconds while
SQLite's strftime (which linq2db wraps around every timestamp
comparison) rounds to the nearest millisecond, so WhereAfter via
ToLinqToDB() classified targetCommit as after itself and deleted it —
the PreserveAllFieldWorksCommits CI failure (~25% of runs,
timezone-independent; reproducible on this branch, not on develop,
because reusing Harmony's mapping schema changed how the parameter
renders). sillsdev/harmony#78 fixes the parameter rendering, but
linq2db comparisons stay millisecond-grained, so exact commit
ordering belongs in EF regardless.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An active test alarms when a linq2db upgrade changes the translation,
unlike a skipped failing test, which never runs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
myieye added a commit to sillsdev/languageforge-lexbox that referenced this pull request Jul 7, 2026
…mp (#2391)

* Add cross-ORM date parity test; run FwLite tests under non-UTC zone

* Reuse Harmony's linq2db schema so NormalizeTimestamp is unneeded

* Cover DeletedAt and de-duplicate the timestamp parity test

* Delete commits after a snapshot target via EF, not linq2db

linq2db renders timestamp parameters truncated to milliseconds while
SQLite's strftime (which linq2db wraps around every timestamp
comparison) rounds to the nearest millisecond, so WhereAfter via
ToLinqToDB() classified targetCommit as after itself and deleted it —
the PreserveAllFieldWorksCommits CI failure (~25% of runs,
timezone-independent; reproducible on this branch, not on develop,
because reusing Harmony's mapping schema changed how the parameter
renders). sillsdev/harmony#78 fixes the parameter rendering, but
linq2db comparisons stay millisecond-grained, so exact commit
ordering belongs in EF regardless.

* Set a last user in the comment timestamp parity test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant