Triggers that aren't idempotent across no-op updates
Problem
Section titled “Problem”A trigger sets tickets.resolved_at = now() when a ticket is resolved. A few weeks later, an agent edits the subject of an already-resolved ticket to fix a typo. The resolved_at jumps forward by three weeks. SLA reporting silently breaks.
The code
Section titled “The code”Why review misses it
Section titled “Why review misses it”The trigger reads as “when a ticket is resolved, set the timestamp.” Reviewers think in terms of the resolve action, not in terms of every future edit that happens to leave the status set to 'resolved'.
The example test that passes
Section titled “The example test that passes”Tests the transition; doesn’t test the no-op update.
The SqlProof property
Section titled “The SqlProof property”The phrasing is “applying the update does not change resolved_at” — an idempotency property: doing the operation N times should equal doing it once (and zero times changes nothing).
The counterexample
Section titled “The counterexample”Illustrative — Hypothesis would print the actual draw and assertion:
The fix
Section titled “The fix”Check that the status transitioned into 'resolved':