doc: clarify timeTruncate units and when to use it - #1792
Conversation
The listed unit suffixes omitted "ns" and "us", which hid the most useful setting for DATETIME(6) columns. Also document that truncation applies to query arguments only, why truncating to the column's precision matters for indexed comparisons, and that the option cannot be set through Config.Params.
|
For context: this documents the motivation None of that reached the README, so the parameter currently reads as a generic rounding knob rather than the index-usage fix it was added to be. The measurements above just re-confirm it across the currently supported range (MariaDB 10.5-11.8, MySQL 5.7-8.4) and add the |
WalkthroughThe README expands ChangestimeTruncate documentation
Estimated code review effort: 1 (Trivial) | ~2 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@README.md`:
- Line 317: Update the README description for the timeTruncate query argument to
explicitly document "0" as a valid value that disables truncation, while
retaining the existing unit-suffixed duration formats and examples.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
Description
timeTruncateis documented as what it does, but not why you would enable it — and the listed unit suffixes omit the one that matters most for it.1. The unit list is incomplete. The current sentence lists "ms", "s", "m", "h"; it is a copy of the one under
readTimeout, where sub-millisecond units are pointless.time.ParseDurationalso acceptsnsandus, and1usis the interesting value here because it matchesDATETIME(6). As written, the README implies microsecond truncation isn't available.2. There is no motivation.
time.Timearguments are formatted with up to 9 fractional digits (appendDateTimetrims only trailing zeros), so atime.Now()-derived value almost always carries more precision than the column stores. On MariaDB this silently prevents an index range scan — nothing errors and nothing is logged.Measured on a 1M-row table with an indexed
DATETIME(6)column,WHERE last_activity_at >= ?with a 9-fractional-digit argument, driver defaults:timeTruncatetimeTruncate=1usRow counts are identical in every run (876), so truncation does not change the result set. MySQL is unaffected across the supported range; only MariaDB degrades, which is why the README text names it rather than generalising.
On MariaDB,
EXPLAINshowstypegoing fromrange(1000 rows) toindex(998490 rows).keyandkey_lenare unchanged, so the plan still looks like it is using the index — which is what makes this easy to miss.The
interpolateParams=truepath behaves identically (both paths go throughappendDateTime).I have deliberately kept these numbers out of the README; the README change only states the qualitative behaviour.
3.
Config.Paramsis a footgun here.Config.timeTruncateis unexported, so the natural-lookingcfg.Params["timeTruncate"] = "1us"does not set it. Instead the key falls through tohandleParams, which emitsSET timeTruncate = 1usat connect time and fails every connection. The supported paths are the DSN string orcfg.Apply(mysql.TimeTruncate(time.Microsecond)). This is also true ofcompressandcharset; I documented it only undertimeTruncateto keep the change small, but I'm happy to drop that paragraph or move it to a general note under#### Parametersif you'd prefer.Reproduction
Fixture (portable across both engines, no CTEs):
Server-side control, no driver involved:
Driver side — run with and without
timeTruncate=1us, usingtime.Date(2024, 1, 1, 0, 16, 39, 123456789, time.UTC)as the argument, on a single pinned*sql.Conn, readingHandler_read_next+Handler_read_rnd_nextbefore and after:SELECT CAST(? AS CHAR)with the same argument confirms what goes on the wire:2024-01-01 00:16:39.123456789without the option,2024-01-01 00:16:39.123456with it.Checklist