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;
867 memset(nulls,
false,
sizeof(nulls));
876 values[Anum_pg_trigger_tgenabled - 1] = trigger_fires_when;
891 foreach(le,
stmt->args)
895 len += strlen(ar) + 4;
904 foreach(le,
stmt->args)
938 foreach(cell,
stmt->columns)
948 (
errcode(ERRCODE_UNDEFINED_COLUMN),
949 errmsg(
"column \"%s\" of relation \"%s\" does not exist",
953 for (
j =
i - 1;
j >= 0;
j--)
957 (
errcode(ERRCODE_DUPLICATE_COLUMN),
958 errmsg(
"column \"%s\" specified more than once",
972 nulls[Anum_pg_trigger_tgqual - 1] =
true;
978 nulls[Anum_pg_trigger_tgoldtable - 1] =
true;
983 nulls[Anum_pg_trigger_tgnewtable - 1] =
true;
1021 elog(
ERROR,
"cache lookup failed for relation %u",
1048 myself.
classId = TriggerRelationId;
1052 referenced.
classId = ProcedureRelationId;
1065 referenced.
classId = ConstraintRelationId;
1066 referenced.
objectId = constraintOid;
1077 referenced.
classId = RelationRelationId;
1084 referenced.
classId = RelationRelationId;
1098 referenced.
classId = ConstraintRelationId;
1099 referenced.
objectId = constraintOid;
1117 if (columns != NULL)
1121 referenced.
classId = RelationRelationId;
1123 for (
i = 0;
i < ncolumns;
i++)
1134 if (whenRtable !=
NIL)
1145 if (partition_recurse)
1192 partdesc->
oids[
i], refRelOid,
1194 funcoid, trigoid, qual,
1195 isInternal,
true, trigger_fires_when);
1239 Anum_pg_trigger_oid,
1248 elog(
ERROR,
"could not find tuple for trigger %u", childTrigId);
1255 elog(
ERROR,
"trigger %u already has a parent trigger",
1258 trigForm->tgparentid = parentTrigId;
1308 Anum_pg_trigger_oid,
1317 elog(
ERROR,
"could not find tuple for trigger %u", trigOid);
1326 if (rel->
rd_rel->relkind != RELKIND_RELATION &&
1327 rel->
rd_rel->relkind != RELKIND_VIEW &&
1328 rel->
rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1329 rel->
rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1331 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1332 errmsg(
"relation \"%s\" cannot have triggers",
1338 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1339 errmsg(
"permission denied: \"%s\" is a system catalog",
1386 Anum_pg_trigger_tgrelid,
1390 Anum_pg_trigger_tgname,
1403 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1404 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1434 if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
1435 form->relkind != RELKIND_FOREIGN_TABLE &&
1436 form->relkind != RELKIND_PARTITIONED_TABLE)
1438 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1439 errmsg(
"relation \"%s\" cannot have triggers",
1448 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1449 errmsg(
"permission denied: \"%s\" is a system catalog",
1496 if (targetrel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1505 Anum_pg_trigger_tgrelid,
1509 Anum_pg_trigger_tgname,
1519 tgoid = trigform->oid;
1529 errmsg(
"cannot rename trigger \"%s\" on table \"%s\"",
1531 errhint(
"Rename the trigger on the partitioned table \"%s\" instead.",
1540 if (targetrel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1544 for (
int i = 0;
i < partdesc->
nparts;
i++)
1546 Oid partitionId = partdesc->
oids[
i];
1556 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1557 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1584 const char *newname,
const char *expected_name)
1593 if (strcmp(
NameStr(tgform->tgname), newname) == 0)
1602 Anum_pg_trigger_tgrelid,
1606 Anum_pg_trigger_tgname,
1614 errmsg(
"trigger \"%s\" for relation \"%s\" already exists",
1629 if (strcmp(
NameStr(tgform->tgname), expected_name) != 0)
1631 errmsg(
"renamed trigger \"%s\" on relation \"%s\"",
1655 const char *newname,
const char *expected_name)
1667 Anum_pg_trigger_tgrelid,
1677 if (tgform->tgparentid != parentTriggerOid)
1686 if (partitionRel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1691 for (
int i = 0;
i < partdesc->
nparts;
i++)
1728 char fires_when,
bool skip_system,
bool recurse,
1743 Anum_pg_trigger_tgrelid,
1749 Anum_pg_trigger_tgname,
1760 found = changed =
false;
1766 if (
OidIsValid(tgparent) && tgparent != oldtrig->tgparentid)
1769 if (oldtrig->tgisinternal)
1776 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1777 errmsg(
"permission denied: \"%s\" is a system trigger",
1783 if (oldtrig->tgenabled != fires_when)
1789 newtrig->tgenabled = fires_when;
1808 rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
1809 (TRIGGER_FOR_ROW(oldtrig->tgtype)))
1821 fires_when, skip_system, recurse,
1835 if (tgname && !found)
1837 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1838 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1890 Anum_pg_trigger_tgrelid,
1905 if (numtrigs >= maxtrigs)
1910 build = &(triggers[numtrigs]);
1912 build->
tgoid = pg_trigger->oid;
1915 build->
tgfoid = pg_trigger->tgfoid;
1916 build->
tgtype = pg_trigger->tgtype;
1917 build->
tgenabled = pg_trigger->tgenabled;
1925 build->
tgnargs = pg_trigger->tgnargs;
1927 build->
tgnattr = pg_trigger->tgattr.dim1;
1931 memcpy(build->
tgattr, &(pg_trigger->tgattr.values),
1942 Anum_pg_trigger_tgargs,
1943 tgrel->
rd_att, &isnull));
1945 elog(
ERROR,
"tgargs is null in trigger for relation \"%s\"",
1958 datum =
fastgetattr(htup, Anum_pg_trigger_tgoldtable,
1966 datum =
fastgetattr(htup, Anum_pg_trigger_tgnewtable,
1998 for (
i = 0;
i < numtrigs;
i++)
2019 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2020 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
2022 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2023 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
2025 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2026 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_INSERT);
2028 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2029 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
2031 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2032 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
2034 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2035 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
2037 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2038 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
2040 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2041 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_UPDATE);
2043 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2044 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
2046 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2047 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
2049 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2050 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
2052 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2053 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
2055 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2056 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_DELETE);
2058 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2059 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
2061 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2062 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
2065 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2066 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_TRUNCATE);
2068 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2069 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_TRUNCATE);
2072 (TRIGGER_FOR_INSERT(tgtype) &&
2073 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgnewtable));
2075 (TRIGGER_FOR_UPDATE(tgtype) &&
2076 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgoldtable));
2078 (TRIGGER_FOR_UPDATE(tgtype) &&
2079 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgnewtable));
2081 (TRIGGER_FOR_DELETE(tgtype) &&
2082 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgoldtable));
2097 if (trigdesc == NULL || trigdesc->
numtriggers <= 0)
2104 memcpy(trigger, trigdesc->
triggers,
2116 memcpy(newattr, trigger->
tgattr,
2118 trigger->
tgattr = newattr;
2125 newargs = (
char **)
palloc(trigger->
tgnargs *
sizeof(
char *));
2128 trigger->
tgargs = newargs;
2151 if (trigdesc == NULL)
2162 while (--(trigger->
tgnargs) >= 0)
2200 if (trigdesc1 != NULL)
2202 if (trigdesc2 == NULL)
2248 else if (trig1->
tgqual == NULL || trig2->
tgqual == NULL)
2266 else if (trigdesc2 != NULL)
2280 if (trigdesc != NULL)
2385 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2386 errmsg(
"trigger function %u returned null value",
2387 fcinfo->flinfo->fn_oid)));
2408 if (trigdesc == NULL)
2418 LocTriggerData.
type = T_TriggerData;
2427 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2428 TRIGGER_TYPE_STATEMENT,
2429 TRIGGER_TYPE_BEFORE,
2430 TRIGGER_TYPE_INSERT))
2445 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2446 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2459 false, NULL, NULL,
NIL, NULL, transition_capture,
2473 LocTriggerData.
type = T_TriggerData;
2483 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2485 TRIGGER_TYPE_BEFORE,
2486 TRIGGER_TYPE_INSERT))
2503 if (newtuple == NULL)
2509 else if (newtuple != oldtuple)
2521 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2522 errmsg(
"moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported"),
2523 errdetail(
"Before executing trigger \"%s\", the row was to be in partition \"%s.%s\".",
2551 recheckIndexes, NULL,
2566 LocTriggerData.
type = T_TriggerData;
2576 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2578 TRIGGER_TYPE_INSTEAD,
2579 TRIGGER_TYPE_INSERT))
2596 if (newtuple == NULL)
2602 else if (newtuple != oldtuple)
2626 if (trigdesc == NULL)
2636 LocTriggerData.
type = T_TriggerData;
2645 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2646 TRIGGER_TYPE_STATEMENT,
2647 TRIGGER_TYPE_BEFORE,
2648 TRIGGER_TYPE_DELETE))
2663 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2664 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2677 false, NULL, NULL,
NIL, NULL, transition_capture,
2702 bool should_free =
false;
2706 if (fdw_trigtuple == NULL)
2720 if (epqslot_candidate != NULL && epqslot != NULL)
2722 *epqslot = epqslot_candidate;
2730 trigtuple = fdw_trigtuple;
2734 LocTriggerData.
type = T_TriggerData;
2744 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2746 TRIGGER_TYPE_BEFORE,
2747 TRIGGER_TYPE_DELETE))
2761 if (newtuple == NULL)
2766 if (newtuple != trigtuple)
2785 bool is_crosspart_update)
2795 if (fdw_trigtuple == NULL)
2810 true, slot, NULL,
NIL, NULL,
2812 is_crosspart_update);
2825 LocTriggerData.
type = T_TriggerData;
2838 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2840 TRIGGER_TYPE_INSTEAD,
2841 TRIGGER_TYPE_DELETE))
2855 if (rettuple == NULL)
2857 if (rettuple != trigtuple)
2873 if (trigdesc == NULL)
2888 LocTriggerData.
type = T_TriggerData;
2898 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2899 TRIGGER_TYPE_STATEMENT,
2900 TRIGGER_TYPE_BEFORE,
2901 TRIGGER_TYPE_UPDATE))
2904 updatedCols, NULL, NULL))
2916 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2917 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2933 false, NULL, NULL,
NIL,
2952 bool should_free_trig =
false;
2953 bool should_free_new =
false;
2963 if (fdw_trigtuple == NULL)
2969 lockmode, oldslot, &epqslot_candidate,
2986 if (epqslot_candidate != NULL)
2993 if (newslot != epqslot_clean)
3002 trigtuple = fdw_trigtuple;
3005 LocTriggerData.
type = T_TriggerData;
3017 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3019 TRIGGER_TYPE_BEFORE,
3020 TRIGGER_TYPE_UPDATE))
3023 updatedCols, oldslot, newslot))
3040 if (newtuple == NULL)
3042 if (should_free_trig)
3044 if (should_free_new)
3048 else if (newtuple != oldtuple)
3058 if (should_free_trig && newtuple == trigtuple)
3061 if (should_free_new)
3068 if (should_free_trig)
3091 List *recheckIndexes,
3093 bool is_crosspart_update)
3098 (transition_capture &&
3111 Assert((src_partinfo != NULL && dst_partinfo != NULL) ||
3112 !is_crosspart_update);
3114 tupsrc = src_partinfo ? src_partinfo : relinfo;
3127 else if (fdw_trigtuple != NULL)
3133 src_partinfo, dst_partinfo,
3136 oldslot, newslot, recheckIndexes,
3139 is_crosspart_update);
3154 LocTriggerData.
type = T_TriggerData;
3167 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3169 TRIGGER_TYPE_INSTEAD,
3170 TRIGGER_TYPE_UPDATE))
3173 NULL, oldslot, newslot))
3190 if (newtuple == NULL)
3194 else if (newtuple != oldtuple)
3218 if (trigdesc == NULL)
3223 LocTriggerData.
type = T_TriggerData;
3233 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3234 TRIGGER_TYPE_STATEMENT,
3235 TRIGGER_TYPE_BEFORE,
3236 TRIGGER_TYPE_TRUNCATE))
3251 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
3252 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
3265 false, NULL, NULL,
NIL, NULL, NULL,
3286 if (epqslot != NULL)
3295 Assert(epqstate != NULL);
3328 (
errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
3329 errmsg(
"tuple to be updated was already modified by an operation triggered by the current command"),
3330 errhint(
"Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
3371 errmsg(
"could not serialize access due to concurrent update")));
3372 elog(
ERROR,
"unexpected table_tuple_lock status: %u",
test);
3379 errmsg(
"could not serialize access due to concurrent delete")));
3384 elog(
ERROR,
"attempted to lock invisible tuple");
3388 elog(
ERROR,
"unrecognized table_tuple_lock status: %u",
test);
3400 elog(
ERROR,
"failed to fetch tuple for trigger");
3474 if (*predicate == NULL)
3501 if (!
ExecQual(*predicate, econtext))
3607 #define AFTER_TRIGGER_OFFSET 0x07FFFFFF
3608 #define AFTER_TRIGGER_DONE 0x80000000
3609 #define AFTER_TRIGGER_IN_PROGRESS 0x40000000
3611 #define AFTER_TRIGGER_FDW_REUSE 0x00000000
3612 #define AFTER_TRIGGER_FDW_FETCH 0x20000000
3613 #define AFTER_TRIGGER_1CTID 0x10000000
3614 #define AFTER_TRIGGER_2CTID 0x30000000
3615 #define AFTER_TRIGGER_CP_UPDATE 0x08000000
3616 #define AFTER_TRIGGER_TUP_BITS 0x38000000
3667 #define SizeofTriggerEvent(evt) \
3668 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_CP_UPDATE ? \
3669 sizeof(AfterTriggerEventData) : \
3670 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \
3671 sizeof(AfterTriggerEventDataNoOids) : \
3672 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \
3673 sizeof(AfterTriggerEventDataOneCtid) : \
3674 sizeof(AfterTriggerEventDataZeroCtids))))
3676 #define GetTriggerSharedData(evt) \
3677 ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
3695 #define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
3706 #define for_each_chunk(cptr, evtlist) \
3707 for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
3708 #define for_each_event(eptr, cptr) \
3709 for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
3710 (char *) eptr < (cptr)->freeptr; \
3711 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3713 #define for_each_event_chunk(eptr, cptr, evtlist) \
3714 for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
3717 #define for_each_chunk_from(cptr) \
3718 for (; cptr != NULL; cptr = cptr->next)
3719 #define for_each_event_from(eptr, cptr) \
3721 (char *) eptr < (cptr)->freeptr; \
3722 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3897 Oid tgoid,
bool tgisdeferred);
3962 for (
i = 0;
i <
state->numstates;
i++)
3964 if (
state->trigstates[
i].sct_tgoid == tgoid)
3965 return state->trigstates[
i].sct_tgisdeferred;
3969 if (
state->all_isset)
3970 return state->all_isdeferred;
3999 "AfterTriggerEvents",
4032 chunk = events->
tail;
4033 if (chunk == NULL ||
4034 chunk->endfree - chunk->freeptr < needed)
4042 "AfterTriggerEvents",
4060 #define MIN_CHUNK_SIZE 1024
4061 #define MAX_CHUNK_SIZE (1024*1024)
4063 #if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
4064 #error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
4072 chunksize = chunk->endptr - (
char *) chunk;
4074 if ((chunk->endptr - chunk->endfree) <=
4084 chunk->endptr = chunk->endfree = (
char *) chunk + chunksize;
4085 Assert(chunk->endfree - chunk->freeptr >= needed);
4087 if (events->
head == NULL)
4088 events->
head = chunk;
4091 events->
tail = chunk;
4100 (
char *) newshared >= chunk->endfree;
4110 if ((
char *) newshared < chunk->endfree)
4112 *newshared = *evtshared;
4114 chunk->endfree = (
char *) newshared;
4119 memcpy(newevent, event, eventsize);
4122 newevent->
ate_flags |= (
char *) newshared - (
char *) newevent;
4124 chunk->freeptr += eventsize;
4139 while ((chunk = events->
head) != NULL)
4144 events->
tail = NULL;
4162 if (old_events->
tail == NULL)
4169 *events = *old_events;
4171 for (chunk = events->
tail->
next; chunk != NULL; chunk = next_chunk)
4173 next_chunk = chunk->
next;
4277 bool should_free_trig =
false;
4278 bool should_free_new =
false;
4283 for (tgindx = 0; tgindx < trigdesc->
numtriggers; tgindx++)
4292 elog(
ERROR,
"could not find trigger %u", tgoid);
4312 elog(
ERROR,
"failed to fetch tuple1 for AFTER trigger");
4318 elog(
ERROR,
"failed to fetch tuple2 for AFTER trigger");
4339 LocTriggerData.
tg_newslot = trig_tuple_slot2;
4359 elog(
ERROR,
"failed to fetch tuple1 for AFTER trigger");
4365 if (src_relInfo != relInfo)
4401 elog(
ERROR,
"failed to fetch tuple2 for AFTER trigger");
4408 if (dst_relInfo != relInfo)
4465 LocTriggerData.
type = T_TriggerData;
4483 if (rettuple != NULL &&
4491 if (should_free_trig)
4493 if (should_free_new)
4497 if (trig_tuple_slot1 == NULL)
4531 bool immediate_only)
4534 bool deferred_found =
false;
4541 bool defer_it =
false;
4568 if (defer_it && move_list != NULL)
4570 deferred_found =
true;
4585 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4586 errmsg(
"cannot fire deferred trigger within security-restricted operation")));
4618 bool all_fired =
true;
4621 bool local_estate =
false;
4634 local_estate =
true;
4640 "AfterTriggerTupleContext",
4646 bool all_fired_in_chunk =
true;
4679 slot1 = slot2 = NULL;
4681 if (rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4688 if (trigdesc == NULL)
4689 elog(
ERROR,
"relation %u has no triggers",
4710 src_rInfo = dst_rInfo = rInfo;
4718 src_rInfo, dst_rInfo,
4719 trigdesc, finfo, instr,
4720 per_tuple_context, slot1, slot2);
4731 all_fired = all_fired_in_chunk =
false;
4736 if (delete_ok && all_fired_in_chunk)
4747 if (chunk == events->
tail)
4799 if (table->
relid == relid && table->
cmdType == cmdType &&
4807 table->
relid = relid;
4881 if (trigdesc == NULL)
4888 need_old_upd = need_old_del = need_new_upd =
false;
4894 need_old_del = need_new_ins =
false;
4898 need_old_upd = need_new_upd = need_new_ins =
false;
4907 elog(
ERROR,
"unexpected CmdType: %d", (
int) cmdType);
4909 need_old_upd = need_new_upd = need_old_del = need_new_ins =
false;
4912 if (!need_old_upd && !need_new_upd && !need_new_ins && !need_old_del)
4917 elog(
ERROR,
"MakeTransitionCaptureState() called outside of query");
4960 state->tcs_private = table;
5188 bool snap_pushed =
false;
5199 if (events->
head != NULL)
5497 if (tuplestore == NULL)
5500 if (original_insert_tuple)