Skip to content

fix(migrations): serialize datetime as ISO string for new drivers - #8170

Closed
mjq wants to merge 6 commits into
masterfrom
mjq/fix-migration-datetime-serialization
Closed

fix(migrations): serialize datetime as ISO string for new drivers#8170
mjq wants to merge 6 commits into
masterfrom
mjq/fix-migration-datetime-serialization

Conversation

@mjq

@mjq mjq commented Jul 9, 2026

Copy link
Copy Markdown
Member

The migration runner passes datetime.now() as a parameter in INSERT FORMAT JSONEachRow queries to record migration status. The native ClickHouse driver handles datetime serialization via its binary protocol, but the clickhouse-connect HTTP driver passes parameters through json.dumps which cannot serialize Python datetime objects.

This causes all migrations to fail with 'TypeError: Object of type datetime is not JSON serializable' in regions where the use_clickhouse_connect_driver flag is enabled.

Convert to .isoformat() which is JSON-serializable and parsed correctly by ClickHouse's DateTime type.

Fixes SENTRY-5RCC


🤖: Claude diagnosed and fixed this.

… drivers

The migration runner passes datetime.now() as a parameter in INSERT
FORMAT JSONEachRow queries to record migration status. The native
ClickHouse driver handles datetime serialization via its binary
protocol, but the clickhouse-connect HTTP driver passes parameters
through json.dumps which cannot serialize Python datetime objects.

This causes all migrations to fail with 'TypeError: Object of type
datetime is not JSON serializable' in regions where the
use_clickhouse_connect_driver flag is enabled.

Convert to .isoformat() which is JSON-serializable and parsed
correctly by ClickHouse's DateTime type.

Fixes SENTRY-5RCC
@mjq
mjq marked this pull request as ready for review July 9, 2026 19:10
@mjq
mjq requested a review from a team as a code owner July 9, 2026 19:10
@mjq
mjq marked this pull request as draft July 9, 2026 19:14
mjq added 5 commits July 9, 2026 15:19
…ization

The clickhouse-connect HTTP driver serializes query parameters via
json.dumps, which raises on bare Python datetime objects. The native
driver handles them transparently via its binary protocol, so callers
(e.g. the migration runner) pass datetime values directly.

Add a _make_json_safe shim in ClickhouseConnectPool that converts
datetime objects to ISO format strings before they reach the
clickhouse-connect binding layer. This keeps the existing contract
(callers can pass datetime objects) working on both driver paths.

Reverts the runner.py change from the previous commit — the fix
belongs in the driver layer, not in every caller.

Fixes SENTRY-5RCC
…driver

Reproduces the production failure from SENTRY-5RCC: the migration
runner passes datetime.now() in an INSERT FORMAT JSONEachRow query,
which the clickhouse-connect HTTP driver routes through json.dumps.
Without the _make_json_safe fix, this raises TypeError.
The native clickhouse-driver treats INSERT … FORMAT JSONEachRow with a
data list specially, serializing the rows as JSON lines in the request
body. clickhouse-connect's query() instead interprets the parameters
as %-style bind params, which fails with 'not all arguments converted
during string formatting'.

Detect the JSONEachRow INSERT pattern in _execute_once and inline the
data rows (after datetime sanitization) directly into the query string.
Regular queries with bind params are unaffected.
Iterate params directly (already narrowed to Sequence by isinstance)
and apply _make_json_safe per-row, avoiding an intermediate variable
whose Params union type mypy cannot narrow.
@mjq mjq closed this Jul 14, 2026
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