You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(plex): add source/remote_id columns for Plex source tracking (TASK-342.2)
Add idempotent migrations for source TEXT NOT NULL DEFAULT 'local' and
remote_id TEXT to the library table, with idx_library_source and
idx_library_remote_id indexes. Update Track model, row_to_track, all
SELECT statements, and library_get_all with optional source_filter param.
Copy file name to clipboardExpand all lines: backlog/tasks/task-342.2 - Backend-Database-migration-for-Plex-source-tracking.md
+67-11Lines changed: 67 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,10 @@
1
1
---
2
2
id: TASK-342.2
3
3
title: 'Backend: Database migration for Plex source tracking'
4
-
status: In Progress
4
+
status: Done
5
5
assignee: []
6
6
created_date: '2026-05-21 22:56'
7
-
updated_date: '2026-05-22 04:31'
7
+
updated_date: '2026-05-23 00:48'
8
8
labels: []
9
9
dependencies: []
10
10
parent_task_id: TASK-342
@@ -32,13 +32,69 @@ Key files:
32
32
33
33
## Acceptance Criteria
34
34
<!-- AC:BEGIN -->
35
-
-[]#1 Schema migration follows the column-presence idiom in `crates/mt-tauri/src/db/schema.rs::run_migrations` — read columns via `get_table_columns(conn, "library")`, then `conn.execute("ALTER TABLE library ADD COLUMN X ...", [])` guarded by `if !cols.contains(...)`. Do not introduce `PRAGMA user_version` or any new versioning system.
36
-
-[]#2 New columns on `library`: `source TEXT NOT NULL DEFAULT 'local'` and `remote_id TEXT`. Existing rows acquire `source='local'` via the DEFAULT; `remote_id` stays NULL.
37
-
-[]#3 Add index `idx_library_remote_id ON library(remote_id) WHERE remote_id IS NOT NULL`, created behind an `index_exists(conn, "idx_library_remote_id")?` guard.
38
-
-[]#4 Add index `idx_library_source ON library(source)`, created behind an `index_exists` guard, to support `WHERE source = ?` filters efficiently.
39
-
-[]#5 The `Track` model in `crates/mt-tauri/src/db/models.rs` gains `source: String` (default `"local"` in constructors) and `remote_id: Option<String>`. All existing row-builder functions read the new columns.
40
-
-[]#6 Existing library queries (`library_get_all`, `library_get_section` in `crates/mt-tauri/src/library/commands.rs`) continue to return all tracks by default (no source filter on the WHERE clause). A new optional `source_filter: Option<String>` parameter is added to `library_get_all`; when `Some("local")` or `Some("plex")` it appends `AND source = ?`. When `None`, behavior is unchanged.
41
-
-[]#7 Library stats (`library_get_stats` at `commands.rs:476`) count both sources — no change required (existing query has no source filter).
42
-
-[]#8 Migration is verified idempotent by a Rust unit test that runs `run_migrations` twice in a row against a fresh in-memory SQLite DB and asserts (a) both new columns exist after the first call, (b) the second call is a no-op (no error, no duplicate columns).
43
-
-[]#9 A second test inserts one row with `source='local'`, one with `source='plex'` + `remote_id='12345'`, and asserts `library_get_all(source_filter=Some("plex"))` returns exactly the second row.
35
+
-[x]#1 Schema migration follows the column-presence idiom in `crates/mt-tauri/src/db/schema.rs::run_migrations` — read columns via `get_table_columns(conn, "library")`, then `conn.execute("ALTER TABLE library ADD COLUMN X ...", [])` guarded by `if !cols.contains(...)`. Do not introduce `PRAGMA user_version` or any new versioning system.
36
+
-[x]#2 New columns on `library`: `source TEXT NOT NULL DEFAULT 'local'` and `remote_id TEXT`. Existing rows acquire `source='local'` via the DEFAULT; `remote_id` stays NULL.
37
+
-[x]#3 Add index `idx_library_remote_id ON library(remote_id) WHERE remote_id IS NOT NULL`, created behind an `index_exists(conn, "idx_library_remote_id")?` guard.
38
+
-[x]#4 Add index `idx_library_source ON library(source)`, created behind an `index_exists` guard, to support `WHERE source = ?` filters efficiently.
39
+
-[x]#5 The `Track` model in `crates/mt-tauri/src/db/models.rs` gains `source: String` (default `"local"` in constructors) and `remote_id: Option<String>`. All existing row-builder functions read the new columns.
40
+
-[x]#6 Existing library queries (`library_get_all`, `library_get_section` in `crates/mt-tauri/src/library/commands.rs`) continue to return all tracks by default (no source filter on the WHERE clause). A new optional `source_filter: Option<String>` parameter is added to `library_get_all`; when `Some("local")` or `Some("plex")` it appends `AND source = ?`. When `None`, behavior is unchanged.
41
+
-[x]#7 Library stats (`library_get_stats` at `commands.rs:476`) count both sources — no change required (existing query has no source filter).
42
+
-[x]#8 Migration is verified idempotent by a Rust unit test that runs `run_migrations` twice in a row against a fresh in-memory SQLite DB and asserts (a) both new columns exist after the first call, (b) the second call is a no-op (no error, no duplicate columns).
43
+
-[x]#9 A second test inserts one row with `source='local'`, one with `source='plex'` + `remote_id='12345'`, and asserts `library_get_all(source_filter=Some("plex"))` returns exactly the second row.
44
44
<!-- AC:END -->
45
+
46
+
## Implementation Plan
47
+
48
+
<!-- SECTION:PLAN:BEGIN -->
49
+
## Implementation Plan
50
+
51
+
### Files to modify
52
+
1.`crates/mt-tauri/src/db/schema.rs` — 4 new migrations + update existing idempotent test
53
+
2.`crates/mt-tauri/src/db/models.rs` — add `source: String` and `remote_id: Option<String>` to Track
- library.rs test_source_filter: insert local + plex row, assert plex filter works (AC#9)
94
+
<!-- SECTION:PLAN:END -->
95
+
96
+
## Final Summary
97
+
98
+
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
99
+
Added source/remote_id columns to the library table with idempotent migrations following the existing column-presence pattern. Updated Track model, row_to_track, all SELECT statements across library/favorites/queue/playlists, and library_get_all command. All 817 tests pass.
0 commit comments