49 lines
2.1 KiB
PL/PgSQL
49 lines
2.1 KiB
PL/PgSQL
-- Incremental hardening; no records or application tables are copied.
|
|
BEGIN;
|
|
SET LOCAL lock_timeout = '10s';
|
|
SELECT pg_advisory_xact_lock(290926, 170003);
|
|
DO $indexes$
|
|
DECLARE fk record; index_name text;
|
|
BEGIN
|
|
FOR fk IN
|
|
SELECT c.conrelid, c.conkey, c.conname, t.relname,
|
|
(SELECT string_agg(quote_ident(a.attname), ', ' ORDER BY k.position)
|
|
FROM unnest(c.conkey) WITH ORDINALITY k(attnum, position)
|
|
JOIN pg_attribute a ON a.attrelid=c.conrelid AND a.attnum=k.attnum) AS columns
|
|
FROM pg_constraint c JOIN pg_class t ON t.oid=c.conrelid
|
|
JOIN pg_namespace n ON n.oid=t.relnamespace
|
|
WHERE n.nspname='mne' AND c.contype='f'
|
|
ORDER BY t.relname,c.conname
|
|
LOOP
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM pg_index i JOIN pg_class ix ON ix.oid=i.indexrelid
|
|
JOIN pg_am am ON am.oid=ix.relam
|
|
WHERE i.indrelid=fk.conrelid AND i.indisvalid AND i.indisready
|
|
AND i.indpred IS NULL AND am.amname='btree'
|
|
AND i.indnkeyatts >= cardinality(fk.conkey)
|
|
AND ARRAY(SELECT x FROM unnest(i.indkey::smallint[]) WITH ORDINALITY u(x,p)
|
|
WHERE p <= cardinality(fk.conkey) ORDER BY p)=fk.conkey
|
|
) THEN
|
|
index_name := 'ix_mne_003_' || md5(fk.relname || ':' || fk.conname);
|
|
EXECUTE format('CREATE INDEX %I ON mne.%I (%s)', index_name, fk.relname, fk.columns);
|
|
EXECUTE format('COMMENT ON INDEX mne.%I IS %L', index_name, 'Owned by 003_mne_integrity');
|
|
END IF;
|
|
END LOOP;
|
|
END $indexes$;
|
|
|
|
CREATE OR REPLACE FUNCTION mne.reject_evidence_mutation() RETURNS trigger
|
|
LANGUAGE plpgsql SET search_path = pg_catalog AS $guard$
|
|
BEGIN
|
|
RAISE EXCEPTION 'MNE evidence is append-only: %.%', TG_TABLE_SCHEMA, TG_TABLE_NAME
|
|
USING ERRCODE = '23514';
|
|
END $guard$;
|
|
|
|
DO $triggers$
|
|
DECLARE table_name text;
|
|
BEGIN
|
|
FOREACH table_name IN ARRAY ARRAY['audit_events','business_status_history','document_versions','negotiation_events'] LOOP
|
|
EXECUTE format('CREATE OR REPLACE TRIGGER mne_evidence_immutable BEFORE UPDATE OR DELETE OR TRUNCATE ON mne.%I FOR EACH STATEMENT EXECUTE FUNCTION mne.reject_evidence_mutation()', table_name);
|
|
END LOOP;
|
|
END $triggers$;
|
|
COMMIT;
|