51#include "utils/fmgroids.h"
72 const char *expected_name);
74 Oid parentTriggerOid,
const char *newname,
75 const char *expected_name);
98 int event,
bool row_trigger,
102 bool is_crosspart_update);
161 Oid relOid,
Oid refRelOid,
Oid constraintOid,
Oid indexOid,
162 Oid funcoid,
Oid parentTriggerOid,
Node *whenClause,
163 bool isInternal,
bool in_partition)
167 constraintOid, indexOid, funcoid,
168 parentTriggerOid, whenClause, isInternal,
178 Oid relOid,
Oid refRelOid,
Oid constraintOid,
179 Oid indexOid,
Oid funcoid,
Oid parentTriggerOid,
180 Node *whenClause,
bool isInternal,
bool in_partition,
181 char trigger_fires_when)
190 bool nulls[Natts_pg_trigger];
203 char *oldtablename = NULL;
204 char *newtablename = NULL;
205 bool partition_recurse;
206 bool trigger_exists =
false;
208 bool existing_isInternal =
false;
209 bool existing_isClone =
false;
220 if (rel->
rd_rel->relkind == RELKIND_RELATION)
223 if (
stmt->timing != TRIGGER_TYPE_BEFORE &&
224 stmt->timing != TRIGGER_TYPE_AFTER)
226 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
227 errmsg(
"\"%s\" is a table",
229 errdetail(
"Tables cannot have INSTEAD OF triggers.")));
231 else if (rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
234 if (
stmt->timing != TRIGGER_TYPE_BEFORE &&
235 stmt->timing != TRIGGER_TYPE_AFTER)
237 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
238 errmsg(
"\"%s\" is a table",
240 errdetail(
"Tables cannot have INSTEAD OF triggers.")));
258 if (
stmt->transitionRels !=
NIL)
260 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
261 errmsg(
"\"%s\" is a partitioned table",
263 errdetail(
"ROW triggers with transition tables are not supported on partitioned tables.")));
266 else if (rel->
rd_rel->relkind == RELKIND_VIEW)
272 if (
stmt->timing != TRIGGER_TYPE_INSTEAD &&
stmt->row)
274 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
275 errmsg(
"\"%s\" is a view",
277 errdetail(
"Views cannot have row-level BEFORE or AFTER triggers.")));
279 if (TRIGGER_FOR_TRUNCATE(
stmt->events))
281 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
282 errmsg(
"\"%s\" is a view",
284 errdetail(
"Views cannot have TRUNCATE triggers.")));
286 else if (rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
288 if (
stmt->timing != TRIGGER_TYPE_BEFORE &&
289 stmt->timing != TRIGGER_TYPE_AFTER)
291 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
292 errmsg(
"\"%s\" is a foreign table",
294 errdetail(
"Foreign tables cannot have INSTEAD OF triggers.")));
301 if (
stmt->isconstraint)
303 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
304 errmsg(
"\"%s\" is a foreign table",
306 errdetail(
"Foreign tables cannot have constraint triggers.")));
310 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
311 errmsg(
"relation \"%s\" cannot have triggers",
317 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
318 errmsg(
"permission denied: \"%s\" is a system catalog",
321 if (
stmt->isconstraint)
333 constrrelid = refRelOid;
335 else if (
stmt->constrrel != NULL)
365 partition_recurse = !isInternal &&
stmt->row &&
366 rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE;
367 if (partition_recurse)
372 TRIGGER_CLEAR_TYPE(tgtype);
374 TRIGGER_SETT_ROW(tgtype);
375 tgtype |=
stmt->timing;
376 tgtype |=
stmt->events;
379 if (TRIGGER_FOR_ROW(tgtype) && TRIGGER_FOR_TRUNCATE(tgtype))
381 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
382 errmsg(
"TRUNCATE FOR EACH ROW triggers are not supported")));
385 if (TRIGGER_FOR_INSTEAD(tgtype))
387 if (!TRIGGER_FOR_ROW(tgtype))
389 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
390 errmsg(
"INSTEAD OF triggers must be FOR EACH ROW")));
391 if (
stmt->whenClause)
393 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
394 errmsg(
"INSTEAD OF triggers cannot have WHEN conditions")));
397 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
398 errmsg(
"INSTEAD OF triggers cannot have column lists")));
415 if (
stmt->transitionRels !=
NIL)
417 List *varList =
stmt->transitionRels;
426 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
427 errmsg(
"ROW variable naming in the REFERENCING clause is not supported"),
428 errhint(
"Use OLD TABLE or NEW TABLE for naming transition tables.")));
436 if (rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
438 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
439 errmsg(
"\"%s\" is a foreign table",
441 errdetail(
"Triggers on foreign tables cannot have transition tables.")));
443 if (rel->
rd_rel->relkind == RELKIND_VIEW)
445 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
446 errmsg(
"\"%s\" is a view",
448 errdetail(
"Triggers on views cannot have transition tables.")));
461 if (rel->
rd_rel->relispartition)
463 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
464 errmsg(
"ROW triggers with transition tables are not supported on partitions")));
467 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
468 errmsg(
"ROW triggers with transition tables are not supported on inheritance children")));
471 if (
stmt->timing != TRIGGER_TYPE_AFTER)
473 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
474 errmsg(
"transition table name can only be specified for an AFTER trigger")));
476 if (TRIGGER_FOR_TRUNCATE(tgtype))
478 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
479 errmsg(
"TRUNCATE triggers with transition tables are not supported")));
491 if (((TRIGGER_FOR_INSERT(tgtype) ? 1 : 0) +
492 (TRIGGER_FOR_UPDATE(tgtype) ? 1 : 0) +
493 (TRIGGER_FOR_DELETE(tgtype) ? 1 : 0)) != 1)
495 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
496 errmsg(
"transition tables cannot be specified for triggers with more than one event")));
506 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
507 errmsg(
"transition tables cannot be specified for triggers with column lists")));
520 if (!(TRIGGER_FOR_INSERT(tgtype) ||
521 TRIGGER_FOR_UPDATE(tgtype)))
523 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
524 errmsg(
"NEW TABLE can only be specified for an INSERT or UPDATE trigger")));
526 if (newtablename != NULL)
528 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
529 errmsg(
"NEW TABLE cannot be specified multiple times")));
531 newtablename = tt->
name;
535 if (!(TRIGGER_FOR_DELETE(tgtype) ||
536 TRIGGER_FOR_UPDATE(tgtype)))
538 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
539 errmsg(
"OLD TABLE can only be specified for a DELETE or UPDATE trigger")));
541 if (oldtablename != NULL)
543 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
544 errmsg(
"OLD TABLE cannot be specified multiple times")));
546 oldtablename = tt->
name;
550 if (newtablename != NULL && oldtablename != NULL &&
551 strcmp(newtablename, oldtablename) == 0)
553 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
554 errmsg(
"OLD TABLE name and NEW TABLE name cannot be the same")));
565 if (!whenClause &&
stmt->whenClause)
615 if (!TRIGGER_FOR_ROW(tgtype))
617 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
618 errmsg(
"statement trigger's WHEN condition cannot reference column values"),
620 if (TRIGGER_FOR_INSERT(tgtype))
622 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
623 errmsg(
"INSERT trigger's WHEN condition cannot reference OLD values"),
628 if (!TRIGGER_FOR_ROW(tgtype))
630 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
631 errmsg(
"statement trigger's WHEN condition cannot reference column values"),
633 if (TRIGGER_FOR_DELETE(tgtype))
635 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
636 errmsg(
"DELETE trigger's WHEN condition cannot reference NEW values"),
638 if (var->
varattno < 0 && TRIGGER_FOR_BEFORE(tgtype))
640 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
641 errmsg(
"BEFORE trigger's WHEN condition cannot reference NEW system columns"),
643 if (TRIGGER_FOR_BEFORE(tgtype) &&
649 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
650 errmsg(
"BEFORE trigger's WHEN condition cannot reference NEW generated columns"),
651 errdetail(
"A whole-row reference is used and the table contains generated columns."),
653 if (TRIGGER_FOR_BEFORE(tgtype) &&
657 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
658 errmsg(
"BEFORE trigger's WHEN condition cannot reference NEW generated columns"),
659 errdetail(
"Column \"%s\" is a generated column.",
665 elog(
ERROR,
"trigger WHEN condition cannot contain references to other relations");
677 else if (!whenClause)
702 if (funcrettype != TRIGGEROID)
704 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
705 errmsg(
"function %s must return type %s",
723 Anum_pg_trigger_tgrelid,
728 Anum_pg_trigger_tgname,
740 trigoid = oldtrigger->oid;
741 existing_constraint_oid = oldtrigger->tgconstraint;
742 existing_isInternal = oldtrigger->tgisinternal;
743 existing_isClone =
OidIsValid(oldtrigger->tgparentid);
744 trigger_exists =
true;
755 Anum_pg_trigger_oid);
766 errmsg(
"trigger \"%s\" for relation \"%s\" already exists",
775 if ((existing_isInternal || existing_isClone) &&
776 !isInternal && !in_partition)
779 errmsg(
"trigger \"%s\" for relation \"%s\" is an internal or a child trigger",
798 errmsg(
"trigger \"%s\" for relation \"%s\" is a constraint trigger",
852 snprintf(internaltrigname,
sizeof(internaltrigname),
853 "%s_%u",
stmt->trigname, trigoid);
854 trigname = internaltrigname;
859 trigname =
stmt->trigname;
865 memset(nulls,
false,
sizeof(nulls));
874 values[Anum_pg_trigger_tgenabled - 1] = trigger_fires_when;
889 foreach(le,
stmt->args)
893 len += strlen(ar) + 4;
902 foreach(le,
stmt->args)
936 foreach(cell,
stmt->columns)
946 (
errcode(ERRCODE_UNDEFINED_COLUMN),
947 errmsg(
"column \"%s\" of relation \"%s\" does not exist",
951 for (
j =
i - 1;
j >= 0;
j--)
955 (
errcode(ERRCODE_DUPLICATE_COLUMN),
956 errmsg(
"column \"%s\" specified more than once",
970 nulls[Anum_pg_trigger_tgqual - 1] =
true;
976 nulls[Anum_pg_trigger_tgoldtable - 1] =
true;
981 nulls[Anum_pg_trigger_tgnewtable - 1] =
true;
1019 elog(
ERROR,
"cache lookup failed for relation %u",
1046 myself.
classId = TriggerRelationId;
1050 referenced.
classId = ProcedureRelationId;
1063 referenced.
classId = ConstraintRelationId;
1064 referenced.
objectId = constraintOid;
1075 referenced.
classId = RelationRelationId;
1082 referenced.
classId = RelationRelationId;
1096 referenced.
classId = ConstraintRelationId;
1097 referenced.
objectId = constraintOid;
1115 if (columns != NULL)
1119 referenced.
classId = RelationRelationId;
1121 for (
i = 0;
i < ncolumns;
i++)
1132 if (whenRtable !=
NIL)
1143 if (partition_recurse)
1190 partdesc->
oids[
i], refRelOid,
1192 funcoid, trigoid, qual,
1193 isInternal,
true, trigger_fires_when);
1237 Anum_pg_trigger_oid,
1246 elog(
ERROR,
"could not find tuple for trigger %u", childTrigId);
1253 elog(
ERROR,
"trigger %u already has a parent trigger",
1256 trigForm->tgparentid = parentTrigId;
1306 Anum_pg_trigger_oid,
1315 elog(
ERROR,
"could not find tuple for trigger %u", trigOid);
1324 if (rel->
rd_rel->relkind != RELKIND_RELATION &&
1325 rel->
rd_rel->relkind != RELKIND_VIEW &&
1326 rel->
rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1327 rel->
rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1329 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1330 errmsg(
"relation \"%s\" cannot have triggers",
1336 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1337 errmsg(
"permission denied: \"%s\" is a system catalog",
1384 Anum_pg_trigger_tgrelid,
1388 Anum_pg_trigger_tgname,
1401 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1402 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1432 if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
1433 form->relkind != RELKIND_FOREIGN_TABLE &&
1434 form->relkind != RELKIND_PARTITIONED_TABLE)
1436 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1437 errmsg(
"relation \"%s\" cannot have triggers",
1446 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1447 errmsg(
"permission denied: \"%s\" is a system catalog",
1494 if (targetrel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1503 Anum_pg_trigger_tgrelid,
1507 Anum_pg_trigger_tgname,
1517 tgoid = trigform->oid;
1527 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1528 errmsg(
"cannot rename trigger \"%s\" on table \"%s\"",
1530 errhint(
"Rename the trigger on the partitioned table \"%s\" instead.",
1539 if (targetrel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1543 for (
int i = 0;
i < partdesc->
nparts;
i++)
1545 Oid partitionId = partdesc->
oids[
i];
1555 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1556 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1583 const char *newname,
const char *expected_name)
1592 if (strcmp(
NameStr(tgform->tgname), newname) == 0)
1601 Anum_pg_trigger_tgrelid,
1605 Anum_pg_trigger_tgname,
1613 errmsg(
"trigger \"%s\" for relation \"%s\" already exists",
1628 if (strcmp(
NameStr(tgform->tgname), expected_name) != 0)
1630 errmsg(
"renamed trigger \"%s\" on relation \"%s\"",
1654 const char *newname,
const char *expected_name)
1666 Anum_pg_trigger_tgrelid,
1676 if (tgform->tgparentid != parentTriggerOid)
1685 if (partitionRel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1690 for (
int i = 0;
i < partdesc->
nparts;
i++)
1727 char fires_when,
bool skip_system,
bool recurse,
1742 Anum_pg_trigger_tgrelid,
1748 Anum_pg_trigger_tgname,
1759 found = changed =
false;
1765 if (
OidIsValid(tgparent) && tgparent != oldtrig->tgparentid)
1768 if (oldtrig->tgisinternal)
1775 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1776 errmsg(
"permission denied: \"%s\" is a system trigger",
1782 if (oldtrig->tgenabled != fires_when)
1788 newtrig->tgenabled = fires_when;
1807 rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
1808 (TRIGGER_FOR_ROW(oldtrig->tgtype)))
1820 fires_when, skip_system, recurse,
1834 if (tgname && !found)
1836 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1837 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1889 Anum_pg_trigger_tgrelid,
1904 if (numtrigs >= maxtrigs)
1909 build = &(triggers[numtrigs]);
1911 build->
tgoid = pg_trigger->oid;
1914 build->
tgfoid = pg_trigger->tgfoid;
1915 build->
tgtype = pg_trigger->tgtype;
1916 build->
tgenabled = pg_trigger->tgenabled;
1924 build->
tgnargs = pg_trigger->tgnargs;
1926 build->
tgnattr = pg_trigger->tgattr.dim1;
1930 memcpy(build->
tgattr, &(pg_trigger->tgattr.values),
1941 Anum_pg_trigger_tgargs,
1942 tgrel->
rd_att, &isnull));
1944 elog(
ERROR,
"tgargs is null in trigger for relation \"%s\"",
1957 datum =
fastgetattr(htup, Anum_pg_trigger_tgoldtable,
1965 datum =
fastgetattr(htup, Anum_pg_trigger_tgnewtable,
1997 for (
i = 0;
i < numtrigs;
i++)
2018 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2019 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
2021 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2022 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
2024 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2025 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_INSERT);
2027 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2028 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
2030 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2031 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
2033 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2034 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
2036 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2037 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
2039 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2040 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_UPDATE);
2042 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2043 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
2045 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2046 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
2048 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2049 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
2051 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2052 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
2054 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2055 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_DELETE);
2057 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2058 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
2060 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2061 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
2064 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2065 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_TRUNCATE);
2067 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2068 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_TRUNCATE);
2071 (TRIGGER_FOR_INSERT(tgtype) &&
2072 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgnewtable));
2074 (TRIGGER_FOR_UPDATE(tgtype) &&
2075 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgoldtable));
2077 (TRIGGER_FOR_UPDATE(tgtype) &&
2078 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgnewtable));
2080 (TRIGGER_FOR_DELETE(tgtype) &&
2081 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgoldtable));
2096 if (trigdesc == NULL || trigdesc->
numtriggers <= 0)
2103 memcpy(trigger, trigdesc->
triggers,
2115 memcpy(newattr, trigger->
tgattr,
2117 trigger->
tgattr = newattr;
2124 newargs = (
char **)
palloc(trigger->
tgnargs *
sizeof(
char *));
2127 trigger->
tgargs = newargs;
2150 if (trigdesc == NULL)
2161 while (--(trigger->
tgnargs) >= 0)
2199 if (trigdesc1 != NULL)
2201 if (trigdesc2 == NULL)
2247 else if (trig1->
tgqual == NULL || trig2->
tgqual == NULL)
2265 else if (trigdesc2 != NULL)
2279 if (trigdesc != NULL)
2384 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2385 errmsg(
"trigger function %u returned null value",
2386 fcinfo->flinfo->fn_oid)));
2407 if (trigdesc == NULL)
2417 LocTriggerData.
type = T_TriggerData;
2426 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2427 TRIGGER_TYPE_STATEMENT,
2428 TRIGGER_TYPE_BEFORE,
2429 TRIGGER_TYPE_INSERT))
2444 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2445 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2458 false, NULL, NULL,
NIL, NULL, transition_capture,
2472 LocTriggerData.
type = T_TriggerData;
2482 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2484 TRIGGER_TYPE_BEFORE,
2485 TRIGGER_TYPE_INSERT))
2502 if (newtuple == NULL)
2508 else if (newtuple != oldtuple)
2522 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2523 errmsg(
"moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported"),
2524 errdetail(
"Before executing trigger \"%s\", the row was to be in partition \"%s.%s\".",
2552 recheckIndexes, NULL,
2567 LocTriggerData.
type = T_TriggerData;
2577 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2579 TRIGGER_TYPE_INSTEAD,
2580 TRIGGER_TYPE_INSERT))
2597 if (newtuple == NULL)
2603 else if (newtuple != oldtuple)
2627 if (trigdesc == NULL)
2637 LocTriggerData.
type = T_TriggerData;
2646 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2647 TRIGGER_TYPE_STATEMENT,
2648 TRIGGER_TYPE_BEFORE,
2649 TRIGGER_TYPE_DELETE))
2664 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2665 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2678 false, NULL, NULL,
NIL, NULL, transition_capture,
2703 bool should_free =
false;
2707 if (fdw_trigtuple == NULL)
2721 if (epqslot_candidate != NULL && epqslot != NULL)
2723 *epqslot = epqslot_candidate;
2731 trigtuple = fdw_trigtuple;
2735 LocTriggerData.
type = T_TriggerData;
2745 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2747 TRIGGER_TYPE_BEFORE,
2748 TRIGGER_TYPE_DELETE))
2762 if (newtuple == NULL)
2767 if (newtuple != trigtuple)
2786 bool is_crosspart_update)
2796 if (fdw_trigtuple == NULL)
2811 true, slot, NULL,
NIL, NULL,
2813 is_crosspart_update);
2826 LocTriggerData.
type = T_TriggerData;
2839 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2841 TRIGGER_TYPE_INSTEAD,
2842 TRIGGER_TYPE_DELETE))
2856 if (rettuple == NULL)
2858 if (rettuple != trigtuple)
2874 if (trigdesc == NULL)
2889 LocTriggerData.
type = T_TriggerData;
2899 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2900 TRIGGER_TYPE_STATEMENT,
2901 TRIGGER_TYPE_BEFORE,
2902 TRIGGER_TYPE_UPDATE))
2905 updatedCols, NULL, NULL))
2917 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2918 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2934 false, NULL, NULL,
NIL,
2953 bool should_free_trig =
false;
2954 bool should_free_new =
false;
2964 if (fdw_trigtuple == NULL)
2970 lockmode, oldslot, &epqslot_candidate,
2983 if (epqslot_candidate != NULL)
2996 if (
unlikely(newslot != epqslot_clean))
3021 trigtuple = fdw_trigtuple;
3024 LocTriggerData.
type = T_TriggerData;
3036 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3038 TRIGGER_TYPE_BEFORE,
3039 TRIGGER_TYPE_UPDATE))
3042 updatedCols, oldslot, newslot))
3059 if (newtuple == NULL)
3061 if (should_free_trig)
3063 if (should_free_new)
3067 else if (newtuple != oldtuple)
3079 if (should_free_trig && newtuple == trigtuple)
3082 if (should_free_new)
3089 if (should_free_trig)
3112 List *recheckIndexes,
3114 bool is_crosspart_update)
3119 (transition_capture &&
3132 Assert((src_partinfo != NULL && dst_partinfo != NULL) ||
3133 !is_crosspart_update);
3135 tupsrc = src_partinfo ? src_partinfo : relinfo;
3148 else if (fdw_trigtuple != NULL)
3154 src_partinfo, dst_partinfo,
3157 oldslot, newslot, recheckIndexes,
3160 is_crosspart_update);
3175 LocTriggerData.
type = T_TriggerData;
3188 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3190 TRIGGER_TYPE_INSTEAD,
3191 TRIGGER_TYPE_UPDATE))
3194 NULL, oldslot, newslot))
3211 if (newtuple == NULL)
3215 else if (newtuple != oldtuple)
3239 if (trigdesc == NULL)
3244 LocTriggerData.
type = T_TriggerData;
3254 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3255 TRIGGER_TYPE_STATEMENT,
3256 TRIGGER_TYPE_BEFORE,
3257 TRIGGER_TYPE_TRUNCATE))
3272 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
3273 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
3286 false, NULL, NULL,
NIL, NULL, NULL,
3307 if (epqslot != NULL)
3316 Assert(epqstate != NULL);
3349 (
errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
3350 errmsg(
"tuple to be updated was already modified by an operation triggered by the current command"),
3351 errhint(
"Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
3392 errmsg(
"could not serialize access due to concurrent update")));
3393 elog(
ERROR,
"unexpected table_tuple_lock status: %u",
test);
3400 errmsg(
"could not serialize access due to concurrent delete")));
3405 elog(
ERROR,
"attempted to lock invisible tuple");
3409 elog(
ERROR,
"unrecognized table_tuple_lock status: %u",
test);
3421 elog(
ERROR,
"failed to fetch tuple for trigger");
3495 if (*predicate == NULL)
3524 if (!
ExecQual(*predicate, econtext))
3630#define AFTER_TRIGGER_OFFSET 0x07FFFFFF
3631#define AFTER_TRIGGER_DONE 0x80000000
3632#define AFTER_TRIGGER_IN_PROGRESS 0x40000000
3634#define AFTER_TRIGGER_FDW_REUSE 0x00000000
3635#define AFTER_TRIGGER_FDW_FETCH 0x20000000
3636#define AFTER_TRIGGER_1CTID 0x10000000
3637#define AFTER_TRIGGER_2CTID 0x30000000
3638#define AFTER_TRIGGER_CP_UPDATE 0x08000000
3639#define AFTER_TRIGGER_TUP_BITS 0x38000000
3691#define SizeofTriggerEvent(evt) \
3692 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_CP_UPDATE ? \
3693 sizeof(AfterTriggerEventData) : \
3694 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \
3695 sizeof(AfterTriggerEventDataNoOids) : \
3696 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \
3697 sizeof(AfterTriggerEventDataOneCtid) : \
3698 sizeof(AfterTriggerEventDataZeroCtids))))
3700#define GetTriggerSharedData(evt) \
3701 ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
3719#define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
3730#define for_each_chunk(cptr, evtlist) \
3731 for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
3732#define for_each_event(eptr, cptr) \
3733 for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
3734 (char *) eptr < (cptr)->freeptr; \
3735 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3737#define for_each_event_chunk(eptr, cptr, evtlist) \
3738 for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
3741#define for_each_chunk_from(cptr) \
3742 for (; cptr != NULL; cptr = cptr->next)
3743#define for_each_event_from(eptr, cptr) \
3745 (char *) eptr < (cptr)->freeptr; \
3746 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3921 Oid tgoid,
bool tgisdeferred);
3986 for (
i = 0;
i <
state->numstates;
i++)
3988 if (
state->trigstates[
i].sct_tgoid == tgoid)
3989 return state->trigstates[
i].sct_tgisdeferred;
3993 if (
state->all_isset)
3994 return state->all_isdeferred;
4049 chunk = events->
tail;
4050 if (chunk == NULL ||
4051 chunk->endfree - chunk->freeptr < needed)
4059 "AfterTriggerEvents",
4077#define MIN_CHUNK_SIZE 1024
4078#define MAX_CHUNK_SIZE (1024*1024)
4080#if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
4081#error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
4089 chunksize = chunk->endptr - (
char *) chunk;
4091 if ((chunk->endptr - chunk->endfree) <=
4101 chunk->endptr = chunk->endfree = (
char *) chunk + chunksize;
4102 Assert(chunk->endfree - chunk->freeptr >= needed);
4104 if (events->
tail == NULL)
4107 events->
head = chunk;
4111 events->
tail = chunk;
4121 (
char *) newshared < chunk->endptr;
4135 if ((
char *) newshared >= chunk->endptr)
4138 *newshared = *evtshared;
4142 chunk->endfree = (
char *) newshared;
4147 memcpy(newevent, event, eventsize);
4149 newevent->
ate_flags &= ~AFTER_TRIGGER_OFFSET;
4150 newevent->
ate_flags |= (
char *) newshared - (
char *) newevent;
4152 chunk->freeptr += eventsize;
4167 while ((chunk = events->
head) != NULL)
4172 events->
tail = NULL;
4190 if (old_events->
tail == NULL)
4197 *events = *old_events;
4199 for (chunk = events->
tail->
next; chunk != NULL; chunk = next_chunk)
4201 next_chunk = chunk->
next;
4304 int save_sec_context;
4307 bool should_free_trig =
false;
4308 bool should_free_new =
false;
4315 if (trigdesc == NULL)
4317 for (tgindx = 0; tgindx < trigdesc->
numtriggers; tgindx++)
4346 elog(
ERROR,
"failed to fetch tuple1 for AFTER trigger");
4352 elog(
ERROR,
"failed to fetch tuple2 for AFTER trigger");
4373 LocTriggerData.
tg_newslot = trig_tuple_slot2;
4393 elog(
ERROR,
"failed to fetch tuple1 for AFTER trigger");
4399 if (src_relInfo != relInfo)
4435 elog(
ERROR,
"failed to fetch tuple2 for AFTER trigger");
4442 if (dst_relInfo != relInfo)
4499 LocTriggerData.
type = T_TriggerData;
4528 if (rettuple != NULL &&
4540 if (should_free_trig)
4542 if (should_free_new)
4546 if (trig_tuple_slot1 == NULL)
4580 bool immediate_only)
4583 bool deferred_found =
false;
4590 bool defer_it =
false;
4617 if (defer_it && move_list != NULL)
4619 deferred_found =
true;
4634 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4635 errmsg(
"cannot fire deferred trigger within security-restricted operation")));
4667 bool all_fired =
true;
4670 bool local_estate =
false;
4683 local_estate =
true;
4689 "AfterTriggerTupleContext",
4695 bool all_fired_in_chunk =
true;
4729 slot1 = slot2 = NULL;
4731 if (rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4757 src_rInfo = dst_rInfo = rInfo;
4765 src_rInfo, dst_rInfo,
4766 trigdesc, finfo, instr,
4767 per_tuple_context, slot1, slot2);
4772 event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
4778 all_fired = all_fired_in_chunk =
false;
4783 if (delete_ok && all_fired_in_chunk)
4794 if (chunk == events->
tail)
4846 if (table->
relid == relid && table->
cmdType == cmdType &&
4854 table->
relid = relid;
4928 if (trigdesc == NULL)
4935 need_old_upd = need_old_del = need_new_upd =
false;
4941 need_old_del = need_new_ins =
false;
4945 need_old_upd = need_new_upd = need_new_ins =
false;
4954 elog(
ERROR,
"unexpected CmdType: %d", (
int) cmdType);
4956 need_old_upd = need_new_upd = need_old_del = need_new_ins =
false;
4959 if (!need_old_upd && !need_new_upd && !need_new_ins && !need_old_del)
4964 elog(
ERROR,
"MakeTransitionCaptureState() called outside of query");
5003 state->tcs_delete_old_table = need_old_del;
5004 state->tcs_update_old_table = need_old_upd;
5005 state->tcs_update_new_table = need_new_upd;
5006 state->tcs_insert_new_table = need_new_ins;
5007 state->tcs_private = table;
5235 bool snap_pushed =
false;