feat: implement connection option getters - #65
Conversation
`ClickhouseConnection::get_option_string()` returned `NotImplemented` for every key. ADBC driver managers read these back before they will use a connection, so erroring on all of them can leave the driver unusable through one. Implements the variants that have a well-defined answer for ClickHouse: * `AutoCommit` -> `"true"`. ClickHouse has no transactions, so statements always commit as they run. `rollback()` already reports this; answering here too lets managers check without provoking an error. * `CurrentCatalog` -> `""`. ClickHouse has no catalog level above the database. The database maps onto ADBC's `db_schema` (cf. `get_table_schema()`), which leaves the catalog empty rather than unsupported. * `CurrentSchema` -> `SELECT currentDatabase()`. `ReadOnly` and `IsolationLevel` keep returning `NotImplemented`, as `set_option()` does not accept them either, and readback of custom (`Other`) options is left for a follow-up. The remaining getters mirror `ClickhouseDatabase`: `get_option_bytes()` defers to `get_option_string()`, and the numeric getters report `InvalidArguments`. The upstream blocker noted on ClickHouse#8, ClickHouse/clickhouse-rs#358, is now closed and released in `clickhouse` 0.15.1. Note that `get_objects()` (ClickHouse#10) is also required before a driver manager can attach a ClickHouse database; this change is necessary but not sufficient on its own.
798f86d to
2b75b70
Compare
There was a problem hiding this comment.
Pull request overview
Implements missing Connection::get_option_* readbacks needed by ADBC driver managers to successfully validate and use a ClickHouse connection, aligning connection option behavior with the existing ClickhouseDatabase option handling.
Changes:
- Implemented
ClickhouseConnection::get_option_string()forAutoCommit,CurrentCatalog, andCurrentSchema. - Made
get_option_bytes()delegate toget_option_string(), and updatedget_option_int()/get_option_double()to returnInvalidArguments. - Added integration tests covering the connection option getters and updated the changelog.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| tests/it/main.rs | Adds an integration test validating the new connection option getter behaviors and statuses. |
| src/lib.rs | Implements connection option getters (string/bytes/int/double) for well-defined ClickHouse behaviors. |
| CHANGELOG.md | Documents the new option getter support under Unreleased and links the tracking issue. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
| OptionConnection::CurrentSchema => self | ||
| .tokio | ||
| .block_on(async { | ||
| self.client | ||
| .query("SELECT currentDatabase()") | ||
| .fetch_one::<String>() | ||
| .await | ||
| }) | ||
| .map_err(|e| { | ||
| Error::with_message_and_status( | ||
| format!("could not read the current database: {e}"), | ||
| Status::Internal, | ||
| ) | ||
| }), |
There was a problem hiding this comment.
I have some concerns with this approach to get the currentDatabase.
- It would require one roundtrip to the database to get it.
- It's already static in the ADBC connector: as we use HTTP here, we can't just call a
SETto change it and then depend on CH to know which is the current one. Even if we do it with CH sessions (as we carry a session_id), this may change after the default session timeout of 60 seconds.
To manage the defaultSchema I think we should:
- Allow the default Schema to be configured as a configuration paramenter
- Use that value in each call as the
databaseURL parameter /X-ClickHouse-Databaseheader - the return that value back here.
If the user wants to change that value (not sure if something like set_option(CurrentSchema) may happen) then the change needs to be applied at the ADBC CH driver level, not with a SET.
Btw this is specially relevant for me as in DBT we need to be able to define a different default database to make operations in and right now that is a limitation in this ADBC. I can tackle it in a different PR to leave this one more compact if you prefer @pedro-filardi .
CC @abonander . What do you think?
There was a problem hiding this comment.
Makes sense to land the setter first and rebase this on top of it, go ahead
in a separate PR if you like.
One question either way: what should CurrentSchema return when nothing is
configured? Do we fall back to SELECT currentDatabase() cached once per connection?
There was a problem hiding this comment.
Added #67 to track the need to be able to set the default database for the connection
what should CurrentSchema return when nothing is configured? Do we fall back to SELECT currentDatabase() cached once per connection?
Good question. I think we must just return default which is the name for the default one in CH
There was a problem hiding this comment.
If so, we are not covering cases where default_database is configured by the admin, either at user or server level. Maybe it's good enough for a first iteration, but it should at least be a known limitation
There was a problem hiding this comment.
I think we can get away with returning whatever is configured, or an empty string otherwise. If the admin has set a default_database on the server-side, then the empty string is essentially an alias for that database.
I'm worried about doing a fallible blocking call in get_option_string() as it's rather surprising for a simple getter to execute a query on the database. I'm not sure if that's how it's intended for this API to behave.
There was a problem hiding this comment.
@pedro-filardi we added a way to set the database in #72 so this can just read that back.
Summary
Connection::get_option_string()returnedNotImplementedfor every key. ADBC driver managers read these back before they will use a connection, so erroring on all of them can leave the driver unusable through one.Connection::get_option_string()for the variants that have a well-defined answer for ClickHouse:OptionConnection::AutoCommit→"true". ClickHouse has no transactions, so statements always commit as they run.rollback()already reports this; answering here too lets managers check without provoking an error.OptionConnection::CurrentCatalog→"". ClickHouse has no catalog level above the database. The database maps onto ADBC'sdb_schema(cf.get_table_schema()), which leaves the catalog empty rather than unsupported.OptionConnection::CurrentSchema→SELECT currentDatabase().get_option_bytes()defers toget_option_string(), andget_option_int()/get_option_double()reportInvalidArguments, mirroring theClickhouseDatabaseimpl added in feat: supportclickhouse://URLs #62.ReadOnlyandIsolationLevelkeep returningNotImplemented, sinceset_option()does not accept them either.Addresses #8 — readback of custom (
Other) options is not covered here, as it would need the connection to retain itsproduct_info; happy to fold that in if you'd prefer the issue closed outright.The upstream blocker noted on #8, ClickHouse/clickhouse-rs#358, is now closed and released in
clickhouse0.15.1.Note on scope
This is necessary but not sufficient for a driver manager to attach a ClickHouse database —
get_objects()(#10) is required as well. I verified the pair is sufficient by building this branch as acdyliband pairing it with a temporary pass-through driver supplying onlyget_objects(); attaching then succeeded and a 1,000,000-rowINSERT ... SELECTstreamed through bulk ingest in 0.26s.With this branch alone, attaching fails on
get_objects()instead ofCurrentCatalog, which is the intended progression.Checklist
Delete items not relevant to your PR: