From c662df94c40d6acbc70d2f4a6cd31b639618d4de Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Mon, 18 May 2026 19:46:42 -0400 Subject: [PATCH] fix(db): add CHECK constraints, UNIQUE, and asset_id index to sequences schema --- .../mam-api/src/db/schema_patch_editor.sql | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/services/mam-api/src/db/schema_patch_editor.sql b/services/mam-api/src/db/schema_patch_editor.sql index b964860..476daf6 100644 --- a/services/mam-api/src/db/schema_patch_editor.sql +++ b/services/mam-api/src/db/schema_patch_editor.sql @@ -1,5 +1,5 @@ --- services/mam-api/src/db/schema_patch_editor.sql --- Run once against the Wild Dragon PostgreSQL database. +-- Wild Dragon MAM – Editor sequences schema patch +-- Run with: psql $DATABASE_URL -f schema_patch_editor.sql -- Named timelines within a project (multiple per project, like Premiere) CREATE TABLE IF NOT EXISTS sequences ( @@ -10,7 +10,8 @@ CREATE TABLE IF NOT EXISTS sequences ( width INTEGER NOT NULL DEFAULT 1920, height INTEGER NOT NULL DEFAULT 1080, created_at TIMESTAMPTZ DEFAULT NOW(), - updated_at TIMESTAMPTZ DEFAULT NOW() + updated_at TIMESTAMPTZ DEFAULT NOW(), + CONSTRAINT uq_sequences_project_name UNIQUE (project_id, name) ); CREATE INDEX IF NOT EXISTS idx_sequences_project_id ON sequences(project_id); @@ -21,15 +22,40 @@ CREATE TABLE IF NOT EXISTS sequence_clips ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), sequence_id UUID NOT NULL REFERENCES sequences ON DELETE CASCADE, asset_id UUID NOT NULL REFERENCES assets ON DELETE CASCADE, - track INTEGER NOT NULL DEFAULT 0, + track INTEGER NOT NULL DEFAULT 0 CHECK (track >= 0), -- track encoding: 0=V1, 1=V2, 100=A1, 101=A2 + -- Open-ended CHECK (track >= 0) used instead of an enumerated list so that + -- additional tracks can be added in the future without a schema migration. timeline_in_frames BIGINT NOT NULL, timeline_out_frames BIGINT NOT NULL, source_in_frames BIGINT NOT NULL DEFAULT 0, source_out_frames BIGINT NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW(), - updated_at TIMESTAMPTZ DEFAULT NOW() + updated_at TIMESTAMPTZ DEFAULT NOW(), + CONSTRAINT chk_timeline_range CHECK (timeline_out_frames > timeline_in_frames), + CONSTRAINT chk_source_range CHECK (source_out_frames > source_in_frames) ); -CREATE INDEX IF NOT EXISTS idx_sequence_clips_sequence_id ON sequence_clips(sequence_id); +CREATE INDEX IF NOT EXISTS idx_sequence_clips_sequence_id ON sequence_clips(sequence_id); CREATE INDEX IF NOT EXISTS idx_sequence_clips_track_position ON sequence_clips(sequence_id, track, timeline_in_frames); +CREATE INDEX IF NOT EXISTS idx_sequence_clips_asset_id ON sequence_clips(asset_id); + +-- --------------------------------------------------------------------------- +-- Idempotent ALTER TABLE block — applies the new constraints and index to +-- tables that were already created by an earlier run of this file. +-- Safe to re-run: ADD CONSTRAINT IF NOT EXISTS / CREATE INDEX IF NOT EXISTS. +-- --------------------------------------------------------------------------- + +ALTER TABLE sequences + ADD CONSTRAINT IF NOT EXISTS uq_sequences_project_name UNIQUE (project_id, name); + +ALTER TABLE sequence_clips + ADD CONSTRAINT IF NOT EXISTS chk_timeline_range CHECK (timeline_out_frames > timeline_in_frames); + +ALTER TABLE sequence_clips + ADD CONSTRAINT IF NOT EXISTS chk_source_range CHECK (source_out_frames > source_in_frames); + +ALTER TABLE sequence_clips + ADD CONSTRAINT IF NOT EXISTS chk_track_valid CHECK (track >= 0); + +CREATE INDEX IF NOT EXISTS idx_sequence_clips_asset_id ON sequence_clips(asset_id);