CREATE TABLE IF NOT EXISTS playlists ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, room_id BIGINT NOT NULL REFERENCES rooms(id) ON DELETE RESTRICT, creator_id BIGINT REFERENCES users(id) ON DELETE RESTRICT, name VARCHAR(255) NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', cover_file_reference_id BIGINT NULL REFERENCES file_references(id) ON DELETE SET NULL, parent_id BIGINT, position DOUBLE PRECISION NOT NULL, source_provider SMALLINT, source_config JSONB, provider_instance_name VARCHAR(64), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), version INTEGER NOT NULL DEFAULT 0, CONSTRAINT playlists_parent_not_self CHECK (parent_id IS NULL OR parent_id != id), CONSTRAINT playlists_source_fields_consistent CHECK ( (source_provider IS NOT NULL AND source_config IS NOT NULL) OR (source_provider IS NULL AND source_config IS NULL) ), CONSTRAINT playlists_source_config_object CHECK (source_config IS NULL OR jsonb_typeof(source_config) = 'object'), CONSTRAINT playlists_provider_instance_requires_source_provider CHECK ( provider_instance_name IS NULL OR source_provider IS NOT NULL ), CONSTRAINT playlists_provider_instance_fk FOREIGN KEY (provider_instance_name) REFERENCES media_provider_instances(name) ON DELETE RESTRICT, CONSTRAINT playlists_id_room_unique UNIQUE (id, room_id), CONSTRAINT playlists_parent_same_room_fk FOREIGN KEY (parent_id, room_id) REFERENCES playlists(id, room_id) ON DELETE RESTRICT ); CREATE INDEX IF NOT EXISTS idx_playlists_room ON playlists(room_id); CREATE INDEX IF NOT EXISTS idx_playlists_name_trgm ON playlists USING gin(name gin_trgm_ops); CREATE INDEX IF NOT EXISTS idx_playlists_description_trgm ON playlists USING gin(description gin_trgm_ops); CREATE INDEX IF NOT EXISTS idx_playlists_parent ON playlists(parent_id, position, id); CREATE INDEX IF NOT EXISTS idx_playlists_tree ON playlists(room_id, parent_id, position, id); CREATE INDEX IF NOT EXISTS idx_playlists_creator ON playlists(creator_id); CREATE INDEX IF NOT EXISTS idx_playlists_source_provider ON playlists(source_provider) WHERE source_provider IS NOT NULL; CREATE INDEX IF NOT EXISTS idx_playlists_provider_name ON playlists(provider_instance_name); CREATE INDEX IF NOT EXISTS idx_playlists_created_at ON playlists(created_at DESC); CREATE TRIGGER update_playlists_updated_at BEFORE UPDATE ON playlists FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();