Skip to content

Releases: ClickHouse/clickhouse-connect

v1.1.0a1

06 May 18:17

Choose a tag to compare

v1.1.0a1 Pre-release
Pre-release

1.1.0a1 — Alpha Preview (Alembic Integration)

This is an alpha preview of the upcoming 1.1.0 release, published from the joe/alembic-integration-work branch for early testing of the new SQLAlchemy and Alembic features. It includes everything in 1.0.0rc2 plus the additions listed below.

Installation

Pre-releases are not installed by default. Pin the exact version:

pip install clickhouse-connect==1.1.0a1

# To use the new Alembic integration:
pip install "clickhouse-connect[alembic]==1.1.0a1"

What's new in this preview

  • Alembic migration support: Full Alembic integration for ClickHouse schema migrations: autogeneration from SQLAlchemy metadata, upgrade/downgrade lifecycle, and round-tripping of ClickHouse-specific DDL. Engines (MergeTree, ReplacingMergeTree, etc.) and Dictionaries are preserved through the migration lifecycle. Supported operations include create/drop table, add/alter/drop/rename column, type and nullability changes, defaults, comments, IF EXISTS guards, column placement with AFTER, and operation-level clickhouse_settings. See WORKED_EXAMPLE.md for an end-to-end walkthrough.
  • ClickHouse Dictionary type support in SQLAlchemy and Alembic.
  • New SQLAlchemy chainables: PREWHERE, LIMIT BY, and lambda expressions as Select constructs for ClickHouse-specific query shapes.
  • Multi-column ARRAY JOIN label preservation — aliases now survive through compilation, fixing label loss with parallel array expansion.
  • Migration shim for clickhouse-sqlalchemy users — new cc_sqlalchemy.types and cc_sqlalchemy.engines import-compatible modules. See MIGRATING_FROM_CLICKHOUSE_SQLALCHEMY.md.
  • SQLAlchemy 1.4 and 2.x compatibility improvements across the dialect and DDL compiler paths.
  • Inspector: cloud quirk reflection fixes for ClickHouse Cloud-specific schema reflection edge cases.
  • DDL compiler: better handling of nested container types and Tuple adaptation.
  • Alembic autogenerated migrations rendering enum types (including nested container types) with the correct ClickHouse-compatible representation.

Feedback

This alpha exists to shake out the new SQLAlchemy/Alembic surface before it ships in 1.1.0 final. Please file issues at https://github.com/ClickHouse/clickhouse-connect/issues with the alembic or sqlalchemy label so they're easy to triage.

Full changelog

See CHANGELOG.md for the complete entry, plus everything inherited from 1.0.0rc2.

v1.0.0rc2

05 May 23:21
dfb53fd

Choose a tag to compare

v1.0.0rc2 Pre-release
Pre-release

Release Candidate 1.0.0 (rc2)

This is a release candidate for clickhouse-connect 1.0.0. Please test thoroughly with your workloads and report any issues before the final release.

Installation:

pip install clickhouse-connect==1.0.0rc2

If upgrading from 0.15.x, see the migration notes in rc1. All 1.0 breaking changes were introduced there. rc2 contains no new breaking changes.

Highlights

rc2 is primarily a performance release. There is order-of-magnitude faster DateTime/DateTime64 reads, Decimal reads, and fixed-width numpy inserts, plus significantly faster Map reads and writes.

What's Changed

Improvements

  • Order-of-magnitude faster DateTime and DateTime64 reads for naive UTC and UTC-equivalent timezones. The Cython read paths now decode via epoch arithmetic and construct datetime objects directly via the CPython datetime C API, bypassing datetime.fromtimestamp and the Python-level datetime(...) constructor. Also fixes Cython DateTime conversion bugs and expands epoch-arithmetic test coverage.
  • Significantly faster Map reads and writes. The read path avoids materializing an intermediate pair tuple. The write path moves into a new Cython build_map_columns helper.
  • Order-of-magnitude faster fixed-width numeric inserts from numpy arrays, with significantly lower peak memory. A new Cython write_native_col helper writes 1-D C-contiguous numpy arrays of matching dtype directly into the output buffer via memcpy, avoiding the per-element conversion the previous path required.
  • Significantly faster Decimal and BigDecimal reads. The decode path no longer constructs intermediate strings per row, building values directly from the integer column via Decimal.scaleb.

Bug Fixes

  • Async client: retry once when a pooled keep-alive connection is closed by the server and aiohttp raises ServerDisconnectedError with the default "Server disconnected" message. The existing retry path covered "Connection reset" and "Remote end closed", but not the bare ServerDisconnectedError() produced by recent aiohttp versions, which surfaced as an OperationalError("Network Error: Server disconnected") on the first request after an idle period.
  • SQLAlchemy Bool type now accepts and forwards **kwargs to the underlying SqlaBoolean constructor. SQLAlchemy's SchemaType machinery passes internal kwargs (e.g., _create_events) when copying or adapting the type during ORM model use or Table.to_metadata(), which previously raised a TypeError. Fixes #705
  • SQLAlchemy: CreateDatabase with engine="Replicated" now emits a closing ) after the (zoo_path, shard, replica) arguments, fixing previously invalid DDL on this path. The same arguments and the system.tables lookup in get_engine now go through bound parameters and the existing format_str helper instead of raw f-string interpolation.

v1.0.0rc1

22 Apr 19:37
f886c40

Choose a tag to compare

v1.0.0rc1 Pre-release
Pre-release

Release Candidate 1.0.0

This is a release candidate for clickhouse-connect 1.0.0. Please test thoroughly with your workloads and report any issues before the final release.

Installation:

pip install clickhouse-connect==1.0.0rc1

Important Migration Notes

Python Version: Minimum Python version is now 3.10. If you're on Python 3.9, pin to clickhouse-connect<1.0 or upgrade Python.

Timezone Handling: The pytz dependency has been replaced with the standard library zoneinfo. On Windows, tzdata is pulled in automatically. On slim Linux containers, install with pip install clickhouse-connect[tzdata].

Async Client: The executor-based async client has been removed. Use clickhouse_connect.get_async_client() for a native aiohttp-based client. Install with pip install clickhouse-connect[async].

Pandas: Minimum pandas version is now 2.0.

What's Changed

Breaking Changes

  • Dropped Python 3.9 support. Minimum supported Python version is now 3.10. 0.15.x is the last series supporting Python 3.9.
  • Dropped the pytz dependency in favor of the standard library zoneinfo. On Windows, tzdata is pulled in automatically. On slim Linux containers without a system tzdb, install pip install clickhouse-connect[tzdata].
  • Unknown timezone strings from query_tz, column_tzs, or the server now surface zoneinfo.ZoneInfoNotFoundError internally (previously pytz.exceptions.UnknownTimeZoneError). User-visible ProgrammingError/log messages suggest the tzdata extra. Closes #714.
  • Removed the deprecated utc_tz_aware parameter entirely. Use tz_mode instead: "naive_utc" (default, was False), "aware" (was True), or "schema" (unchanged). Closes #654, #665
  • Removed the deprecated apply_server_timezone parameter entirely. Use tz_source instead: "auto" (default), "server" (was True), or "local" (was False).
  • Remove the legacy executor-based async client. The AsyncClient(client=...) constructor pattern, executor_threads, and executor parameters are no longer supported. Use clickhouse_connect.get_async_client() (or create_async_client()) which creates a native aiohttp-based async client directly. The pool_mgr parameter is also rejected on the async path. aiohttp remains an optional dependency, installed via pip install clickhouse-connect[async].
  • The internal AiohttpAsyncClient class has been renamed to AsyncClient and the module clickhouse_connect.driver.aiohttp_client has been removed. Import AsyncClient from clickhouse_connect.driver as before.
  • Dropped pandas 1.x support. Minimum pandas version is now 2.0. Users with pandas < 2.0 will get a NotSupportedError at import time. Non-pandas usage is unaffected. Closes #661
  • Removed the preserve_pandas_datetime_resolution common setting. Datetime columns now always return their natural resolution, e.g. datetime64[s] for DateTime, datetime64[ms] for DateTime64(3), instead of coercing everything to datetime64[ns]. Closes #662

Bug Fixes

  • Fix Dynamic/JSON column reads when a path's inferred type sorts alphabetically after "SharedVariant". ClickHouse's DataTypeVariant constructor sorts its members alphabetically by name, and discriminator bytes on the wire index into that sorted order. The client appended SharedVariant to the variant list without sorting, so affected paths were read as the wrong variant. Closes #712
  • Fix async streaming race condition that caused unhandled InvalidStateError exceptions on early stream termination. When breaking out of an async stream early, shutdown() scheduled a set_result callback for pending futures via call_soon_threadsafe, but Task.cancel() could cancel the future before the callback ran. The done-check is now deferred into the callback itself so it sees the actual future state at execution time.
  • SQLAlchemy: Wrap raw SQL strings in text() in ChClickHouseDialect.get_schema_names() and get_table_names(), so Inspector.get_schema_names() and get_table_names() work on SQLAlchemy 2.x instead of raising ObjectNotExecutableError.

Improvements

  • Package version is now exposed as clickhouse_connect.__version__ (a string), following Python packaging conventions. The version remains single-sourced from clickhouse_connect/_version.py. Users can access version information via clickhouse_connect.__version__, importlib.metadata.version("clickhouse-connect"), or the clickhouse_connect.common.version() helper.
  • Lazy loading of optional dependencies (numpy, pandas, pyarrow, polars) now applies to the async client as well, matching the pattern established in 0.15.0 for the sync client.
  • Clearer error message when attempting to use the async client without aiohttp installed.
  • The generic_args parameter is now properly parsed on the async client creation path, matching the sync client behavior.
  • Pandas 3.x compatibility. Removed deprecated copy=False parameter from Series(), concat(), and astype() calls. Updated datetime insert path to use vectorized numpy conversion instead of element-by-element nanosecond arithmetic.

Development

  • Replaced pylint with Ruff for linting and formatting. Double quotes are now the standard quote style. Bulk formatting commits are listed in .git-blame-ignore-revs. CI lint job no longer requires building C extensions or installing project dependencies, significantly reducing lint check time.

v0.15.1

30 Mar 18:29

Choose a tag to compare

Bug Fixes

  • Use timezone from parameter type hint instead of server_tz when formatting tz-aware datetimes in {param:Type} bind expressions. Fixes #697

v0.15.0

26 Mar 18:07
c4c2a4e

Choose a tag to compare

Improvements

  • Comprehensive ClickHouse JOIN support in SQLAlchemy via ch_join() with all strictness/distribution modifiers and USING syntax (#635, #636)
  • Multi-column array_join() for parallel array expansion (#633)
  • Add missing Replicated engine variants (ReplicatedReplacingMergeTree, etc.) (#687)
  • Lazy imports for numpy, pandas, pyarrow, and polars, ~4x faster bare import time (#589)

Bug Fixes

  • Fix .final() and .sample() silently overwriting each other when chained (#658)
  • Fix sqlalchemy.values() to emit ClickHouse VALUES table function syntax (#681)
  • Fix GraphiteMergeTree to properly quote config_section argument

Other

  • Remove py.typed marker that was causing false type errors for mypy/pyright users (#691)

Full Changelog: v0.14.1...v0.15.0

v0.14.1

12 Mar 14:29
c40bbac

Choose a tag to compare

Bug fixes

  • Fixed JSON and Dynamic column read paths to properly decode shared variant data instead of returning raw binary with discriminator byte prefixes. Closes #599, #615, #674
  • Fixed empty ORM/DBAPI SELECT results so cursor.description is still populated when ClickHouse Native format returns no data blocks. This restores correct handling for empty result sets, including parameterized and limited queries. Closes #675
  • Reenabled the default Cython runtime path so compiled driverc modules are used again unless CLICKHOUSE_CONNECT_USE_C=0 is exoplicitly set. Closes #676

Full Changelog: v0.14.0...v0.14.1

v0.14.0

09 Mar 17:28
2dda715

Choose a tag to compare

High level notes

This release is primarily focused on preparing the path to 1.0.0. It introduces a handful of breaking changes and deprecation warnings for APIs that will be removed or finalized in 1.0.0. If your code uses any of the deprecated parameters, you'll now see DeprecationWarnings with clear migration guidance and highly recommend addressing these before upgrading to 1.0.0 when it ships.

Breaking Changes

  • apply_server_timezone renamed to tz_source. Options are "auto" (the default), "server", or "local". The old parameter currently still works with a deprecation warning. #670
  • utc_tz_aware renamed to tz_mode. Options are "naive_utc" (the default), "aware", or "schema". The old parameter still currently still works with a deprecation warning. #664
  • Removed Object('json') type. This was a legacy experimental JSON type has been removed in favor of the new JSON type in ClickHouse. #666

Deprecations

  • Pandas 1.x support is deprecated and will be removed in 1.0.0. #667
  • There's a async-native client based on clickhouse-connect v0.11.0 that is available for testing via pip install clickhouse_connect[async]==0.12.0rc1. A FutureWarning advertising this will now be emitted on creation of the (to be legacy) async client. #672

Experimental

  • Python 3.14 free-threading (cp314t) wheel builds for all platforms. #660

Improvements

  • Fix issue where sending redundant settings is skipped. #639
  • Add support for SAMPLE in SQLAlchemy dialect. #656

New Contributors

Full Changelog: v0.13.0...v0.14.0

v0.13.0

26 Feb 21:32
6bc0c86

Choose a tag to compare

What's Changed

Improvements

  • BREAKING CHANGE: Implement native write path for Variant data type with type-aware dispatching. Previously, all values inserted into a Variant column were stringified and sent to the server, which would store them in the String member if present, or attempt server-side conversion otherwise. Values are now serialized using their native ClickHouse types client-side (e.g. inserting 100 into Variant(Int64, String) stores Int64(100) instead of String("100")).

    Key changes:

    • Values that don't match any variant member now raise DataError instead of being stringified and
      delegated to the server.
    • A typed_variant(value, 'TypeName') helper is provided for cases where automatic dispatch
      cannot resolve the target type, such as when multiple variant members map to the same Python
      type (e.g. Array(UInt32) vs Array(String)).
  • Added utc_tz_aware="schema" mode which returns timezone-aware datetimes only when the server's column schema explicitly defines a timezone (e.g. DateTime('UTC')), and naive datetimes for bare DateTime columns. This matches the ClickHouse schema definition exactly. Not yet supported for Arrow-based query methods. Closes #645

  • Add type annotations to public API methods in Client, AsyncClient, HttpClient, and QueryResult. Ref #567

Bug Fixes

  • Fix dict_add parameter typed as builtin any instead of typing.Any.
  • Recognize UPDATE as a command so lightweight updates work correctly via client.query() and SQLAlchemy.
  • SQLAlchemy: GROUP BY now renders label aliases instead of full expressions which avoids circular reference errors when an alias shadows a source column name in ClickHouse.

Full Changelog: v0.11.0...v0.13.0

v0.12.0rc1

12 Feb 19:00

Choose a tag to compare

v0.12.0rc1 Pre-release
Pre-release

Native Async Client (Pre-release)

This is a pre-release for testing and feedback on the new native async client built on aiohttp. Closes #141.

If you're using the sync client and have been looking for a reason to go async, this is a good opportunity to give it a shot. If you're already using AsyncClient, this is a drop-in upgrade. The API surface is identical but under the hood it's completely redesigned.

Previously, the AsyncClient was just the sync urllib3 client wrapped in a thread executor. This is a from-scratch async implementation with real async I/O, proper connection pooling, and a pipelined architecture that streams and processes response data concurrently rather than a read-then-parse pattern, providing a potentially significant performance increase depending on your workload. The old executor-based path still works but is now deprecated and will be removed after release candidate testing and benchmarking is completed.

Install

aiohttp is now a required dependency for using the native async client, but its installation is not included by default. To install this release candidate with the required aiohttp for async use, install clickhouse_connect as follows:

pip install clickhouse-connect[async]==0.12.0rc1

Usage

import asyncio

import clickhouse_connect


async def main():
    async with await clickhouse_connect.get_async_client(host="localhost") as client:
        # create a test table
        await client.command(
            "CREATE TABLE IF NOT EXISTS test_example "
            "(id UInt32, name String) "
            "ENGINE MergeTree ORDER BY id"
        )

        # insert
        data = [[1, "clickhouse"], [2, "joe"]]
        await client.insert("test_example", data, column_names=["id", "name"])

        # query
        result = await client.query("SELECT id, name FROM test_example")
        print(result.result_rows)

        # cleanup
        await client.command("DROP TABLE IF EXISTS test_example")


asyncio.run(main())

As you can see, the method names and signatures are the same as the sync client, you just await them. And for users of the the original async client, you don't have to change anything.

Migrating from the previous AsyncClient

If you're creating your async client like this, you're already on the new native implementation and no changes are needed:

client = await clickhouse_connect.get_async_client(host="localhost")

The only case where you'll still get the old executor-based wrapper is if you're explicitly constructing it from a sync client:

from clickhouse_connect.driver import AsyncClient

sync_client = clickhouse_connect.get_client(host="localhost")
async_client = AsyncClient(client=sync_client)  # legacy path, now deprecated

If you're doing this, it will continue to work for a very short time but you'll see a DeprecationWarning. We recommend switching to get_async_client() when you get a chance so that you're using the native async client, not the deprecated executor-based client. The legacy path has been left in temporarily so users can benchmark it against the native version if they desire, as significant unexpected performance degradation would be very helpful feedback before we remove it entirely.

What we're looking for

  • General stability feedback
  • Performance compared to the sync client and legacy async client in your workloads
  • Any issues with connection pooling, streaming, or concurrent usage
  • Edge cases we haven't hit yet

Please report issues on this repo with [async] in the title.

Note

This release also includes everything from v0.11.0 release.

v0.11.0

10 Feb 23:50
eef09a9

Choose a tag to compare

What's Changed

Improvements

  • Add support for mid-stream exceptions. Closes #626
  • Add support for QBit data type. Closes #570
  • Add the ability to create table from PyArrow objects. Addresses #588
  • Always generate query_id from the client side as a UUID4 if it is not explicitly set. Closes #596
  • Extend support for creating tables from PyArrow objects to include datetime/timestamp types. Closes #605
  • Add pre-commit hooks for auto-linting contributions at commit time. Addresses #607
  • Auto-enable cancel_http_readonly_queries_on_client_close setting for HTTP clients to ensure SELECT queries are cancelled on the server when the client disconnects. Closes #641

Bug Fixes

  • Raise OperationalError when ResponseSource hits network failure before any data is received. Previously, empty result would be returned. Closes #620
  • Fixed a bug where InsertContext state was not reset on insert failure, leading to reuse errors when data was passed separately. Closes #616
  • Fixed UTC-equivalent timezone recognition issue where servers returning Etc/UCT, GMT, or other UTC-equivalent timezone names caused inconsistent behavior with utc_tz_aware=False. DateTime columns with explicit UTC timezones now correctly return naive datetimes when utc_tz_aware=False regardless of the specific UTC-equivalent timezone name returned by the server. Closes #629
  • Extend UTC-equivalence checks to Arrow queries.

New Contributors

Full Changelog: v0.10.0...v0.11.0