Skip to content

feat: convert TO_TIMESTAMP_NTZ of a UTC-offset TIMESTAMP_TZ - #125

Closed
kvlonge wants to merge 10 commits into
mainfrom
feat/to-timestamp-ntz-utc
Closed

kvlonge wants to merge 10 commits into
mainfrom
feat/to-timestamp-ntz-utc

Conversation

@kvlonge

@kvlonge kvlonge commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Why

dbt-snowflake's snapshot time, to_timestamp_ntz(convert_timezone('UTC', current_timestamp())), refused with "TO_TIMESTAMP_NTZ of TIMESTAMP_TZ(9) with these arguments". That blocks every check-strategy snapshot and every snapshot with hard_deletes='invalidate'.

Changes

  • TO_TIMESTAMP_NTZ of a TIMESTAMP_TZ known to hold the UTC offset (for example the result of CONVERT_TIMEZONE('UTC', …)) now converts. It takes the same path as the receipt-backed cast to TIMESTAMP_NTZ and keeps the UTC wall-clock time as TIMESTAMP_NTZ(9).

  • TO_TIMESTAMP, the TRY_ form and a TIMESTAMP_TZ without a known offset still refuse.

  • The rule's conditions say so.

  • New receipts, cases/temporal/to_timestamp_ntz_of_utc.toml, recorded under utc-v1:

    • TIMESTAMP_TZ values at four offsets
    • TIMESTAMP_LTZ values
    • the exact snapshot expression, as typing evidence

    Every result is TIMESTAMP_NTZ(9).

This branch includes the layout PR (#124); review the four commits above it.

Verification

  • verify replays the three new cases against their receipts. The existing to_timestamp_ntz_of_zoned receipt (a TIMESTAMP_TZ without a known offset) stays refused.
  • make check-ci, make test-rust, make verify-recorded (results in the gate comment).

The Translate stage's SQL block uses white-space: pre with horizontal scroll,
so a clause-per-line layout shows as laid out. Diagnostics keep wrapping. A
stage is a grid item, so it takes min-width: 0; without it, a long line
widened the whole page.
Converted statements print each clause on its own line, select items and
common table expressions one per line, queries indented by depth and long
CASE expressions broken at WHEN, ELSE and END. Short ones stay on one line.
Only whitespace between tokens changes. convert --compact keeps the single
line, in --json too. Verify replays the laid-out SQL beside the single line
and fails a case whose results differ, whose tokens differ, or whose layout
is not idempotent.
The playground engine takes a compact setting like convert --compact, and
the docs pages that print convert output show the laid-out form.
# Conflicts:
#	tests/unit/python/src/sqlquack/api/main/test_convert.py
Three cases for the snapshot time expression: TIMESTAMP_TZ values at
several offsets, TIMESTAMP_LTZ values under a UTC session, and the
CURRENT_TIMESTAMP() form as typing evidence.
…er utc-v1

Three Snowflake results for cases/temporal/to_timestamp_ntz_of_utc.toml:
the UTC wall-clock time typed TIMESTAMP_NTZ(9) for TIMESTAMP_TZ and
TIMESTAMP_LTZ inputs, and the type of the CURRENT_TIMESTAMP() form.
…C offset

TO_TIMESTAMP_NTZ(CONVERT_TIMEZONE('UTC', x)), the snapshot time
expression dbt-snowflake emits, keeps the UTC wall-clock time as
TIMESTAMP_NTZ(9), as recorded. It takes the same path as the cast to
TIMESTAMP_NTZ. TO_TIMESTAMP, the TRY_ form and a TIMESTAMP_TZ without
a known offset still refuse.
… cases to verify

fensu reads a compared string literal as an unnamed decision; the
function already reads TRY_ and _DATE by affix. The CLI cases repeat
what the recorded cases prove and pushed test_convert.rs past 2,000
lines.
kvlonge added a commit that referenced this pull request Nov 6, 2026

kvlonge commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

Gate at a6176c1: check-ci 0, test-rust passed, verify FAILED with 2 of 11803 cases. to_timestamp_ntz_of_utc_tz and _ltz have nanosecond rows, and the converted SQL raises the existing timestamp_tz_submicro guard where Snowflake returns rows. Nothing wrong is produced, but the cases don't declare that divergence. This moves to after launch: declare the divergence (or drop the nanosecond rows), add the TZ(3) receipt, re-gate.

kvlonge commented Nov 8, 2026

Copy link
Copy Markdown
Contributor Author

Closing: SQLQuack lands through local-gate trains, not PR merges (D94), so open PRs only add clutter (D628/D630). The branch is kept. Any work here that isn't on main yet is tracked by the train owner and lands through a train.

@kvlonge kvlonge closed this Nov 8, 2026
@kvlonge
kvlonge deleted the feat/to-timestamp-ntz-utc branch November 9, 2026 21:31
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