Fix the client losing its default database after USE {db:Identifier} - #111982
Merged
alexey-milovidov merged 3 commits intoJul 28, 2026
Conversation
`USE {db:Identifier}` keeps the database name in a query parameter, so the
parsed `ASTUseQuery` carries an empty name and `ASTUseQuery::getDatabase`
returns an empty string until the parameters are substituted. The client used
that empty name to update its `default_database`, which it needs to restore the
current database whenever it has to re-establish a lost connection. So after a
`USE` with a query parameter, a reconnect silently moved the session to the
`default` database, and every later unqualified table reference failed with
`UNKNOWN_TABLE`.
Substitute the query parameters on the client side, the same way the server does
when it executes the query, and the same way the client already does for `SET`.
This is what made stateless tests that combine `USE {CLICKHOUSE_DATABASE:Identifier}`
with unqualified table names flaky - the client re-establishes the connection on
its own when a ping does not come back in time, which happens on a loaded
sanitizer runner. For example `03101_analyzer_identifiers_4`:
Code: 60. DB::Exception: Unknown table expression identifier 't' in scope
SELECT COLUMNS('^c') FROM t. Maybe you meant test_qp0dhise.t?. (UNKNOWN_TABLE)
with the server log showing the re-established connection arriving without a
database: `Connected ClickHouse client version 26.8.0, revision: 54488, user: default.`
https://s3.amazonaws.com/clickhouse-test-reports/json.html?REF=master&sha=a58de9c1a55e6577c3a6cafdac5609bc90234ef0&name_0=MasterCI&name_1=Stateless%20tests%20%28amd_msan%2C%20WasmEdge%2C%20parallel%2C%202%2F2%29
Contributor
|
Workflow [PR], commit [ab4ab4e] Summary: ✅
AI ReviewSummaryThis PR fixes Final Verdict
|
1 task
…eter-default-database
The `.sql` version of the test was flaky (it was the only failure in eight `Stateless tests` jobs, e.g. https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=111982&sha=17d09d1e6ac7b9ed21ec7d2857713c26c2497c33&name_0=PR&name_1=Stateless%20tests%20%28amd_msan%2C%20WasmEdge%2C%20parallel%2C%201%2F2%29 ). With `idle_connection_timeout = 0` the server closes the connection immediately after every query, including right after the `Ping` that the client sends before a query - the query then goes into an already closed socket and the client reports `NETWORK_ERROR` or `ATTEMPT_TO_READ_AFTER_EOF` instead of reconnecting. Replace it with an `expect` test that lets the client sit idle for several seconds with `idle_connection_timeout = 2`, so the connection is closed long before the client checks it and the reconnection is deterministic. Verified locally: 5/5 runs pass with the fix, and the test fails with `UNKNOWN_TABLE` without it. Note that `idle_connection_timeout` has to be passed on the command line: the server extracts the connection settings when it receives a query, so an in-session `SET idle_connection_timeout` only takes effect from the next query and does not shorten the idle period that follows the `SET` itself.
Contributor
LLVM Coverage Report
Changed lines: Changed C/C++ lines covered: 6/6 (100.00%) · Uncovered code |
alexey-milovidov
left a comment
Member
Author
There was a problem hiding this comment.
Yes, this is good.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
USE {db:Identifier}keeps the database name in a query parameter, so the parsedASTUseQuerycarries an empty name andASTUseQuery::getDatabasereturns an empty string until the parameters are substituted. The client used that empty name to update itsdefault_database, which it needs to restore the current database whenever it has to re-establish a lost connection. So after aUSEwith a query parameter, a reconnect silently moved the session to thedefaultdatabase, and every later unqualified table reference failed withUNKNOWN_TABLE.The fix substitutes the query parameters on the client side, the same way the server does when it executes the query, and the same way the client already does for
SET.This is what made stateless tests that combine
USE {CLICKHOUSE_DATABASE:Identifier}with unqualified table names flaky - the client re-establishes the connection on its own when a ping does not come back in time, which happens on a loaded sanitizer runner.03101_analyzer_identifiers_4failed onmasterwith:and the server log shows the client dropping the connection mid-script and coming back without a database:
The same failure mode hit
03101_analyzer_identifiers_1(four occurrences of the two tests over the last three weeks, alwaysUNKNOWN_TABLEon an unqualified name).The new test
04647_use_query_parameter_survives_reconnectis anexpecttest: it lets an interactive client sit idle for several seconds withidle_connection_timeout = 2, so the server closes the connection long before the client checks it and the reconnection happens deterministically. It fails withUNKNOWN_TABLEbefore this change and passes after it.Note that
idle_connection_timeouthas to be passed on the command line rather than withSET: the server extracts the connection settings when it receives a query, so an in-sessionSET idle_connection_timeoutonly takes effect from the next query and does not shorten the idle period that follows theSETitself. The first version of the test usedSET idle_connection_timeout = 0, which closes the connection immediately after every query - including right after thePingthat the client sends before a query - so the query went into an already closed socket and the client reportedNETWORK_ERRORorATTEMPT_TO_READ_AFTER_EOFinstead of reconnecting. That made the test itself flaky.Note that
03101_analyzer_identifiers_2fails the same way onmaster, but for a different reason that this change does not address: it usesCREATE TEMPORARY TABLE, and temporary tables live in the session, so they cannot survive a reconnect at all.CI report: https://s3.amazonaws.com/clickhouse-test-reports/json.html?REF=master&sha=a58de9c1a55e6577c3a6cafdac5609bc90234ef0&name_0=MasterCI&name_1=Stateless%20tests%20%28amd_msan%2C%20WasmEdge%2C%20parallel%2C%202%2F2%29
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):
Fixed
clickhouse-clientlosing the current database afterUSEwith a query parameter, e.g.USE {db:Identifier}. If the client had to re-establish the connection later, it silently switched the session to thedefaultdatabase, and subsequent queries using unqualified table names failed withUNKNOWN_TABLE.Documentation entry for user-facing changes
Version info
26.8.1.294(included in26.8and later)