feat(plugin-duckdb): add remote Quack protocol connections#1720
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 340e4c203e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| case "quack": | ||
| return .duckdb |
There was a problem hiding this comment.
Populate DuckDB remote fields for quack URLs
When a quack:// URL is opened and does not match a saved connection, TabRouter.openDatabaseURL builds a transient connection via TransientConnectionFactory, which copies only host/port/database and never sets duckdbMode, duckdbHost, or duckdbAlias. The DuckDB driver only enters the remote path when additionalFields["duckdbMode"] == "remote", so these transient Quack links fall back to connectLocal() and open or create a local DuckDB file named after the alias instead of connecting to the remote server. Please carry the parsed Quack mode into the transient connection's additional fields.
Useful? React with 👍 / 👎.
| # After bumping the version, set DUCKDB_SHA256 to the checksum of the new | ||
| # libduckdb-src.zip: shasum -a 256 /tmp/duckdb-build/libduckdb-src.zip | ||
| DUCKDB_VERSION="v1.5.3" | ||
| DUCKDB_SHA256="REPLACE_WITH_libduckdb-src.zip_SHA256_FOR_v1.5.3" |
There was a problem hiding this comment.
Replace the DuckDB checksum placeholder
With a clean /tmp/duckdb-build, this placeholder is piped directly into shasum -a 256 -c - before the source archive is unzipped, so scripts/build-duckdb.sh now fails immediately for the v1.5.3 rebuild needed by Quack. Please commit the real libduckdb-src.zip SHA-256 or change the script so it does not ship an unusable checksum.
Useful? React with 👍 / 👎.
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
340e4c2 to
b215225
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b2152257a4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| static func attachSQL(host: String, port: Int, alias: String) -> String { | ||
| "ATTACH '\(quackTarget(host: host, port: port))' AS \(quoteIdentifier(alias))" |
There was a problem hiding this comment.
Support plain-HTTP Quack remotes
When the host is non-local but the server is exposed as plain HTTP (for example CALL quack_serve('quack:0.0.0.0:9494', allow_other_hostname => true) on a LAN/dev box), DuckDB's Quack client assumes HTTPS unless the ATTACH includes DISABLE_SSL true (DuckDB docs). This builder never emits that option and the new fields do not expose any way to request it, so those remote connections fail at attach time even with the correct host, port, and token.
Useful? React with 👍 / 👎.
| } | ||
|
|
||
| private static func quackTarget(host: String, port: Int) -> String { | ||
| "quack:\(escapeLiteral(host)):\(port)" |
There was a problem hiding this comment.
Preserve IPv6 brackets in Quack targets
For an IPv6 host parsed from a URL such as quack://[::1]:9494/remotedb or entered as ::1, the stored host value is ::1, but this constructs quack:::1:9494 instead of the bracketed Quack URI form quack:[::1]:9494 that DuckDB documents for IPv6 endpoints. Those connections cannot be parsed by Quack; wrap colon-containing hosts in brackets before building the target.
Useful? React with 👍 / 👎.
Addresses #1716.
Adds an experimental remote connection mode to the DuckDB driver using DuckDB's Quack client-server protocol, alongside the existing local-file mode. macOS and iOS.
Scope (and an honest limitation)
You can connect to a remote DuckDB server over Quack and run SQL against it (e.g.
SELECT * FROM alias.main.table). The sidebar does not list remote tables: the current Quack beta cannot enumerate a remote catalog. Every listing path is rejected server-side (duckdb_databases()returns "not implemented",information_schemais empty,SHOW TABLESfails with "multiple streaming scans"). DuckLake over Quack hits the same wall (attaching it runs a snapshot query that needs multiple streaming scans), so it is not included.This is upstream in DuckDB 1.5.4, not fixable client-side. Browsing and DuckLake are expected once Quack stabilizes in DuckDB 2.0. The mode is labeled "Remote (Quack, experimental)" and the limitation is documented.
What changed
DuckDB switches to the libSQL/Turso pattern:
connectionMode: .apiOnlywith aduckdbModepicker (Local File / Remote). NoConnectionModeenum change and no PluginKit ABI bump; new fields ride the existingadditionalFieldschannel.databasepath into the new file-path field.INSTALL quack/LOAD quack,CREATE SECRET (TYPE quack, ...), thenATTACH 'quack:host:port'andUSEthe alias. SQL is built inQuackConnectBuilderwith literal escaping and identifier quoting; the port is range-validated.duckdb_databases()(which the remote rejects), so the connection no longer errors.quack://host:port/aliasparses and formats as a remote DuckDB URL;duckdb:///pathstays file-based.Tests
DuckDBConnectionFieldsTests: field set, visibility rules, password row stays hidden, token is secure.DuckDBQuackConnectTests:QuackConnectBuilderSQL and escaping against injection-hostile tokens/hosts/aliases, plus host/port validation.Live remote needs a server, so it is not in CI; the tests cover the SQL the driver sends.
Library prerequisites
scripts/build-duckdb.shto DuckDB 1.5.3+ (Quack ships as a core extension from 1.5.3), fill the reallibduckdb-src.zipchecksum, rebuild, publish viascripts/publish-libs.sh, commit the checksums.scripts/build-duckdb-ios.sh+scripts/duckdb-ios-extensions.cmakestatically linkquack+httpfs(iOS cannot autoload), against the OpenSSL already inLibs/ios. No x86_64 simulator OpenSSL slice ships, so that slice is skipped unlessBUILD_X86_SIMULATOR=1.Notes
swiftlint --strictis clean on the changed files.