d58b939e1c
attach_agnostic_triggers(schema) recria nos schemas os triggers de public cuja funcao e provadamente schema-agnostica (so mexe em NEW/OLD): familia updated_at (8: set_updated_at, fn_clinical_notes_updated_at, set_insurance_plans/medicos/ services_updated_at, set_updated_at_recurrence, update_payment_settings/ professional_pricing_updated_at) + prevent_promoting_to_system + prevent_system_group_changes. Backfill dos 9 (54 triggers/schema). Smoke: set_updated_at dispara no schema. Schema-aware vem no Lote B; wiring no clone no fim da F6.2 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
77 lines
3.1 KiB
PL/PgSQL
77 lines
3.1 KiB
PL/PgSQL
-- =============================================================================
|
|
-- F6.2 Lote A — anexa triggers schema-agnósticos aos schemas tenant
|
|
--
|
|
-- O clone (LIKE INCLUDING ALL) NÃO copia triggers. As tabelas tenant nos
|
|
-- schemas precisam dos triggers de negócio. Lote A: os PROVADAMENTE
|
|
-- schema-agnósticos (só mexem em NEW/OLD, não referenciam outras tabelas) —
|
|
-- seguros pra anexar sem reescrever a função:
|
|
-- família updated_at (8) + prevent_promoting_to_system +
|
|
-- prevent_system_group_changes
|
|
-- Os schema-aware (financeiro/audit/notif/timeline/sync) vêm no Lote B.
|
|
--
|
|
-- attach_agnostic_triggers(schema) recria, no schema dado, os triggers de
|
|
-- public cuja função está na whitelist agnóstica. A função do trigger continua
|
|
-- sendo a de public (agnóstica → funciona em qualquer schema). Backfill dos 9;
|
|
-- o wiring no clone_tenant_template acontece no fim da F6.2 (com todos prontos).
|
|
-- =============================================================================
|
|
|
|
BEGIN;
|
|
|
|
CREATE OR REPLACE FUNCTION public.attach_agnostic_triggers(p_schema text)
|
|
RETURNS int
|
|
LANGUAGE plpgsql
|
|
SECURITY DEFINER
|
|
SET search_path TO 'public', 'pg_temp'
|
|
AS $$
|
|
DECLARE
|
|
agnostic text[] := ARRAY[
|
|
'set_updated_at','fn_clinical_notes_updated_at','set_insurance_plans_updated_at',
|
|
'set_medicos_updated_at','set_services_updated_at','set_updated_at_recurrence',
|
|
'update_payment_settings_updated_at','update_professional_pricing_updated_at',
|
|
'prevent_promoting_to_system','prevent_system_group_changes'
|
|
];
|
|
r record;
|
|
v_def text;
|
|
v_count int := 0;
|
|
BEGIN
|
|
IF p_schema NOT LIKE 'tenant\_%' THEN
|
|
RAISE EXCEPTION 'attach_agnostic_triggers: schema inválido %', p_schema;
|
|
END IF;
|
|
|
|
FOR r IN
|
|
SELECT c.relname AS tab, t.tgname, pg_get_triggerdef(t.oid) AS def
|
|
FROM pg_trigger t
|
|
JOIN pg_class c ON c.oid = t.tgrelid
|
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
JOIN pg_proc p ON p.oid = t.tgfoid
|
|
WHERE n.nspname = 'public' AND NOT t.tgisinternal
|
|
AND p.proname = ANY(agnostic)
|
|
AND EXISTS (SELECT 1 FROM information_schema.tables
|
|
WHERE table_schema = p_schema AND table_name = c.relname)
|
|
LOOP
|
|
-- redireciona o ON public.<tab> pro schema do tenant (a função fica em public)
|
|
v_def := replace(r.def, 'ON public.' || r.tab || ' ', 'ON ' || p_schema || '.' || r.tab || ' ');
|
|
IF v_def = r.def THEN
|
|
RAISE EXCEPTION 'attach_agnostic_triggers: não consegui redirecionar % (%.%)', r.tgname, p_schema, r.tab;
|
|
END IF;
|
|
EXECUTE format('DROP TRIGGER IF EXISTS %I ON %I.%I', r.tgname, p_schema, r.tab);
|
|
EXECUTE v_def;
|
|
v_count := v_count + 1;
|
|
END LOOP;
|
|
|
|
RETURN v_count;
|
|
END;
|
|
$$;
|
|
|
|
-- Backfill dos 9 schemas existentes
|
|
DO $$
|
|
DECLARE r record; v int;
|
|
BEGIN
|
|
FOR r IN SELECT schema_name FROM public.tenant_schemas ORDER BY schema_name LOOP
|
|
v := public.attach_agnostic_triggers(r.schema_name);
|
|
RAISE NOTICE 'F6.2A %: % triggers agnósticos', r.schema_name, v;
|
|
END LOOP;
|
|
END $$;
|
|
|
|
COMMIT;
|