-- --------------------------------------------------------------------------- -- HANDGESCHRIEBEN. Prisma hatte hier zusaetzlich sieben Loeschbefehle erzeugt: -- vier zusammengesetzte Fremdschluessel (Mandantengrenze) und drei -- Trigramm-Indizes (Archivsuche) aus der ersten Migration. Prisma kennt sie -- nicht, weil sie sich im Schema nicht ausdruecken lassen, und will sie deshalb -- bei jeder Migration entfernen. Die Loeschbefehle sind bewusst gestrichen. -- -- tests/datenbankregeln.test.ts prueft, dass alle diese Objekte vorhanden sind – -- ein versehentlich stehengelassener Loeschbefehl faellt dort sofort auf. -- --------------------------------------------------------------------------- -- Stand des Entwurfs, gegen den der Editor beim Speichern prueft. ALTER TABLE "VorlagenVersion" ADD COLUMN "geaendertAm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; -- --------------------------------------------------------------------------- -- Eine veroeffentlichte Version ist unveraenderlich. -- -- Diese Regel traegt die Nachvollziehbarkeit des ganzen Archivs: ein Lauf zeigt -- auch in zehn Jahren genau die Schritte, die damals abgearbeitet wurden. -- Bisher stand sie nur in der Service-Schicht — Migrationen, psql, Skripte und -- ab Phase 4 die Connectoren schreiben daran vorbei. Deshalb steht sie jetzt -- auch hier. -- -- TRUNCATE loest Zeilen-Trigger nicht aus; das Leeren der Testdatenbank bleibt -- also moeglich. -- --------------------------------------------------------------------------- CREATE OR REPLACE FUNCTION laufzettel_version_unveraenderlich() RETURNS trigger AS $$ DECLARE betroffene_version TEXT; aktueller_status TEXT; BEGIN betroffene_version := COALESCE(NEW."versionId", OLD."versionId"); SELECT status::TEXT INTO aktueller_status FROM "VorlagenVersion" WHERE id = betroffene_version; IF aktueller_status = 'VEROEFFENTLICHT' THEN RAISE EXCEPTION 'Version % ist veroeffentlicht und unveraenderlich (%).', betroffene_version, TG_TABLE_NAME USING ERRCODE = 'integrity_constraint_violation'; END IF; RETURN COALESCE(NEW, OLD); END; $$ LANGUAGE plpgsql; CREATE TRIGGER "VorlagenAbschnitt_unveraenderlich" BEFORE INSERT OR UPDATE OR DELETE ON "VorlagenAbschnitt" FOR EACH ROW EXECUTE FUNCTION laufzettel_version_unveraenderlich(); CREATE TRIGGER "VorlagenVariable_unveraenderlich" BEFORE INSERT OR UPDATE OR DELETE ON "VorlagenVariable" FOR EACH ROW EXECUTE FUNCTION laufzettel_version_unveraenderlich(); -- Schritte haengen ueber den Abschnitt an der Version, brauchen also den Umweg. CREATE OR REPLACE FUNCTION laufzettel_schritt_unveraenderlich() RETURNS trigger AS $$ DECLARE aktueller_status TEXT; BEGIN SELECT v.status::TEXT INTO aktueller_status FROM "VorlagenAbschnitt" a JOIN "VorlagenVersion" v ON v.id = a."versionId" WHERE a.id = COALESCE(NEW."abschnittId", OLD."abschnittId"); IF aktueller_status = 'VEROEFFENTLICHT' THEN RAISE EXCEPTION 'Der Abschnitt gehoert zu einer veroeffentlichten Version und ist unveraenderlich.' USING ERRCODE = 'integrity_constraint_violation'; END IF; RETURN COALESCE(NEW, OLD); END; $$ LANGUAGE plpgsql; CREATE TRIGGER "VorlagenSchritt_unveraenderlich" BEFORE INSERT OR UPDATE OR DELETE ON "VorlagenSchritt" FOR EACH ROW EXECUTE FUNCTION laufzettel_schritt_unveraenderlich(); -- Der Weg zurueck von VEROEFFENTLICHT nach ENTWURF waere die Hintertuer, durch -- die sich alles Obige aushebeln liesse. CREATE OR REPLACE FUNCTION laufzettel_version_status_einbahn() RETURNS trigger AS $$ BEGIN IF OLD.status = 'VEROEFFENTLICHT' AND NEW.status <> 'VEROEFFENTLICHT' THEN RAISE EXCEPTION 'Eine veroeffentlichte Version laesst sich nicht wieder zum Entwurf machen.' USING ERRCODE = 'integrity_constraint_violation'; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER "VorlagenVersion_status_einbahn" BEFORE UPDATE ON "VorlagenVersion" FOR EACH ROW EXECUTE FUNCTION laufzettel_version_status_einbahn();