Skip to content

fix(deps): stop enabling litewire-backend's rusqlite feature by default across the workspace - #45

Merged
luthermonson merged 2 commits into
mainfrom
fix/backend-no-default-rusqlite
Oct 11, 2026
Merged

luthermonson merged 2 commits into
mainfrom
fix/backend-no-default-rusqlite

Conversation

@luthermonson

@luthermonson luthermonson commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The workspace entry for litewire-backend inherits that crate's default features, and its default is rusqlite. Every sibling crate (litewire-session, -mysql, -postgres, -tds, -hrana) depends on it through the workspace entry, so they all switch rusqlite back on. A downstream build that asks for

litewire = { ..., default-features = false, features = ["mysql", "postgres", "tds", "hrana", "turso"] }

still compiles rusqlite with bundled, which links a whole SQLite 3.46.0 and exports its sqlite3_* symbols.

ePHPm hit this. Its PHP pdo_sqlite/sqlite3 extensions link the PHP SDK's libsqlite3 by symbol name, and rusqlite's copy won the link, so PHP ran on a different SQLite than the one it was built against:

  • ENABLE_MEMORY_MANAGEMENT: SQLite then uses one shared page cache with one process-wide mutex for every connection. With PHP running requests on 32 threads, a read-only FTS5 search endpoint did about 1,050 req/s, against about 9,000 req/s with the SDK's SQLite (numbers in fix(php): pdo_sqlite serializes under threaded PHP; run it on the SDK's SQLite ephpm#563, which bumps to this rev).
  • DEFAULT_FOREIGN_KEYS=1: PRAGMA foreign_keys defaulted to on in PHP. Stock SQLite and stock PHP default it to off.
  • No ENABLE_MATH_FUNCTIONS.

Change

litewire-backend = { path = "crates/litewire-backend", default-features = false } in [workspace.dependencies], plus a comment explaining why the flag matters.

The rusqlite backend is now opt-in only:

  • litewire's backend-rusqlite feature, which is still in litewire's default, so the standalone crate behaves the same.
  • An explicit features = ["rusqlite"]. The dev-dependencies already use this (litewire-session, litewire-mysql, litewire-turso), so the tests still get the backend.

Verification

  • cargo tree -p litewire --no-default-features --features mysql,postgres,tds,hrana,turso -i rusqlite now reports that the package is not in the graph. Before this change it was there through every sibling crate. cargo tree -p litewire -i rusqlite with default features still shows it, through litewire.
  • cargo check passes for each member crate on its own (-p litewire-backend/-session/-mysql/-postgres/-tds/-hrana/-turso), so no crate depended on the default without saying so.
  • cargo clippy --workspace --all-targets -- -D warnings: clean. Also clean with ePHPm's feature set.
  • cargo test --workspace --no-fail-fast: all pass except mysql_multi_tenant::single_tenant_attach_keeps_working_over_the_wire. That test fails the same way on main on Windows: the ATTACH path loses its backslashes and the test leaves UserslutherAppDataLocalTemp...other.db files in crates/litewire/. It is unrelated to this change, which I checked by running it with the previous Cargo.toml.
  • In ePHPm with this rev pinned, libsqlite3-sys and rusqlite drop out of Cargo.lock, and PHP reports the SDK's SQLite 3.45.2 with foreign_keys = 0.

…t in the workspace

The workspace dependency on litewire-backend inherited its default
features, and litewire-backend's default is `rusqlite`. Every sibling
crate (session, mysql, postgres, tds, hrana) depends on it through the
workspace entry, so a downstream build with
`default-features = false, features = ["turso"]` still compiled
rusqlite's bundled SQLite and exported its sqlite3_* symbols.

ePHPm hit this: its PHP pdo_sqlite/sqlite3 extensions were resolved
against rusqlite's bundled SQLite 3.46.0 instead of the PHP SDK's
libsqlite3. That copy is built with SQLITE_ENABLE_MEMORY_MANAGEMENT
(one process-wide page-cache mutex for every connection, which
serializes threaded PHP) and SQLITE_DEFAULT_FOREIGN_KEYS=1 (foreign keys
on by default, unlike stock SQLite and PHP).

With default-features = false the rusqlite backend is opt-in only:
through litewire's backend-rusqlite feature (still default for the
standalone crate) or an explicit features = ["rusqlite"], which the
dev-dependencies already declare. cargo tree -p litewire
--no-default-features --features mysql,postgres,tds,hrana,turso no
longer contains rusqlite.
@ephpm

ephpm Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

ePHPm Preview — removed

Preview deployment has been torn down.

@ephpm
ephpm Bot temporarily deployed to preview-pr-45 October 10, 2026 23:55 Inactive
@ephpm
ephpm Bot temporarily deployed to preview-pr-45 October 10, 2026 23:55 Inactive
@ephpm
ephpm Bot temporarily deployed to preview-pr-45 October 10, 2026 23:55 Inactive
With litewire-backend's default off, two places relied on it implicitly:
litewire-hrana's unit tests use Rusqlite::memory() (cargo test -p
litewire-hrana failed with E0432), and the litewire CLI binary opens its
database with Rusqlite and wires the MySQL and Hrana frontends, so
--no-default-features --features cli no longer compiled.
@ephpm
ephpm Bot temporarily deployed to preview-pr-45 October 11, 2026 15:11 Inactive
@ephpm
ephpm Bot temporarily deployed to preview-pr-45 October 11, 2026 15:11 Inactive
@luthermonson
luthermonson merged commit b0c12bf into main Oct 11, 2026
5 checks passed
@luthermonson
luthermonson deleted the fix/backend-no-default-rusqlite branch October 11, 2026 15:13

This branch was successfully deployed

1 active deployment
preview-pr-45 — f4f184b8 Deployed Oct 11, 2026 by ephpm[bot]
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.

1 participant