Skip to content

feat(postgres, core): PgConnection::connect_with_socket and a wasm-safe Instant - #4444

Open
iamralch wants to merge 2 commits into
transact-rs:mainfrom
iamralch:wasm-custom-socket
Open

iamralch wants to merge 2 commits into
transact-rs:mainfrom
iamralch:wasm-custom-socket

Conversation

@iamralch

@iamralch iamralch commented Oct 4, 2026

Copy link
Copy Markdown

Does your PR solve an issue?

fixes #4426

This is option 1 from the discussion there: socket-only, Postgres only. A caller-supplied TLS upgrade, which a MySQL connect_with_socket would need, is left for a follow-up if this direction is accepted.

Two commits, each usable on its own. Happy to split them into separate PRs if that's easier to review.

  1. fix(core): use a wasm-safe Instant on wasm32-unknown-unknown. QueryLogger::new calls std::time::Instant::now() for every query, and that panics on wasm32-unknown-unknown with time not implemented on this platform. This adds sqlx_core::rt::Instant, which is std::time::Instant everywhere else and web_time::Instant (the host's performance.now()) on that target. It's used in the query logger and the Postgres, MySQL and SQLite migrators. web-time is a dependency on that target only.
  2. feat(postgres): add PgConnection::connect_with_socket. This takes any sqlx_core::net::Socket the caller has already connected. The host, port and socket path in the options are ignored. Everything else, including ssl_mode, applies as it does for connect_with. establish now goes through the same path after opening its own socket, so existing connections are unchanged.

The motivating host is Cloudflare Workers, which hands out its own TCP sockets (e.g. to reach Postgres through Hyperdrive) and has no tokio. TLS doesn't need a hook for Postgres: a caller whose host upgrades the socket itself can send the SSLRequest, upgrade, and pass the result in with ssl_mode = Disable.

Tests

  • New it_connects_with_socket in tests/postgres/postgres.rs: a tokio TcpStream opened by the test, then connect_with_socket.
  • Existing tests/postgres/postgres.rs (58 passed, 2 ignored) and tests/postgres/migrate.rs (4 passed).
  • On wasm32-unknown-unknown, a Worker under wrangler dev --local against Postgres 17 with SCRAM auth: connect, bound parameters and scalar types, 2,000 rows over many socket reads, unique-violation mapping, rollback and commit, prepared-statement reuse, sqlx::migrate!(), ping and close. Reverting only the Instant commit makes the same Worker panic.

A downstream crate built on this branch, with those scenarios in CI: sqlx-contrib/sqlx-cloudflare#16 (sqlx-cloudflare-hd).

Is this a breaking change?

No. Both changes only add public items (PgConnection::connect_with_socket, sqlx_core::rt::Instant). sqlx_core::rt::Instant is std::time::Instant on every target except wasm32-unknown-unknown, where Instant::now() panicked before. Existing connect_with behaviour is unchanged; it now delegates to the same code path after opening its socket.

`std::time::Instant::now()` panics on `wasm32-unknown-unknown` ("time not
implemented on this platform"), and `QueryLogger::new` calls it for every
query, so no driver can run a query there, even over a transport the host
provides.

Add `sqlx_core::rt::Instant`: `std::time::Instant` everywhere else, and
`web_time::Instant`, which reads the host's `performance.now()`, on that
target. Use it in the query logger and the Postgres, MySQL and SQLite
migrators. `web-time` is only a dependency on that target; nothing changes
elsewhere.
sqlx opens its own sockets through `sqlx_core::net::connect_tcp`, which needs
a supported async runtime; without one it panics in `missing_rt`. Hosts that
hand out their own socket type, such as Cloudflare Workers
(`wasm32-unknown-unknown`, with `connect()` sockets), have no way to connect.

`connect_with_socket` takes any `sqlx_core::net::Socket` the caller has already
connected. The host, port and socket path in the options are ignored;
everything else, including `ssl_mode`, applies as it does for `connect_with`.
`establish` now goes through the same path after opening its own socket.
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.

Postgres: connect over a caller-provided socket, and a wasm-safe Instant, for hosts like Cloudflare Workers

1 participant