Releases: ClickHouse/clickhouse-connect
v1.1.0a1
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 EXISTSguards, column placement withAFTER, and operation-levelclickhouse_settings. SeeWORKED_EXAMPLE.mdfor an end-to-end walkthrough. - ClickHouse
Dictionarytype 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 JOINlabel preservation — aliases now survive through compilation, fixing label loss with parallel array expansion. - Migration shim for
clickhouse-sqlalchemyusers — newcc_sqlalchemy.typesandcc_sqlalchemy.enginesimport-compatible modules. SeeMIGRATING_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
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
DateTimeandDateTime64reads for naive UTC and UTC-equivalent timezones. The Cython read paths now decode via epoch arithmetic and constructdatetimeobjects directly via the CPython datetime C API, bypassingdatetime.fromtimestampand the Python-leveldatetime(...)constructor. Also fixes CythonDateTimeconversion bugs and expands epoch-arithmetic test coverage. - Significantly faster
Mapreads and writes. The read path avoids materializing an intermediate pair tuple. The write path moves into a new Cythonbuild_map_columnshelper. - Order-of-magnitude faster fixed-width numeric inserts from numpy arrays, with significantly lower peak memory. A new Cython
write_native_colhelper writes 1-D C-contiguous numpy arrays of matching dtype directly into the output buffer viamemcpy, avoiding the per-element conversion the previous path required. - Significantly faster
DecimalandBigDecimalreads. The decode path no longer constructs intermediate strings per row, building values directly from the integer column viaDecimal.scaleb.
Bug Fixes
- Async client: retry once when a pooled keep-alive connection is closed by the server and aiohttp raises
ServerDisconnectedErrorwith the default"Server disconnected"message. The existing retry path covered"Connection reset"and"Remote end closed", but not the bareServerDisconnectedError()produced by recent aiohttp versions, which surfaced as anOperationalError("Network Error: Server disconnected")on the first request after an idle period. - SQLAlchemy
Booltype now accepts and forwards**kwargsto the underlyingSqlaBooleanconstructor. SQLAlchemy'sSchemaTypemachinery passes internal kwargs (e.g.,_create_events) when copying or adapting the type during ORM model use orTable.to_metadata(), which previously raised aTypeError. Fixes #705 - SQLAlchemy:
CreateDatabasewithengine="Replicated"now emits a closing)after the(zoo_path, shard, replica)arguments, fixing previously invalid DDL on this path. The same arguments and thesystem.tableslookup inget_enginenow go through bound parameters and the existingformat_strhelper instead of raw f-string interpolation.
v1.0.0rc1
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
pytzdependency in favor of the standard libraryzoneinfo. On Windows,tzdatais pulled in automatically. On slim Linux containers without a system tzdb, installpip install clickhouse-connect[tzdata]. - Unknown timezone strings from
query_tz,column_tzs, or the server now surfacezoneinfo.ZoneInfoNotFoundErrorinternally (previouslypytz.exceptions.UnknownTimeZoneError). User-visibleProgrammingError/log messages suggest thetzdataextra. Closes #714. - Removed the deprecated
utc_tz_awareparameter entirely. Usetz_modeinstead:"naive_utc"(default, wasFalse),"aware"(wasTrue), or"schema"(unchanged). Closes #654, #665 - Removed the deprecated
apply_server_timezoneparameter entirely. Usetz_sourceinstead:"auto"(default),"server"(wasTrue), or"local"(wasFalse). - Remove the legacy executor-based async client. The
AsyncClient(client=...)constructor pattern,executor_threads, andexecutorparameters are no longer supported. Useclickhouse_connect.get_async_client()(orcreate_async_client()) which creates a native aiohttp-based async client directly. Thepool_mgrparameter is also rejected on the async path.aiohttpremains an optional dependency, installed viapip install clickhouse-connect[async]. - The internal
AiohttpAsyncClientclass has been renamed toAsyncClientand the moduleclickhouse_connect.driver.aiohttp_clienthas been removed. ImportAsyncClientfromclickhouse_connect.driveras before. - Dropped pandas 1.x support. Minimum pandas version is now 2.0. Users with pandas < 2.0 will get a
NotSupportedErrorat import time. Non-pandas usage is unaffected. Closes #661 - Removed the
preserve_pandas_datetime_resolutioncommon setting. Datetime columns now always return their natural resolution, e.g.datetime64[s]forDateTime,datetime64[ms]forDateTime64(3), instead of coercing everything todatetime64[ns]. Closes #662
Bug Fixes
- Fix Dynamic/JSON column reads when a path's inferred type sorts alphabetically after
"SharedVariant". ClickHouse'sDataTypeVariantconstructor sorts its members alphabetically by name, and discriminator bytes on the wire index into that sorted order. The client appendedSharedVariantto the variant list without sorting, so affected paths were read as the wrong variant. Closes #712 - Fix async streaming race condition that caused unhandled
InvalidStateErrorexceptions on early stream termination. When breaking out of an async stream early,shutdown()scheduled aset_resultcallback for pending futures viacall_soon_threadsafe, butTask.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()inChClickHouseDialect.get_schema_names()andget_table_names(), soInspector.get_schema_names()andget_table_names()work on SQLAlchemy 2.x instead of raisingObjectNotExecutableError.
Improvements
- Package version is now exposed as
clickhouse_connect.__version__(a string), following Python packaging conventions. The version remains single-sourced fromclickhouse_connect/_version.py. Users can access version information viaclickhouse_connect.__version__,importlib.metadata.version("clickhouse-connect"), or theclickhouse_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_argsparameter is now properly parsed on the async client creation path, matching the sync client behavior. - Pandas 3.x compatibility. Removed deprecated
copy=Falseparameter fromSeries(),concat(), andastype()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
v0.15.0
Improvements
- Comprehensive ClickHouse
JOINsupport in SQLAlchemy viach_join()with all strictness/distribution modifiers andUSINGsyntax (#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, andpolars, ~4x faster bare import time (#589)
Bug Fixes
- Fix
.final()and.sample()silently overwriting each other when chained (#658) - Fix
sqlalchemy.values()to emit ClickHouseVALUEStable function syntax (#681) - Fix
GraphiteMergeTreeto properly quoteconfig_sectionargument
Other
- Remove
py.typedmarker that was causing false type errors for mypy/pyright users (#691)
Full Changelog: v0.14.1...v0.15.0
v0.14.1
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
SELECTresults socursor.descriptionis 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=0is exoplicitly set. Closes #676
Full Changelog: v0.14.0...v0.14.1
v0.14.0
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_timezonerenamed totz_source. Options are"auto"(the default),"server", or"local". The old parameter currently still works with a deprecation warning. #670utc_tz_awarerenamed totz_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. AFutureWarningadvertising 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
SAMPLEin SQLAlchemy dialect. #656
New Contributors
- @bsushmith made their first contribution in #656
Full Changelog: v0.13.0...v0.14.0
v0.13.0
What's Changed
Improvements
-
BREAKING CHANGE: Implement native write path for
Variantdata type with type-aware dispatching. Previously, all values inserted into aVariantcolumn were stringified and sent to the server, which would store them in theStringmember if present, or attempt server-side conversion otherwise. Values are now serialized using their native ClickHouse types client-side (e.g. inserting100intoVariant(Int64, String)storesInt64(100)instead ofString("100")).Key changes:
- Values that don't match any variant member now raise
DataErrorinstead 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)vsArray(String)).
- Values that don't match any variant member now raise
-
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 bareDateTimecolumns. 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, andQueryResult. Ref #567
Bug Fixes
- Fix
dict_addparameter typed as builtinanyinstead oftyping.Any. - Recognize
UPDATEas a command so lightweight updates work correctly viaclient.query()and SQLAlchemy. - SQLAlchemy:
GROUP BYnow 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
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 deprecatedIf 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
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_idfrom the client side as aUUID4if 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_closesetting for HTTP clients to ensure SELECT queries are cancelled on the server when the client disconnects. Closes #641
Bug Fixes
- Raise
OperationalErrorwhenResponseSourcehits network failure before any data is received. Previously, empty result would be returned. Closes #620 - Fixed a bug where
InsertContextstate 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 withutc_tz_aware=False. DateTime columns with explicit UTC timezones now correctly return naive datetimes whenutc_tz_aware=Falseregardless of the specific UTC-equivalent timezone name returned by the server. Closes #629 - Extend UTC-equivalence checks to Arrow queries.
New Contributors
- @akkik04 made their first contribution in #597
- @m-dziuba made their first contribution in #613
- @abhisheksurve45 made their first contribution in #618
- @dave-shawley made their first contribution in #611
- @Milias made their first contribution in #621
- @veeceey made their first contribution in #643
Full Changelog: v0.10.0...v0.11.0