v1.9.0rc1
Pre-releaseclickhouse-connect v1.9.0rc1
This is the first release candidate for clickhouse-connect 1.9.0. Please test the native async SQLAlchemy dialect in your applications and report results.
Installation
pip install "clickhouse-connect[sqlalchemy-async]==1.9.0rc1"Documentation and examples
- SQLAlchemy guide: start with "Async connections" for engine setup, queries, pooling, cleanup, and limitations.
- Async Alembic environment: example configuration for online and offline migrations.
- Alembic worked example: a complete migration walkthrough.
For async connections, follow the guide's async setup and use the environment above.
Highlights
- Native async SQLAlchemy support for SQLAlchemy 2.0.44 and later. Use
clickhousedb+async://withcreate_async_engine(). The dialect supports buffered Core and ORM execution, query settings, read formats, server-side parameters, and direct access to the nativeAsyncClient. - DDL, reflection, and online Alembic migrations work through
run_sync(). Offline Alembic compilation is also supported, with a checked-in async environment example. - SQLAlchemy multi-row
Insert.values()statements now support dictionaries, tuples, and SQL expressions. This also enables Pandasto_sql(method="multi"). #1024
SQLAlchemy results are buffered. Server-side cursors and AsyncConnection.stream() are unsupported at this time. AsyncSession.stream() returns a buffered result. Use the native client for streaming and bulk inserts. Async executemany sends one request per parameter set. Pooled connections generate distinct session IDs by default. Fixed session IDs require a single-connection pool or external serialization.
Bug fixes
- Failed synchronous client construction releases its dedicated pool manager. Multiprocessing workers also reuse one process-local manager instead of retaining unused managers per client. #1039, #1016
- Async pool waits no longer consume
connect_timeout. Connection timeouts receive one retry for queries and replayable insert bodies; read timeouts, connector errors, certificate errors, and raw generator/file bodies remain non-retryable. #1013, #1012 - Typed SQLAlchemy
DateTime64SQL binds and literals preserve fractional seconds, including nested arrays and tuples. Declared SQLAlchemy types must match the server schema. #1030 - Native
DateandDate32inserts accept timezone-aware datetimes and mixed date/datetime values while preserving their calendar dates. #1031 - SQLAlchemy Decimal arithmetic and aggregates no longer raise invalid precision or scale errors. #1027
- DB-API
executemany()preserves parameterized INSERT statements and their SQL semantics. These inserts send one request per parameter set, so earlier rows remain committed after a later failure. Row counts aggregate server summaries or report-1when unavailable. SQLAlchemy retains Native bulk inserts for compiler-generated plain INSERT statements, and the established placeholder-less DB-API Native form remains supported. UseClient.insert()for explicit Native bulk throughput. #930, #932, #934 - Async Rust stream cleanup no longer blocks the event loop during early exit or leaves abandoned read-ahead resources.
- Async clients reject use of a live aiohttp session from another event loop before network I/O.
- Sync and async
ping()normalize trailing slashes inproxy_path. - Async SQLAlchemy connections close correctly after disposal, recycling, invalidation, or garbage collection. Pool pre-ping uses
SELECT 1; closed sessions are replaced while reusable sessions survive execution errors. - Async close and connection rotation handle cancellation without leaking transports or replaying requests interrupted by explicit shutdown. Concurrent close callers retain independent cancellation.
- Cancelled inserts release blocked serializer queues and reusable insert state. Cancelled queries release responses and session leases during parser handoff and streaming startup.
- Failed or cancelled async initialization releases newly created sessions. Overlapping initialization no longer lets one cancelled caller close another caller's successful session.
- Coroutine token providers, including partial wrappers, work in asyncio debug mode. Cancellation cleans up late coroutine results from synchronous providers.
- Client factories parse boolean and numeric strings from DSNs and generic arguments consistently. Async factories preserve fractional timeouts and correctly apply connector option precedence.
- The DB-API module exposes the driver's exception hierarchy so SQLAlchemy wraps errors correctly. Stream failures are also
OperationalErrorinstances and expose available ClickHouse error details.
Please include your Python, SQLAlchemy, and SQLModel versions when reporting feedback, along with any cancellation, pooling, startup/shutdown, or resource-warning issues.