EXPLAIN ANALYZE fails on INSERT ... ON CONFLICT: ON CONFLICT Tuples Inserted/Conflicting Tuples need ntuples2 accounting
pgrust version: 0.2 (binary pgrust-0.2-linux-x86_64, PostgreSQL 18 compatible)
Component: show_modifytable_info() in explain.c (ModifyTable instrument, ntuples2)
Summary
EXPLAIN ANALYZE on any INSERT ... ON CONFLICT statement fails during plan display. pgrust's show_modifytable_info() needs the ntuples2 accounting from nodeModifyTable.c instrumentation (tuples inserted vs. tuples that hit the conflict path) and that counter is not wired up, so EXPLAIN aborts instead of printing the plan.
Reproducer
CREATE TABLE t (id int PRIMARY KEY, v int);
EXPLAIN (ANALYZE) INSERT INTO t (id, v) VALUES (1, 1)
ON CONFLICT (id) DO UPDATE SET v = EXCLUDED.v;
Also reproduces with ON CONFLICT DO NOTHING — any ON CONFLICT clause is enough.
Expected behaviour
A normal query plan like PostgreSQL 18.6 produces, including a Tuples Inserted / Tuples Conflicted breakdown on the Insert node.
Actual behaviour
ERROR: show_modifytable_info (explain.c): ON CONFLICT Tuples Inserted/Conflicting Tuples need ntuples2 accounting nodeModifyTable instrument)
No plan is printed. There is no workaround — removing ANALYZE avoids the failure but then no execution stats (the reason you use EXPLAIN ANALYZE)
appear.
Notes
- Independent of
VERBOSE/BUFFERS/WAL; ANALYZE alone is sufficient.
- Also breaks
DO NOTHING, not just DO UPDATE.
- This blocks
EXPLAIN (ANALYZE) on any upsert, a very common write pattern.
EXPLAIN ANALYZE fails on
INSERT ... ON CONFLICT:ON CONFLICT Tuples Inserted/Conflicting Tuples need ntuples2 accountingpgrust version: 0.2 (binary
pgrust-0.2-linux-x86_64, PostgreSQL 18 compatible)Component:
show_modifytable_info()inexplain.c(ModifyTable instrument,ntuples2)Summary
EXPLAIN ANALYZEon anyINSERT ... ON CONFLICTstatement fails during plan display. pgrust'sshow_modifytable_info()needs thentuples2accounting fromnodeModifyTable.cinstrumentation (tuples inserted vs. tuples that hit the conflict path) and that counter is not wired up, so EXPLAIN aborts instead of printing the plan.Reproducer
Also reproduces with
ON CONFLICT DO NOTHING— anyON CONFLICTclause is enough.Expected behaviour
A normal query plan like PostgreSQL 18.6 produces, including a
Tuples Inserted/Tuples Conflictedbreakdown on theInsertnode.Actual behaviour
No plan is printed. There is no workaround — removing
ANALYZEavoids the failure but then no execution stats (the reason you useEXPLAIN ANALYZE)appear.
Notes
VERBOSE/BUFFERS/WAL;ANALYZEalone is sufficient.DO NOTHING, not justDO UPDATE.EXPLAIN (ANALYZE)on any upsert, a very common write pattern.