Skip to content

feat(mysql): connect to MySQL / MariaDB through a local Unix socket (#1002) - #1246

Closed
markankamaransheogarat-sys wants to merge 1 commit into
TabularisDB:mainfrom
markankamaransheogarat-sys:feat/mysql-unix-socket-1002
Closed

markankamaransheogarat-sys wants to merge 1 commit into
TabularisDB:mainfrom
markankamaransheogarat-sys:feat/mysql-unix-socket-1002

Conversation

@markankamaransheogarat-sys

Copy link
Copy Markdown
Contributor

Summary

Closes #1002

MySQL and MariaDB connections can now go through a local Unix socket (/var/run/mysqld/mysqld.sock, /tmp/mysql.sock, …) instead of host and port. Existing TCP connections behave exactly as before, and their pool keys don't change.

Backend

  • Model (models.rs): optional socket on ConnectionParams (#[serde(default, skip_serializing_if = "Option::is_none")], so saved connections without it are unaffected), plus ConnectionParams::mysql_socket(). It returns the trimmed path for the mysql driver only, and treats a blank path as unset.
  • Options builder (pool_manager::build_mysql_options): with a socket it calls MySqlConnectOptions::socket(path) instead of host/port, and:
    • forces ssl_mode = Disabled and skips ssl_ca/ssl_cert/ssl_key. This one is required, not cosmetic: the unset default is required, and sqlx-mysql 0.8 aborts the handshake under required when the server doesn't advertise TLS, which is typical on the socket (e.g. MariaDB without certificates).
    • rejects AWS IAM auth (the RDS token needs a verified TLS link to RDS).
    • allows the cleartext plugin, since MySQL documents the socket as a secure transport for mysql_clear_password. Over TCP the existing enforced-TLS check is unchanged.
    • returns a clear error on Windows, which has no Unix sockets.
  • Pool key (build_connection_key): socket connections get a :socket:<path> suffix, and ad-hoc keys use the path in place of host:port. TCP keys are byte-for-byte the same.
  • Transport (commands::resolve_connection_transport): a socket connection returns early. An enabled SSH / Kubernetes / AWS SSM tunnel is an error instead of being silently ignored. Proxies are skipped rather than rejected, because the global proxy scopes apply to every connection.
  • Driver URL (MysqlDriver::build_connection_url): emits mysql://user@localhost/db?socket=<encoded>&…&ssl-mode=disabled, which sqlx's own URL parser reads back (covered by a round-trip test).

Frontend

  • Form (NewConnectionModal.tsx): a "Connect via Unix socket" checkbox for MySQL/MariaDB, hidden on Windows and for URI-passthrough drivers. It swaps the host/port row for a socket path field with a file picker. In socket mode the SSL, SSH, Kubernetes and AWS SSM tabs are hidden and the tunnels and IAM are switched off. The SSL fields themselves are kept, so they come back if the user switches back to host/port. Test and Save require a path, and "Load databases" works with a socket path instead of a host.
  • Import (connectionStringParser.ts): mysql://root@localhost/db?socket=/tmp/mysql.sock (also percent-encoded) imports as a socket connection. The parameter is ignored for other drivers.
  • Labels (utils/connections.ts): formatConnectionString and connectionSubtitle show the socket path instead of host:port.
  • i18n: connectViaSocket, socketPath, socketPathHint, socketPathRequired in all 11 locales.

Tests

  • Rust (16 new): options builder (socket used, TLS disabled even when verify_identity + CA are set, path trimmed, blank path keeps TCP + required, IAM rejected, cleartext allowed, Windows rejection), pool keys (TCP unchanged, socket paths separated, ad-hoc key), model (mysql_socket, JSON default/omission), driver URL (+ sqlx round trip), transport (unchanged params, every tunnel rejected, blank socket keeps the SSH path). The Unix-only ones are #[cfg(unix)] and the Windows rejection test is #[cfg(windows)].
  • Vitest: parser (?socket=, percent-encoding, blank/missing, other drivers), label helpers, platform helper, and three modal tests (toggle swaps fields and hides tabs, a path is required before testing, a saved socket connection opens in socket mode and is tested with the socket).

Verification

  • pnpm vitest run: 402 files / 6828 tests passed
  • pnpm exec tsc -b, pnpm lint (ESLint + theme tokens): clean
  • cargo test --lib on Windows: 1907 passed. The 5 failures (askpass tilde path, kubectl exec bit, 3× ssm extend_path) are Windows-only and fail identically on main. The #[cfg(unix)] socket tests run in CI.
  • No new clippy warnings, and the changed code is rustfmt-clean.

I couldn't run a live MySQL 8 / MariaDB socket from this machine (Windows). If you'd like, I can add an integration test next to tests/mysql_*.rs that connects through MYSQL_SOCKET when it's set.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QF7qKtRn5r6CrdDoU7ZmvY

…abularisDB#1002)

- add an optional `socket` path to ConnectionParams; when set, the MySQL
  driver uses MySqlConnectOptions::socket instead of host/port
- force ssl_mode=disabled for sockets (sqlx-mysql fails `required` when the
  server does not offer TLS on the socket) and ignore the SSL file options
- reject IAM auth over a socket, allow the cleartext plugin (a socket is a
  secure local transport for MySQL), reject sockets on Windows
- keep socket and TCP pools apart; TCP pool keys are unchanged
- refuse SSH / Kubernetes / SSM tunnels with a socket and skip proxies
- emit `?socket=` from the driver's connection URL
- connection form: "Connect via Unix socket" toggle with a path field and
  file picker, hidden on Windows; SSL and tunnel tabs hidden in socket mode
- import `mysql://...?socket=/path` connection strings as socket connections
- show the socket path instead of host:port in connection labels
- new i18n keys in all 11 locales

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QF7qKtRn5r6CrdDoU7ZmvY
@kilo-code-bot

kilo-code-bot Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Reviewed the Unix socket support for MySQL/MariaDB end to end. The review was static only (no code executed), and these checks came out clean:

  • Socket detection: mysql_socket() trims the path and treats a blank path as unset. It applies to the mysql driver only.
  • Pool keys: TCP keys are unchanged. Socket connections get a :socket:<path> suffix, and ad-hoc keys use the path in place of host and port.
  • Options builder: build_mysql_options forces TLS off and skips the CA, cert and key. It rejects IAM auth and Windows. It allows the cleartext plugin only over a socket, so the TCP TLS check is unchanged.
  • Tunnels: resolve_connection_transport returns early for sockets and rejects an enabled SSH, Kubernetes or AWS SSM tunnel instead of ignoring it.
  • Driver URL: build_connection_url encodes the socket path and sets ssl-mode=disabled.
  • Frontend: the form hides the host, SSL and tunnel tabs in socket mode, requires a path before Test and Save, and resets the tunnel and IAM flags. The connection string parser and the label helpers handle ?socket=. The 11 locales carry the four new keys.
  • Other call sites: I found none that need a socket-specific code path.

Not verified:

  • rustfmt: I could not run it in this environment. The if socket.is_none() && !matches!( condition at src-tauri/src/pool_manager.rs:464 may not be rustfmt-clean, so run cargo fmt --check before merge.
  • Live socket connection: the PR states none was tested on a real MySQL or MariaDB server. The #[cfg(unix)] tests need to pass in CI.
Files Reviewed (25 files)
  • src-tauri/src/commands.rs
  • src-tauri/src/drivers/mysql/mod.rs
  • src-tauri/src/drivers/mysql/tests.rs
  • src-tauri/src/models.rs
  • src-tauri/src/models_tests.rs
  • src-tauri/src/plugins/driver.rs
  • src-tauri/src/pool_manager.rs
  • src-tauri/src/pool_manager_tests.rs
  • src/components/modals/NewConnectionModal.tsx
  • src/i18n/locales/*.json (11 locales)
  • src/utils/connectionStringParser.ts
  • src/utils/connections.ts
  • tests/components/modals/NewConnectionModal.test.tsx
  • tests/utils/connectionStringParser.test.ts
  • tests/utils/connections.test.ts

Reviewed by claude-sonnet-5.5 · Input: 298 · Output: 9.6K · Cached: 1.9M

Review guidance: REVIEW.md from base branch main

@markankamaransheogarat-sys

Copy link
Copy Markdown
Contributor Author

Thanks for the review. On the two open points:

  • rustfmt: cargo fmt --check shows no diff in the lines this PR touches, including the socket.is_none() && !matches!( condition. The only diffs it reports in pool_manager.rs are the two long use lines at the top, which are already on main.
  • Unix tests: the #[cfg(unix)] socket tests ran in CI (test, test-mysql on 8.4 and 5.7-debian) and all checks pass.

@markankamaransheogarat-sys

Copy link
Copy Markdown
Contributor Author

@debba I missed your pointer to #492 in the issue before I started, sorry about that. I've now gone through it, and it's the better foundation. The main differences:

#492 this PR
field unix_socket_path socket
SSH tunnel socket on the remote host via direct-streamlocal / ssh -L port:/path rejected
PostgreSQL local socket via Config::host_path no (MySQL only)
plugins unix_socket driver capability no

The SSH and Postgres parts in particular are things this PR gets wrong or doesn't do. So I'd like to switch to your design. Two options, whichever you prefer:

  1. Finish feat(connections): Unix socket support — dialed locally or through the SSH tunnel #492 on current main. I'd rebase your branch, keeping your commits and authorship. It's 6 commits behind ~1,100 on main, with conflicts in commands.rs, ssh_tunnel.rs, NewConnectionModal.tsx and tests/utils/connections.test.ts. Then I'd add on top what [Feat]: MySQL / MariaDB connection through a local Unix socket #1002 asks for that feat(connections): Unix socket support — dialed locally or through the SSH tunnel #492 doesn't cover yet:

    • mysql://…?socket=/path import, one of the acceptance criteria
    • the socket path shown in connection labels instead of host:port
    • rejecting IAM auth over a socket
    • hiding the field on Windows
    • the extra tests from here
    • the two locales added since July (pt-BR, zh)

    This PR would then be closed in favour of that one.

  2. Rework this PR onto your model (unix_socket_path, the capability, SSH forwarding, Postgres), if you'd rather review it as a fresh branch.

I'd go with 1 unless you say otherwise. Is that OK with you, and should it land in #492 itself or in a new PR based on it?

@debba

debba commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator

Thanks for digging into #492 and for the comparison, that's really helpful.

I agree with option 1: let's build on the #492 design (unix_socket_path, the unix_socket capability, SSH forwarding to the remote socket, and PostgreSQL via host_path), plus the #1002 extras you listed (?socket= import, socket path in labels, IAM rejection, hiding the field on Windows, the extra tests, and the pt-BR/zh locales).

As for where it should land: #492 is quite old by now and about 1,100 commits behind main, so rebasing it is probably more trouble than it's worth. I'd start a fresh PR from current main and port the #492 changes over, then add the extras on top. Once the new PR is up, we can close both #492 and this one in favour of it. Please link both from the new PR description so the history is easy to find.

Thanks again!

@markankamaransheogarat-sys

Copy link
Copy Markdown
Contributor Author

Superseded by #1250 (the #492 design ported onto current main, plus the #1002 extras from here). Fine to close this one in its favour.

@markankamaransheogarat-sys

Copy link
Copy Markdown
Contributor Author

Closing in favour of #1250, which ports the #492 design onto current main and carries the #1002 extras from here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat]: MySQL / MariaDB connection through a local Unix socket

2 participants