From 06d5fdb5ffc997394bb5c35ad3b3ee7b1027f86a Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Tue, 11 Mar 2025 12:01:40 +0100 Subject: [PATCH] fix(event cache): enable foreign keys on a connection basis As opposed to WAL mode, foreign keys must be enabled for each database connection, according to https://www.sqlite.org/foreignkeys.html#fk_enable Unfortunately, we can't track which connection objects have already executed the pragma, so the safer we can do is enable it everytime we try to acquire a connection from the pool. Fixes #4785. --- .../matrix-sdk-sqlite/src/event_cache_store.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/matrix-sdk-sqlite/src/event_cache_store.rs b/crates/matrix-sdk-sqlite/src/event_cache_store.rs index 7434fa1cf..96858570b 100644 --- a/crates/matrix-sdk-sqlite/src/event_cache_store.rs +++ b/crates/matrix-sdk-sqlite/src/event_cache_store.rs @@ -156,7 +156,15 @@ impl SqliteEventCacheStore { } async fn acquire(&self) -> Result { - Ok(self.pool.get().await?) + let connection = self.pool.get().await?; + + // Per https://www.sqlite.org/foreignkeys.html#fk_enable, foreign key support must be + // enabled on a per-connection basis. Execute it every time we try to get a + // connection, since we can't guarantee a previous connection did enable + // it before. + connection.execute_batch("PRAGMA foreign_keys = ON;").await?; + + Ok(connection) } fn map_row_to_chunk( @@ -302,6 +310,9 @@ async fn run_migrations(conn: &SqliteAsyncConn, version: u8) -> Result<()> { return Ok(()); } + // Always enable foreign keys for the current connection. + conn.execute_batch("PRAGMA foreign_keys = ON;").await?; + if version < 1 { // First turn on WAL mode, this can't be done in the transaction, it fails with // the error message: "cannot change into wal mode from within a transaction". @@ -322,9 +333,6 @@ async fn run_migrations(conn: &SqliteAsyncConn, version: u8) -> Result<()> { } if version < 3 { - // Enable foreign keys for this database. - conn.execute_batch("PRAGMA foreign_keys = ON;").await?; - conn.with_transaction(|txn| { txn.execute_batch(include_str!("../migrations/event_cache_store/003_events.sql"))?; txn.set_db_version(3)