fix(plugin-snowflake): keep a timestamp offset the date parser cannot represent as text - #2468
Merged
datlechin merged 1 commit intoAug 26, 2026
Conversation
… represent as text Claude-Session: https://claude.ai/code/session_01Qk1xfY3vnneRifC22eV2r7
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This was referenced Aug 26, 2026
Merged
datlechin
added a commit
that referenced
this pull request
Aug 26, 2026
…dpoint sends (#2466) * fix(plugin-snowflake): decode the wire encodings the query-request endpoint sends Claude-Session: https://claude.ai/code/session_01Qk1xfY3vnneRifC22eV2r7 * fix(plugin-snowflake): give every statement builder one SQL escaper (#2467) Claude-Session: https://claude.ai/code/session_01Qk1xfY3vnneRifC22eV2r7 * fix(plugin-snowflake): keep a timestamp offset the date parser cannot represent as text (#2468) Claude-Session: https://claude.ai/code/session_01Qk1xfY3vnneRifC22eV2r7 * fix(plugin-snowflake): take the affected row count from the statement type, not a column name (#2469) Claude-Session: https://claude.ai/code/session_01Qk1xfY3vnneRifC22eV2r7 * fix(plugin-snowflake): key the shared session on the saved connection and scope Stop to its own driver (#2470) Claude-Session: https://claude.ai/code/session_01Qk1xfY3vnneRifC22eV2r7 --------- Co-authored-by: Ngo Quoc Dat <datlechin@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found by a Codex review of the decoder.
The defect
TIMESTAMP_TZcarries its zone as minutes biased by +1440, so the field can express any offset in a day. The decoder accepted anything under 24 hours and wrote it as a+HH:MMsuffix.DatabaseDateParser.timeZone(fromSuffix:)ends in:Measured on this toolchain,
TimeZone(secondsFromGMT:)returns a zone up to exactly+18:00and nil at+18:30. So an offset above eighteen hours becamenil, the?? .gmtread it as UTC, and an epoch-zero payload at+18:30was shown as 18:30 UTC instead of 00:00 UTC: the instant moved by eighteen and a half hours, silently.The fix
The decoder now emits an offset only when the shared parser can represent it, and keeps the raw text otherwise. A value that cannot survive the round trip is not written in a spelling the reader will misread.
This follows the rule the rest of the decoder already keeps: an encoding that cannot be decoded confidently is returned exactly as it arrived, never turned into a plausible looking value.
Tests
Four cases pinning the boundary:
+18:00and-18:00decode,+18:30and-18:30keep their raw text.Verified: build PASS, 38/38 across the decoder and escaping suites, SwiftLint 0 violations.
Related, not fixed here
The same review raised a second boundary problem worth recording. The decoder emits proleptic Gregorian dates, which is what Snowflake documents, but
DatabaseDateParserbuilds a Foundation.gregoriancalendar that applies the 1582 Julian cutover. A date in the reform gap,1582-10-05through1582-10-14, failskeepsItsDayand does not parse, and an older date resolves to a different absolute day.The practical effect is limited and is not a regression: an unparsed date still displays as its own correct text, and the picker routing added with the primary fix sends it to the text editor rather than to a picker set to today. What it loses is date-format rendering and charting for pre-1582 values.
Fixing it properly means making the shared parser proleptic, which changes behaviour for every driver, so it belongs with the app-side temporal work rather than here.