pub const CREATE_CONCEPTS_GUARD_DELETE: &str = "\n CREATE TRIGGER IF NOT EXISTS trg_concepts_guard_delete\n BEFORE DELETE ON concepts\n WHEN NOT EXISTS (\n SELECT 1 FROM sqlite_master\n WHERE type = \'table\' AND name = \'macrame_archive_session\'\n )\n BEGIN\n SELECT RAISE(ABORT, \'macrame: physical delete blocked outside archive session\');\n END;\n ";Expand description
The concepts delete guard, marker-gated since v9 (0.9.0, C2, D-126).
A pub const rather than an anonymous entry in CREATE_TRIGGERS because
two readers need exactly this text: the baseline, which installs it on a new
database, and the v8 → v9 rung, which replaces the v8 body on an existing
one. A second copy is a copy that drifts, and this trigger is the one whose
body carries a doctrine decision.
§What changed, and why re-issuing the baseline could not do it
Through v8 this guard was unconditional: BEFORE DELETE ON concepts
aborting every time, on the reasoning that concepts are never physically
archived (D-022). C2
makes that false — a declared archive session may now move a retired,
unreferenced concept to the cold file — so the guard takes the same shape its
two siblings have had since 0.5.3: it fires unless the archive-session
marker is present.
It needs a rung of its own, and that was measured rather than assumed
(D-126). CREATE TRIGGER IF NOT EXISTS on an existing name keeps the old
body — re-issuing the baseline against a v8 database leaves the
unconditional guard exactly where it was — and verify compared type and
name and never bodies, so the stale guard passed verification in silence.
Both halves are now closed: the rung drops and recreates, and verify
checks that every delete guard’s body probes the marker.