Files
rosterchirp-dev/backend/src/models/migrations/002_triggers_and_indexes.sql

97 lines
3.3 KiB
PL/PgSQL

-- Migration 002: updated_at auto-trigger + additional indexes
--
-- Adds a reusable Postgres trigger function that automatically sets
-- updated_at = NOW() on any UPDATE, eliminating the need to set it
-- manually in every route. Also adds a few missing indexes.
-- ── Auto-updated_at trigger function ─────────────────────────────────────────
CREATE OR REPLACE FUNCTION set_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Apply to all tables that have an updated_at column
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_users_updated_at') THEN
CREATE TRIGGER trg_users_updated_at
BEFORE UPDATE ON users
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
END IF;
END $$;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_groups_updated_at') THEN
CREATE TRIGGER trg_groups_updated_at
BEFORE UPDATE ON groups
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
END IF;
END $$;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_settings_updated_at') THEN
CREATE TRIGGER trg_settings_updated_at
BEFORE UPDATE ON settings
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
END IF;
END $$;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_user_groups_updated_at') THEN
CREATE TRIGGER trg_user_groups_updated_at
BEFORE UPDATE ON user_groups
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
END IF;
END $$;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_multi_group_dms_updated_at') THEN
CREATE TRIGGER trg_multi_group_dms_updated_at
BEFORE UPDATE ON multi_group_dms
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
END IF;
END $$;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_events_updated_at') THEN
CREATE TRIGGER trg_events_updated_at
BEFORE UPDATE ON events
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
END IF;
END $$;
-- ── Additional indexes ────────────────────────────────────────────────────────
-- Notifications: most queries filter by user + read status
CREATE INDEX IF NOT EXISTS idx_notifications_user_unread
ON notifications(user_id, is_read)
WHERE is_read = FALSE;
-- Sessions: lookup by user is common on logout / session cleanup
CREATE INDEX IF NOT EXISTS idx_sessions_user_id
ON sessions(user_id);
-- Active sessions: covered by PK (user_id, device) but explicit for clarity
CREATE INDEX IF NOT EXISTS idx_active_sessions_token
ON active_sessions(token);
-- Push subscriptions: lookup by user is the hot path
CREATE INDEX IF NOT EXISTS idx_push_subscriptions_user
ON push_subscriptions(user_id);
-- User group members: reverse lookup (which groups is a user in?)
CREATE INDEX IF NOT EXISTS idx_user_group_members_user
ON user_group_members(user_id);
-- Event availability: reverse lookup (which events has a user responded to?)
CREATE INDEX IF NOT EXISTS idx_event_availability_user
ON event_availability(user_id);
-- Events: filter by created_by (schedule manager views)
CREATE INDEX IF NOT EXISTS idx_events_type
ON events(event_type_id);