Skip to content

Support fetching TIMESTAMPTZ as SQL_TYPE_TIMESTAMP #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

staticlibs
Copy link
Collaborator

DuckDB supports TIMESTAMP WITH TIME ZONE data type that stores UTC dates (with specified time zone already applied on DB insert). ODBC does not have a notion of time zones. When client app reads such TIMESTAMP WITH TIME ZONE it needs to be converted into TIMESTAMP WITHOUT TIME ZONE with client-local time zone applied. And such converted timestamp must represent the same moment of time as stored UTC timestamp.

Applying client-local time zone to timestamp is a non-trivial operation

  • the UTC offset depends on both the time zone (for fixed shift) and on the timestamp value (for DST shift).

There are two options to get the effective offset for the specified UTC timestamp in the specified time zone:

  • DuckDB ICU extension, that will use DB-configured time zone
  • OS API, will use OS-configured time zone

Variant with ICU extension appeared to be problematic, as we would like to not link neither to ICU extension (C++ API, not in DuckDB C API) nor to ICU itself (C API exists, but symbols include ICU major version that can change). We can do ICU call from ODBC by creating SQL string and executing it. But this conversion must be performed for every value in every row. And there no reasonbly-easy ways to cache the results. Thus the idea of SQL calls was rejected.

Variant with OS API matches the approach used in JDBC (see duckdb/duckdb-java#166) where JVM-configured time zone is used (invariant 1 there).

The problem with accessing OS API is that <ctime> utilities are not thread-safe until C++20. Thus Windows <timezoneapi.h> and POSIX <time.h> API are used directly. And <ctime> approach is used in tests for cross-checking.

Testing: new test added that fetches TIMESTAMP WITH TIME ZONE value as SQL_C_TYPE_TIMESTAMP and checks that it is shifted correctly.

This change implements support for returning variable-length data to
client with multiple subsequent calls to `SQLGetData`. The ODBC spec
logic for buffer/write/return sizing is relatively straightforward, but
there is a number of corner cases. Also the logic for char, widechar
and binary data differs slightly (different null-termination handling).
This change unifies this logic for all variable-length types in one
place.

Testing: new test is added that covers retrieving data by parts for
char, widechar and binary data. PyODBC test suite is extended to check
the retrieval of overly long strings and also enabled on CI on Windows
(to check the retrieval through the Windows Driver Manager).

Fixes: duckdb#121
@staticlibs staticlibs force-pushed the timestamp_tz_fetch branch from 98b1ff6 to 8dbf0ac Compare May 14, 2025 11:47
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