munin/internal/store/migrations/sqlite/005_papierkorb.sql

41 lines
2.5 KiB
SQL

-- Papierkorb: Löschen ist nicht mehr sofort endgültig (AUSBAUSTUFEN.md 3.9).
--
-- ── Warum? ───────────────────────────────────────────────────────────────────
--
-- Seit der Änderungshistorie (004) lässt sich jedes Überschreiben reparieren.
-- Löschen nicht: DELETE entfernte den Eintrag samt aller Fassungen (ON DELETE
-- CASCADE). Damit war "forget" der schlimmste Fall, den ein fehlgeleiteter
-- Agent anrichten konnte.
--
-- ── Aufbau ───────────────────────────────────────────────────────────────────
--
-- Löschen setzt jetzt nur noch deleted_at (Zeitpunkt) und deleted_by (Name des
-- Zugangs). Die Zeile bleibt mit Schlagworten, Verweisen und Verlauf stehen.
-- Endgültig entfernt wird sie erst, wenn ein Mensch den Papierkorb leert oder
-- die tägliche Aufgabe sie nach 30 Tagen abräumt — dann greift das bekannte
-- ON DELETE CASCADE.
--
-- deleted_at ist NULL für jeden normalen Eintrag. NULL statt eines leeren
-- Textes, weil "nicht gelöscht" kein Zeitpunkt ist — und weil sich
-- "deleted_at IS NULL" in jeder Abfrage eindeutig liest.
--
-- Jede lesende Abfrage auf entries braucht ab jetzt diese Bedingung. In Go
-- steht sie als Konstante (store.nichtImPapierkorb), damit sie sich leicht
-- finden lässt; ein Test prüft jeden lesenden Weg.
--
-- Der Bezeichner bleibt belegt, solange der Eintrag im Papierkorb liegt
-- (UNIQUE (project_id, slug) gilt weiter). Wer denselben Bezeichner neu
-- schreibt, holt den Eintrag zurück und überschreibt ihn — der Stand aus dem
-- Papierkorb wandert dabei in den Verlauf (siehe PutEntry).
ALTER TABLE entries ADD COLUMN deleted_at TEXT;
ALTER TABLE entries ADD COLUMN deleted_by TEXT NOT NULL DEFAULT '';
-- Ein Teilindex nur über die Einträge im Papierkorb. Er bleibt winzig, denn
-- dort liegt fast nie etwas, und bedient die drei Fragen, die nur den
-- Papierkorb betreffen: "was liegt im Papierkorb dieses Projekts" (Seite),
-- "was ist älter als die Frist" (tägliches Aufräumen) und "welche
-- Schlagworte gehören zu gelöschten Einträgen" (ListTags).
--
-- Teilindizes (CREATE INDEX … WHERE …) kennt PostgreSQL genauso — der Weg
-- dorthin bleibt offen.
CREATE INDEX idx_entries_papierkorb ON entries (project_id, deleted_at) WHERE deleted_at IS NOT NULL;