-- Catalog row timestamps for dev/prod harmonize (last-write-wins merge). -- Idempotent: safe to re-run on existing databases. CREATE OR REPLACE FUNCTION sync_touch_updated_at() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = now(); RETURN NEW; END; $$ LANGUAGE plpgsql; DO $$ DECLARE tbl TEXT; BEGIN FOREACH tbl IN ARRAY ARRAY[ 'historical_eras', 'art_movements', 'artists', 'artist_periods', 'paintings', 'painting_influences', 'painting_influence_sources', 'painting_annotations', 'tour_stops' ] LOOP -- Skip tables not created yet (e.g. tour_stops before migrate-tours.sql). IF to_regclass(format('public.%I', tbl)) IS NULL THEN CONTINUE; END IF; EXECUTE format( 'ALTER TABLE %I ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT now()', tbl ); EXECUTE format('DROP TRIGGER IF EXISTS %I ON %I', tbl || '_updated_at', tbl); EXECUTE format( 'CREATE TRIGGER %I BEFORE UPDATE ON %I FOR EACH ROW EXECUTE PROCEDURE sync_touch_updated_at()', tbl || '_updated_at', tbl ); END LOOP; END $$;