Change trigger type to AFTER trigger.

During repacking table, if a transaction executes INSERT CONFLICT
ON UPDATE/DO NOTHING, because we define BEFORE trigger on target
table, the contents of operation log table becomes inconsistent
easliy. As a result, pg_reapck fails with a high probability.

To resolve this issue, this changes the trigger type from BEFORE
to AFTER. We define AFTER trigger that is the first of the AFTER
trigger to fire on the table.
This commit is contained in:
Masahiko Sawada
2017-01-19 13:47:18 +09:00
parent e1056c003c
commit d83ee3d6a0
7 changed files with 43 additions and 43 deletions

View File

@ -151,7 +151,7 @@ repack_trigger(PG_FUNCTION_ARGS)
/* make sure it's called as a trigger at all */
if (!CALLED_AS_TRIGGER(fcinfo) ||
!TRIGGER_FIRED_BEFORE(trigdata->tg_event) ||
!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event) ||
trigdata->tg_trigger->tgnargs != 1)
elog(ERROR, "repack_trigger: invalid trigger call");
@ -921,7 +921,7 @@ repack_swap(PG_FUNCTION_ARGS)
/* drop repack trigger */
execute_with_format(
SPI_OK_UTILITY,
"DROP TRIGGER IF EXISTS z_repack_trigger ON %s.%s CASCADE",
"DROP TRIGGER IF EXISTS a_repack_trigger ON %s.%s CASCADE",
nspname, relname);
SPI_finish();
@ -962,7 +962,7 @@ repack_drop(PG_FUNCTION_ARGS)
* To prevent concurrent lockers of the repack target table from causing
* deadlocks, take an exclusive lock on it. Consider that the following
* commands take exclusive lock on tables log_xxx and the target table
* itself when deleting the z_repack_trigger on it, while concurrent
* itself when deleting the a_repack_trigger on it, while concurrent
* updaters require row exclusive lock on the target table and in
* addition, on the log_xxx table, because of the trigger.
*
@ -1011,7 +1011,7 @@ repack_drop(PG_FUNCTION_ARGS)
{
execute_with_format(
SPI_OK_UTILITY,
"DROP TRIGGER IF EXISTS z_repack_trigger ON %s.%s CASCADE",
"DROP TRIGGER IF EXISTS a_repack_trigger ON %s.%s CASCADE",
nspname, relname);
--numobj;
}