diff --git a/src/vault/euph.rs b/src/vault/euph.rs index bc08c13..642f3c3 100644 --- a/src/vault/euph.rs +++ b/src/vault/euph.rs @@ -624,14 +624,6 @@ impl EuphRequest { [&room], )?; - tx.execute( - " - DELETE FROM euph_trees - WHERE room = ? - ", - [&room], - )?; - tx.commit()?; Ok(()) } @@ -683,26 +675,6 @@ impl EuphRequest { real_client_address = :real_client_address " )?; - let mut delete_trees = tx.prepare( - " - DELETE FROM euph_trees - WHERE room = ? AND id = ? - ", - )?; - let mut insert_trees = tx.prepare( - " - INSERT OR IGNORE INTO euph_trees (room, id) - SELECT * - FROM (VALUES (:room, :id)) - WHERE NOT EXISTS( - SELECT * - FROM euph_msgs - WHERE room = :room - AND id = :id - AND parent IS NOT NULL - ) - ", - )?; let own_user_id = own_user_id.as_ref().map(|u| &u.0); for msg in msgs { @@ -728,13 +700,6 @@ impl EuphRequest { ":real_client_address": msg.sender.real_client_address, ":own_user_id": own_user_id, // May be NULL })?; - - if let Some(parent) = msg.parent { - delete_trees.execute(params![room, msg.id])?; - insert_trees.execute(named_params! {":room": room, ":id": parent})?; - } else { - insert_trees.execute(named_params! {":room": room, ":id": msg.id})?; - } } Ok(()) diff --git a/src/vault/prepare.rs b/src/vault/prepare.rs index 0875db7..75f351f 100644 --- a/src/vault/prepare.rs +++ b/src/vault/prepare.rs @@ -3,8 +3,7 @@ use rusqlite::Connection; pub fn prepare(conn: &mut Connection) -> rusqlite::Result<()> { println!("Opening vault"); - // This temporary table has no foreign key constraint on euph_rooms since - // cross-schema constraints like that are not supported by SQLite. + // Cache ids of tree roots. conn.execute_batch( " CREATE TEMPORARY TABLE euph_trees ( @@ -28,6 +27,41 @@ pub fn prepare(conn: &mut Connection) -> rusqlite::Result<()> { WHERE parents.room = euph_msgs.room AND parents.id = euph_msgs.parent ); + + CREATE TEMPORARY TRIGGER et_delete_room + AFTER DELETE ON main.euph_rooms + BEGIN + DELETE FROM euph_trees + WHERE room = old.room; + END; + + CREATE TEMPORARY TRIGGER et_insert_msg_without_parent + AFTER INSERT ON main.euph_msgs + WHEN new.parent IS NULL + BEGIN + INSERT OR IGNORE INTO euph_trees (room, id) + VALUES (new.room, new.id); + END; + + CREATE TEMPORARY TRIGGER et_insert_msg_with_parent + AFTER INSERT ON main.euph_msgs + WHEN new.parent IS NOT NULL + BEGIN + DELETE FROM euph_trees + WHERE room = new.room + AND id = new.id; + + INSERT OR IGNORE INTO euph_trees (room, id) + SELECT * + FROM (VALUES (new.room, new.parent)) + WHERE NOT EXISTS( + SELECT * + FROM euph_msgs + WHERE room = new.room + AND id = new.parent + AND parent IS NOT NULL + ); + END; ", )?;