diff --git a/UPGRADE.md b/UPGRADE.md index 117b4bff..f87c2079 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -39,6 +39,13 @@ Report your issue on Xibalba BBS, hop in #enigma-bbs on FreeNode and chat, or ] } ``` +* A set of database fixes were made that cause some records to be properly cleaned up when e.g. deleting a file. Existing `file.db` databases will need to be updated **manually**. Note that this applies to users upgrading within 0.0.12-beta as well: +1. **Make a backup of your file.db!** +2. Shut down ENiGMA. +3. From the enigma-bbs directory: +``` +sqlite3 db/file.sqlite3 < ./misc/update/tables_update_2020-11-29.sql +``` # 0.0.10-alpha to 0.0.11-beta * Node.js 12.x LTS is now in use. Follow standard Node.js upgrade procedures (e.g.: `nvm install 12 && nvm use 12`). diff --git a/WHATSNEW.md b/WHATSNEW.md index f03b6cee..ee0e4943 100644 --- a/WHATSNEW.md +++ b/WHATSNEW.md @@ -13,6 +13,7 @@ This document attempts to track **major** changes and additions in ENiGMA½. For * Default file browser up/down/pageUp/pageDown scrolls description (e.g. FILE_ID.DIZ). If you want to expose this on an existing system see the `fileBaseListEntries` in the default `file_base.in.hjson` template. * File base search has had an improvement to search term handling. * `./oputil user group -group` to now accepts `~group` removing the need for special handling of the "-" character. #331 +* A fix has been made to clean up old `file.db` entries when a file is removed. Previously stale records could be left or even recycled into new entries. Please see [UPGRADE.md](UPGRADE.md) for details on applying this fix (look for `tables_update_2020-11-29.sql`). ## 0.0.11-beta * Upgraded from `alpha` to `beta` -- The software is far along and mature enough at this point! diff --git a/core/database.js b/core/database.js index 17bc3844..55ed4e2e 100644 --- a/core/database.js +++ b/core/database.js @@ -421,7 +421,8 @@ const DB_INIT_TABLE = { hash_tag_id INTEGER NOT NULL, file_id INTEGER NOT NULL, - UNIQUE(hash_tag_id, file_id) + UNIQUE(hash_tag_id, file_id), + FOREIGN KEY(file_id) REFERENCES file(file_id) ON DELETE CASCADE );` ); @@ -431,7 +432,10 @@ const DB_INIT_TABLE = { user_id INTEGER NOT NULL, rating INTEGER NOT NULL, - UNIQUE(file_id, user_id) + UNIQUE(file_id, user_id), + FOREIGN KEY(file_id) REFERENCES file(file_id) ON DELETE CASCADE + -- Note that we cannot CASCADE if user_id is removed from user.db + -- See processing in oputil's removeUser() );` ); @@ -447,7 +451,8 @@ const DB_INIT_TABLE = { hash_id VARCHAR NOT NULL, file_id INTEGER NOT NULL, - UNIQUE(hash_id, file_id) + UNIQUE(hash_id, file_id), + FOREIGN KEY(file_id) REFERENCES file(file_id) ON DELETE CASCADE );` ); diff --git a/core/file_entry.js b/core/file_entry.js index 90a9bac2..476864ca 100644 --- a/core/file_entry.js +++ b/core/file_entry.js @@ -243,6 +243,15 @@ module.exports = class FileEntry { ); } + static removeUserRatings(userId, cb) { + return fileDb.run( + `DELETE FROM file_user_rating + WHERE user_id = ?;`, + [ userId ], + cb + ); + } + static persistMetaValue(fileId, name, value, transOrDb, cb) { if(!_.isFunction(cb) && _.isFunction(transOrDb)) { cb = transOrDb; diff --git a/core/oputil/oputil_user.js b/core/oputil/oputil_user.js index 7c71523f..d3a13931 100644 --- a/core/oputil/oputil_user.js +++ b/core/oputil/oputil_user.js @@ -172,6 +172,7 @@ function removeUser(user) { message : [ 'user_message_area_last_read' ], system : [ 'user_event_log', ], user : [ 'user_group_member', 'user' ], + file : [ 'file_user_rating'] }; async.eachSeries(Object.keys(DeleteFrom), (dbName, nextDbName) => { diff --git a/misc/update/tables_update_2020-11-29.sql b/misc/update/tables_update_2020-11-29.sql new file mode 100644 index 00000000..7d8ac862 --- /dev/null +++ b/misc/update/tables_update_2020-11-29.sql @@ -0,0 +1,41 @@ +PRAGMA foreign_keys=OFF; + +BEGIN; + +CREATE TABLE IF NOT EXISTS file_hash_tag_new ( + hash_tag_id INTEGER NOT NULL, + file_id INTEGER NOT NULL, + + UNIQUE(hash_tag_id, file_id), + FOREIGN KEY(file_id) REFERENCES file(file_id) ON DELETE CASCADE +); +INSERT INTO file_hash_tag_new SELECT * FROM file_hash_tag; +DROP TABLE file_hash_tag; +ALTER TABLE file_hash_tag_new RENAME TO file_hash_tag; + +CREATE TABLE IF NOT EXISTS file_user_rating_new ( + file_id INTEGER NOT NULL, + user_id INTEGER NOT NULL, + rating INTEGER NOT NULL, + + UNIQUE(file_id, user_id), + FOREIGN KEY(file_id) REFERENCES file(file_id) ON DELETE CASCADE +); +INSERT INTO file_user_rating_new SELECT * FROM file_user_rating; +DROP TABLE file_user_rating; +ALTER TABLE file_user_rating_new RENAME TO file_user_rating; + +CREATE TABLE IF NOT EXISTS file_web_serve_batch_new ( + hash_id VARCHAR NOT NULL, + file_id INTEGER NOT NULL, + + UNIQUE(hash_id, file_id), + FOREIGN KEY(file_id) REFERENCES file(file_id) ON DELETE CASCADE +); +INSERT INTO file_web_serve_batch_new SELECT * FROM file_web_serve_batch; +DROP TABLE file_web_serve_batch; +ALTER TABLE file_web_serve_batch_new RENAME TO file_web_serve_batch; + +PRAGMA foreign_key_check; +COMMIT; +PRAGMA foreign_keys=ON;