-- Treat an invitation room as the account's initial room rather than an -- immutable lifetime binding. Room IDs remain unique across accounts so two -- listeners cannot accidentally claim the same upstream room. DROP TRIGGER IF EXISTS users_room_id_immutable ON users; DROP FUNCTION IF EXISTS prevent_user_room_id_change(); CREATE OR REPLACE FUNCTION enforce_live_source_account_room() RETURNS trigger LANGUAGE plpgsql SET search_path = pg_catalog, public AS $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM public.users WHERE id = NEW.owner_user_id AND room_id = NEW.room_id ) THEN RAISE EXCEPTION 'live source room_id must equal its owning account room_id'; END IF; IF TG_OP = 'UPDATE' AND NEW.owner_user_id IS DISTINCT FROM OLD.owner_user_id THEN RAISE EXCEPTION 'live source ownership is immutable'; END IF; RETURN NEW; END; $$; COMMENT ON COLUMN users.room_id IS 'Current account-level Bilibili room; initialized by invitation and user-switchable.'; COMMENT ON COLUMN live_sources.room_id IS 'Current room of the owning account; updated atomically with users.room_id.';