Skip to content

fix(semantics): type DuckDB JSON casts, to_json, AT TIME ZONE and TO_TIMESTAMP - #168

Merged
kvlonge merged 2 commits into
mainfrom
fix/duckdb-json-timezone-types
Nov 11, 2026
Merged

kvlonge merged 2 commits into
mainfrom
fix/duckdb-json-timezone-types

Conversation

@kvlonge

@kvlonge kvlonge commented Nov 11, 2026

Copy link
Copy Markdown
Contributor

Why

DuckDB type inference got four expressions wrong. A cast to JSON (CAST(x AS JSON), x::JSON), to_json(...) and x AT TIME ZONE z had no inferred type. TO_TIMESTAMP(<number>) was inferred as TIMESTAMP, but DuckDB returns TIMESTAMPTZ. Callers that compare declared types with inferred ones reported these columns as unproven.

Changes

  • A cast to JSON and to_json are typed JSON. A cast to JSON[] is typed JSON[].
  • AT TIME ZONE and timezone(z, x) turn TIMESTAMP into TIMESTAMPTZ and TIMESTAMPTZ into TIMESTAMP. Any other or unknown operand stays unknown.
  • TO_TIMESTAMP with one argument is TIMESTAMPTZ.
  • A cast to TIMESTAMP(p) with p other than 6 stays unknown. DuckDB types it TIMESTAMP_S, _MS or _NS, and AT TIME ZONE over it gives TIMESTAMPTZ_NS.
  • Only DuckDB's typing rules change. Other dialects are untouched.

Verification

  • New tests fail on main and pass here, under both DuckDB's own parser and the shared parser. Every expected type is DuckDB 2.0.0's typeof.
  • The engine-recorded type replay types one more case than before (the JSON cast) and allows one untyped case instead of two.
  • Recorded cases: DuckDB is the only target, and 5,253 of 7,961 recorded cases convert. Of those, 584 cases change 786 output types: 774 from unknown to JSON (for example ARRAY_AGG, OBJECT_AGG, MAX_BY and VARIANT reads) and 12 from unknown to TIMESTAMPTZ (TO_TIMESTAMP of a number). No known type changes. DuckDB 2.0.0 DESCRIBE of each converted statement agrees on all 786.
  • cargo test -p sqlquack-semantics --all-features, make check-ci
  • make verify-recorded: 0 failed, and translation results and SQL sizes are unchanged.

…TIMESTAMP

DuckDB type inference left a cast to JSON, to_json and AT TIME ZONE
untyped, and gave TO_TIMESTAMP of a number the type TIMESTAMP. DuckDB
2.0.0 types the first two JSON, flips AT TIME ZONE between TIMESTAMP and
TIMESTAMPTZ, and returns TIMESTAMPTZ from TO_TIMESTAMP. Each is now
typed as the engine types it; AT TIME ZONE over any other operand stays
unknown.
DuckDB's TIMESTAMP holds microseconds; TIMESTAMP(0), (3) and (9) are
TIMESTAMP_S, TIMESTAMP_MS and TIMESTAMP_NS, and AT TIME ZONE over them
gives TIMESTAMPTZ_NS. A cast to any precision but 6 was typed TIMESTAMP,
which AT TIME ZONE now turns into a wrong TIMESTAMPTZ. Such casts stay
unknown.
@kvlonge
kvlonge merged commit 4f7b865 into main Nov 11, 2026
8 checks passed
@kvlonge
kvlonge deleted the fix/duckdb-json-timezone-types branch November 11, 2026 02:27
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