57 #include "utils/fmgroids.h"
78 const char *expected_name);
80 Oid parentTriggerOid,
const char *newname,
81 const char *expected_name);
104 int event,
bool row_trigger,
108 bool is_crosspart_update);
166 Oid relOid,
Oid refRelOid,
Oid constraintOid,
Oid indexOid,
167 Oid funcoid,
Oid parentTriggerOid,
Node *whenClause,
168 bool isInternal,
bool in_partition)
172 constraintOid, indexOid, funcoid,
173 parentTriggerOid, whenClause, isInternal,
183 Oid relOid,
Oid refRelOid,
Oid constraintOid,
184 Oid indexOid,
Oid funcoid,
Oid parentTriggerOid,
185 Node *whenClause,
bool isInternal,
bool in_partition,
186 char trigger_fires_when)
195 bool nulls[Natts_pg_trigger];
208 char *oldtablename = NULL;
209 char *newtablename = NULL;
210 bool partition_recurse;
211 bool trigger_exists =
false;
213 bool existing_isInternal =
false;
214 bool existing_isClone =
false;
225 if (rel->
rd_rel->relkind == RELKIND_RELATION)
228 if (
stmt->timing != TRIGGER_TYPE_BEFORE &&
229 stmt->timing != TRIGGER_TYPE_AFTER)
231 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
232 errmsg(
"\"%s\" is a table",
234 errdetail(
"Tables cannot have INSTEAD OF triggers.")));
236 else if (rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
239 if (
stmt->timing != TRIGGER_TYPE_BEFORE &&
240 stmt->timing != TRIGGER_TYPE_AFTER)
242 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
243 errmsg(
"\"%s\" is a table",
245 errdetail(
"Tables cannot have INSTEAD OF triggers.")));
263 if (
stmt->transitionRels !=
NIL)
265 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
266 errmsg(
"\"%s\" is a partitioned table",
268 errdetail(
"ROW triggers with transition tables are not supported on partitioned tables.")));
271 else if (rel->
rd_rel->relkind == RELKIND_VIEW)
277 if (
stmt->timing != TRIGGER_TYPE_INSTEAD &&
stmt->row)
279 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
280 errmsg(
"\"%s\" is a view",
282 errdetail(
"Views cannot have row-level BEFORE or AFTER triggers.")));
284 if (TRIGGER_FOR_TRUNCATE(
stmt->events))
286 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
287 errmsg(
"\"%s\" is a view",
289 errdetail(
"Views cannot have TRUNCATE triggers.")));
291 else if (rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
293 if (
stmt->timing != TRIGGER_TYPE_BEFORE &&
294 stmt->timing != TRIGGER_TYPE_AFTER)
296 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
297 errmsg(
"\"%s\" is a foreign table",
299 errdetail(
"Foreign tables cannot have INSTEAD OF triggers.")));
306 if (
stmt->isconstraint)
308 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
309 errmsg(
"\"%s\" is a foreign table",
311 errdetail(
"Foreign tables cannot have constraint triggers.")));
315 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
316 errmsg(
"relation \"%s\" cannot have triggers",
322 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
323 errmsg(
"permission denied: \"%s\" is a system catalog",
326 if (
stmt->isconstraint)
338 constrrelid = refRelOid;
340 else if (
stmt->constrrel != NULL)
370 partition_recurse = !isInternal &&
stmt->row &&
371 rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE;
372 if (partition_recurse)
377 TRIGGER_CLEAR_TYPE(tgtype);
379 TRIGGER_SETT_ROW(tgtype);
380 tgtype |=
stmt->timing;
381 tgtype |=
stmt->events;
384 if (TRIGGER_FOR_ROW(tgtype) && TRIGGER_FOR_TRUNCATE(tgtype))
386 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
387 errmsg(
"TRUNCATE FOR EACH ROW triggers are not supported")));
390 if (TRIGGER_FOR_INSTEAD(tgtype))
392 if (!TRIGGER_FOR_ROW(tgtype))
394 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
395 errmsg(
"INSTEAD OF triggers must be FOR EACH ROW")));
396 if (
stmt->whenClause)
398 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
399 errmsg(
"INSTEAD OF triggers cannot have WHEN conditions")));
402 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
403 errmsg(
"INSTEAD OF triggers cannot have column lists")));
420 if (
stmt->transitionRels !=
NIL)
422 List *varList =
stmt->transitionRels;
431 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
432 errmsg(
"ROW variable naming in the REFERENCING clause is not supported"),
433 errhint(
"Use OLD TABLE or NEW TABLE for naming transition tables.")));
441 if (rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
443 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
444 errmsg(
"\"%s\" is a foreign table",
446 errdetail(
"Triggers on foreign tables cannot have transition tables.")));
448 if (rel->
rd_rel->relkind == RELKIND_VIEW)
450 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
451 errmsg(
"\"%s\" is a view",
453 errdetail(
"Triggers on views cannot have transition tables.")));
466 if (rel->
rd_rel->relispartition)
468 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
469 errmsg(
"ROW triggers with transition tables are not supported on partitions")));
472 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
473 errmsg(
"ROW triggers with transition tables are not supported on inheritance children")));
476 if (
stmt->timing != TRIGGER_TYPE_AFTER)
478 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
479 errmsg(
"transition table name can only be specified for an AFTER trigger")));
481 if (TRIGGER_FOR_TRUNCATE(tgtype))
483 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
484 errmsg(
"TRUNCATE triggers with transition tables are not supported")));
496 if (((TRIGGER_FOR_INSERT(tgtype) ? 1 : 0) +
497 (TRIGGER_FOR_UPDATE(tgtype) ? 1 : 0) +
498 (TRIGGER_FOR_DELETE(tgtype) ? 1 : 0)) != 1)
500 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
501 errmsg(
"transition tables cannot be specified for triggers with more than one event")));
511 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
512 errmsg(
"transition tables cannot be specified for triggers with column lists")));
525 if (!(TRIGGER_FOR_INSERT(tgtype) ||
526 TRIGGER_FOR_UPDATE(tgtype)))
528 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
529 errmsg(
"NEW TABLE can only be specified for an INSERT or UPDATE trigger")));
531 if (newtablename != NULL)
533 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
534 errmsg(
"NEW TABLE cannot be specified multiple times")));
536 newtablename = tt->
name;
540 if (!(TRIGGER_FOR_DELETE(tgtype) ||
541 TRIGGER_FOR_UPDATE(tgtype)))
543 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
544 errmsg(
"OLD TABLE can only be specified for a DELETE or UPDATE trigger")));
546 if (oldtablename != NULL)
548 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
549 errmsg(
"OLD TABLE cannot be specified multiple times")));
551 oldtablename = tt->
name;
555 if (newtablename != NULL && oldtablename != NULL &&
556 strcmp(newtablename, oldtablename) == 0)
558 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
559 errmsg(
"OLD TABLE name and NEW TABLE name cannot be the same")));
570 if (!whenClause &&
stmt->whenClause)
620 if (!TRIGGER_FOR_ROW(tgtype))
622 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
623 errmsg(
"statement trigger's WHEN condition cannot reference column values"),
625 if (TRIGGER_FOR_INSERT(tgtype))
627 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
628 errmsg(
"INSERT trigger's WHEN condition cannot reference OLD values"),
633 if (!TRIGGER_FOR_ROW(tgtype))
635 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
636 errmsg(
"statement trigger's WHEN condition cannot reference column values"),
638 if (TRIGGER_FOR_DELETE(tgtype))
640 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
641 errmsg(
"DELETE trigger's WHEN condition cannot reference NEW values"),
643 if (var->
varattno < 0 && TRIGGER_FOR_BEFORE(tgtype))
645 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
646 errmsg(
"BEFORE trigger's WHEN condition cannot reference NEW system columns"),
648 if (TRIGGER_FOR_BEFORE(tgtype) &&
653 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
654 errmsg(
"BEFORE trigger's WHEN condition cannot reference NEW generated columns"),
655 errdetail(
"A whole-row reference is used and the table contains generated columns."),
657 if (TRIGGER_FOR_BEFORE(tgtype) &&
661 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
662 errmsg(
"BEFORE trigger's WHEN condition cannot reference NEW generated columns"),
663 errdetail(
"Column \"%s\" is a generated column.",
669 elog(
ERROR,
"trigger WHEN condition cannot contain references to other relations");
681 else if (!whenClause)
706 if (funcrettype != TRIGGEROID)
708 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
709 errmsg(
"function %s must return type %s",
727 Anum_pg_trigger_tgrelid,
732 Anum_pg_trigger_tgname,
744 trigoid = oldtrigger->oid;
745 existing_constraint_oid = oldtrigger->tgconstraint;
746 existing_isInternal = oldtrigger->tgisinternal;
747 existing_isClone =
OidIsValid(oldtrigger->tgparentid);
748 trigger_exists =
true;
759 Anum_pg_trigger_oid);
770 errmsg(
"trigger \"%s\" for relation \"%s\" already exists",
779 if ((existing_isInternal || existing_isClone) &&
780 !isInternal && !in_partition)
783 errmsg(
"trigger \"%s\" for relation \"%s\" is an internal or a child trigger",
802 errmsg(
"trigger \"%s\" for relation \"%s\" is a constraint trigger",
854 snprintf(internaltrigname,
sizeof(internaltrigname),
855 "%s_%u",
stmt->trigname, trigoid);
856 trigname = internaltrigname;
861 trigname =
stmt->trigname;
872 memset(nulls,
false,
sizeof(nulls));
881 values[Anum_pg_trigger_tgenabled - 1] = trigger_fires_when;
896 foreach(le,
stmt->args)
900 len += strlen(ar) + 4;
909 foreach(le,
stmt->args)
943 foreach(cell,
stmt->columns)
953 (
errcode(ERRCODE_UNDEFINED_COLUMN),
954 errmsg(
"column \"%s\" of relation \"%s\" does not exist",
958 for (
j =
i - 1;
j >= 0;
j--)
962 (
errcode(ERRCODE_DUPLICATE_COLUMN),
963 errmsg(
"column \"%s\" specified more than once",
977 nulls[Anum_pg_trigger_tgqual - 1] =
true;
983 nulls[Anum_pg_trigger_tgoldtable - 1] =
true;
988 nulls[Anum_pg_trigger_tgnewtable - 1] =
true;
1026 elog(
ERROR,
"cache lookup failed for relation %u",
1053 myself.
classId = TriggerRelationId;
1057 referenced.
classId = ProcedureRelationId;
1070 referenced.
classId = ConstraintRelationId;
1071 referenced.
objectId = constraintOid;
1082 referenced.
classId = RelationRelationId;
1089 referenced.
classId = RelationRelationId;
1103 referenced.
classId = ConstraintRelationId;
1104 referenced.
objectId = constraintOid;
1122 if (columns != NULL)
1126 referenced.
classId = RelationRelationId;
1128 for (
i = 0;
i < ncolumns;
i++)
1139 if (whenRtable !=
NIL)
1150 if (partition_recurse)
1197 partdesc->
oids[
i], refRelOid,
1199 funcoid, trigoid, qual,
1200 isInternal,
true, trigger_fires_when);
1244 Anum_pg_trigger_oid,
1253 elog(
ERROR,
"could not find tuple for trigger %u", childTrigId);
1260 elog(
ERROR,
"trigger %u already has a parent trigger",
1263 trigForm->tgparentid = parentTrigId;
1313 Anum_pg_trigger_oid,
1322 elog(
ERROR,
"could not find tuple for trigger %u", trigOid);
1331 if (rel->
rd_rel->relkind != RELKIND_RELATION &&
1332 rel->
rd_rel->relkind != RELKIND_VIEW &&
1333 rel->
rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1334 rel->
rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1336 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1337 errmsg(
"relation \"%s\" cannot have triggers",
1343 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1344 errmsg(
"permission denied: \"%s\" is a system catalog",
1391 Anum_pg_trigger_tgrelid,
1395 Anum_pg_trigger_tgname,
1408 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1409 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1439 if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
1440 form->relkind != RELKIND_FOREIGN_TABLE &&
1441 form->relkind != RELKIND_PARTITIONED_TABLE)
1443 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1444 errmsg(
"relation \"%s\" cannot have triggers",
1453 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1454 errmsg(
"permission denied: \"%s\" is a system catalog",
1501 if (targetrel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1510 Anum_pg_trigger_tgrelid,
1514 Anum_pg_trigger_tgname,
1524 tgoid = trigform->oid;
1534 errmsg(
"cannot rename trigger \"%s\" on table \"%s\"",
1536 errhint(
"Rename the trigger on the partitioned table \"%s\" instead.",
1545 if (targetrel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1549 for (
int i = 0;
i < partdesc->
nparts;
i++)
1551 Oid partitionId = partdesc->
oids[
i];
1561 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1562 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1589 const char *newname,
const char *expected_name)
1598 if (strcmp(
NameStr(tgform->tgname), newname) == 0)
1607 Anum_pg_trigger_tgrelid,
1611 Anum_pg_trigger_tgname,
1619 errmsg(
"trigger \"%s\" for relation \"%s\" already exists",
1634 if (strcmp(
NameStr(tgform->tgname), expected_name) != 0)
1636 errmsg(
"renamed trigger \"%s\" on relation \"%s\"",
1660 const char *newname,
const char *expected_name)
1672 Anum_pg_trigger_tgrelid,
1682 if (tgform->tgparentid != parentTriggerOid)
1691 if (partitionRel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1696 for (
int i = 0;
i < partdesc->
nparts;
i++)
1733 char fires_when,
bool skip_system,
bool recurse,
1748 Anum_pg_trigger_tgrelid,
1754 Anum_pg_trigger_tgname,
1765 found = changed =
false;
1771 if (
OidIsValid(tgparent) && tgparent != oldtrig->tgparentid)
1774 if (oldtrig->tgisinternal)
1781 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1782 errmsg(
"permission denied: \"%s\" is a system trigger",
1788 if (oldtrig->tgenabled != fires_when)
1794 newtrig->tgenabled = fires_when;
1813 rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
1814 (TRIGGER_FOR_ROW(oldtrig->tgtype)))
1826 fires_when, skip_system, recurse,
1840 if (tgname && !found)
1842 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1843 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1895 Anum_pg_trigger_tgrelid,
1910 if (numtrigs >= maxtrigs)
1915 build = &(triggers[numtrigs]);
1917 build->
tgoid = pg_trigger->oid;
1920 build->
tgfoid = pg_trigger->tgfoid;
1921 build->
tgtype = pg_trigger->tgtype;
1922 build->
tgenabled = pg_trigger->tgenabled;
1930 build->
tgnargs = pg_trigger->tgnargs;
1932 build->
tgnattr = pg_trigger->tgattr.dim1;
1936 memcpy(build->
tgattr, &(pg_trigger->tgattr.values),
1947 Anum_pg_trigger_tgargs,
1948 tgrel->
rd_att, &isnull));
1950 elog(
ERROR,
"tgargs is null in trigger for relation \"%s\"",
1963 datum =
fastgetattr(htup, Anum_pg_trigger_tgoldtable,
1971 datum =
fastgetattr(htup, Anum_pg_trigger_tgnewtable,
2003 for (
i = 0;
i < numtrigs;
i++)
2024 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2025 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
2027 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2028 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
2030 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2031 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_INSERT);
2033 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2034 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
2036 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2037 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
2039 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2040 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
2042 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2043 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
2045 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2046 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_UPDATE);
2048 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2049 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
2051 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2052 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
2054 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2055 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
2057 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2058 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
2060 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2061 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_DELETE);
2063 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2064 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
2066 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2067 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
2070 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2071 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_TRUNCATE);
2073 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2074 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_TRUNCATE);
2077 (TRIGGER_FOR_INSERT(tgtype) &&
2078 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgnewtable));
2080 (TRIGGER_FOR_UPDATE(tgtype) &&
2081 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgoldtable));
2083 (TRIGGER_FOR_UPDATE(tgtype) &&
2084 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgnewtable));
2086 (TRIGGER_FOR_DELETE(tgtype) &&
2087 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgoldtable));
2102 if (trigdesc == NULL || trigdesc->
numtriggers <= 0)
2109 memcpy(trigger, trigdesc->
triggers,
2121 memcpy(newattr, trigger->
tgattr,
2123 trigger->
tgattr = newattr;
2130 newargs = (
char **)
palloc(trigger->
tgnargs *
sizeof(
char *));
2133 trigger->
tgargs = newargs;
2156 if (trigdesc == NULL)
2167 while (--(trigger->
tgnargs) >= 0)
2205 if (trigdesc1 != NULL)
2207 if (trigdesc2 == NULL)
2253 else if (trig1->
tgqual == NULL || trig2->
tgqual == NULL)
2271 else if (trigdesc2 != NULL)
2285 if (trigdesc != NULL)
2390 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2391 errmsg(
"trigger function %u returned null value",
2392 fcinfo->flinfo->fn_oid)));
2413 if (trigdesc == NULL)
2423 LocTriggerData.
type = T_TriggerData;
2432 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2433 TRIGGER_TYPE_STATEMENT,
2434 TRIGGER_TYPE_BEFORE,
2435 TRIGGER_TYPE_INSERT))
2450 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2451 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2464 false, NULL, NULL,
NIL, NULL, transition_capture,
2478 LocTriggerData.
type = T_TriggerData;
2488 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2490 TRIGGER_TYPE_BEFORE,
2491 TRIGGER_TYPE_INSERT))
2508 if (newtuple == NULL)
2514 else if (newtuple != oldtuple)
2526 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2527 errmsg(
"moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported"),
2528 errdetail(
"Before executing trigger \"%s\", the row was to be in partition \"%s.%s\".",
2556 recheckIndexes, NULL,
2571 LocTriggerData.
type = T_TriggerData;
2581 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2583 TRIGGER_TYPE_INSTEAD,
2584 TRIGGER_TYPE_INSERT))
2601 if (newtuple == NULL)
2607 else if (newtuple != oldtuple)
2631 if (trigdesc == NULL)
2641 LocTriggerData.
type = T_TriggerData;
2650 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2651 TRIGGER_TYPE_STATEMENT,
2652 TRIGGER_TYPE_BEFORE,
2653 TRIGGER_TYPE_DELETE))
2668 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2669 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2682 false, NULL, NULL,
NIL, NULL, transition_capture,
2707 bool should_free =
false;
2711 if (fdw_trigtuple == NULL)
2725 if (epqslot_candidate != NULL && epqslot != NULL)
2727 *epqslot = epqslot_candidate;
2735 trigtuple = fdw_trigtuple;
2739 LocTriggerData.
type = T_TriggerData;
2749 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2751 TRIGGER_TYPE_BEFORE,
2752 TRIGGER_TYPE_DELETE))
2766 if (newtuple == NULL)
2771 if (newtuple != trigtuple)
2790 bool is_crosspart_update)
2800 if (fdw_trigtuple == NULL)
2815 true, slot, NULL,
NIL, NULL,
2817 is_crosspart_update);
2830 LocTriggerData.
type = T_TriggerData;
2843 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2845 TRIGGER_TYPE_INSTEAD,
2846 TRIGGER_TYPE_DELETE))
2860 if (rettuple == NULL)
2862 if (rettuple != trigtuple)
2878 if (trigdesc == NULL)
2893 LocTriggerData.
type = T_TriggerData;
2903 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2904 TRIGGER_TYPE_STATEMENT,
2905 TRIGGER_TYPE_BEFORE,
2906 TRIGGER_TYPE_UPDATE))
2909 updatedCols, NULL, NULL))
2921 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2922 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2938 false, NULL, NULL,
NIL,
2957 bool should_free_trig =
false;
2958 bool should_free_new =
false;
2968 if (fdw_trigtuple == NULL)
2974 lockmode, oldslot, &epqslot_candidate,
2991 if (epqslot_candidate != NULL)
2998 if (newslot != epqslot_clean)
3007 trigtuple = fdw_trigtuple;
3010 LocTriggerData.
type = T_TriggerData;
3022 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3024 TRIGGER_TYPE_BEFORE,
3025 TRIGGER_TYPE_UPDATE))
3028 updatedCols, oldslot, newslot))
3045 if (newtuple == NULL)
3047 if (should_free_trig)
3049 if (should_free_new)
3053 else if (newtuple != oldtuple)
3063 if (should_free_trig && newtuple == trigtuple)
3066 if (should_free_new)
3073 if (should_free_trig)
3096 List *recheckIndexes,
3098 bool is_crosspart_update)
3103 (transition_capture &&
3116 Assert((src_partinfo != NULL && dst_partinfo != NULL) ||
3117 !is_crosspart_update);
3119 tupsrc = src_partinfo ? src_partinfo : relinfo;
3132 else if (fdw_trigtuple != NULL)
3138 src_partinfo, dst_partinfo,
3141 oldslot, newslot, recheckIndexes,
3144 is_crosspart_update);
3159 LocTriggerData.
type = T_TriggerData;
3172 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3174 TRIGGER_TYPE_INSTEAD,
3175 TRIGGER_TYPE_UPDATE))
3178 NULL, oldslot, newslot))
3195 if (newtuple == NULL)
3199 else if (newtuple != oldtuple)
3223 if (trigdesc == NULL)
3228 LocTriggerData.
type = T_TriggerData;
3238 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3239 TRIGGER_TYPE_STATEMENT,
3240 TRIGGER_TYPE_BEFORE,
3241 TRIGGER_TYPE_TRUNCATE))
3256 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
3257 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
3270 false, NULL, NULL,
NIL, NULL, NULL,
3291 if (epqslot != NULL)
3300 Assert(epqstate != NULL);
3333 (
errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
3334 errmsg(
"tuple to be updated was already modified by an operation triggered by the current command"),
3335 errhint(
"Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
3376 errmsg(
"could not serialize access due to concurrent update")));
3377 elog(
ERROR,
"unexpected table_tuple_lock status: %u",
test);
3384 errmsg(
"could not serialize access due to concurrent delete")));
3389 elog(
ERROR,
"attempted to lock invisible tuple");
3393 elog(
ERROR,
"unrecognized table_tuple_lock status: %u",
test);
3405 elog(
ERROR,
"failed to fetch tuple for trigger");
3479 if (*predicate == NULL)
3506 if (!
ExecQual(*predicate, econtext))
3612 #define AFTER_TRIGGER_OFFSET 0x07FFFFFF
3613 #define AFTER_TRIGGER_DONE 0x80000000
3614 #define AFTER_TRIGGER_IN_PROGRESS 0x40000000
3616 #define AFTER_TRIGGER_FDW_REUSE 0x00000000
3617 #define AFTER_TRIGGER_FDW_FETCH 0x20000000
3618 #define AFTER_TRIGGER_1CTID 0x10000000
3619 #define AFTER_TRIGGER_2CTID 0x30000000
3620 #define AFTER_TRIGGER_CP_UPDATE 0x08000000
3621 #define AFTER_TRIGGER_TUP_BITS 0x38000000
3672 #define SizeofTriggerEvent(evt) \
3673 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_CP_UPDATE ? \
3674 sizeof(AfterTriggerEventData) : \
3675 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \
3676 sizeof(AfterTriggerEventDataNoOids) : \
3677 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \
3678 sizeof(AfterTriggerEventDataOneCtid) : \
3679 sizeof(AfterTriggerEventDataZeroCtids))))
3681 #define GetTriggerSharedData(evt) \
3682 ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
3700 #define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
3711 #define for_each_chunk(cptr, evtlist) \
3712 for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
3713 #define for_each_event(eptr, cptr) \
3714 for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
3715 (char *) eptr < (cptr)->freeptr; \
3716 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3718 #define for_each_event_chunk(eptr, cptr, evtlist) \
3719 for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
3722 #define for_each_chunk_from(cptr) \
3723 for (; cptr != NULL; cptr = cptr->next)
3724 #define for_each_event_from(eptr, cptr) \
3726 (char *) eptr < (cptr)->freeptr; \
3727 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3902 Oid tgoid,
bool tgisdeferred);
3967 for (
i = 0;
i <
state->numstates;
i++)
3969 if (
state->trigstates[
i].sct_tgoid == tgoid)
3970 return state->trigstates[
i].sct_tgisdeferred;
3974 if (
state->all_isset)
3975 return state->all_isdeferred;
4006 chunk = events->
tail;
4007 if (chunk == NULL ||
4008 chunk->endfree - chunk->freeptr < needed)
4016 "AfterTriggerEvents",
4034 #define MIN_CHUNK_SIZE 1024
4035 #define MAX_CHUNK_SIZE (1024*1024)
4037 #if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
4038 #error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
4046 chunksize = chunk->endptr - (
char *) chunk;
4048 if ((chunk->endptr - chunk->endfree) <=
4058 chunk->endptr = chunk->endfree = (
char *) chunk + chunksize;
4059 Assert(chunk->endfree - chunk->freeptr >= needed);
4061 if (events->
head == NULL)
4062 events->
head = chunk;
4065 events->
tail = chunk;
4074 (
char *) newshared >= chunk->endfree;
4084 if ((
char *) newshared < chunk->endfree)
4086 *newshared = *evtshared;
4088 chunk->endfree = (
char *) newshared;
4093 memcpy(newevent, event, eventsize);
4096 newevent->
ate_flags |= (
char *) newshared - (
char *) newevent;
4098 chunk->freeptr += eventsize;
4113 while ((chunk = events->
head) != NULL)
4118 events->
tail = NULL;
4136 if (old_events->
tail == NULL)
4143 *events = *old_events;
4145 for (chunk = events->
tail->
next; chunk != NULL; chunk = next_chunk)
4147 next_chunk = chunk->
next;
4251 bool should_free_trig =
false;
4252 bool should_free_new =
false;
4257 for (tgindx = 0; tgindx < trigdesc->
numtriggers; tgindx++)
4266 elog(
ERROR,
"could not find trigger %u", tgoid);
4286 elog(
ERROR,
"failed to fetch tuple1 for AFTER trigger");
4292 elog(
ERROR,
"failed to fetch tuple2 for AFTER trigger");
4313 LocTriggerData.
tg_newslot = trig_tuple_slot2;
4333 elog(
ERROR,
"failed to fetch tuple1 for AFTER trigger");
4339 if (src_relInfo != relInfo)
4375 elog(
ERROR,
"failed to fetch tuple2 for AFTER trigger");
4382 if (dst_relInfo != relInfo)
4439 LocTriggerData.
type = T_TriggerData;
4457 if (rettuple != NULL &&
4465 if (should_free_trig)
4467 if (should_free_new)
4471 if (trig_tuple_slot1 == NULL)
4505 bool immediate_only)
4508 bool deferred_found =
false;
4515 bool defer_it =
false;
4542 if (defer_it && move_list != NULL)
4544 deferred_found =
true;
4559 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4560 errmsg(
"cannot fire deferred trigger within security-restricted operation")));
4592 bool all_fired =
true;
4595 bool local_estate =
false;
4608 local_estate =
true;
4614 "AfterTriggerTupleContext",
4620 bool all_fired_in_chunk =
true;
4653 slot1 = slot2 = NULL;
4655 if (rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4662 if (trigdesc == NULL)
4663 elog(
ERROR,
"relation %u has no triggers",
4684 src_rInfo = dst_rInfo = rInfo;
4692 src_rInfo, dst_rInfo,
4693 trigdesc, finfo, instr,
4694 per_tuple_context, slot1, slot2);
4705 all_fired = all_fired_in_chunk =
false;
4710 if (delete_ok && all_fired_in_chunk)
4721 if (chunk == events->
tail)
4773 if (table->
relid == relid && table->
cmdType == cmdType &&
4781 table->
relid = relid;
4855 if (trigdesc == NULL)
4862 need_old_upd = need_old_del = need_new_upd =
false;
4868 need_old_del = need_new_ins =
false;
4872 need_old_upd = need_new_upd = need_new_ins =
false;
4881 elog(
ERROR,
"unexpected CmdType: %d", (
int) cmdType);
4883 need_old_upd = need_new_upd = need_old_del = need_new_ins =
false;
4886 if (!need_old_upd && !need_new_upd && !need_new_ins && !need_old_del)
4891 elog(
ERROR,
"MakeTransitionCaptureState() called outside of query");
4934 state->tcs_private = table;
5162 bool snap_pushed =
false;
5173 if (events->
head != NULL)
5471 if (tuplestore == NULL)
5474 if (original_insert_tuple)
5562 state->numalloc = numalloc;
5580 memcpy(
state->trigstates, origstate->