Use VecDeque for trigger storage for similar reasons as indexes do

This commit is contained in:
Jussi Saurio
2025-11-18 15:06:13 +02:00
parent e1dee4a072
commit 5c1ebbd011
2 changed files with 17 additions and 2 deletions

View File

@@ -172,7 +172,7 @@ pub struct Schema {
pub views: ViewsMap,
/// table_name to list of triggers
pub triggers: HashMap<String, Vec<Arc<Trigger>>>,
pub triggers: HashMap<String, VecDeque<Arc<Trigger>>>,
/// table_name to list of indexes for the table
pub indexes: HashMap<String, VecDeque<Arc<Index>>>,
@@ -360,10 +360,11 @@ impl Schema {
self.check_object_name_conflict(&trigger.name)?;
let table_name = normalize_ident(table_name);
// See [Schema::add_index] for why we push to the front of the deque.
self.triggers
.entry(table_name)
.or_default()
.push(Arc::new(trigger));
.push_front(Arc::new(trigger));
Ok(())
}

View File

@@ -745,3 +745,17 @@ do_execsql_test_on_specific_db {:memory:} trigger-before-update-parent-expressio
UPDATE test66 SET c0 = c1+1;
SELECT * FROM test66;
} {2|666|666}
# Multiple BEFORE INSERT triggers - last added trigger fires first
# SQLite evaluates triggers in reverse order of creation (LIFO)
do_execsql_test_on_specific_db {:memory:} trigger-multiple-before-insert-lifo {
CREATE TABLE t67(c0 INTEGER, c1 INTEGER, c2 INTEGER, whodunnit TEXT);
CREATE TRIGGER t67_first BEFORE INSERT ON t67 BEGIN INSERT INTO t67 VALUES (NEW.c0+1, NEW.c1+2, NEW.c2+3, 't67_first'); END;
CREATE TRIGGER t67_second BEFORE INSERT ON t67 BEGIN INSERT INTO t67 VALUES (NEW.c0+2, NEW.c1+3, NEW.c2+4, 't67_second'); END;
INSERT INTO t67 VALUES (1, 1, 1, 'jussi');
SELECT rowid, * FROM t67 ORDER BY rowid;
} {1|4|6|8|t67_first
2|3|4|5|t67_second
3|4|6|8|t67_second
4|2|3|4|t67_first
5|1|1|1|jussi}