Repository navigation
A ClickHouse warehouse can be mounted read-only, with slow queries stopped by the server timeout or KILL QUERY - #1094
Conversation
…opped by the server timeout or KILL QUERY Closes #1092 Signed-off-by: Asaf Shitrit <asafshitrit.dev@gmail.com>
…the query tool names MySQL and ClickHouse among its dialects Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Wayland Yang <wayland0916@gmail.com>
WaylandYang
left a comment
There was a problem hiding this comment.
Thank you. This is careful work, and every point from #1092 is answered with a measurement.
I ran it against a real server (26.9.12.8 in Docker, the fixture from the doc comment):
| account | Test connection | slow query, as recorded in system.query_log |
|---|---|---|
default |
ok | stopped by the server at 10 s (159) |
readonly=1 with the grant |
ok | killed at 12 s (394) |
readonly=2 with the grant |
ok | stopped by the server at 10 s (159) |
CONST timeout with the grant |
ok | killed at 12 s (394) |
readonly=1 without the grant |
refused, message names the grant | none sent |
- The live tests pass with each of the four accounts, and no
utopia-query is left insystem.processesafterwards. - Through the API on a fresh database: migration 0106 applies, and create, grant, mount and schema sync work with the
readonly=1account. - A wrong password and a closed port each return their own error.
One correction, and it is mine. I wrote on #1092 that Settings has a single connection-string box. That was wrong: each engine has its own form, and the box is the last option. You followed what I said, so I pushed 59b086d to add the ClickHouse form (host, port, optional database, user and password) with a test. The same commit names MySQL and ClickHouse in the query tool's dialect list, which had been missing MySQL since #303.
For the record, not a request: the gate parses with sqlparser 0.62, which rejects four ClickHouse forms I tried, namely WITH <expr> AS name, tuple access t.1, GLOBAL IN and ASOF JOIN … ON. Seventeen other idioms pass. The gate fails closed, so this limits what the model can write and does not open anything.
Merging when CI is green on the new commit. Thanks again.
|
Thank you for the review, and for the ClickHouse form in Settings. The note about the four forms that sqlparser rejects is useful to know. 🙏 |
Why
Closes #1092.
What changes
clickhouse://user[:password]@host[:port]/[database]mounts a warehouse over HTTP.ssl=true,secure=true, or port 443 or 8443 selects https.Each request asks for
readonly=1andmax_execution_time. If the account's profile refuses one of them, the engine sends the request again without it. It dropsreadonlyonly for an account that is read-only itself. Each request has aquery_id. The engine kills the query after 12 s, when the caller cancels the request, or when the connection drops during the reply. A gateway error in front of ClickHouse, such as a 504, also starts a KILL.Some accounts do not let the server hold the shared 10 s statement timeout: a
readonly=1orreadonly=2profile, or aCONSTtimeout. For these accounts the KILL needsGRANT SELECT ON system.processes. An account inreadonly=1mode whose ownmax_execution_timeis 10 s or less also works. The engine checks this before it sends a query without the server timeout. If the check fails, the engine refuses every query and the Test connection button, with a message that names the grant.is_primary_keystays false: a ClickHouse primary key allows duplicate rows.data_typekeepsNullable(...)andLowCardinality(...). The engine readsJSONCompactStringsand converts values by column type.The quoting of 64-bit integers in JSON changes with the server version:
output_format_json_quote_64bit_integersis off by default from 25.8. A read-only account cannot change this setting. Unquoted 128-bit and 256-bit integers also lose precision. So integers that fit in 64 bits come back as exact JSON numbers. Larger 128-bit and 256-bit values, andDecimal(P, S)values with P above 15, come back as strings.Limits:
fetch_schemareads only that database. Without one, it reads every non-system database.Nullable(String)column,JSONCompactStringswrites NULL and the textᴺᵁᴸᴸthe same way, so both read as NULL. With the ASCII grid charset the marker isNULL, and both read as the textNULL. This is the cost of exact integers.max_execution_time.The roadmap line also names Feishu, so I moved ClickHouse to the feature table, as #315 did for MySQL. The Chinese feature table lists no engines.
How it was checked
The live test passed on 26.9.12.8 with four accounts: the server's
defaultuser, areadonly=1profile, areadonly=2profile and aCONSTtimeout. Each account refused a write, and no slow query stayed on the server. The engine refused an account without the grant, on a query and on the Test connection check.I also checked these cases on a real server:
readonly=1account with a 5 smax_execution_timeand no grant. The engine accepted it, and the server stopped a slow query at 5 s.Before review
git commit -s)cargo fmt --all --check,cargo clippy --workspace --all-targets -- -D warningsandcargo test --workspacepassweb/:pnpm buildandpnpm testpassdev, andCURRENT_SCHEMA_VERSIONincrates/utopia-cli/src/main.rsequals the number of files inmigrations/web/src/i18n/en.tsandzh.ts