205 lines
No EOL
7.7 KiB
SQL
205 lines
No EOL
7.7 KiB
SQL
-- 040_streaming_core.sql
|
|
-- Core Streaming Entities: Tracks, Playlists (Aligned with ORIGIN)
|
|
|
|
-- === TRACKS ===
|
|
CREATE TABLE public.tracks (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
creator_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
|
file_id UUID REFERENCES public.files(id) ON DELETE RESTRICT, -- NULL temporairement avant création fichier
|
|
|
|
-- Track Info
|
|
title VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
artist VARCHAR(255),
|
|
album VARCHAR(255),
|
|
genre VARCHAR(100),
|
|
year INTEGER DEFAULT 0, -- Release year (for Go model compatibility)
|
|
|
|
-- Audio Properties
|
|
duration INTEGER NOT NULL, -- seconds
|
|
bpm INTEGER,
|
|
musical_key VARCHAR(10),
|
|
|
|
-- Visibility
|
|
visibility public.visibility NOT NULL DEFAULT 'public',
|
|
is_downloadable BOOLEAN NOT NULL DEFAULT false,
|
|
|
|
-- Media
|
|
cover_art_file_id UUID REFERENCES public.files(id) ON DELETE SET NULL,
|
|
waveform_data JSONB,
|
|
|
|
-- Counts (denormalized)
|
|
play_count INTEGER NOT NULL DEFAULT 0,
|
|
like_count INTEGER NOT NULL DEFAULT 0,
|
|
comment_count INTEGER NOT NULL DEFAULT 0,
|
|
download_count INTEGER NOT NULL DEFAULT 0,
|
|
|
|
-- Legacy/Go Compatibility fields (Denormalized or Mapped)
|
|
user_id UUID, -- Maps to creator_id
|
|
file_path VARCHAR(500), -- Maps to files.url or storage_path
|
|
file_size BIGINT, -- Maps to files.file_size
|
|
format VARCHAR(10),
|
|
bitrate INTEGER,
|
|
sample_rate INTEGER,
|
|
waveform_path VARCHAR(500), -- Legacy
|
|
cover_art_path VARCHAR(500), -- Legacy
|
|
status VARCHAR(20) DEFAULT 'uploading', -- Legacy status
|
|
status_message TEXT,
|
|
stream_status VARCHAR(20) DEFAULT 'pending', -- Legacy stream status (pending, processing, ready, error)
|
|
stream_manifest_url VARCHAR(500), -- Legacy stream manifest URL
|
|
is_public BOOLEAN DEFAULT true, -- Maps to visibility='public'
|
|
|
|
-- Timestamps
|
|
published_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ,
|
|
|
|
CONSTRAINT chk_tracks_duration_positive CHECK (duration >= 0) -- Permet 0 temporairement avant extraction métadonnées
|
|
);
|
|
|
|
-- Indexes
|
|
CREATE INDEX idx_tracks_creator_id ON public.tracks(creator_id);
|
|
CREATE INDEX idx_tracks_genre ON public.tracks(genre);
|
|
CREATE INDEX idx_tracks_visibility ON public.tracks(visibility);
|
|
CREATE INDEX idx_tracks_published_at_desc ON public.tracks(published_at DESC) WHERE published_at IS NOT NULL;
|
|
CREATE INDEX idx_tracks_play_count_desc ON public.tracks(play_count DESC);
|
|
CREATE INDEX idx_tracks_created_at_desc ON public.tracks(created_at DESC);
|
|
CREATE INDEX idx_tracks_search_gin ON public.tracks USING GIN(to_tsvector('english', title || ' ' || COALESCE(artist, '') || ' ' || COALESCE(album, '')));
|
|
|
|
-- === TRACK VERSIONS (Legacy/Go Support) ===
|
|
-- Origin doesn't strictly specify this, but code implies it. Keeping minimal.
|
|
CREATE TABLE public.track_versions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
track_id UUID NOT NULL REFERENCES public.tracks(id) ON DELETE CASCADE,
|
|
|
|
version_number INTEGER NOT NULL,
|
|
file_path VARCHAR(500) NOT NULL,
|
|
file_size BIGINT NOT NULL,
|
|
changelog TEXT,
|
|
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE INDEX idx_track_versions_track_id ON public.track_versions(track_id);
|
|
CREATE INDEX idx_track_versions_created_at ON public.track_versions(created_at DESC);
|
|
|
|
-- === PLAYLISTS ===
|
|
CREATE TABLE public.playlists (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
|
|
|
-- Playlist Info
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
|
|
-- Media
|
|
cover_url TEXT,
|
|
|
|
-- Properties
|
|
visibility public.visibility NOT NULL DEFAULT 'public',
|
|
is_collaborative BOOLEAN NOT NULL DEFAULT false,
|
|
|
|
-- Counts
|
|
track_count INTEGER NOT NULL DEFAULT 0,
|
|
duration_seconds INTEGER NOT NULL DEFAULT 0,
|
|
follower_count INTEGER NOT NULL DEFAULT 0,
|
|
|
|
-- Legacy
|
|
title VARCHAR(200), -- Maps to name
|
|
is_public BOOLEAN DEFAULT true, -- Maps to visibility
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
-- Indexes
|
|
CREATE INDEX idx_playlists_user_id ON public.playlists(user_id);
|
|
CREATE INDEX idx_playlists_visibility ON public.playlists(visibility);
|
|
CREATE INDEX idx_playlists_created_at_desc ON public.playlists(created_at DESC);
|
|
|
|
-- === PLAYLIST TRACKS (Junction) ===
|
|
CREATE TABLE public.playlist_tracks (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
playlist_id UUID NOT NULL REFERENCES public.playlists(id) ON DELETE CASCADE,
|
|
track_id UUID NOT NULL REFERENCES public.tracks(id) ON DELETE CASCADE,
|
|
|
|
-- Order
|
|
position INTEGER NOT NULL,
|
|
|
|
-- Metadata
|
|
added_by UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
|
added_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
|
|
CONSTRAINT uq_playlist_tracks_playlist_track UNIQUE (playlist_id, track_id)
|
|
);
|
|
|
|
CREATE INDEX idx_playlist_tracks_playlist_id_position ON public.playlist_tracks(playlist_id, position);
|
|
CREATE INDEX idx_playlist_tracks_track_id ON public.playlist_tracks(track_id);
|
|
CREATE INDEX idx_playlist_tracks_added_by ON public.playlist_tracks(added_by);
|
|
|
|
-- === PLAYLIST COLLABORATORS (Legacy/Lab) ===
|
|
CREATE TABLE public.playlist_collaborators (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
playlist_id UUID NOT NULL REFERENCES public.playlists(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
|
|
|
permission public.playlist_permission NOT NULL DEFAULT 'read',
|
|
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE INDEX idx_playlist_collaborators_playlist_id ON public.playlist_collaborators(playlist_id);
|
|
CREATE INDEX idx_playlist_collaborators_user_id ON public.playlist_collaborators(user_id);
|
|
|
|
-- === PLAYLIST FOLLOWS (Legacy/Lab - likely covered by 'follows' or custom logic) ===
|
|
CREATE TABLE public.playlist_follows (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
playlist_id UUID NOT NULL REFERENCES public.playlists(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
|
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE INDEX idx_playlist_follows_playlist_id ON public.playlist_follows(playlist_id);
|
|
CREATE INDEX idx_playlist_follows_user_id ON public.playlist_follows(user_id);
|
|
|
|
-- === QUEUES ===
|
|
CREATE TABLE public.queues (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE UNIQUE,
|
|
|
|
-- Current Track
|
|
current_track_id UUID REFERENCES public.tracks(id) ON DELETE SET NULL,
|
|
current_position INTEGER NOT NULL DEFAULT 0,
|
|
|
|
-- Playback State
|
|
is_playing BOOLEAN NOT NULL DEFAULT false,
|
|
shuffle BOOLEAN NOT NULL DEFAULT false,
|
|
repeat_mode VARCHAR(20) NOT NULL DEFAULT 'off',
|
|
volume INTEGER NOT NULL DEFAULT 100,
|
|
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE UNIQUE INDEX idx_queues_user_id ON public.queues(user_id);
|
|
|
|
-- === QUEUE ITEMS ===
|
|
CREATE TABLE public.queue_items (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
queue_id UUID NOT NULL REFERENCES public.queues(id) ON DELETE CASCADE,
|
|
track_id UUID NOT NULL REFERENCES public.tracks(id) ON DELETE CASCADE,
|
|
|
|
position INTEGER NOT NULL,
|
|
added_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_queue_items_queue_id_position ON public.queue_items(queue_id, position); |