Files
minstrel/internal/db/migrations/0014_playlists.up.sql
T
bvandeusenandClaude Opus 5.5 6028d78844
release / govulncheck (push) Successful in 17s
release / web (push) Successful in 1m33s
release / go (push) Successful in 1m49s
release / integration (push) Successful in 5m42s
release / android (push) Successful in 5m59s
release / Build signed APK (releases and dev) (push) Successful in 6m9s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 16s
release / Verify release artifacts (tag releases only) (push) Skipped
docs: migration headers keep the before and after, without ids, quotes or one library's numbers (#6277)
Applies rule 32's migration exception: each header still says what the
schema was, what changes and what it prevents, but task, milestone,
decision and rule ids are replaced by the practice they stood for, the
operator quotes by the decision, single-install counts are dropped, and
pointers to a deleted package and an external design doc are gone.
golang-migrate keeps no checksum, so editing applied migrations'
comments is safe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 12:34:39 -04:00

39 lines
1.7 KiB
SQL

-- User playlists.
CREATE TABLE playlists (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name text NOT NULL,
description text NOT NULL DEFAULT '',
is_public boolean NOT NULL DEFAULT false,
cover_path text,
track_count integer NOT NULL DEFAULT 0,
duration_sec integer NOT NULL DEFAULT 0,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX playlists_user_idx ON playlists (user_id, updated_at DESC);
CREATE INDEX playlists_public_idx ON playlists (is_public, updated_at DESC) WHERE is_public;
-- track_id is nullable + ON DELETE SET NULL so deleting a track from
-- the library doesn't silently drop entries from operators' playlists.
-- Denormalized title/artist/album/duration carry a snapshot so the row
-- is still legible after the upstream track row is gone.
CREATE TABLE playlist_tracks (
playlist_id uuid NOT NULL REFERENCES playlists(id) ON DELETE CASCADE,
position integer NOT NULL,
track_id uuid REFERENCES tracks(id) ON DELETE SET NULL,
title text NOT NULL,
artist_name text NOT NULL,
album_title text NOT NULL,
duration_sec integer NOT NULL,
added_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (playlist_id, position)
);
-- Partial index supports the FK lookup that fires when a track is
-- deleted (ON DELETE SET NULL) — without it, deleting a track triggers
-- a full scan of playlist_tracks.
CREATE INDEX playlist_tracks_track_idx ON playlist_tracks (track_id) WHERE track_id IS NOT NULL;