Include domain in temporary tables

This commit is contained in:
Joscha 2023-12-29 00:51:57 +01:00
parent c6a1dd8632
commit 076c8f1a72
2 changed files with 34 additions and 25 deletions

View file

@ -50,8 +50,6 @@ fn launch_from_connection(conn: Connection, ephemeral: bool) -> rusqlite::Result
conn.pragma_update(None, "foreign_keys", true)?; conn.pragma_update(None, "foreign_keys", true)?;
conn.pragma_update(None, "trusted_schema", false)?; conn.pragma_update(None, "trusted_schema", false)?;
eprintln!("Opening vault");
let tokio_vault = TokioVault::launch_and_prepare(conn, &migrate::MIGRATIONS, prepare::prepare)?; let tokio_vault = TokioVault::launch_and_prepare(conn, &migrate::MIGRATIONS, prepare::prepare)?;
Ok(Vault { Ok(Vault {
tokio_vault, tokio_vault,

View file

@ -1,28 +1,32 @@
use rusqlite::Connection; use rusqlite::Connection;
pub fn prepare(conn: &mut Connection) -> rusqlite::Result<()> { pub fn prepare(conn: &mut Connection) -> rusqlite::Result<()> {
eprintln!("Preparing vault");
// Cache ids of tree roots. // Cache ids of tree roots.
conn.execute_batch( conn.execute_batch(
" "
CREATE TEMPORARY TABLE euph_trees ( CREATE TEMPORARY TABLE euph_trees (
domain TEXT NOT NULL,
room TEXT NOT NULL, room TEXT NOT NULL,
id INT NOT NULL, id INT NOT NULL,
PRIMARY KEY (room, id) PRIMARY KEY (domain, room, id)
) STRICT; ) STRICT;
INSERT INTO euph_trees (room, id) INSERT INTO euph_trees (domain, room, id)
SELECT room, id SELECT domain, room, id
FROM euph_msgs FROM euph_msgs
WHERE parent IS NULL WHERE parent IS NULL
UNION UNION
SELECT room, parent SELECT domain, room, parent
FROM euph_msgs FROM euph_msgs
WHERE parent IS NOT NULL WHERE parent IS NOT NULL
AND NOT EXISTS( AND NOT EXISTS(
SELECT * SELECT *
FROM euph_msgs AS parents FROM euph_msgs AS parents
WHERE parents.room = euph_msgs.room WHERE parents.domain = euph_msgs.domain
AND parents.room = euph_msgs.room
AND parents.id = euph_msgs.parent AND parents.id = euph_msgs.parent
); );
@ -30,15 +34,16 @@ pub fn prepare(conn: &mut Connection) -> rusqlite::Result<()> {
AFTER DELETE ON main.euph_rooms AFTER DELETE ON main.euph_rooms
BEGIN BEGIN
DELETE FROM euph_trees DELETE FROM euph_trees
WHERE room = old.room; WHERE domain = old.domain
AND room = old.room;
END; END;
CREATE TEMPORARY TRIGGER et_insert_msg_without_parent CREATE TEMPORARY TRIGGER et_insert_msg_without_parent
AFTER INSERT ON main.euph_msgs AFTER INSERT ON main.euph_msgs
WHEN new.parent IS NULL WHEN new.parent IS NULL
BEGIN BEGIN
INSERT OR IGNORE INTO euph_trees (room, id) INSERT OR IGNORE INTO euph_trees (domain, room, id)
VALUES (new.room, new.id); VALUES (new.domain, new.room, new.id);
END; END;
CREATE TEMPORARY TRIGGER et_insert_msg_with_parent CREATE TEMPORARY TRIGGER et_insert_msg_with_parent
@ -46,16 +51,18 @@ pub fn prepare(conn: &mut Connection) -> rusqlite::Result<()> {
WHEN new.parent IS NOT NULL WHEN new.parent IS NOT NULL
BEGIN BEGIN
DELETE FROM euph_trees DELETE FROM euph_trees
WHERE room = new.room WHERE domain = new.domain
AND room = new.room
AND id = new.id; AND id = new.id;
INSERT OR IGNORE INTO euph_trees (room, id) INSERT OR IGNORE INTO euph_trees (domain, room, id)
SELECT * SELECT *
FROM (VALUES (new.room, new.parent)) FROM (VALUES (new.domain, new.room, new.parent))
WHERE NOT EXISTS( WHERE NOT EXISTS(
SELECT * SELECT *
FROM euph_msgs FROM euph_msgs
WHERE room = new.room WHERE domain = new.domain
AND room = new.room
AND id = new.parent AND id = new.parent
AND parent IS NOT NULL AND parent IS NOT NULL
); );
@ -67,35 +74,37 @@ pub fn prepare(conn: &mut Connection) -> rusqlite::Result<()> {
conn.execute_batch( conn.execute_batch(
" "
CREATE TEMPORARY TABLE euph_unseen_counts ( CREATE TEMPORARY TABLE euph_unseen_counts (
domain TEXT NOT NULL,
room TEXT NOT NULL, room TEXT NOT NULL,
amount INTEGER NOT NULL, amount INTEGER NOT NULL,
PRIMARY KEY (room) PRIMARY KEY (domain, room)
) STRICT; ) STRICT;
-- There must be an entry for every existing room. -- There must be an entry for every existing room.
INSERT INTO euph_unseen_counts (room, amount) INSERT INTO euph_unseen_counts (domain, room, amount)
SELECT room, 0 SELECT domain, room, 0
FROM euph_rooms; FROM euph_rooms;
INSERT OR REPLACE INTO euph_unseen_counts (room, amount) INSERT OR REPLACE INTO euph_unseen_counts (domain, room, amount)
SELECT room, COUNT(*) SELECT domain, room, COUNT(*)
FROM euph_msgs FROM euph_msgs
WHERE NOT seen WHERE NOT seen
GROUP BY room; GROUP BY domain, room;
CREATE TEMPORARY TRIGGER euc_insert_room CREATE TEMPORARY TRIGGER euc_insert_room
AFTER INSERT ON main.euph_rooms AFTER INSERT ON main.euph_rooms
BEGIN BEGIN
INSERT INTO euph_unseen_counts (room, amount) INSERT INTO euph_unseen_counts (domain, room, amount)
VALUES (new.room, 0); VALUES (new.domain, new.room, 0);
END; END;
CREATE TEMPORARY TRIGGER euc_delete_room CREATE TEMPORARY TRIGGER euc_delete_room
AFTER DELETE ON main.euph_rooms AFTER DELETE ON main.euph_rooms
BEGIN BEGIN
DELETE FROM euph_unseen_counts DELETE FROM euph_unseen_counts
WHERE room = old.room; WHERE domain = old.domain
AND room = old.room;
END; END;
CREATE TEMPORARY TRIGGER euc_insert_msg CREATE TEMPORARY TRIGGER euc_insert_msg
@ -104,7 +113,8 @@ pub fn prepare(conn: &mut Connection) -> rusqlite::Result<()> {
BEGIN BEGIN
UPDATE euph_unseen_counts UPDATE euph_unseen_counts
SET amount = amount + 1 SET amount = amount + 1
WHERE room = new.room; WHERE domain = new.domain
AND room = new.room;
END; END;
CREATE TEMPORARY TRIGGER euc_update_msg CREATE TEMPORARY TRIGGER euc_update_msg
@ -113,7 +123,8 @@ pub fn prepare(conn: &mut Connection) -> rusqlite::Result<()> {
BEGIN BEGIN
UPDATE euph_unseen_counts UPDATE euph_unseen_counts
SET amount = CASE WHEN new.seen THEN amount - 1 ELSE amount + 1 END SET amount = CASE WHEN new.seen THEN amount - 1 ELSE amount + 1 END
WHERE room = new.room; WHERE domain = new.domain
AND room = new.room;
END; END;
", ",
)?; )?;