Read-only ClickHouse Users
How hypequery works with ClickHouse users set to readonly = 1 or readonly = 2, and what each level costs you.
Give hypequery a dedicated ClickHouse user that can only read. ClickHouse has two ways to make a user read-only, and hypequery accepts both. They differ in one thing: whether hypequery can still apply its own query settings.
The two levels
readonly = 1 | readonly = 2 | |
|---|---|---|
| Blocks writes and schema changes | Yes | Yes |
| Accepts per-query settings | Only when the value matches the user's profile | Yes, except readonly itself |
| Limits hypequery can apply | Only what the profile already sets | All of them |
Both keep your data equally safe. The difference is who controls query limits:
- With
readonly = 1, only the user's profile does. Nobody, hypequery included, can change a setting for a single query. - With
readonly = 2, hypequery can tighten limits per query. To stop anyone raising a limit past what you allow, add constraints to the profile, for example amaxonmax_memory_usage.
Use readonly = 2 unless you have a reason not to. If you use readonly = 1,
put the limits you want in the user's profile.
TypeScript query builder
@hypequery/clickhouse sends one setting by default,
output_format_json_quote_64bit_integers = 1, so Int64 and wider values arrive
as exact strings.
readonly = 2and unrestricted users work without changes.- A
readonly = 1user works without changes if its profile already setsoutput_format_json_quote_64bit_integers = 1. - Otherwise, set
integerJsonEncoding: 'server-default'. Wide integers may then lose precision beyond2^53. See 64-bit integer encoding.
Any setting you pass yourself with .settings({...}) follows the same rule: a
readonly = 1 user rejects it unless the value already matches the profile.
Python datasets
The Python planner attaches readonly = 1, max_execution_time,
max_result_rows, max_result_bytes, and max_threads to every query. By
default, the executor sends all five. It never silently drops a query limit.
readonly = 1: Set the same limits in the user's profile. If a limit differs, ClickHouse rejects the query; change the profile rather than disabling the limit in HypeQuery.readonly = 2: ClickHouse rejects the planner'sreadonly = 1setting. Explicitly choosereadonly_policy="profile"on the connection. HypeQuery verifies that the connected profile hasreadonly = 1or2, then omits only thereadonlysetting. It still sends every query limit.
from hypequery.execution import ClickHouseConnection, create_clickhouse_executor
executor = create_clickhouse_executor(
ClickHouseConnection(
host="localhost",
username="hypequery_reader",
password="...",
readonly_policy="profile",
)
)
The same connection option works with create_async_clickhouse_executor.
For readonly = 1, profile mode still requires the profile's limits to match
the planner settings. A missing or unrestricted profile is rejected before
the query is sent.
Cancellation and deadlines still stop queries on the server for both levels,
because the executor cancels with KILL QUERY, which read-only users may run.
hypequery Cloud
Cloud's executor sends readonly = 2, server-side cancellation, per-query
resource limits, and precision-safe integers on every query. A readonly = 1 user
refuses those, so Cloud sends it no settings at all, and your profile is the only
protection those queries get.
When you connect a readonly = 1 user, setup lists what your profile leaves out,
for example "Cancelled queries keep running" or "No per-query memory limit". It
also generates the profile SQL that fixes it. You must confirm before saving.
This profile gives a readonly = 1 user every protection Cloud relies on:
CREATE SETTINGS PROFILE hypequery_cloud SETTINGS
readonly = 1,
cancel_http_readonly_queries_on_client_close = 1,
output_format_json_quote_64bit_integers = 1,
max_execution_time = 25,
timeout_overflow_mode = 'throw',
max_threads = 8,
max_memory_usage = 4294967296,
max_result_rows = 20000,
max_result_bytes = 67108864,
result_overflow_mode = 'throw'
TO hypequery_user;
Stricter limits are fine. Keep max_result_rows at 10,001 or more, or full pages
of results will be refused.