Skip to content

Releases: ClickHouse/clickhouse-connect

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

v0.10.0

14 Nov 19:59
f40cd28

Choose a tag to compare

What's Changed

Improvements

  • Added SQLAlchemy core API support for ARRAY JOIN and FINAL modifier. Closes #579
  • Added Python 3.14 support 🎉 (non-free-threaded build only; free-threaded builds are not yet supported). Closes #574
  • Added utc_tz_aware parameter to client and query methods to opt in to returning timezone-aware UTC objects for DateTime/DateTime64 columns. Default behavior remains the same and returns tz naive objects for backward compatibility.
    • Note: this parameter will likely be removed and only return tz-aware dts in some future release. Closes #566
  • Added executor parameter to AsyncClient constructor to allow passing a custom executor for async operations. This allows users to control the concurrency and thread pool used by the async client.

Bug Fixes

  • Fixed DST fallback bug in DateTime and DateTime64 types caused by passing potentially ambiguous times to pd.DateTimeIndex constructor. Closes #585
  • Fixed issue with JSON key dot escaping. Closes #571

New Contributors

Full Changelog: v0.9.2...v0.10.0

v0.9.2

25 Sep 23:02
03db21e

Choose a tag to compare

What's Changed

  • Updated python_requires to drop Python 3.8 and advertise support for 3.9–3.13
  • Allow passing role as a field in the settings keyword argument to set a role for a specific query

New Contributors

Full Changelog: v0.9.1...v0.9.2

v0.9.1

17 Sep 04:35
1dcd0eb

Choose a tag to compare

What's Changed

  • Fixed typing issue that required numpy to be installed during clickhouse_connect import

Full Changelog: v0.9.0...v0.9.1

v0.9.0

16 Sep 21:09
53595eb

Choose a tag to compare

What's Changed

Breaking Changes

  • WARNING: BREAKING CHANGE — Removed support for sqlalchemy 1.3 which reached its EOL in 2021. The minimum required version is now 1.4.40.
  • WARNING: BREAKING CHANGE — Behavior for reading from IPv6 columns has changed:
    • With read_format='native', the client will always return ipaddress.IPv6Address objects, even for IPv4-mapped addresses (e.g., "::ffff:192.168.1.1"). Previously, the client returned ipaddress.IPv4Address objects for these cases. This change enforces type consistency and avoids surprising implicit conversions. If your application requires IPv4 objects, you can explicitly convert using the ipv4_mapped attribute of IPv6Address.
    • With read_format='string', the client will always return IPv6 string representations, e.g., "::ffff:192.168.1.1" instead of "192.168.1.1", for the same reasons as above. If you require only the IPv4 string, you can parse or truncate this in your application code.
    • Closes #493

Major Features

  • Added support for SQLAlchemy 2.x. The minimum required version is 1.4.40. Closes #263
  • Added Polars support for Arrow-based query and insert methods (query_df_arrow, query_df_arrow_stream, insert_df_arrow). This initial implementation provides basic dataframe conversion through the Arrow format, similar to how we support the pyarrow-backed pandas dataframes. Closes #111 and #542
  • Added support for querying/inserting pyarrow-backed DataFrames:
    • query_df_arrow(): returns a pandas DataFrame with PyArrow dtype backend. Note that Arrow data types are preserved without additional conversions.
    • query_df_arrow_stream(): Streaming version of query_df_arrow() for processing large result sets.
    • insert_df_arrow(): Optimized insertion method for pandas DataFrames with PyArrow backend, which should provide better performance than standard insert_df().
  • Added Time and Time64 type support. Closes #509
  • Support for both pandas 1.x and 2.x.
  • Added support for Nullable(JSON) types
  • Added support for BFloat16 types

Improvements

  • Add support for lightweight DELETE in sqlalchemy. Closes #382
  • Added support for SELECT/JOIN operations via SQLAlchemy's core API (table operations and explicit statements--not ORM sessions-based queries)
  • Added client connection option rename_response_column (default None) that allows the user to define how response columns are automatically renamed according to a predefined scheme. Helpful for stripping alias prefixes, etc. in potentially complex queries. Closes #228
  • Add third-party library identifiers (name/version) in the User-Agent, e.g. pandas/2.2.5. Users can opt out by changing the common setting send_integration_tags to False.
  • Added support for form encoding query parameters when using HTTP interface. This addresses #342. Query parameters can now be sent as form-encoded data in the request body by setting form_encode_query_params=True when creating the client. This is particularly useful for queries with large parameter payloads that might exceed URL length limits.
  • Added support for special interval types. Closes #391
  • Added new common setting option "preserve_pandas_datetime_resolution" (default is False) allowing pandas 2.x users to opt into (when set to True) using the additional pandas 2.x datetime64/timedelta64 resolutions of "s", "ms", "us". If set to False or using pandas 1.x, all datetime64/timedelta64 resolutions will be coerced to "ns". (See here for more info). Closes #165 and #531
  • Tightens up type consistency of date-like objects when using query_df
  • When writing to an IPv6 column type, the client will "promote" IPv4 addresses to IPv4-mapped IPv6 addresses to prevent write errors. Closes #498
  • Changed AsyncClient.settings typing to Optional[Dict[str, Any]] to accept None inputs.
  • Added more robust error handling and tests. Closes #508
  • Replace the use of deprecated datetime.utcfromtimestamp

Bug Fixes

  • Fixed an AttributeError on http.client when importing clickhouse_connect under certain circumstances
  • Fixes problem with df inserts of Time and Time64 types. Closes #524

New Contributors

Full Changelog: v0.8.18...v0.9.0

v0.8.18 Collected bug fixes

24 Jun 17:59
ca60aa1

Choose a tag to compare

What's Changed

  • Fix SQLAlchemy execution error by using text() function by @lakako in #491
  • Test fixes for main by @genzgd in #497
  • Ensure types are returned even if there are no rows by @orian in #500
  • Fix some issues with cursor behavior by @joe-clickhouse in #506
    • Reset cursor location after performing an execute.
    • Fix behavior of fetchall to only return rows from the current cursor location.
    • Fixes logic of fetchmany to respect size parameter.
  • Added a standalone test file (tests/unit_tests/test_driver/test_cursor.py) for testing cursor behavior

New Contributors

Full Changelog: v0.8.17...v0.8.18

v0.8.17 Transport settings

13 Apr 21:37
50569f4

Choose a tag to compare

What's Changed

  • Updates for 0.8.17 release by @genzgd in #488
  • Add param extra_http_headers to query/command methods by @orian in #489
  • Change extra_http_headers to transport_settings by @genzgd in #490

Full Changelog: v0.8.16...v0.8.17

v0.8.16 Collected Bug Fixes

28 Mar 23:39
0a77c0e

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: v0.8.15...v0.8.16

v0.8.15 AsyncInsert Close Fix

25 Jan 23:52
a15a2ca

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: v0.8.14...v0.8.15