Files
media-map/backend/alembic/versions/001_initial_schema.py
Danilo Reyes 96fcc2b9e8 init
2025-12-28 20:59:09 -06:00

134 lines
4.4 KiB
Python

"""Initial schema
Revision ID: 001
Revises:
Create Date: 2024-01-01 00:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '001'
down_revision = None
branch_labels = None
depends_on = None
def upgrade() -> None:
# Create schema
op.execute("CREATE SCHEMA IF NOT EXISTS moviemap")
# Create enums
op.execute("""
DO $$ BEGIN
CREATE TYPE moviemap.source_kind AS ENUM ('radarr', 'sonarr', 'lidarr');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
""")
op.execute("""
DO $$ BEGIN
CREATE TYPE moviemap.media_type AS ENUM ('movie', 'show', 'music');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
""")
op.execute("""
DO $$ BEGIN
CREATE TYPE moviemap.watched_media_type AS ENUM ('movie', 'show');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
""")
# Create source table
op.execute("""
CREATE TABLE IF NOT EXISTS moviemap.source (
id SERIAL PRIMARY KEY,
kind moviemap.source_kind NOT NULL UNIQUE,
base_url TEXT NOT NULL,
enabled BOOLEAN NOT NULL DEFAULT true,
last_sync_at TIMESTAMPTZ
)
""")
# Create media_item table
op.execute("""
CREATE TABLE IF NOT EXISTS moviemap.media_item (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
source_kind moviemap.source_kind NOT NULL,
source_item_id INTEGER NOT NULL,
title TEXT NOT NULL,
year INTEGER,
media_type moviemap.media_type NOT NULL,
arr_raw JSONB,
UNIQUE (source_kind, source_item_id)
)
""")
# Create media_country table
op.execute("""
CREATE TABLE IF NOT EXISTS moviemap.media_country (
media_item_id UUID NOT NULL REFERENCES moviemap.media_item(id) ON DELETE CASCADE,
country_code CHAR(2) NOT NULL,
weight SMALLINT NOT NULL DEFAULT 1,
PRIMARY KEY (media_item_id, country_code)
)
""")
# Create watched_item table
op.execute("""
CREATE TABLE IF NOT EXISTS moviemap.watched_item (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
media_type moviemap.watched_media_type NOT NULL,
title TEXT NOT NULL,
year INTEGER,
country_code CHAR(2) NOT NULL,
watched_at TIMESTAMPTZ,
notes TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
)
""")
# Create manual_pin table
op.execute("""
CREATE TABLE IF NOT EXISTS moviemap.manual_pin (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
country_code CHAR(2) NOT NULL,
label TEXT,
pinned_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
)
""")
# Create indexes
op.execute("CREATE INDEX IF NOT EXISTS idx_media_item_source ON moviemap.media_item (source_kind, source_item_id)")
op.execute("CREATE INDEX IF NOT EXISTS idx_media_country_code ON moviemap.media_country (country_code)")
op.execute("CREATE INDEX IF NOT EXISTS idx_watched_country ON moviemap.watched_item (country_code)")
op.execute("CREATE INDEX IF NOT EXISTS idx_watched_media_type ON moviemap.watched_item (media_type)")
op.execute("CREATE INDEX IF NOT EXISTS idx_pin_country ON moviemap.manual_pin (country_code)")
def downgrade() -> None:
op.execute("DROP INDEX IF EXISTS moviemap.idx_pin_country")
op.execute("DROP INDEX IF EXISTS moviemap.idx_watched_media_type")
op.execute("DROP INDEX IF EXISTS moviemap.idx_watched_country")
op.execute("DROP INDEX IF EXISTS moviemap.idx_media_country_code")
op.execute("DROP INDEX IF EXISTS moviemap.idx_media_item_source")
op.execute("DROP TABLE IF EXISTS moviemap.manual_pin")
op.execute("DROP TABLE IF EXISTS moviemap.watched_item")
op.execute("DROP TABLE IF EXISTS moviemap.media_country")
op.execute("DROP TABLE IF EXISTS moviemap.media_item")
op.execute("DROP TABLE IF EXISTS moviemap.source")
op.execute("DROP TYPE IF EXISTS moviemap.watched_media_type")
op.execute("DROP TYPE IF EXISTS moviemap.media_type")
op.execute("DROP TYPE IF EXISTS moviemap.source_kind")
op.execute("DROP SCHEMA IF EXISTS moviemap")