feat(db): store poster, backdrop and rating on titles
§9.6 keeps rich detail out of the database except for the three fields pure-SQL views need. Adds poster_path, backdrop_path and vote_average to movies and series, written by the daily metadata refresh in both lanes and filled at add time from the TMDB response the create flows already fetch.
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
-- §9.6: the three fields rich detail keeps out of the database are the ones
|
||||
-- pure-SQL views need — the in-library half of unified search (§9.2) and the
|
||||
-- library grid would otherwise cost one TMDB call per row. Nullable, no
|
||||
-- default: a title added before its first metadata refresh has no artwork
|
||||
-- yet, and TMDB itself has entries with no poster.
|
||||
ALTER TABLE movies ADD COLUMN poster_path TEXT;
|
||||
ALTER TABLE movies ADD COLUMN backdrop_path TEXT;
|
||||
ALTER TABLE movies ADD COLUMN vote_average REAL;
|
||||
ALTER TABLE series ADD COLUMN poster_path TEXT;
|
||||
ALTER TABLE series ADD COLUMN backdrop_path TEXT;
|
||||
ALTER TABLE series ADD COLUMN vote_average REAL;
|
||||
@@ -228,6 +228,38 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// §9.6: the stored artwork columns are nullable, and `REAL` is a valid
|
||||
/// STRICT type — a rating must not be squeezed into an integer.
|
||||
#[tokio::test]
|
||||
async fn title_artwork_columns_are_nullable_and_take_reals() {
|
||||
let (_dir, db) = fresh().await;
|
||||
|
||||
sqlx::query(
|
||||
"INSERT INTO movies (tmdb_id, title, root_id)
|
||||
SELECT 1, 'No Artwork Yet', id FROM roots WHERE kind = 'movie' LIMIT 1",
|
||||
)
|
||||
.execute(db.pool())
|
||||
.await
|
||||
.expect("row without artwork");
|
||||
sqlx::query(
|
||||
"UPDATE movies SET poster_path = '/dune.jpg', backdrop_path = '/dune-wide.jpg',
|
||||
vote_average = 8.152
|
||||
WHERE tmdb_id = 1",
|
||||
)
|
||||
.execute(db.pool())
|
||||
.await
|
||||
.expect("artwork write");
|
||||
|
||||
let (poster, backdrop, vote): (Option<String>, Option<String>, Option<f64>) =
|
||||
sqlx::query_as("SELECT poster_path, backdrop_path, vote_average FROM movies")
|
||||
.fetch_one(db.pool())
|
||||
.await
|
||||
.expect("movie row");
|
||||
assert_eq!(poster.as_deref(), Some("/dune.jpg"));
|
||||
assert_eq!(backdrop.as_deref(), Some("/dune-wide.jpg"));
|
||||
assert_eq!(vote, Some(8.152));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn foreign_keys_are_enforced() {
|
||||
let (_dir, db) = fresh().await;
|
||||
|
||||
Reference in New Issue
Block a user