You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
synctv/migrations/20260426010_create_rooms.sql

110 lines
5.0 KiB
SQL

CREATE TABLE IF NOT EXISTS room_categories (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
key TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
sort_order INTEGER NOT NULL DEFAULT 0,
is_enabled BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT room_categories_key_not_empty
CHECK (length(trim(key)) > 0),
CONSTRAINT room_categories_key_format
CHECK (key ~ '^[a-z0-9][a-z0-9_-]{0,63}$'),
CONSTRAINT room_categories_name_not_empty
CHECK (length(trim(name)) > 0),
CONSTRAINT room_categories_name_length
CHECK (char_length(name) <= 80),
CONSTRAINT room_categories_description_length
CHECK (char_length(description) <= 300)
);
INSERT INTO room_categories (key, name, description, sort_order, is_enabled)
VALUES ('general', 'General', 'General rooms', 0, TRUE)
ON CONFLICT (key) DO NOTHING;
CREATE TABLE IF NOT EXISTS rooms (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
cover_file_reference_id BIGINT NULL REFERENCES file_references(id) ON DELETE SET NULL,
category_id BIGINT NULL REFERENCES room_categories(id) ON DELETE SET NULL,
created_by BIGINT NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
closed_at TIMESTAMPTZ NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMPTZ NULL,
version INTEGER NOT NULL DEFAULT 0,
last_activity_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS room_labels (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
key TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
color TEXT NOT NULL DEFAULT '',
category_id BIGINT NULL REFERENCES room_categories(id) ON DELETE SET NULL,
sort_order INTEGER NOT NULL DEFAULT 0,
is_enabled BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT room_labels_key_not_empty
CHECK (length(trim(key)) > 0),
CONSTRAINT room_labels_key_format
CHECK (key ~ '^[a-z0-9][a-z0-9_-]{0,63}$'),
CONSTRAINT room_labels_name_not_empty
CHECK (length(trim(name)) > 0),
CONSTRAINT room_labels_name_length
CHECK (char_length(name) <= 80),
CONSTRAINT room_labels_description_length
CHECK (char_length(description) <= 300),
CONSTRAINT room_labels_color_format
CHECK (color = '' OR color ~ '^#[0-9A-Fa-f]{6}$')
);
CREATE TABLE IF NOT EXISTS room_label_assignments (
room_id BIGINT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
label_id BIGINT NOT NULL REFERENCES room_labels(id) ON DELETE RESTRICT,
assigned_by BIGINT NULL REFERENCES users(id) ON DELETE SET NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (room_id, label_id)
);
CREATE INDEX IF NOT EXISTS idx_room_categories_enabled_order
ON room_categories(is_enabled, sort_order, id);
CREATE INDEX IF NOT EXISTS idx_room_labels_enabled_order
ON room_labels(is_enabled, sort_order, id);
CREATE INDEX IF NOT EXISTS idx_room_labels_category_order
ON room_labels(category_id, sort_order, id);
CREATE INDEX IF NOT EXISTS idx_room_label_assignments_label_room
ON room_label_assignments(label_id, room_id);
CREATE INDEX IF NOT EXISTS idx_rooms_created_by ON rooms(created_by);
CREATE INDEX IF NOT EXISTS idx_rooms_category_created_at ON rooms(category_id, created_at DESC) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_rooms_category_last_activity ON rooms(category_id, last_activity_at DESC) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_rooms_closed_at ON rooms(closed_at) WHERE closed_at IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_rooms_deleted_at ON rooms(deleted_at) WHERE deleted_at IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_rooms_name_trgm ON rooms USING gin(name gin_trgm_ops) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_rooms_description_trgm ON rooms USING gin(description gin_trgm_ops) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_rooms_last_activity ON rooms(last_activity_at) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_rooms_created_at ON rooms(created_at DESC) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_rooms_creator_created_at ON rooms(created_by, created_at DESC) WHERE deleted_at IS NULL;
CREATE TRIGGER update_room_categories_updated_at
BEFORE UPDATE ON room_categories
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_rooms_updated_at
BEFORE UPDATE ON rooms
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_room_labels_updated_at
BEFORE UPDATE ON room_labels
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();