Releases: ClickHouse/clickhouse-connect
v1.1.1
clickhouse-connect v1.1.1
This patch release fixes a handful of async-client connectivity bugs and a SHOW ROW POLICIES query routing issue. Recommended for all users on 1.1.0, especially those running the async client behind a proxy or against keep-alive-prone pools.
What's Changed
Bug Fixes
- Async client:
ping()now routes through the configured proxy, matching_raw_request. Previously the proxy was omitted, soping()falsely returnedFalseon networks where the server was only reachable via the proxy. Closes #757. - Fix
query("SHOW ROW POLICIES")/query("SHOW POLICIES")by routing these non-tabular statements without appendingFORMAT Native. Empty row-policySHOWresults now return""instead ofQuerySummary. Closes #761. - Async client: retry stale keep-alive resets surfaced by aiohttp as
ClientOSErrororClientConnectionResetError, fixing large async inserts on killed pooled connections. Closes #763. - Async client: do not retry aiohttp timeout, connector, or fingerprint errors — these can indicate the request was already delivered or a config issue, not a stale connection.
- Sync client: also retry stale keep-alive
BrokenPipeError(in addition toConnectionResetError), matching the async behavior.
Installation
pip install clickhouse-connect
v1.1.0
clickhouse-connect 1.1.0
This is the first minor release on the 1.x line. 1.1.0 consolidates everything from the 1.1.0a1 and 1.1.0a2 alphas i.e. the Alembic/SQLAlchemy integration work and adds a handful of bug fixes on top of 1.0.1.
If you're upgrading from a 0.15.x or earlier release, please read MIGRATION.md for the 1.0 breaking changes first.
Regarding Alembic support
This is the first clickhouse-connect release to ship Alembic integration. SQLAlchemy and Alembic each have a large surface area, and ClickHouse has plenty of dialect-specific quirks, so this release should best understood as a focused first cut. The common autogenerate/upgrade/downgrade flows for tables, columns, engines, dictionaries, comments, and operation-level settings rather than an exhaustive port of every Alembic feature. If you hit a gap, an inconvenience, or unexpected behavior, please open an issue with a repro. Enhancement requests are equally welcome and will help prioritize what to focus on.
Highlights
SQLAlchemy & Alembic
- Alembic migration support. Full Alembic integration for ClickHouse schema migrations: autogeneration of migration scripts from SQLAlchemy metadata, upgrade/downgrade lifecycle, and round-tripping of ClickHouse-specific DDL. 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. ClickHouse table engines (MergeTree,ReplacingMergeTree, etc.) and dictionaries are preserved through the migration lifecycle. Install viapip install clickhouse-connect[alembic]. Seeclickhouse_connect/cc_sqlalchemy/alembic/WORKED_EXAMPLE.mdfor an end-to-end walkthrough. - ClickHouse
Dictionarytype support. Reflect, create, and drop ClickHouse dictionaries through SQLAlchemy and Alembic. - New Select constructs:
PREWHERE,LIMIT BY, and lambda expressions are now chainable onselect()for ClickHouse-specific queries. - Multi-column
ARRAY JOINlabel preservation.ARRAY JOINaliases now survive through compilation, fixing label-loss issues with parallel array expansion. - Migration shim for
clickhouse-sqlalchemyusers. Newcc_sqlalchemy.typesandcc_sqlalchemy.enginesimport-compatible modules ease migration fromclickhouse-sqlalchemy. Seeclickhouse_connect/cc_sqlalchemy/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 improvements including better handling of nested container types and Tuple adaptation.
Compatibility
- Async client now requires
aiohttp>=3.9.0. This is required to support TLS SNI override viaserver_host_name, because aiohttp added the per-requestserver_hostnameoption in 3.9. - The
alembicextra now requiresalembic>=1.16(previously>=1.9), to expose theIF EXISTS/IF NOT EXISTSoperation kwargs used by the integration.
Bug fixes
- Async client:
server_host_namenow also overrides the TLS SNI / certificate hostname, matching the sync client. Previously the async path only applied it to the HTTPHostheader, so connecting to host A while presenting SNI B (the 0.xpool_mgr=urllib3.PoolManager(server_hostname=...)pattern, useful for ClickHouse Cloud VPC endpoints reached via external DNS) was not expressible against the new aiohttp-based client. Closes #752. - Drain the full
retriesbudget on connection-error retries in_raw_requestinstead of only retrying once. Previously both the sync and async clients gated network-error retries onattempts == 1, so two consecutiveaiohttp.ServerDisconnectedErrors (orConnectionResetErrors on the sync path) surfaced asOperationalErroreven whenquery_retrieswould have allowed another attempt. Read paths will now drainquery_retries. Insert/command paths still get one retry. Syncraw_queryandraw_stream, the foundation forquery_arrow&query_arrow_streamnow also passquery_retriesso they match their async counterparts. Adds a0.1 * attemptsbackoff between connection-error retries to match the 429/503/504 branch. Closes #754. quote_identifiernow re-escapes inputs that start and end with`or"but contain unescaped inner occurrences of the same quote character, instead of passing them through unchanged. Validly pre-quoted identifiers like backslash or doubled-quote escaping still pass through untouched. Closes #737.- SQLAlchemy:
op.add_column(..., clickhouse_settings={...})now works through the public Alembic operations API. Previously the stockOperations.add_columnproxy had a fixed signature that rejectedclickhouse_settingswithTypeError, even though the underlying impl accepted it. RenderedAddColumnOpmigrations also preserve extra ClickHouse kwargs on round-trip, so autogenerated scripts containingclickhouse_settings=...survive regeneration. - SQLAlchemy: Alembic migrations now handle comments with ClickHouse-compatible syntax. Column comments on
CREATE TABLE/ADD COLUMNare rendered inline instead of emitting separateCOMMENT ON COLUMNstatements (which ClickHouse rejects). Table comments are now emitted in generated DDL, reflected for no-op autogenerate, and changed or dropped viaALTER TABLE ... MODIFY COMMENT.Inspector.get_table_comment(...)now raisesNoSuchTableErrorfor missing tables instead of silently returning{"text": None}. - SQLAlchemy: quote string-valued engine and operation settings as ClickHouse string literals when rendering
SETTINGSclauses. Previously settings likeMergeTree(settings={"storage_policy": "hot_cold"})orop.add_column(..., clickhouse_settings={"mutations_sync": "2"})emitted unquoted SQL (storage_policy = hot_cold), which ClickHouse rejected. Numeric and boolean settings are unchanged. - SQLAlchemy: preserve engine
settingson reflection.build_engine()previously hardcodedengine.settings = {}even when the reflected DDL contained aSETTINGSclause, so callers readingengine.settingsafter reflection saw an empty dict.settingsis now populated from the parsed engine kwargs, decoding ClickHouse string-literal escapes (\\,\',\n, etc.) and preserving float-valued settings as floats providing round-trip parity with the construction path. - SQLAlchemy:
Inspectorerror messages fromget_table_metadata()now report the resolved database name i.e. fromcurrentDatabase()whenschemawas not provided instead of literalNone. - SQLAlchemy: preserve
FINAL,SAMPLE,PREWHERE, andLIMIT BYmodifiers when aselect()is built from ORM-mapped attributes e.g.select(Event.id)rather than Core columns. Previously the ORM compile path rebuilt the inner Select viaSelect._create_raw_select, which dropped the modifier instance attributes, so the compiled SQL silently emitted no modifier. The compiler now falls back tocompile_state.select_statementwhich is the original user-built Select to recover the modifiers. Closes #730. - Alembic autogenerated migrations now render enum types (including nested container types) with the correct ClickHouse-compatible representation.
Pre-release tags rolled into 1.1.0
v1.1.0a1(2026-05-06) - initial alembic / SQLAlchemy alphav1.1.0a2(2026-05-07) - ORM modifier compile-path fix
Install
pip install clickhouse-connect
For Alembic integration:
pip install clickhouse-connect[alembic]
v1.0.1
clickhouse-connect 1.0.1
If you are upgrading from 0.15.x or earlier, see MIGRATION.md for the 1.0 breaking changes.
What's Changed
Bug Fixes
- Recognize
Fixed/UTC±HH:MM:SStimezones emitted by ClickHouse servers without an IANA tz database (in column types, theX-ClickHouse-Timezoneheader, andSELECT timezone()). Previously these raisedProgrammingErroron any column read, parameter bind, or client init that touched one. The exact±24:00:00boundary remains rejected because Python'sdatetime.timezonecannot represent it. Closes #702. - Async client: drain in-flight requests before closing the underlying aiohttp session. Sharing a single
AsyncClientacross concurrent coroutines previously raisedRuntimeError: Session is closed(and relatedConnection reset/QUERY_WITH_SAME_ID_IS_ALREADY_RUNNINGcascades) whenevermax_connection_agetriggered a pool rotation while other tasks had requests in flight.close_connections()now installs the new session before retiring the old one, and waits for outstanding requests (including streaming responses) to release their lease before tearing it down.close()clearsself._sessionso post-close calls fail withProgrammingErrorinstead of leaking aiohttp'sRuntimeError. Closes #744. - Async client:
ca_cert="certifi"shorthand now resolves tocertifi.where(), matching the sync client. Previously the async path passed the literal string tossl_context.load_verify_locations, producingFileNotFoundError. Closes #742. - SQLAlchemy: render
ILIKEandNOT ILIKEexpressions using native ClickHouse syntax instead of the generic SQLAlchemylower(...) LIKE lower(...)fallback.
v1.0.0
clickhouse-connect 1.0.0
The first stable release of clickhouse-connect. 1.0.0 is identical in code to 1.0.0rc3. No changes have been merged since that tag.
Installation:
pip install clickhouse-connect
Upgrading from 0.x
The 1.0 release includes breaking changes accumulated across the rc1/rc2/rc3 cycle. If you are upgrading from a 0.15.x or earlier release, please read MIGRATION.md for a guide to the changes and their replacements.
At a glance, the breaking changes are:
- Python 3.10 minimum (3.9 dropped.
0.15.xis the last series supporting 3.9) - pandas 2.0 minimum (1.x dropped)
pytzdependency replaced with stdlibzoneinfo(install thetzdataextra on slim Linux containers)utc_tz_aware->tz_mode("naive_utc"/"aware"/"schema")apply_server_timezone->tz_source("auto"/"server"/"local")preserve_pandas_datetime_resolutionsetting removed:DateTime/DateTime64now return their natural numpy resolution- Executor-based async client removed: use
clickhouse_connect.get_async_client()(native aiohttp, installed via theasyncextra)
Highlights
Performance
1.0 includes substantial Cython read- and write-path improvements over the 0.15.x series:
- Order-of-magnitude faster
DateTime/DateTime64reads for naive UTC and UTC-equivalent timezones, via epoch arithmetic and the CPython datetime C API. - Order-of-magnitude faster fixed-width numeric inserts from numpy arrays, with significantly lower peak memory, 1-D C-contiguous arrays of matching dtype are now copied directly via
memcpy. - Significantly faster
Mapreads and writes, with reads avoiding the intermediate pair-tuple materialization. - Significantly faster
DecimalandBigDecimalreads, the decode path now builds values directly from the integer column viaDecimal.scalebinstead of constructing intermediate strings per row.
Bug fixes
Notable fixes that shipped during the RC cycle:
- Fix intermittent
Code: 62. Empty query. (SYNTAX_ERROR)on inserts when a pooled keep-alive connection is reset between attempts. (#731) - Async client: retry once when aiohttp raises bare
ServerDisconnectedError("Server disconnected")on a pooled keep-alive connection idle-closed by the server. - Fix Dynamic/JSON column reads when a path's inferred type sorts alphabetically after
"SharedVariant". (#712) - Fix async streaming race condition that caused unhandled
InvalidStateErroron early stream termination. - SQLAlchemy: wrap raw SQL strings in
text()inInspector.get_schema_names()/get_table_names()so they work on SQLAlchemy 2.x. - SQLAlchemy:
Booltype now accepts and forwards**kwargs, fixing ORM model use andTable.to_metadata(). (#705) - SQLAlchemy:
CreateDatabasewithengine="Replicated"now emits valid DDL.
Other improvements
- Package version is now exposed as
clickhouse_connect.__version__, following Python packaging conventions. - Lazy loading of optional dependencies (
numpy,pandas,pyarrow,polars) now applies to the async client as well. - Pandas 3.x compatibility.
Full RC notes
For the per-RC breakdown:
v1.1.0a2
1.1.0a2 — Alpha Preview (Bug-fix follow-up)
Quick follow-up to 1.1.0a1, rebased on 1.0.0rc3 so the rc3 insert-retry fix is included. Everything from 1.1.0a1 still applies. See that release for the full preview overview.
Installation
pip install clickhouse-connect==1.1.0a2
# To use the Alembic integration:
pip install "clickhouse-connect[alembic]==1.1.0a2"Fixed in this preview
- SQLAlchemy: ClickHouse Select modifiers preserved through the ORM compile path.
FINAL,SAMPLE,PREWHERE, andLIMIT BYwere silently dropped when aselect()was built from ORM-mapped attributes (e.g.select(Event.id)) rather than Core columns. The ORM compile path rebuilds the innerSelectviaSelect._create_raw_select, which discarded the modifier instance attributes — so the compiled SQL emitted no modifier. The compiler now falls back tocompile_state.select_statementto recover them. Closes #730. - Inserts: rebuild body on connection-reset retry (inherited from
1.0.0rc3). Fixes intermittentCode: 62. Empty query. (SYNTAX_ERROR)on inserts when a pooled keep-alive connection is reset between attempts; the retry path now rebuilds the insert body instead of replaying an already-drained generator. Affects both sync and async clients. Closes #731.
Feedback
Please keep filing issues at https://github.com/ClickHouse/clickhouse-connect/issues with the alembic or sqlalchemy label.
Full changelog
See CHANGELOG.md for the complete entry.
v1.0.0rc3
Release Candidate 1.0.0 (rc3)
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.0rc3
If upgrading from 0.15.x, see the migration notes in rc1. All 1.0 breaking changes were introduced there. rc3 contains no new breaking changes.
Highlights
rc3 is a small bug-fix release on top of rc2. It fixes an intermittent SYNTAX_ERROR on inserts when a pooled keep-alive connection is reset between attempts.
What's Changed
Bug Fixes
- Fix intermittent
Code: 62. Empty query. (SYNTAX_ERROR)on inserts when a pooled keep-alive connection is reset between attempts. The retry path now rebuilds the insert body instead of replaying an already-drained generator. Affects both sync and async clients. Closes #731
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.