Skip to content

Commit d535f79

Browse files
committed
Merge #527: Fix DB migration for SQLite. Backup secondary tables to avoid losing data
094ab8a fix: linter errors (Jose Celano) bd935b3 fix: [#526] DB migration for SQLite. Backup secondary tables (Jose Celano) Pull request description: The table `torrust_torrents` has 8 secondary tables that reference it with a foreign key: ```sql FOREIGN KEY("torrent_id") REFERENCES "torrust_torrents"("torrent_id") ON DELETE CASCADE, ``` The migration fixed in this commit creates a new table in order to alter it and drops the old one. However, when you drop the old table, SQLite uses an implicit DELETE query for the `torrust_torrents` table which triggers a DELETE ON CASCADE, deleting all the related records in secondary tables. The secondary tables are: - torrust_torrent_files - torrust_torrent_announce_urls - torrust_torrent_info - torrust_torrent_tracker_stats - torrust_torrent_tag_links - torrust_torrent_info_hashes - torrust_torrent_http_seeds - torrust_torrent_nodes These tables store the torrent file fiel together with the master `torrust_torrents`. ACKs for top commit: josecelano: ACK 094ab8a Tree-SHA512: 631a40ac3645c67430831a681e04d91c0dc4a62efe9bb65036abb3bf992c1bb289b7af7ca3ca417c4cec0911a64c778b0e0fffedfe7dbf9f5ba1c8af28933f23
2 parents 0cc2663 + 094ab8a commit d535f79

File tree

5 files changed

+101
-18
lines changed

5 files changed

+101
-18
lines changed

migrations/sqlite3/20240305120015_torrust_add_independent_root_hash_field.sql

+90-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,68 @@
1-
-- add field `root_hash` and make `pieces` nullable
1+
PRAGMA foreign_keys = off;
2+
3+
-- Step 1: backup secondary tables. They will be truncated because of the DELETE ON CASCADE
4+
CREATE TEMPORARY TABLE IF NOT EXISTS "torrust_torrent_files_backup" (
5+
"file_id" INTEGER NOT NULL,
6+
"torrent_id" INTEGER NOT NULL,
7+
"md5sum" TEXT DEFAULT NULL,
8+
"length" BIGINT NOT NULL,
9+
"path" TEXT DEFAULT NULL
10+
);
11+
INSERT INTO torrust_torrent_files_backup SELECT * FROM torrust_torrent_files;
12+
13+
CREATE TEMPORARY TABLE IF NOT EXISTS "torrust_torrent_announce_urls_backup" (
14+
"announce_url_id" INTEGER NOT NULL,
15+
"torrent_id" INTEGER NOT NULL,
16+
"tracker_url" TEXT NOT NULL
17+
);
18+
INSERT INTO torrust_torrent_announce_urls_backup SELECT * FROM torrust_torrent_announce_urls;
19+
20+
CREATE TEMPORARY TABLE IF NOT EXISTS "torrust_torrent_info_backup" (
21+
"torrent_id" INTEGER NOT NULL,
22+
"title" VARCHAR(256) NOT NULL UNIQUE,
23+
"description" TEXT DEFAULT NULL
24+
);
25+
INSERT INTO torrust_torrent_info_backup SELECT * FROM torrust_torrent_info;
26+
27+
CREATE TEMPORARY TABLE IF NOT EXISTS "torrust_torrent_tracker_stats_backup" (
28+
"torrent_id" INTEGER NOT NULL,
29+
"tracker_url" VARCHAR(256) NOT NULL,
30+
"seeders" INTEGER NOT NULL DEFAULT 0,
31+
"leechers" INTEGER NOT NULL DEFAULT 0
32+
);
33+
INSERT INTO torrust_torrent_tracker_stats_backup SELECT * FROM torrust_torrent_tracker_stats;
34+
35+
CREATE TEMPORARY TABLE IF NOT EXISTS "torrust_torrent_tag_links_backup" (
36+
"torrent_id" INTEGER NOT NULL,
37+
"tag_id" INTEGER NOT NULL
38+
);
39+
INSERT INTO torrust_torrent_tag_links_backup SELECT * FROM torrust_torrent_tag_links;
40+
41+
CREATE TEMPORARY TABLE IF NOT EXISTS "torrust_torrent_info_hashes_backup" (
42+
"info_hash" TEXT NOT NULL,
43+
"canonical_info_hash" TEXT NOT NULL,
44+
"original_is_known" BOOLEAN NOT NULL
45+
);
46+
INSERT INTO torrust_torrent_info_hashes_backup SELECT * FROM torrust_torrent_info_hashes;
47+
48+
CREATE TEMPORARY TABLE IF NOT EXISTS "torrust_torrent_http_seeds_backup" (
49+
"http_seed_id" INTEGER NOT NULL,
50+
"torrent_id" INTEGER NOT NULL,
51+
"seed_url" TEXT NOT NULL
52+
);
53+
INSERT INTO torrust_torrent_http_seeds_backup SELECT * FROM torrust_torrent_http_seeds;
54+
55+
CREATE TEMPORARY TABLE IF NOT EXISTS "torrust_torrent_nodes_backup" (
56+
"node_id" INTEGER NOT NULL,
57+
"torrent_id" INTEGER NOT NULL,
58+
"node_ip" TEXT NOT NULL,
59+
"node_port" INTEGER NOT NULL
60+
);
61+
INSERT INTO torrust_torrent_nodes_backup SELECT * FROM torrust_torrent_nodes;
62+
63+
-- Step 2: Add field `root_hash` and make `pieces` nullable
264
CREATE TABLE
3-
"torrust_torrents_new" (
65+
IF NOT EXISTS "torrust_torrents_new" (
466
"torrent_id" INTEGER NOT NULL,
567
"uploader_id" INTEGER NOT NULL,
668
"category_id" INTEGER,
@@ -23,7 +85,7 @@ CREATE TABLE
2385
PRIMARY KEY ("torrent_id" AUTOINCREMENT)
2486
);
2587

26-
-- Step 2: Copy data from the old table to the new table
88+
-- Step 3: Copy data from the old table to the new table
2789
INSERT INTO
2890
torrust_torrents_new (
2991
torrent_id,
@@ -69,9 +131,30 @@ SELECT
69131
FROM
70132
torrust_torrents;
71133

72-
-- Step 3: Drop the old table
134+
-- Step 4: Drop the old table
73135
DROP TABLE torrust_torrents;
74136

75-
-- Step 4: Rename the new table to the original name
76-
ALTER TABLE torrust_torrents_new
77-
RENAME TO torrust_torrents;
137+
-- Step 5: Rename the new table to the original name
138+
ALTER TABLE torrust_torrents_new RENAME TO torrust_torrents;
139+
140+
-- Step 6: Repopulate secondary tables from backup tables
141+
INSERT INTO torrust_torrent_files SELECT * FROM torrust_torrent_files_backup;
142+
INSERT INTO torrust_torrent_announce_urls SELECT * FROM torrust_torrent_announce_urls_backup;
143+
INSERT INTO torrust_torrent_info SELECT * FROM torrust_torrent_info_backup;
144+
INSERT INTO torrust_torrent_tracker_stats SELECT * FROM torrust_torrent_tracker_stats_backup;
145+
INSERT INTO torrust_torrent_tag_links SELECT * FROM torrust_torrent_tag_links_backup;
146+
INSERT INTO torrust_torrent_info_hashes SELECT * FROM torrust_torrent_info_hashes_backup;
147+
INSERT INTO torrust_torrent_http_seeds SELECT * FROM torrust_torrent_http_seeds_backup;
148+
INSERT INTO torrust_torrent_nodes SELECT * FROM torrust_torrent_nodes_backup;
149+
150+
-- Step 7: Drop temporary secondary table backups
151+
DROP TABLE torrust_torrent_files_backup;
152+
DROP TABLE torrust_torrent_announce_urls_backup;
153+
DROP TABLE torrust_torrent_info_backup;
154+
DROP TABLE torrust_torrent_tracker_stats_backup;
155+
DROP TABLE torrust_torrent_tag_links_backup;
156+
DROP TABLE torrust_torrent_info_hashes_backup;
157+
DROP TABLE torrust_torrent_http_seeds_backup;
158+
DROP TABLE torrust_torrent_nodes_backup;
159+
160+
PRAGMA foreign_keys = on;

src/config.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -430,10 +430,10 @@ impl TorrustIndex {
430430
}
431431

432432
pub fn remove_secrets(&mut self) {
433-
self.tracker.token = "***".to_owned();
434-
self.database.connect_url = "***".to_owned();
435-
self.mail.password = "***".to_owned();
436-
self.auth.secret_key = "***".to_owned();
433+
"***".clone_into(&mut self.tracker.token);
434+
"***".clone_into(&mut self.database.connect_url);
435+
"***".clone_into(&mut self.mail.password);
436+
"***".clone_into(&mut self.auth.secret_key);
437437
}
438438
}
439439

src/models/torrent_file.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ impl TorrentInfoDictionary {
291291
.first()
292292
.expect("vector `torrent_files` should have at least one element");
293293

294-
info_dict.md5sum = torrent_file.md5sum.clone();
294+
info_dict.md5sum.clone_from(&torrent_file.md5sum); // DevSkim: ignore DS126858
295295

296296
info_dict.length = Some(torrent_file.length);
297297

tests/e2e/environment.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ impl TestEnv {
9090
pub fn server_settings_masking_secrets(&self) -> Option<Settings> {
9191
match self.starting_settings.clone() {
9292
Some(mut settings) => {
93-
settings.tracker.token = "***".to_owned();
94-
settings.database.connect_url = "***".to_owned();
95-
settings.mail.password = "***".to_owned();
96-
settings.auth.secret_key = "***".to_owned();
93+
"***".clone_into(&mut settings.tracker.token);
94+
"***".clone_into(&mut settings.database.connect_url);
95+
"***".clone_into(&mut settings.mail.password);
96+
"***".clone_into(&mut settings.auth.secret_key);
9797
Some(settings)
9898
}
9999
None => None,

tests/e2e/web/api/v1/contexts/torrent/contract.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ mod for_guests {
238238

239239
// Upload the first torrent
240240
let mut first_torrent = TestTorrent::with_custom_info_dict_field(id, &file_contents, "custom 01");
241-
first_torrent.index_info.title = title.clone();
241+
first_torrent.index_info.title.clone_from(&title);
242242

243243
let first_torrent_canonical_info_hash = upload_test_torrent(&client, &first_torrent)
244244
.await
@@ -376,7 +376,7 @@ mod for_guests {
376376

377377
// Upload the first torrent
378378
let mut first_torrent = TestTorrent::with_custom_info_dict_field(id, &file_contents, "custom 01");
379-
first_torrent.index_info.title = title.clone();
379+
first_torrent.index_info.title.clone_from(&title);
380380

381381
let first_torrent_canonical_info_hash = upload_test_torrent(&client, &first_torrent)
382382
.await

0 commit comments

Comments
 (0)