ALTER TABLE topics ADD COLUMN icon_name TEXT NOT NULL DEFAULT ''; ALTER TABLE pieces ADD COLUMN deleted_at_utc TEXT; ALTER TABLE piece_media ADD COLUMN removed_at_utc TEXT; CREATE TABLE piece_presentation_media ( piece_id TEXT PRIMARY KEY REFERENCES pieces(id) ON DELETE CASCADE, media_id TEXT NOT NULL UNIQUE REFERENCES piece_media(id) ON DELETE RESTRICT ); CREATE TRIGGER validate_piece_presentation_media_insert BEFORE INSERT ON piece_presentation_media WHEN NOT EXISTS ( SELECT 1 FROM piece_media WHERE id = NEW.media_id AND piece_id = NEW.piece_id AND removed_at_utc IS NULL ) BEGIN SELECT RAISE(ABORT, 'presentation media does not belong to piece'); END; CREATE TRIGGER validate_piece_presentation_media_update BEFORE UPDATE ON piece_presentation_media WHEN NOT EXISTS ( SELECT 1 FROM piece_media WHERE id = NEW.media_id AND piece_id = NEW.piece_id AND removed_at_utc IS NULL ) BEGIN SELECT RAISE(ABORT, 'presentation media does not belong to piece'); END; ALTER TABLE usage_topic_snapshots ADD COLUMN icon_name TEXT NOT NULL DEFAULT ''; CREATE TABLE usage_media_snapshots ( id TEXT PRIMARY KEY, usage_id TEXT NOT NULL REFERENCES piece_usages(id) ON DELETE CASCADE, original_media_id TEXT NOT NULL REFERENCES piece_media(id) ON DELETE RESTRICT, alt_text TEXT NOT NULL DEFAULT '', position INTEGER NOT NULL CHECK (position >= 0), is_presentation INTEGER NOT NULL DEFAULT 0 CHECK (is_presentation IN (0, 1)), UNIQUE (usage_id, position) ); CREATE INDEX idx_pieces_deleted_at ON pieces(deleted_at_utc); CREATE INDEX idx_piece_media_active ON piece_media(piece_id, position) WHERE removed_at_utc IS NULL; CREATE INDEX idx_usage_media_usage ON usage_media_snapshots(usage_id, position); CREATE UNIQUE INDEX idx_one_presentation_media_per_usage ON usage_media_snapshots(usage_id) WHERE is_presentation = 1;