I have an external content
FTS5 table, and I define triggers like this:
CREATE TRIGGER fts_content_sync_my_fts_AFTER_INSERT AFTER INSERT ON my_table BEGIN
INSERT INTO my_fts(id, meaning) VALUES (new.id, new.meaning);
END;
CREATE TRIGGER fts_content_sync_my_fts_AFTER_UPDATE AFTER UPDATE ON my_table BEGIN
INSERT INTO my_fts(id, meaning) VALUES (new.id, new.meaning);
END;
CREATE TRIGGER fts_content_sync_my_fts_BEFORE_DELETE BEFORE DELETE ON my_table BEGIN
DELETE FROM my_fts WHERE id=old.id;
END;
CREATE TRIGGER fts_content_sync_my_fts_BEFORE_UPDATE BEFORE UPDATE ON my_table BEGIN
DELETE FROM my_fts WHERE id=old.id;
END;
However, I was getting randomly (maybe 10% of the time) a corrupt database after updating meaning
column of my_table
and then querying the FTS5 table (for meaning
) shortly after.
After checking FTS5 documentation I noticed that I should be defining my triggers like this instead:
CREATE TRIGGER fts_content_sync_my_fts_AFTER_INSERT AFTER INSERT ON my_table BEGIN
INSERT INTO my_fts(rowid, meaning) VALUES (new.id, new.meaning);
END;
CREATE TRIGGER fts_content_sync_my_fts_AFTER_DELETE AFTER DELETE ON my_table BEGIN
INSERT INTO my_fts(my_fts, rowid, meaning) VALUES('delete', old.id, old.meaning);
END;
CREATE TRIGGER fts_content_sync_my_fts_AFTER_UPDATE AFTER UPDATE ON my_table BEGIN
INSERT INTO my_fts(my_fts, rowid, meaning) VALUES('delete', old.id, old.meaning);
INSERT INTO my_fts(rowid, meaning) VALUES (new.id, new.meaning);
END;
So far after making this change, I haven't experienced the database corruption, but it's still early days, so cannot be certain yet.
How is it that the old way of defining triggers was generally working but randomly corrupting the database?
EDIT: for context, I'm using latest versions of sqlcipher (sqlite 3.36.0, no encryption) and sqldelight on Android