Skip to content

Catch "1 row reported, 301 committed"

By the end you’ll have seen the same UPDATE sealed twice: once Proven ·Matches, and once, with a trigger on, Proven ·Doesn’t match with the 301 rows Postgres actually changed.

Before you start

  • A Postgres connector with witness.enabled: true and wal_level = logical. The Quickstart stack has one.
  • psql access to the database as an owner, to add a trigger.
Terminal window
deedglass act postgres.execute --args '{"sql":"UPDATE public.orders SET status = '"'"'shipped'"'"' WHERE id = 42"}'

The agent reports one row. Postgres’s change log shows one row of public.orders changed in that transaction. Verdict: L2 · VERIFIED.

As the database owner
CREATE FUNCTION public.ship_open_batch() RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
IF NEW.status = 'shipped' THEN
UPDATE public.orders SET status = 'shipped' WHERE status = 'paid' AND id <> NEW.id;
END IF;
RETURN NEW;
END $$;
CREATE TRIGGER orders_ship_open_batch AFTER UPDATE OF status ON public.orders
FOR EACH ROW WHEN (pg_trigger_depth() = 0) EXECUTE FUNCTION public.ship_open_batch();

Run the same UPDATE on another paid order. The tool still answers UPDATE 1. The Witness reads the transaction from the change log and finds 301 changed rows:

L2 · MISMATCH · Postgres changed 301 rows in public.orders. The agent reported 1.

deedglass actions show <act_…> --diff prints the expected and observed rows side by side. Console › Actions shows the same diff, with changed cells highlighted.

The agent didn’t lie: the tool really did report one row. The extra 300 came from the database itself. Only a check against the system of record sees it.

  • L2 sees the watched tables only. A trigger that writes to an unwatched table, or calls out of Postgres, isn’t seen.
  • Deedglass sees what the trigger did, not its code.
  • A MISMATCH doesn’t roll anything back. The change committed. Undo a bad write puts the rows back.