97 lines
3.3 KiB
PL/PgSQL
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);
|