Skip to content

TIMETZ display drops offset on echo round-trip (12:00:00+00 → 12:00:00) #34

@rustyconover

Description

@rustyconover

Symptom

Round-tripping a TIMETZ value through example.echo strips the timezone
offset from the displayed/serialised value. The filter logic correctly
selects the row, but the value in the result row no longer carries +00
or whatever offset it had on input.

Reproduction

ATTACH 'example' AS example (TYPE vgi, LOCATION '${VGI_TEST_WORKER}');

-- DuckDB-native: row value renders as 12:00:00+00
SELECT t FROM (VALUES ('12:00:00+00'::TIMETZ)) v(t);
-- 12:00:00+00

-- Through example.echo: row value renders as 12:00:00 (offset lost)
SELECT t FROM example.echo((SELECT * FROM (VALUES ('12:00:00+00'::TIMETZ)) v(t)));
-- 12:00:00

Where to look

DuckDB.time_tz is registered as a canonical Arrow extension at
vgi/duckdb/src/common/arrow/arrow_type_extension.cpp:561
backed by fixed_size_binary(8). The echo passthrough rebuilds a
RecordBatch from the input batch on the way back. Probably the schema for
the rebuilt batch reports time64[us] (the canonical Arrow time type)
instead of preserving the extension<DuckDB.time_tz> wrapper, so DuckDB
on receive interprets the value as plain TIME and prints without the
offset.

The fix should keep the extension type marker on the rebuilt schema, so
the wire format declares extension<DuckDB.time_tz> and DuckDB knows to
unpack the offset on read.

Coverage gap

Uncovered today; surfaced while writing
vgi/test/sql/integration/filter_pushdown/time_tz.test.
That test now selects only the row id (SELECT n FROM ...) to sidestep
this display issue. A time_tz_roundtrip.test that verifies the value
round-trips with offset intact would catch this.

Priority

Low-to-medium — only affects display, not correctness of filtering. But
if downstream consumers depend on TIMETZ values carrying their original
offset, this silently corrupts that.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions