ITADN

meta: SQLite meta store does not set `PRAGMA foreign_keys = ON`, so declared foreign keys are not enforced

#26047Openyuhao-su 创建于 2026-06-25
type/bugA-meta
Y
yuhao-sucommented
## Problem The SQLite meta store never enables `PRAGMA foreign_keys = ON`. SQLite defaults foreign-key enforcement to **OFF on every new connection**, and it must be turned on per-connection. Because we never set it, every foreign key declared in our migrations is parsed and stored in the schema but **never enforced** on the SQLite backend — including referential integrity and `ON DELETE CASCADE`. ## Mechanism `src/meta/src/controller/mod.rs` — `sqlite_common()` (applied to both the in-memory `mem` backend and file-based SQLite) configures the connection pool but issues no `PRAGMA`: ```rust fn sqlite_common(&mut self) -> &mut Self { self .min_connections(1) .max_connections(1) .acquire_timeout(MAX_DURATION) .connect_timeout(MAX_DURATION) // <-- no `PRAGMA foreign_keys = ON` } ``` ## Consequences - **Declared foreign keys are not enforced on SQLite.** Orphan child rows can be inserted/left behind with no error. - **`ON DELETE CASCADE` does not fire on SQLite.** Cascade cleanup that works on Postgres/MySQL is a silent no-op on SQLite. - This makes SQLite diverge in behavior from the production backends (Postgres/MySQL), which is a footgun for dev/test that assume parity. Example: #26045 adds `pending_sink_state.sink_id -> object(oid) ON DELETE CASCADE`; it correctly cascades on PG/MySQL but is inert on SQLite, so the leak it fixes can only be prevented on SQLite by the application-level cleanup, not the constraint. ## Considerations for a fix Enabling the pragma is not a one-line change and should be done carefully: 1. **It must be set on every connection** (per-connection, not once per database). sea-orm 1.x `ConnectOptions` does not obviously expose an `after_connect`/init hook, so this may need a workaround (e.g. a connection-string parameter, or a sqlx-level option). Needs investigation. 2. **Turning enforcement on may surface latent referential-integrity violations** already present in existing SQLite meta stores. An audit / cleanup migration likely needs to run first, otherwise existing dev/test stores could fail to open. 3. **SQLite "recreate table" migrations interact with FK enforcement.** SQLite's documented schema-change procedure requires `PRAGMA foreign_keys = OFF` (or `legacy_alter_table`) around a drop+rename table recreate, otherwise child FK references get rewritten/broken on rename. Our existing recreate-style migrations (e.g. `m20240820_081248`, `m20260624_000000` from #26045) would need to account for this. Ties into #26046 (migration atomicity / transaction wrapping on SQLite/MySQL). ## Notes - SQLite is currently labeled "not for prod usage" in the codebase, so this is hardening rather than a production incident — but silently not enforcing declared constraints is a correctness gap and makes SQLite an unreliable stand-in for the prod backends in tests. - Related: #26045 (the FK that is inert on SQLite today), #26046 (migrations not atomic on SQLite/MySQL).
0 条评论