pypi / clickhouse-connect
clickhouse-connect
What changed in clickhouse-connect 0.14 to 1, from its official release notes, upgrade guides and advisories. Sources checked 2026-11-12.
47 breaking4 deprecations46 new APIs and options18 performance21 behavior and defaults3 tooling144 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initclickhouse-connect 1263 changes
Breaking changes 45
Install the lz4 extra to continue using
compress="lz4"on Python 3.14 and later.Closing a client-owned pool now closes idle connections immediately.
Decimal256(S) now resolves to precision 76.
Rust supports Python row and column queries in non-UTC server and local timezones; this requires clickhouse-connect-core>=0.2.3.
The ClickHouse dialect now owns its type mapping, preventing shared-mapping changes from hanging binds or reflection; unresolved custom adaptations raise CompileError after 1024 steps.
Generated schema metadata and Alembic revisions use clickhousedb_* options so copies and migrations work with both drivers installed; mixed installs should rename ClickHouse Connect schema options to this prefix.
Rust NumPy object columns now contain UTC numpy.datetime64 cells instead of Python datetime cells; SQL NULL remains None.
Supported columns convert directly from decoded buffers, reducing conversion overhead while keeping existing output dtypes except for the nanosecond correction.
The Alembic extra now requires Alembic 1.18 or later.
SQLAlchemy now applies ClickHouse backslash escaping to literal strings, defaults, aliases, TTL clauses, comments, and Alembic comment operations; custom pre-escaping workarounds should be removed.
SQLAlchemy union(), intersect(), and except_() now emit explicit DISTINCT operations; use the corresponding _all() methods when duplicate-preserving behavior is required.
Runtime compatibility branches for unsupported ClickHouse versions older than 25.8 have been removed; ClickHouse 25.8 is now the supported baseline.
The driver now quotes these parameters; remove manual quotes around existing
%(name)splaceholders.Compound and temporal values stored in JSON shared data now decode to Python values instead of raw bytes.
Set this setting to
legacyto restore the previous host-timezone conversion behavior for naive datetime query parameters.Naive datetime query parameters now represent wall time in the target timezone; set
common.set_setting("naive_datetime_binding", "legacy")to restore the previous host-timezone conversion behavior.zstd compression now uses Python 3.14's stdlib compression.zstd or backports.zstd on Python 3.10–3.13, replacing the zstandard dependency while remaining supported on standard Python installs.
A read producing an empty result set now returns an empty string instead of a truthy QuerySummary, so callers should check the returned value explicitly.
Standard SQLAlchemy indexes are filtered from ClickHouse autogenerate output, and create-index operations now raise a clear Alembic error before applying DDL; use ClickHouse index helpers for data-skipping indexes.
Client.insert, AsyncClient.insert, and raw_insert now require column_names to be a Sequence rather than a bare Iterable; one-shot iterators such as generators already failed at runtime.
Raises ProgrammingError when binary parameter binds are combined with command data or external data, rather than placing binary content in the URL query string.
Building from source now requires Cython 3.1 or later.
Returns None for an empty result set instead of raising IndexError.
Returns an empty string instead of None when the server reports no query id, keeping the property consistently typed as str.
A connection failure while reading a query result now raises StreamFailureError instead of silently treating the result as complete; it carries the server-side error message when available.
DSNs passed to create_client or create_async_client now percent-decode the username, password, and database. Escape literal percent signs as %25; a username without a password sends an empty password.
The async client no longer retries aiohttp timeout, connector, or fingerprint errors, which can indicate an already delivered request or a configuration issue rather than a stale connection.
The async client now requires aiohttp>=3.9.0 to support the per-request TLS SNI override.
The alembic extra now requires alembic>=1.16 to provide the operation kwargs used by the integration.
Raises NoSuchTableError for missing tables instead of returning {"text": None}.
Re-escapes quoted identifiers that contain unescaped inner occurrences of their surrounding quote character, while leaving valid pre-quoted identifiers unchanged.
The directly imported AiohttpAsyncClient class has been renamed to AsyncClient.
The deprecated parameter has been removed; use tz_source instead.
Install the async extra to use the aiohttp-based async client.
The native aiohttp-based client is now the only async implementation; obtain it with get_async_client.
The aiohttp_client module has been removed; the class moved to clickhouse_connect.driver.AsyncClient.
Datetime columns return their natural resolution: DateTime as datetime64[s], DateTime64(3) as datetime64[ms], DateTime64(6) as datetime64[us], and DateTime64(9) as datetime64[ns].
The executor-based async client is removed; use clickhouse_connect.get_async_client() instead.
pandas 1.x is no longer supported; pandas 2.0 is the minimum, and pandas use with an older version raises NotSupportedError.
This common setting has been removed; datetime columns now return their natural resolution rather than being coerced to datetime64[ns].
Python 3.9 is no longer supported; Python 3.10 is the minimum supported version.
Use tz_mode in place of utc_tz_aware, with naive_utc as the default and aware and schema as additional modes.
Use tz_source in place of apply_server_timezone, with auto as the default and server and local as alternatives.
The deprecated parameter has been removed; use tz_mode instead.
Timezone handling now uses the standard-library zoneinfo module instead of pytz.
New APIs and options 43
A synchronous HTTP client can get its own connection pool by passing
dedicated_pool=True.Sync and async client ping methods accept an optional timeout in seconds, defaulting to 3.
Connections and cursors support with blocks and close on normal or exceptional exit; connection contexts do not manage transactions.
Adds native SQLAlchemy 2.0.44+ async support for buffered Core and ORM execution, DDL, reflection, and Alembic migrations through run_sync().
Opt-in Native Map reads can preserve duplicate keys and server-returned order; dictionary output remains the default, and inserts still require dictionaries.
Source builds now provide an explicit C-extension mode through this environment variable.
Source builds now provide an explicit C-extension mode through this environment variable.
Adds Native query and insert support for Geometry in both codecs.
Adds support for all ClickHouse Interval types.
Adds typed-path configuration and canonical reflection for ClickHouse JSON columns.
Adds Native query and insert support for MultiPoint in both codecs; inserting it requires ClickHouse 26.8 or later.
Adds an opt-in Rust codec for queries, streaming variants, and inserts; rust_strict raises on unsupported paths instead of falling back to Python.
Adds standalone Variant reflection.
SQLAlchemy JSON columns can access storage-backed subcolumns through this method.
The typed SQLAlchemy helper accesses storage-backed JSON subcolumns.
SQLAlchemy statements can create materialized CTEs with
.cte(..., materialized=True)orcc_sqlalchemy.cte(...); this requires ClickHouse 26.3 or later with the analyzer andenable_materialized_cteenabled.Controls whether naive Python datetime inserts use the client host timezone or the column and server timezone; the default remains
local.The
scrubvalue retains useful server error details while removing the server URL and version trailer; transport and streaming errors follow the same setting, and invalid values raiseProgrammingError.A chdb:// DSN selects the experimental in-process chDB backend; chdb:///on/disk/path specifies a persistent database.
The new experimental chDB backend is selected with interface='chdb'; it runs queries against an embedded engine and supports query, insert, streaming, and Arrow client operations. A path argument enables persistence.
Alembic gains runtime operations for ClickHouse-specific DDL, including skip indexes, projections, table settings, materialized views, and dictionaries, with plural add/drop helpers for indexes and projections.
Returns a typed ClickHouseSelect with typed ch_join, final, sample, array_join, prewhere, and limit_by methods, allowing static type checkers to accept these methods without suppressions.
SQLAlchemy execution options can pass per-query ClickHouse settings through Core and text statements, execute, executemany, and bulk inserts; per-statement values take precedence over connection- or engine-level settings.
The typed read format for Variant columns returns TypedVariant values carrying the value and type_name, which can be inserted back without loss when members share a Python type.
Adds chainable SQLAlchemy JOIN modifiers for ALL, ANY, ASOF, SEMI, ANTI, GLOBAL, USING, and CROSS.
Adds a global way to enable the typed read format for Variant columns.
Client creation functions, connect(), and the DB-API Connection constructor now accept None to request the driver's default database.
Client creation functions, connect(), and the DB-API Connection constructor now accept None to request the driver's default port.
DatabaseError and OperationalError expose the numeric ClickHouse error code, allowing callers to branch without parsing the message. The attribute is None when unavailable and is set even when show_clickhouse_errors is disabled.
DatabaseError and OperationalError expose the symbolic ClickHouse error name; the attribute is None when unavailable.
Array now subclasses sqlalchemy.types.ARRAY and exposes item_type.
Add custom HTTP headers to every request, including initialization queries sent during client creation; also available on create_async_client.
Opt in to server-side bind parameters with server_side_params=True; the dialect emits ClickHouse native placeholders instead of client-side string interpolation. Off by default.
Sync and async clients accept a callable that supplies an access token and is called again after an authentication failure to fetch a fresh token and retry once.
Adds Alembic schema migrations for ClickHouse, including autogeneration, upgrade and downgrade flows, and ClickHouse-specific DDL for supported operations, engines, and dictionaries.
Adds an import-compatible module to ease migration from clickhouse-sqlalchemy.
Adds an import-compatible module to ease migration from clickhouse-sqlalchemy.
Adds SQLAlchemy support to reflect, create, and drop ClickHouse dictionaries.
The public Alembic operations API now accepts clickhouse_settings, and rendered AddColumnOp migrations preserve extra ClickHouse kwargs on round-trip.
Adds chainable lambda expressions to SQLAlchemy select constructs for ClickHouse-specific queries.
Adds chainable ClickHouse-specific LIMIT BY support to SQLAlchemy select constructs.
Adds chainable ClickHouse-specific PREWHERE support to SQLAlchemy select constructs.
The package version is exposed as clickhouse_connect.__version__ following Python packaging conventions.
Performance 17
Array column reads are faster with the C extensions across all query methods.
Each block is read in one executor call instead of one call per row, making streaming reads much faster.
Client creation is faster when the server uses a non-UTC IANA timezone.
Cython decoding of Date and Date32 columns is faster.
Python-codec reads of Map, nullable integer, nullable date, and timezone-aware nullable datetime columns are faster.
Eligible SQLAlchemy Core and ORM SELECTs skip the extra LIMIT 0 metadata query for empty results.
DataFrame conversion and Arrow encoding run on a dedicated client worker, reducing event-loop stalls.
Large uploads use bounded writes to reduce event-loop stalls during TLS encryption, and eligible retry payloads are replayable.
Large response chunks feed the decoder in bounded slices, reducing temporary copies and peak memory for NumPy, Pandas, and Python results.
Responses that fit in one chunk no longer start a read-ahead thread.
Rust codec pandas results use Arrow buffers directly instead of first creating Python strings.
Reads are significantly faster because values are built directly from the integer column instead of intermediate strings.
Reads are an order of magnitude faster for naive UTC and UTC-equivalent timezones.
Reads are an order of magnitude faster for naive UTC and UTC-equivalent timezones.
Reads are significantly faster because values are built directly from the integer column instead of intermediate strings.
Inserts from numpy arrays are significantly faster with lower peak memory; matching-dtype, 1-D C-contiguous arrays are copied directly via memcpy.
Reads and writes are significantly faster, and reads avoid intermediate pair-tuple materialization.
Behavior and default changes 20
On Python 3.14 and later,
compress=Truecompresses inserts with standard-library zstd because lz4 is no longer installed by default.A stored command statement now runs when supplied through query context.
Supported compound and scalar values, nullable defaults, and typed JSON null paths decode to Python objects; DataFrame results retain the decoded objects.
NumPy and Pandas queries no longer require PyArrow for buffered or streamed results, including query(..., use_numpy=True). Explicit Arrow output and Arrow storage still require it.
Parameterized DB-API executemany() preserves SQL expressions and sends one request per parameter set; earlier writes remain committed if a later request fails. Use Client.insert() for Native bulk throughput.
SQLAlchemy multi-row inserts now support dictionaries, tuples, and SQL expressions, including Pandas to_sql(method="multi").
Synchronous HTTP connections use operating-system socket buffer sizing for large uploads.
Expands parsing, reflection, query, and insert support across server-valid precisions.
SQLAlchemy Select.with_hint() now emits SAWarning when an applicable table hint would otherwise be ignored; generated SQL remains unchanged.
Settings unavailable through
system.settings, including custom role settings, are now forwarded to ClickHouse for validation.order_by, partition_by, primary_key, sample_by, and ttl now accept arbitrary SQL expressions in scalar and list forms, and expression engines round-trip through repr() for Alembic autogeneration.
Appends the insert summary to cursor.summary after a bulk insert.
The Cython extension modules declare free-threading support, so importing the package on a free-threaded build no longer silently re-enables the GIL; support remains experimental.
Large query parameter payloads are automatically sent as form data in the request body instead of the URL query string. Binary parameter binds are not promoted automatically and use form encoding only when form_encode_query_params=True.
Read paths now use the full query_retries budget for connection-error retries; insert and command paths still get one retry.
The async client now uses server_host_name to override the TLS SNI and certificate hostname as well as the HTTP Host header.
Generated DDL now emits table comments, reflection supports no-op autogenerate, and comment changes or drops use ALTER TABLE ... MODIFY COMMENT.
Lazy loading of numpy, pandas, pyarrow, and polars now applies to the async client as well.
Install the tzdata extra for slim Linux containers without a system timezone database.
Unknown timezone strings raise ZoneInfoNotFoundError internally instead of pytz's UnknownTimeZoneError; user-visible errors remain ProgrammingError.
Tooling 3
insert_blockis now typed as an async iterable of bytes; runtime behavior is unchanged.Return-type annotations were added to close, close_connections, query_np, query_df, query_arrow, set_client_setting, and set_access_token, preventing strict mypy no-untyped-call errors.
The package ships a PEP 561 marker so downstream type checkers can use its annotations.
Fixes and other changes 135
Async connection drops raise OperationalError or StreamFailureError instead of leaking aiohttp errors; mid-stream drops on both clients report StreamFailureError and preserve the original cause.
Per-call arguments from context are now applied.
Decoding is corrected for dates before 1601 and leap centuries such as 1600 and 2400.
Nanosecond precision is preserved for pandas.Timestamp binds and inserts at scales 7–9, and for Tuple, Nested, Map, and Variant parameters.
Enum names containing backslashes or control characters now parse and insert correctly.
Large queries are no longer form-encoded automatically, avoiding Field value too long errors.
The Python codec now reads and inserts nullable points correctly, including NULLs.
The Python codec now reads and inserts nullable tuples correctly, including NULLs.
LIMIT 0 queries return empty results, object-column rows retain their shape, and numeric LowCardinality columns return every row.
Datetime parameters with names ending in
_64no longer fail with KeyError.use_none=Falsenow works with Nullable(Date) and Nullable(Date32).Context tz_mode is preserved across all query methods.
Synchronous HTTP retry delays and failed-response cleanup are fixed for HTTP 429, 503, and 504 codes.
Python 3.15 is supported with wheels, including experimental free-threaded 3.15t wheels; lz4 currently builds from source on 3.15.
Missing-table reflection supports both NoSuchTableError and NoResultFound handlers with the existing message.
Connections closed before final HTTP response headers arrive, including after progress headers, now follow the existing remote-close retry policy.
Inspection of regular, window, and materialized views is fixed while existing table enumeration remains compatible.
Alembic accepts reflected state versions when metadata omits the version, including nested types; unversioned legacy states match explicit version 0.
In mixed installs with clickhouse-sqlalchemy, use clickhousedb:// or clickhousedb+connect:// to avoid conflicting provider registration.
Rust NumPy and Pandas results preserve nanoseconds in nullable scalar columns, including SimpleAggregateFunction aliases; unsupported scalar precisions fail consistently.
SQLAlchemy uses aliases only for matching top-level expressions selected by the query; unselected and nested expressions render in full.
Internal DESCRIBE TABLE requests use their own query ID, while inserts retain the caller's ID, avoiding same-ID-running errors.
Synchronous Native cleanup waits for active reads and drains partially consumed HTTP chunks through the same parser; early Rust stream closure drains before releasing its iterator.
Their return annotations preserve the wrapped type.
These aliases return correct durations and NaT for NULL values.
result_rows works after result_columns has been materialized, including async queries with column_oriented=True.
Cleanup releases response sources once, handles closure during read-ahead startup, releases decoder workers after cancelled reads, and completes before async cancellation is re-raised.
After remote close or HTTP 429/503/504, SQL execution retries only recognized reads; writes and other listed statements are not replayed. This applies through DB-API and SQLAlchemy.
Fixes Alembic version-table handling.
Arrow inserts now correctly quote table and database identifiers on both clients.
Fixes async cancellation, initialization, connection disposal, token-provider cleanup, and pool timeout handling.
Comments, quoted identifiers, and escaped strings containing LIMIT 0 no longer cause results to be discarded. Metadata probes returning rows raise InternalError without replay; use raw_query() for those queries.
DateTime64 declarations must match the server schema; precision handling is fixed.
Fixes Decimal arithmetic in SQLAlchemy.
Fixes SQLAlchemy table-engine reflection.
Fixes timezone-aware Date and Date32 inserts.
Fixes rendering for Nested, named Tuple, AggregateFunction, and SimpleAggregateFunction columns.
Improves parsing for Dynamic arguments.
Improves parsing for generic Enum definitions.
IPv6 host literals are bracketed correctly for sync and async connections.
Improves parsing for quoted type names.
Abandoned Rust streams now promptly release their response, socket, buffered data, and read-ahead thread.
SQLAlchemy and Alembic now connect and reflect correctly when the Rust codec uses strict mode.
Rust streams now honor show_clickhouse_errors.
Fixes empty Tuple Native serialization, including nested and nullable forms.
Fixes dialect-aware DDL compilation for TypeDecorator.
Fixes member ordering that could write Native insert data under the wrong member type.
Fixes dialect-aware DDL compilation for with_variant().
The synchronous client now sends a normalized / request path through forwarding HTTP proxies when proxy_path is not configured.
SQLAlchemy inspectors bound to an Engine now support get_columns() on SQLAlchemy 2.x.
SQLAlchemy ClickHouse types now implement the public literal processor contract for TypeDecorator and with_variant().
The async client now preserves explicit proxy_path values without adding extra slashes.
Queries ending with a semicolon, whitespace, or trailing comment now place client-appended FORMAT clauses correctly, and insert detection follows SQL token rules.
SQLAlchemy inspectors bound to an Engine now support reflect_table() on SQLAlchemy 2.x, honoring include_columns and exclude_columns.
Server-side query placeholders now recognize $ in valid parameter names while preserving raw binary binding and ambiguity checks.
Literals containing percent signs now compile safely alongside bound parameters and in server-side parameter mode.
Column DDL using this option no longer raises AttributeError on SQLAlchemy 1.4 because the rendering helper is implemented locally.
Column DDL using this option no longer raises AttributeError on SQLAlchemy 1.4 because the rendering helper is implemented locally.
Column DDL using this option no longer raises AttributeError on SQLAlchemy 1.4 because the rendering helper is implemented locally.
Identifier quoting no longer forwards the removed force argument to SQLAlchemy's parent quote method, preventing a TypeError with SQLAlchemy 2.1. The optional force parameter remains available on the ClickHouse preparer for direct callers.
Cleanup now runs on the event-loop thread, preserving the original
StreamFailureErrorwhen TLS queries fail mid-stream.The DB-API module now provides the standard
Binaryconstructor, also fixing SQLAlchemyLargeBinaryinserts.DB-API descriptions now report accurate top-level nullability and handle empty-result metadata probes more safely.
The DB-API module now provides the standard
Dateconstructor.Query binding now handles
TimeandTime64values, including nested, negative, extended-duration, timezone-aware, and nanosecond values; SQLAlchemy inserts, comparisons, andliteral_bindssupport them too.Fractional values before the Unix epoch now serialize to the correct second.
Empty bytes inserted into non-nullable
FixedStringcolumns are now padded correctly.Streaming now detects complete mid-stream ClickHouse exception blocks across transport chunk boundaries.
These types now parse correctly when enum values contain escaped quotes.
Nested
Nonevalues in arrays, tuples, and map-formatted maps now render as SQLNULL.SQLAlchemy and DB-API correctly handle percent signs in identifiers, including
%2EJSON key encodings.Removing SQL block comments no longer joins adjacent query tokens or causes incorrect client-side
LIMIThandling.These queries continue returning string identifiers when the global
Stringformat is configured as bytes.The DB-API module now provides the standard
Timeconstructor.The DB-API module now provides the standard
Timestampconstructor.Initialization no longer overwrites user-supplied session settings with generated defaults, matching the sync client.
When client certificates and an access token are both configured, requests now send mutual TLS authentication headers and the Authorization: Bearer header together, matching the sync client.
Async clients now emit URL query parameters in the same order as the sync client on every request.
If the sync client's capability probe errors, client creation now falls back gracefully and logs at debug level.
Dict-valued settings such as additional_table_filters no longer cause a quoted-string parse exception when passed through query()'s settings parameter.
Fixes helper edge cases involving raw SQL bind parsing, dictionary comment escaping, explicit schemas, materialized-view settings suffixes, and autogeneration of custom operation objects.
Retains typed ClickHouse chainables after column-shape methods, and cc_sqlalchemy.select() works on SQLAlchemy 1.4.
Correctly decodes LEB128 varint values of 2^31 and larger on the compiled path, preventing truncation or corruption of string lengths and other varint values.
Preserves the bulk-insert fast path for INSERT statements naming backtick-quoted dotted columns, avoiding slow per-row execution and related ProgrammingError failures.
Uses EXISTS DATABASE instead of system.databases, preventing existing remote databases from being reported as absent on affected server versions.
Generated DDL retains comment, codec, and ttl options and emits column clauses in ClickHouse's required COMMENT, CODEC, TTL order.
Emits RENAME TABLE old TO new rather than the ALTER TABLE form ClickHouse rejects.
Fixes corruption of QBit columns with dimensions greater than 8 on native inserts and reads; affected data written by earlier clients should be re-inserted.
Wrapping a ClickHouse type in a SQLAlchemy TypeDecorator no longer raises a result_processor TypeError when reading results.
Async request bodies larger than 1 MiB are wrapped in io.BytesIO and written in chunks, avoiding aiohttp ResourceWarnings.
Importing the ClickHouse Alembic integration no longer changes autogenerate output for other database dialects; their built-in renderers are used instead.
Importing the package no longer emits a DeprecationWarning for the array 'u' type code, allowing imports when warnings are errors.
Forwards transport_settings correctly instead of passing it positionally as compression.
Forwards transport_settings correctly instead of passing it positionally as compression.
Resets rowcount and reports the number of inserted rows after a bulk insert.
The SQLAlchemy DDL helper is now a function returning a concrete ChSqlaType, avoiding a spurious mypy error in nested type expressions; runtime behavior is unchanged.
The SQLAlchemy DDL helper is now a function returning a concrete ChSqlaType, avoiding a spurious mypy error in nested type expressions; runtime behavior is unchanged.
Returns None for an empty result set instead of raising IndexError.
Cursor.executemany accepts a generator without raising TypeError and skips the bulk-insert optimization for non-indexable iterables.
DB API executemany no longer raises AttributeError when rows are sequences rather than mappings.
UUID, IPv4Address, and IPv6Address values nested inside Array, Tuple, or Map parameters are now quoted, fixing server rejection of bound UUID IN lists.
A datetime parameter whose name genuinely ends in _64 is no longer renamed when the query binds that exact name; the documented _64 convention remains unchanged.
Wheels are now published for Windows ARM64 on CPython 3.10 through 3.14, including the free-threaded 3.14 build.
SQLAlchemy dialect reflection is implemented, enabling MetaData.reflect() and Inspector.get_multi_columns().
Line comments beginning with -- and no following space are stripped when classifying queries, so leading --sql-style comments on DDL are routed as commands.
bytes and bytearray parameters now render as ClickHouse string literals with each byte represented as \xHH, fixing inserts into FixedString and String columns through the SQLAlchemy dialect.
A datetime bound to a server-side DateTime64 placeholder now retains sub-second precision, including through Array and Tuple hints; plain DateTime binds are unchanged.
UDT-based types including UUID, IPv4/IPv6, JSON, Nested, geometry types, and AggregateFunction now return concrete Python type classes instead of None.
The sync client now retries stale keep-alive BrokenPipeError exceptions, in addition to ConnectionResetError.
The async client now retries stale keep-alive resets surfaced as ClientConnectionResetError, helping large async inserts recover from killed pooled connections.
The async client now retries stale keep-alive resets surfaced as ClientOSError, helping large async inserts recover from killed pooled connections.
The async client's ping() now routes through the configured proxy, so it no longer falsely returns False when the server is reachable only via that proxy.
SHOW ROW POLICIES and SHOW POLICIES queries are routed without appending FORMAT Native; empty row-policy SHOW results now return an empty string instead of QuerySummary.
Preserves aliases through compilation for multi-column ARRAY JOIN, fixing label loss during parallel array expansion.
Alembic renders column comments inline in CREATE TABLE and ADD COLUMN statements instead of using separate COMMENT ON COLUMN statements rejected by ClickHouse.
Reflected engines now populate settings from parsed engine kwargs, decoding ClickHouse string-literal escapes and preserving float-valued settings.
Alembic autogenerated migrations now render enum types, including nested container types, in the correct ClickHouse-compatible representation.
Error messages now report the resolved database name from currentDatabase() when schema was not provided, rather than literal None.
Sync raw_query now passes query_retries so its connection-error retries match the async counterpart.
Sync raw_stream now passes query_retries so its connection-error retries match the async counterpart.
Preserves FINAL, SAMPLE, PREWHERE, and LIMIT BY modifiers when select() is built from ORM-mapped attributes.
SQLAlchemy quotes string-valued engine and operation settings as ClickHouse string literals; numeric and boolean settings remain unchanged.
During connection-pool rotation, installs the new session before retiring the old one and waits for outstanding requests to release their lease; close() clears the session so post-close calls fail with ProgrammingError.
The async client resolves the ca_cert="certifi" shorthand to certifi.where(), matching the sync client instead of passing the literal string to SSL certificate loading.
Recognizes ClickHouse Fixed/UTC±HH:MM:SS timezones in column types, the X-ClickHouse-Timezone header, and SELECT timezone(), avoiding ProgrammingError except at the ±24:00:00 boundary.
SQLAlchemy renders ILIKE and NOT ILIKE expressions using native ClickHouse syntax rather than the generic lower(...) LIKE lower(...) fallback.
Retries once when aiohttp raises ServerDisconnectedError on a pooled keep-alive connection idle-closed by the server.
Fixes a race condition that caused unhandled InvalidStateError on early stream termination.
The SQLAlchemy Bool type accepts and forwards **kwargs, fixing ORM model use and Table.to_metadata().
CreateDatabase with engine="Replicated" now emits valid DDL.
Fixes reads when a path's inferred type sorts alphabetically after SharedVariant.
Fixes intermittent empty-query syntax errors when a pooled keep-alive connection is reset between attempts.
Raw SQL strings are wrapped in text() so the method works on SQLAlchemy 2.x.
Raw SQL strings are wrapped in text() so the method works on SQLAlchemy 2.x.
The release adds compatibility with Pandas 3.x.
clickhouse-connect 0.159 changes
Breaking changes 1
Formatting timezone-aware datetimes in bind expressions now uses the parameter type hint's timezone instead of server_tz.
New APIs and options 2
Adds multi-column array expansion for parallel arrays.
Adds comprehensive ClickHouse JOIN support in SQLAlchemy, including strictness and distribution modifiers and USING syntax.
Performance 1
Imports numpy, pandas, pyarrow, and polars lazily, making bare imports about four times faster.
Fixes and other changes 5
Fixes chained
.final()and.sample()calls silently overwriting each other.Fixes quoting of the config_section argument.
Removes the py.typed marker that caused false type errors for mypy and pyright users.
Adds missing Replicated engine variants, including ReplicatedReplacingMergeTree.
Fixes sqlalchemy.values() to emit ClickHouse VALUES table function syntax.
clickhouse-connect 0.1411 changes
Breaking changes 1
The legacy experimental Object('json') type was removed in favor of the new JSON type in ClickHouse.
Deprecations 4
Creating the legacy async client now emits a FutureWarning advertising the async-native client available for testing.
Pandas 1.x support is deprecated and will be removed in 1.0.0.
Replaces utc_tz_aware with options "naive_utc" (the default), "aware", or "schema"; the old parameter still works with a deprecation warning.
Replaces apply_server_timezone with options "auto" (the default), "server", or "local"; the old parameter still works with a deprecation warning.
New APIs and options 1
The SQLAlchemy dialect now supports SAMPLE.
Behavior and default changes 1
The compiled driverc modules are used by default again; set this environment variable to 0 to disable the Cython runtime path.
Fixes and other changes 4
Empty ORM/DBAPI SELECT results now populate cursor.description when ClickHouse Native format returns no data blocks, restoring correct handling of empty result sets.
Read paths now decode shared variant data instead of returning raw binary with discriminator byte prefixes.
Experimental wheel builds are available for Python 3.14 free-threading on all platforms.
Fixes an issue where sending redundant settings is skipped.