Per-row BEFORE INSERT
triggers are fired, and possible effects on the proposed row applied, before checking for conflicts. The manual:
Note that the effects of all per-row BEFORE INSERT
triggers are
reflected in excluded values, since those effects may have contributed
to the row being excluded from insertion.
A plain INSERT
would raise an EXCEPTION
because of the unique violation, and that rolls back everything (except what cannot be rolled back, like incrementing a sequence).
But the UPSERT with ON CONFLICT DO NOTHING
suppresses the exception, hence the effects of any such triggers persist, even if the row proposed for insertion is skipped.
(Consequently, when using ON CONFLICT DO UPDATE ...
, effects of such triggers are reflected in the special EXCLUDED
row that's visible in the UPDATE
part.)
But AFTER INSERT
triggers are not even fired for either case. The row is never actually inserted - with or without raising an exception.
I thought of using a RULE
instead, which can rewrite an INSERT
to run additional commands, independent of the outcome. More tricky than a trigger, but it kicks in before the INSERT
might be cancelled. However, the manual warns:
Note that an INSERT
containing an ON CONFLICT
clause cannot be used on
tables that have either INSERT
or UPDATE
rules. Consider using an
updatable view instead.
So, no dice.