### Install aiochclient with httpx Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Install the aiochclient library with httpx support. For speedups, install with `httpx-speedups`. ```bash pip install aiochclient[httpx] # With speedups (ciso8601) pip install aiochclient[httpx-speedups] ``` -------------------------------- ### Install aiochclient with httpx Source: https://github.com/maximdanilchenko/aiochclient/blob/master/README.md Command to install the client with httpx support. ```bash > pip install aiochclient[httpx] ``` -------------------------------- ### Install aiochclient with aiohttp Source: https://github.com/maximdanilchenko/aiochclient/blob/master/README.md Command to install the client with aiohttp support. ```bash > pip install aiochclient[aiohttp] ``` -------------------------------- ### Install aiochclient Source: https://github.com/maximdanilchenko/aiochclient/blob/master/docs/introduction.md Install aiochclient using pip. Use the -U flag to update to the latest version. ```bash $ pip install aiochclient ``` -------------------------------- ### Build Documentation with Sphinx Source: https://github.com/maximdanilchenko/aiochclient/blob/master/docs/install-docs.md Install the required development dependencies and execute the sphinx-build command to generate the HTML documentation. ```bash $ pip install -r dev-requirements/dev-requirements.txt $ sphinx-build -b html -d build/doctrees docs build/html ``` -------------------------------- ### Quick Start: Check ClickHouse Alive Source: https://github.com/maximdanilchenko/aiochclient/blob/master/docs/introduction.md Connect to ClickHouse on localhost:8123 with default user and check if it's alive. Requires aiohttp.ClientSession. ```python import asyncio from aiochclient import ChClient from aiohttp import ClientSession async def main(): async with ClientSession() as s: client = ChClient(s) alive = await client.is_alive() print(f"Is ClickHouse alive? -> {alive}") if __name__ == '__main__': asyncio.run(main()) ``` -------------------------------- ### Initialize aiochclient in aiohttp Application Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Configures the application factory to manage ClickHouse connection lifecycle using startup and cleanup signals. ```python def create_app(config: dict) -> web.Application: app = web.Application() app['config'] = config app.on_startup.append(init_clickhouse) app.on_cleanup.append(close_clickhouse) app.router.add_get('/health', health_check) app.router.add_get('/events', get_events) app.router.add_post('/events', create_event) return app if __name__ == '__main__': config = { 'clickhouse': { 'url': 'http://localhost:8123', 'user': 'default', 'password': '', 'database': 'default', } } app = create_app(config) web.run_app(app, port=8080) ``` -------------------------------- ### Integrate aiochclient with aiohttp Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Shows how to manage the ChClient lifecycle within an aiohttp application using startup and cleanup handlers. ```python from aiohttp import ClientSession, web from aiochclient import ChClient, ChClientError # Application lifecycle handlers async def init_clickhouse(app: web.Application): """Initialize ClickHouse client on app startup""" app['http_session'] = ClientSession() app['ch'] = ChClient( app['http_session'], url=app['config']['clickhouse']['url'], user=app['config']['clickhouse']['user'], password=app['config']['clickhouse']['password'], database=app['config']['clickhouse']['database'], compress_response=True, ) async def close_clickhouse(app: web.Application): """Close connections on app cleanup""" await app['http_session'].close() # Request handlers async def health_check(request: web.Request) -> web.Response: """Health check endpoint""" ch: ChClient = request.app['ch'] is_alive = await ch.is_alive() return web.json_response({'status': 'ok' if is_alive else 'error'}) async def get_events(request: web.Request) -> web.Response: """Fetch events with pagination""" ch: ChClient = request.app['ch'] limit = int(request.query.get('limit', 100)) offset = int(request.query.get('offset', 0)) try: rows = await ch.fetch( "SELECT * FROM events ORDER BY created_at DESC LIMIT {limit} OFFSET {offset}", params={"limit": limit, "offset": offset} ) events = [dict(zip(row.keys(), row.values())) for row in rows] return web.json_response({'events': events}) except ChClientError as e: return web.json_response({'error': str(e)}, status=500) async def create_event(request: web.Request) -> web.Response: """Create a new event""" ch: ChClient = request.app['ch'] data = await request.json() try: await ch.execute( "INSERT INTO events (name, value) VALUES", (data['name'], data['value']), ) return web.json_response({'status': 'created'}, status=201) except ChClientError as e: return web.json_response({'error': str(e)}, status=500) ``` -------------------------------- ### Connect to ClickHouse Source: https://github.com/maximdanilchenko/aiochclient/blob/master/README.md Initialize the ChClient using an existing aiohttp session. ```python from aiochclient import ChClient from aiohttp import ClientSession async def main(): async with ClientSession() as s: client = ChClient(s) assert await client.is_alive() # returns True if connection is Ok ``` -------------------------------- ### Initialize and check ChClient connection Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Initialize the ChClient with connection parameters and check if the connection to ClickHouse is alive. Ensure an aiohttp.ClientSession is active. ```python import asyncio from aiohttp import ClientSession from aiochclient import ChClient async def main(): async with ClientSession() as session: # Initialize client with connection parameters client = ChClient( session, url="http://localhost:8123/", user="default", password="secret", database="mydb", compress_response=True, # Enable gzip compression max_execution_time=60, # Custom ClickHouse settings ) # Check connection health is_alive = await client.is_alive() print(f"Connection OK: {is_alive}") # Output: Connection OK: True asyncio.run(main()) ``` -------------------------------- ### Perform automatic type conversion with aiochclient Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Demonstrates creating a table with various ClickHouse types and inserting/fetching data using corresponding Python types. ```python import asyncio import datetime as dt from decimal import Decimal from uuid import UUID from ipaddress import IPv4Address, IPv6Address from aiohttp import ClientSession from aiochclient import ChClient async def main(): async with ClientSession() as session: client = ChClient(session, url="http://localhost:8123") # Create table with various types await client.execute(""" CREATE TABLE IF NOT EXISTS typed_data ( bool_col Bool, int_col Int64, float_col Float64, str_col String, date_col Date, datetime_col DateTime, datetime64_col DateTime64(6), uuid_col UUID, ipv4_col IPv4, ipv6_col IPv6, decimal_col Decimal(18, 4), array_col Array(Int32), tuple_col Tuple(String, Int32), map_col Map(String, Int32), nullable_col Nullable(String) ) ENGINE = Memory """) # Insert with automatic Python -> ClickHouse conversion await client.execute( "INSERT INTO typed_data VALUES", ( True, # Bool -> Bool 42, # int -> Int64 3.14159, # float -> Float64 "hello", # str -> String dt.date(2024, 1, 15), # date -> Date dt.datetime(2024, 1, 15, 10, 30, 0), # datetime -> DateTime dt.datetime(2024, 1, 15, 10, 30, 0, 123456), # datetime -> DateTime64 UUID("550e8400-e29b-41d4-a716-446655440000"), # UUID -> UUID IPv4Address("192.168.1.1"), # IPv4Address -> IPv4 IPv6Address("::1"), # IPv6Address -> IPv6 Decimal("12345.6789"), # Decimal -> Decimal [1, 2, 3, 4, 5], # list -> Array ("key", 100), # tuple -> Tuple {"a": 1, "b": 2}, # dict -> Map None, # None -> Nullable ) ) # Fetch with automatic ClickHouse -> Python conversion row = await client.fetchrow("SELECT * FROM typed_data") print(f"Bool: {row['bool_col']} ({type(row['bool_col']).__name__})") # Output: Bool: True (bool) print(f"Date: {row['date_col']} ({type(row['date_col']).__name__})") # Output: Date: 2024-01-15 (date) print(f"UUID: {row['uuid_col']} ({type(row['uuid_col']).__name__})") # Output: UUID: 550e8400-e29b-41d4-a716-446655440000 (UUID) print(f"Array: {row['array_col']} ({type(row['array_col']).__name__})") # Output: Array: [1, 2, 3, 4, 5] (list) print(f"Map: {row['map_col']} ({type(row['map_col']).__name__})") # Output: Map: {'a': 1, 'b': 2} (dict) asyncio.run(main()) ``` -------------------------------- ### Execute Parallel Queries with aiochclient Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Demonstrates running multiple concurrent insert and fetch operations using asyncio.gather and a configured TCPConnector. ```python import asyncio from aiohttp import ClientSession, TCPConnector from aiochclient import ChClient async def insert_batch(client: ChClient, batch_id: int, count: int): """Insert a batch of records""" rows = [(batch_id * 1000 + i, f"item_{i}", i * 1.5) for i in range(count)] await client.execute("INSERT INTO parallel_test VALUES", *rows) return batch_id async def fetch_range(client: ChClient, min_id: int, max_id: int): """Fetch records in a range""" return await client.fetch( "SELECT * FROM parallel_test WHERE id >= {min} AND id < {max}", params={"min": min_id, "max": max_id} ) async def main(): # Configure connection pool size connector = TCPConnector(limit=100) async with ClientSession(connector=connector) as session: client = ChClient(session, url="http://localhost:8123") # Setup await client.execute(""" CREATE TABLE IF NOT EXISTS parallel_test ( id UInt32, name String, value Float64 ) ENGINE = MergeTree() ORDER BY id """) # Parallel inserts insert_tasks = [ insert_batch(client, batch_id, 100) for batch_id in range(10) ] completed_batches = await asyncio.gather(*insert_tasks) print(f"Completed batches: {completed_batches}") # Parallel fetches fetch_tasks = [ fetch_range(client, i * 1000, (i + 1) * 1000) for i in range(10) ] all_results = await asyncio.gather(*fetch_tasks) total_rows = sum(len(result) for result in all_results) print(f"Fetched {total_rows} rows in parallel") # Mix of different operations count_task = client.fetchval("SELECT count() FROM parallel_test") sum_task = client.fetchval("SELECT sum(value) FROM parallel_test") avg_task = client.fetchval("SELECT avg(value) FROM parallel_test") count, total, avg = await asyncio.gather(count_task, sum_task, avg_task) print(f"Count: {count}, Sum: {total}, Avg: {avg}") asyncio.run(main()) ``` -------------------------------- ### Execute CREATE, INSERT, and ALTER queries with ChClient Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Execute various ClickHouse queries including table creation, single and multiple row insertions, and parameterized ALTER statements. Automatic type conversion is handled. ```python import asyncio import datetime as dt from aiohttp import ClientSession from aiochclient import ChClient async def main(): async with ClientSession() as session: client = ChClient(session, url="http://localhost:8123") # Create table await client.execute(""" CREATE TABLE IF NOT EXISTS events ( id UInt32, name String, value Float64, created_at DateTime, tags Array(String), metadata Nullable(String) ) ENGINE = MergeTree() ORDER BY id """) # Insert single row await client.execute( "INSERT INTO events VALUES", (1, "click", 99.5, dt.datetime.now(), ["web", "mobile"], None), ) # Insert multiple rows await client.execute( "INSERT INTO events VALUES", (2, "view", 10.0, dt.datetime(2024, 1, 15, 10, 30), ["web"], "source:organic"), (3, "purchase", 250.0, dt.datetime(2024, 1, 15, 11, 0), ["mobile"], "source:ad"), (4, "signup", 0.0, dt.datetime(2024, 1, 15, 12, 0), [], None), ) # Execute with parameterized query await client.execute( "ALTER TABLE events DELETE WHERE id = {id}", params={"id": 4} ) # Execute with query_id for tracking await client.execute( "INSERT INTO events VALUES", (5, "logout", 0.0, dt.datetime.now(), [], None), query_id="batch-insert-001" ) asyncio.run(main()) ``` -------------------------------- ### ChClient.execute() Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Executes arbitrary ClickHouse queries such as CREATE, INSERT, ALTER, or DROP without returning result sets. ```APIDOC ## POST /execute ### Description Executes a ClickHouse query. For INSERT operations, data can be passed as positional arguments representing rows. ### Method POST ### Parameters #### Request Body - **query** (string) - Required - The SQL query to execute. - **args** (tuple) - Optional - Positional arguments for INSERT values. - **params** (dict) - Optional - Parameters for parameterized queries. - **query_id** (string) - Optional - A unique identifier for the query for tracking purposes. ### Request Example { "query": "INSERT INTO events VALUES", "args": [(1, "click", 99.5, "2024-01-01 10:00:00", ["web"], null)], "query_id": "batch-insert-001" } ``` -------------------------------- ### Execute DDL Queries Source: https://github.com/maximdanilchenko/aiochclient/blob/master/README.md Create a table using the execute method. ```python await client.execute( "CREATE TABLE t (a UInt8, b Tuple(Date, Nullable(Float32))) ENGINE = Memory" ) ``` -------------------------------- ### Handle ChClientError exceptions Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Demonstrates catching various ChClientError scenarios including connection, query, argument, type, and format errors. ```python import asyncio from aiohttp import ClientSession from aiochclient import ChClient, ChClientError async def main(): async with ClientSession() as session: client = ChClient(session, url="http://localhost:8123") # Handle connection errors try: await client.is_alive() except ChClientError as e: print(f"Connection failed: {e}") # Handle query errors try: await client.execute("SELECT * FROM nonexistent_table") except ChClientError as e: print(f"Query error: {e}") # Handle invalid argument usage try: # Cannot pass data arguments to SELECT queries await client.execute("SELECT * FROM events", (1, 2, 3)) except ChClientError as e: print(f"Invalid usage: {e}") # Output: Invalid usage: It is possible to pass arguments only for INSERT queries # Handle type conversion errors try: # Invalid type in insert data await client.execute( "INSERT INTO events VALUES", (object(), "test", 1.0, None, [], None), # object() not supported ) except ChClientError as e: print(f"Type error: {e}") # Handle insert_file format errors try: await client.insert_file( "INSERT INTO events", # Missing FORMAT clause b"data", ) except ChClientError as e: print(f"Format error: {e}") # Output: To insert file its required to specify `FORMAT [...]` in the query. asyncio.run(main()) ``` -------------------------------- ### ChClient.fetch() - Fetch All Rows Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Executes a SELECT query and returns all results as a list of Record objects. Suitable for retrieving all data into memory. ```APIDOC ## ChClient.fetch() - Fetch All Rows ### Description Executes a SELECT query and returns all results as a list of Record objects. Each Record provides both index-based and key-based access to field values. Use this method when you need all results in memory at once. ### Method `POST` (Implicitly, as it sends a query to the server) ### Endpoint `/query` (or similar, depending on ClickHouse client configuration) ### Parameters #### Query Parameters - **query** (string) - Required - The SQL query to execute. - **params** (object) - Optional - A dictionary of parameters to substitute into the query. - **json** (boolean) - Optional - If true, returns raw dictionaries instead of Record objects. - **decode** (boolean) - Optional - If false, returns raw bytes instead of decoded values. ### Request Example ```python # Fetch all rows rows = await client.fetch("SELECT * FROM events ORDER BY id LIMIT 100") # Fetch with parameters rows = await client.fetch( "SELECT name, value FROM events WHERE value > {min_value}", params={"min_value": 50.0} ) # Fetch in JSON mode rows = await client.fetch( "SELECT id, name, value FROM events LIMIT 5", json=True ) # Fetch without type decoding rows = await client.fetch( "SELECT * FROM events LIMIT 5", decode=False ) ``` ### Response #### Success Response (200) - **rows** (list[Record] or list[dict] or list[bytes]) - A list of records, dictionaries, or bytes representing the query results. #### Response Example (Record objects) ```json [ {"id": 1, "name": "click", "value": 99.5, "created_at": "2023-01-01T10:00:00"}, {"id": 2, "name": "view", "value": 10.0, "created_at": "2023-01-01T10:05:00"} ] ``` #### Response Example (JSON mode) ```json [ {"id": 1, "name": "click", "value": 99.5}, {"id": 2, "name": "view", "value": 10.0} ] ``` ``` -------------------------------- ### Insert File Data with ChClient.insert_file() Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Insert data from files in supported formats (CSV, JSON, Parquet) using insert_file(). The query must specify the FORMAT clause. ```python import asyncio from aiohttp import ClientSession from aiochclient import ChClient async def main(): async with ClientSession() as session: client = ChClient(session, url="http://localhost:8123") # Insert from CSV file with open('data.csv', 'rb') as f: await client.insert_file( "INSERT INTO events FORMAT CSV", f.read(), ) # Insert from JSON file with open('events.json', 'rb') as f: await client.insert_file( "INSERT INTO events FORMAT JSONEachRow", f.read(), ) # Insert from Parquet (e.g., downloaded from URL) import requests response = requests.get("https://example.com/data.parquet") await client.insert_file( "INSERT INTO events FORMAT Parquet", response.content, ) # Insert with parameterized table name with open('data.csv', 'rb') as f: await client.insert_file( "INSERT INTO {table} FORMAT CSV", f.read(), params={"table": "events"} ) asyncio.run(main()) ``` -------------------------------- ### aiochclient.ChClient Source: https://github.com/maximdanilchenko/aiochclient/blob/master/docs/reference.md The primary client class for interacting with ClickHouse asynchronously. ```APIDOC ## aiochclient.ChClient ### Description The main entry point for the library, providing methods to execute queries and interact with the ClickHouse database asynchronously. ``` -------------------------------- ### ChClient.is_alive() Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Checks the health and connectivity status of the ClickHouse server. ```APIDOC ## GET /is_alive ### Description Checks if the ClickHouse server is reachable and responding to requests. ### Method GET ### Response #### Success Response (200) - **is_alive** (bool) - Returns True if the connection is successful, False otherwise. ``` -------------------------------- ### Fetch All Rows Source: https://github.com/maximdanilchenko/aiochclient/blob/master/README.md Retrieve all rows from a query result set. ```python all_rows = await client.fetch("SELECT * FROM t") ``` -------------------------------- ### Fetch a single row with ChClient.fetchrow() Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Returns the first row as a Record object or None. Useful for lookups or checking existence. ```python import asyncio from aiohttp import ClientSession from aiochclient import ChClient async def main(): async with ClientSession() as session: client = ChClient(session, url="http://localhost:8123") # Fetch single row by ID row = await client.fetchrow("SELECT * FROM events WHERE id = 1") if row: print(f"Found event: {row['name']}") print(f"Tags: {row['tags']}") # Python list print(f"Created: {row['created_at']}") # Python datetime # Get all column names and values print(f"Columns: {list(row.keys())}") print(f"Values: {list(row.values())}") else: print("Event not found") # Fetch with parameters row = await client.fetchrow( "SELECT name, count() as cnt FROM events WHERE name = {event_name} GROUP BY name", params={"event_name": "click"} ) if row: print(f"Click count: {row['cnt']}") # Check if table exists exists = await client.fetchrow("EXISTS TABLE events") print(f"Table exists: {exists[0]}") # Output: Table exists: 1 asyncio.run(main()) ``` -------------------------------- ### Fetch multiple rows with ChClient.fetch() Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Retrieves all results as a list of Record objects. Supports parameter binding, JSON mode for raw dictionaries, and disabling type decoding. ```python import asyncio from aiohttp import ClientSession from aiochclient import ChClient async def main(): async with ClientSession() as session: client = ChClient(session, url="http://localhost:8123") # Fetch all rows from query rows = await client.fetch("SELECT * FROM events ORDER BY id LIMIT 100") for row in rows: # Access by column name print(f"Event: {row['name']}, Value: {row['value']}") # Access by index print(f"ID: {row[0]}, Created: {row[3]}") # Slice access print(f"First 3 fields: {row[:3]}") # Fetch with parameters rows = await client.fetch( "SELECT name, value FROM events WHERE value > {min_value}", params={"min_value": 50.0} ) print(f"Found {len(rows)} high-value events") # Fetch in JSON mode (returns raw dicts) rows = await client.fetch( "SELECT id, name, value FROM events LIMIT 5", json=True ) for row in rows: print(row) # Output: {'id': 1, 'name': 'click', 'value': 99.5} # Fetch without type decoding (returns raw bytes) rows = await client.fetch( "SELECT * FROM events LIMIT 5", decode=False ) asyncio.run(main()) ``` -------------------------------- ### Connect to a Different ClickHouse Instance Source: https://github.com/maximdanilchenko/aiochclient/blob/master/docs/introduction.md Specify a custom URL for connecting to a ClickHouse instance. The default is http://localhost:8123. ```python client = ChClient(s, url='http://localhost:8123') ``` -------------------------------- ### aiochclient.ChClientError Source: https://github.com/maximdanilchenko/aiochclient/blob/master/docs/reference.md Exception class for handling errors specific to the aiochclient library. ```APIDOC ## aiochclient.ChClientError ### Description Base exception class used for reporting errors that occur during ClickHouse operations within the client. ``` -------------------------------- ### Fetch a single value with ChClient.fetchval() Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Returns the first value of the first row or None. Ideal for aggregate queries and scalar results. ```python import asyncio from aiohttp import ClientSession from aiochclient import ChClient async def main(): async with ClientSession() as session: client = ChClient(session, url="http://localhost:8123") # Get count count = await client.fetchval("SELECT count() FROM events") print(f"Total events: {count}") # Output: Total events: 5 # Get sum total_value = await client.fetchval("SELECT sum(value) FROM events") print(f"Total value: {total_value}") # Output: Total value: 359.5 # Get average with parameters avg_value = await client.fetchval( "SELECT avg(value) FROM events WHERE name = {name}", params={"name": "click"} ) print(f"Avg click value: {avg_value}") # Check existence exists = await client.fetchval("SELECT 1 FROM events WHERE id = 1 LIMIT 1") print(f"Event 1 exists: {exists is not None}") # Get max datetime latest = await client.fetchval("SELECT max(created_at) FROM events") print(f"Latest event: {latest}") # Output: datetime object # Get database version version = await client.fetchval("SELECT version()") print(f"ClickHouse version: {version}") asyncio.run(main()) ``` -------------------------------- ### Insert Data into ClickHouse Source: https://github.com/maximdanilchenko/aiochclient/blob/master/README.md Insert rows by passing iterables as arguments to the execute method. ```python await client.execute( "INSERT INTO t VALUES", (1, (dt.date(2018, 9, 7), None)), (2, (dt.date(2018, 9, 8), 3.14)), ) ``` -------------------------------- ### ChClient.fetchrow() - Fetch Single Row Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Executes a query and returns only the first row as a Record object, or None if no results exist. Efficient for retrieving a single record. ```APIDOC ## ChClient.fetchrow() - Fetch Single Row ### Description Executes a query and returns only the first row as a Record object, or None if no results exist. This is efficient when you only need one record, such as looking up a specific item or checking existence. ### Method `POST` (Implicitly, as it sends a query to the server) ### Endpoint `/query` (or similar, depending on ClickHouse client configuration) ### Parameters #### Query Parameters - **query** (string) - Required - The SQL query to execute. - **params** (object) - Optional - A dictionary of parameters to substitute into the query. ### Request Example ```python # Fetch single row by ID row = await client.fetchrow("SELECT * FROM events WHERE id = 1") # Fetch with parameters row = await client.fetchrow( "SELECT name, count() as cnt FROM events WHERE name = {event_name} GROUP BY name", params={"event_name": "click"} ) # Check if table exists exists = await client.fetchrow("EXISTS TABLE events") ``` ### Response #### Success Response (200) - **row** (Record or None) - The first row of the query result as a Record object, or None if no rows were found. #### Response Example (Record object) ```json { "id": 1, "name": "click", "value": 99.5, "created_at": "2023-01-01T10:00:00" } ``` #### Response Example (None) ```json null ``` ``` -------------------------------- ### Fetch Single Row Source: https://github.com/maximdanilchenko/aiochclient/blob/master/README.md Retrieve the first row from a query result. ```python row = await client.fetchrow("SELECT * FROM t WHERE a=1") assert row[0] == 1 assert row["b"] == (dt.date(2018, 9, 7), None) ``` -------------------------------- ### aiochclient.Record Source: https://github.com/maximdanilchenko/aiochclient/blob/master/docs/reference.md Data structure representing a single record returned from ClickHouse queries. ```APIDOC ## aiochclient.Record ### Description A container class representing a row of data returned by the ClickHouse database. ``` -------------------------------- ### Stream Results with ChClient.iterate() Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Use iterate() to stream rows one at a time, essential for large datasets. Supports parameters, JSON mode, and early exit. ```python import asyncio from aiohttp import ClientSession from aiochclient import ChClient async def main(): async with ClientSession() as session: client = ChClient(session, url="http://localhost:8123") # Stream large result set count = 0 total_value = 0.0 async for row in client.iterate( "SELECT id, name, value FROM events ORDER BY id" ): count += 1 total_value += row['value'] # Process each row without holding all in memory if row['value'] > 100: print(f"High value event: {row['name']} = {row['value']}") print(f"Processed {count} rows, total value: {total_value}") # Stream with parameters and limit async for row in client.iterate( "SELECT number, number * 2 as doubled FROM system.numbers LIMIT {limit}", params={"limit": 10000} ): assert row[0] * 2 == row[1] # Stream in JSON mode async for record in client.iterate( "SELECT * FROM events", json=True ): print(record) # Returns dict directly # Early exit from streaming async for row in client.iterate("SELECT * FROM events ORDER BY value DESC"): print(f"Highest value: {row['value']}") break # Stop after first row asyncio.run(main()) ``` -------------------------------- ### ChClient.fetchval() - Fetch Single Value Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt Executes a query and returns just the first value of the first row, or None if no results. Useful for aggregate queries or single scalar values. ```APIDOC ## ChClient.fetchval() - Fetch Single Value ### Description Executes a query and returns just the first value of the first row, or None if no results. This is useful for aggregate queries or when you need a single scalar value like counts, sums, or existence checks. ### Method `POST` (Implicitly, as it sends a query to the server) ### Endpoint `/query` (or similar, depending on ClickHouse client configuration) ### Parameters #### Query Parameters - **query** (string) - Required - The SQL query to execute. - **params** (object) - Optional - A dictionary of parameters to substitute into the query. ### Request Example ```python # Get count count = await client.fetchval("SELECT count() FROM events") # Get sum total_value = await client.fetchval("SELECT sum(value) FROM events") # Get average with parameters avg_value = await client.fetchval( "SELECT avg(value) FROM events WHERE name = {name}", params={"name": "click"} ) # Check existence exists = await client.fetchval("SELECT 1 FROM events WHERE id = 1 LIMIT 1") # Get database version version = await client.fetchval("SELECT version()") ``` ### Response #### Success Response (200) - **value** (any or None) - The first value of the first row, or None if no rows were found. #### Response Example (Scalar value) ```json 5 ``` #### Response Example (Datetime value) ```json "2023-01-01T10:00:00" ``` #### Response Example (None) ```json null ``` ``` -------------------------------- ### Access Query Result Fields Source: https://github.com/maximdanilchenko/aiochclient/blob/master/README.md Access row data using both index and key mapping interfaces. ```python row = await client.fetchrow("SELECT a, b FROM t WHERE a=1") assert row["a"] == 1 assert row[0] == 1 assert row[:] == (1, (dt.date(2018, 9, 8), 3.14)) assert list(row.keys()) == ["a", "b"] assert list(row.values()) == [1, (dt.date(2018, 9, 8), 3.14)] ``` -------------------------------- ### Iterate Over Query Results Source: https://github.com/maximdanilchenko/aiochclient/blob/master/README.md Stream query results to process rows without loading them all into memory. ```python async for row in client.iterate( "SELECT number, number*2 FROM system.numbers LIMIT 10000" ): assert row[0] * 2 == row[1] ``` -------------------------------- ### Fetch Single Value Source: https://github.com/maximdanilchenko/aiochclient/blob/master/README.md Retrieve the first value of the first row from a query result. ```python val = await client.fetchval("SELECT b FROM t WHERE a=2") assert val == (dt.date(2018, 9, 8), 3.14) ``` -------------------------------- ### Access Query Results with Record Object Source: https://context7.com/maximdanilchenko/aiochclient/llms.txt The Record object provides flexible access to query results by column name, index, or slice. Values are lazily decoded. ```python import asyncio from aiohttp import ClientSession from aiochclient import ChClient async def main(): async with ClientSession() as session: client = ChClient(session, url="http://localhost:8123") row = await client.fetchrow(""" SELECT 1 as id, 'test' as name, [1, 2, 3] as numbers, ('a', 100) as data """) # Access by column name print(row['id']) # Output: 1 print(row['name']) # Output: 'test' print(row['numbers']) # Output: [1, 2, 3] print(row['data']) # Output: ('a', 100) # Access by index print(row[0]) # Output: 1 print(row[1]) # Output: 'test' # Slice access print(row[:2]) # Output: (1, 'test') print(row[1:3]) # Output: ('test', [1, 2, 3]) # Mapping interface print(list(row.keys())) # Output: ['id', 'name', 'numbers', 'data'] print(list(row.values())) # Output: [1, 'test', [1, 2, 3], ('a', 100)] print(len(row)) # Output: 4 print('name' in row) # Output: True # Iterate over column names for col in row: print(f"{col}: {row[col]}") asyncio.run(main()) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.