50 #include "utils/fmgroids.h"
71 const char *expected_name);
73 Oid parentTriggerOid,
const char *newname,
74 const char *expected_name);
97 int event,
bool row_trigger,
101 bool is_crosspart_update);
159 Oid relOid,
Oid refRelOid,
Oid constraintOid,
Oid indexOid,
160 Oid funcoid,
Oid parentTriggerOid,
Node *whenClause,
161 bool isInternal,
bool in_partition)
165 constraintOid, indexOid, funcoid,
166 parentTriggerOid, whenClause, isInternal,
176 Oid relOid,
Oid refRelOid,
Oid constraintOid,
177 Oid indexOid,
Oid funcoid,
Oid parentTriggerOid,
178 Node *whenClause,
bool isInternal,
bool in_partition,
179 char trigger_fires_when)
188 bool nulls[Natts_pg_trigger];
201 char *oldtablename = NULL;
202 char *newtablename = NULL;
203 bool partition_recurse;
204 bool trigger_exists =
false;
206 bool existing_isInternal =
false;
207 bool existing_isClone =
false;
218 if (rel->
rd_rel->relkind == RELKIND_RELATION)
221 if (
stmt->timing != TRIGGER_TYPE_BEFORE &&
222 stmt->timing != TRIGGER_TYPE_AFTER)
224 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
225 errmsg(
"\"%s\" is a table",
227 errdetail(
"Tables cannot have INSTEAD OF triggers.")));
229 else if (rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
232 if (
stmt->timing != TRIGGER_TYPE_BEFORE &&
233 stmt->timing != TRIGGER_TYPE_AFTER)
235 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
236 errmsg(
"\"%s\" is a table",
238 errdetail(
"Tables cannot have INSTEAD OF triggers.")));
256 if (
stmt->transitionRels !=
NIL)
258 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
259 errmsg(
"\"%s\" is a partitioned table",
261 errdetail(
"ROW triggers with transition tables are not supported on partitioned tables.")));
264 else if (rel->
rd_rel->relkind == RELKIND_VIEW)
270 if (
stmt->timing != TRIGGER_TYPE_INSTEAD &&
stmt->row)
272 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
273 errmsg(
"\"%s\" is a view",
275 errdetail(
"Views cannot have row-level BEFORE or AFTER triggers.")));
277 if (TRIGGER_FOR_TRUNCATE(
stmt->events))
279 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
280 errmsg(
"\"%s\" is a view",
282 errdetail(
"Views cannot have TRUNCATE triggers.")));
284 else if (rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
286 if (
stmt->timing != TRIGGER_TYPE_BEFORE &&
287 stmt->timing != TRIGGER_TYPE_AFTER)
289 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
290 errmsg(
"\"%s\" is a foreign table",
292 errdetail(
"Foreign tables cannot have INSTEAD OF triggers.")));
299 if (
stmt->isconstraint)
301 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
302 errmsg(
"\"%s\" is a foreign table",
304 errdetail(
"Foreign tables cannot have constraint triggers.")));
308 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
309 errmsg(
"relation \"%s\" cannot have triggers",
315 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
316 errmsg(
"permission denied: \"%s\" is a system catalog",
319 if (
stmt->isconstraint)
331 constrrelid = refRelOid;
333 else if (
stmt->constrrel != NULL)
363 partition_recurse = !isInternal &&
stmt->row &&
364 rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE;
365 if (partition_recurse)
370 TRIGGER_CLEAR_TYPE(tgtype);
372 TRIGGER_SETT_ROW(tgtype);
373 tgtype |=
stmt->timing;
374 tgtype |=
stmt->events;
377 if (TRIGGER_FOR_ROW(tgtype) && TRIGGER_FOR_TRUNCATE(tgtype))
379 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
380 errmsg(
"TRUNCATE FOR EACH ROW triggers are not supported")));
383 if (TRIGGER_FOR_INSTEAD(tgtype))
385 if (!TRIGGER_FOR_ROW(tgtype))
387 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
388 errmsg(
"INSTEAD OF triggers must be FOR EACH ROW")));
389 if (
stmt->whenClause)
391 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
392 errmsg(
"INSTEAD OF triggers cannot have WHEN conditions")));
395 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
396 errmsg(
"INSTEAD OF triggers cannot have column lists")));
413 if (
stmt->transitionRels !=
NIL)
415 List *varList =
stmt->transitionRels;
424 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
425 errmsg(
"ROW variable naming in the REFERENCING clause is not supported"),
426 errhint(
"Use OLD TABLE or NEW TABLE for naming transition tables.")));
434 if (rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
436 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
437 errmsg(
"\"%s\" is a foreign table",
439 errdetail(
"Triggers on foreign tables cannot have transition tables.")));
441 if (rel->
rd_rel->relkind == RELKIND_VIEW)
443 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
444 errmsg(
"\"%s\" is a view",
446 errdetail(
"Triggers on views cannot have transition tables.")));
459 if (rel->
rd_rel->relispartition)
461 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
462 errmsg(
"ROW triggers with transition tables are not supported on partitions")));
465 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
466 errmsg(
"ROW triggers with transition tables are not supported on inheritance children")));
469 if (
stmt->timing != TRIGGER_TYPE_AFTER)
471 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
472 errmsg(
"transition table name can only be specified for an AFTER trigger")));
474 if (TRIGGER_FOR_TRUNCATE(tgtype))
476 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
477 errmsg(
"TRUNCATE triggers with transition tables are not supported")));
489 if (((TRIGGER_FOR_INSERT(tgtype) ? 1 : 0) +
490 (TRIGGER_FOR_UPDATE(tgtype) ? 1 : 0) +
491 (TRIGGER_FOR_DELETE(tgtype) ? 1 : 0)) != 1)
493 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
494 errmsg(
"transition tables cannot be specified for triggers with more than one event")));
504 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
505 errmsg(
"transition tables cannot be specified for triggers with column lists")));
518 if (!(TRIGGER_FOR_INSERT(tgtype) ||
519 TRIGGER_FOR_UPDATE(tgtype)))
521 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
522 errmsg(
"NEW TABLE can only be specified for an INSERT or UPDATE trigger")));
524 if (newtablename != NULL)
526 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
527 errmsg(
"NEW TABLE cannot be specified multiple times")));
529 newtablename = tt->
name;
533 if (!(TRIGGER_FOR_DELETE(tgtype) ||
534 TRIGGER_FOR_UPDATE(tgtype)))
536 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
537 errmsg(
"OLD TABLE can only be specified for a DELETE or UPDATE trigger")));
539 if (oldtablename != NULL)
541 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
542 errmsg(
"OLD TABLE cannot be specified multiple times")));
544 oldtablename = tt->
name;
548 if (newtablename != NULL && oldtablename != NULL &&
549 strcmp(newtablename, oldtablename) == 0)
551 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
552 errmsg(
"OLD TABLE name and NEW TABLE name cannot be the same")));
563 if (!whenClause &&
stmt->whenClause)
613 if (!TRIGGER_FOR_ROW(tgtype))
615 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
616 errmsg(
"statement trigger's WHEN condition cannot reference column values"),
618 if (TRIGGER_FOR_INSERT(tgtype))
620 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
621 errmsg(
"INSERT trigger's WHEN condition cannot reference OLD values"),
626 if (!TRIGGER_FOR_ROW(tgtype))
628 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
629 errmsg(
"statement trigger's WHEN condition cannot reference column values"),
631 if (TRIGGER_FOR_DELETE(tgtype))
633 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
634 errmsg(
"DELETE trigger's WHEN condition cannot reference NEW values"),
636 if (var->
varattno < 0 && TRIGGER_FOR_BEFORE(tgtype))
638 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
639 errmsg(
"BEFORE trigger's WHEN condition cannot reference NEW system columns"),
641 if (TRIGGER_FOR_BEFORE(tgtype) &&
646 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
647 errmsg(
"BEFORE trigger's WHEN condition cannot reference NEW generated columns"),
648 errdetail(
"A whole-row reference is used and the table contains generated columns."),
650 if (TRIGGER_FOR_BEFORE(tgtype) &&
654 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
655 errmsg(
"BEFORE trigger's WHEN condition cannot reference NEW generated columns"),
656 errdetail(
"Column \"%s\" is a generated column.",
662 elog(
ERROR,
"trigger WHEN condition cannot contain references to other relations");
674 else if (!whenClause)
699 if (funcrettype != TRIGGEROID)
701 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
702 errmsg(
"function %s must return type %s",
720 Anum_pg_trigger_tgrelid,
725 Anum_pg_trigger_tgname,
737 trigoid = oldtrigger->oid;
738 existing_constraint_oid = oldtrigger->tgconstraint;
739 existing_isInternal = oldtrigger->tgisinternal;
740 existing_isClone =
OidIsValid(oldtrigger->tgparentid);
741 trigger_exists =
true;
752 Anum_pg_trigger_oid);
763 errmsg(
"trigger \"%s\" for relation \"%s\" already exists",
772 if ((existing_isInternal || existing_isClone) &&
773 !isInternal && !in_partition)
776 errmsg(
"trigger \"%s\" for relation \"%s\" is an internal or a child trigger",
795 errmsg(
"trigger \"%s\" for relation \"%s\" is a constraint trigger",
848 snprintf(internaltrigname,
sizeof(internaltrigname),
849 "%s_%u",
stmt->trigname, trigoid);
850 trigname = internaltrigname;
855 trigname =
stmt->trigname;
861 memset(nulls,
false,
sizeof(nulls));
870 values[Anum_pg_trigger_tgenabled - 1] = trigger_fires_when;
885 foreach(le,
stmt->args)
889 len += strlen(ar) + 4;
898 foreach(le,
stmt->args)
932 foreach(cell,
stmt->columns)
942 (
errcode(ERRCODE_UNDEFINED_COLUMN),
943 errmsg(
"column \"%s\" of relation \"%s\" does not exist",
947 for (
j =
i - 1;
j >= 0;
j--)
951 (
errcode(ERRCODE_DUPLICATE_COLUMN),
952 errmsg(
"column \"%s\" specified more than once",
966 nulls[Anum_pg_trigger_tgqual - 1] =
true;
972 nulls[Anum_pg_trigger_tgoldtable - 1] =
true;
977 nulls[Anum_pg_trigger_tgnewtable - 1] =
true;
1015 elog(
ERROR,
"cache lookup failed for relation %u",
1042 myself.
classId = TriggerRelationId;
1046 referenced.
classId = ProcedureRelationId;
1059 referenced.
classId = ConstraintRelationId;
1060 referenced.
objectId = constraintOid;
1071 referenced.
classId = RelationRelationId;
1078 referenced.
classId = RelationRelationId;
1092 referenced.
classId = ConstraintRelationId;
1093 referenced.
objectId = constraintOid;
1111 if (columns != NULL)
1115 referenced.
classId = RelationRelationId;
1117 for (
i = 0;
i < ncolumns;
i++)
1128 if (whenRtable !=
NIL)
1139 if (partition_recurse)
1186 partdesc->
oids[
i], refRelOid,
1188 funcoid, trigoid, qual,
1189 isInternal,
true, trigger_fires_when);
1233 Anum_pg_trigger_oid,
1242 elog(
ERROR,
"could not find tuple for trigger %u", childTrigId);
1249 elog(
ERROR,
"trigger %u already has a parent trigger",
1252 trigForm->tgparentid = parentTrigId;
1302 Anum_pg_trigger_oid,
1311 elog(
ERROR,
"could not find tuple for trigger %u", trigOid);
1320 if (rel->
rd_rel->relkind != RELKIND_RELATION &&
1321 rel->
rd_rel->relkind != RELKIND_VIEW &&
1322 rel->
rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1323 rel->
rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1325 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1326 errmsg(
"relation \"%s\" cannot have triggers",
1332 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1333 errmsg(
"permission denied: \"%s\" is a system catalog",
1380 Anum_pg_trigger_tgrelid,
1384 Anum_pg_trigger_tgname,
1397 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1398 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1428 if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
1429 form->relkind != RELKIND_FOREIGN_TABLE &&
1430 form->relkind != RELKIND_PARTITIONED_TABLE)
1432 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1433 errmsg(
"relation \"%s\" cannot have triggers",
1442 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1443 errmsg(
"permission denied: \"%s\" is a system catalog",
1490 if (targetrel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1499 Anum_pg_trigger_tgrelid,
1503 Anum_pg_trigger_tgname,
1513 tgoid = trigform->oid;
1523 errmsg(
"cannot rename trigger \"%s\" on table \"%s\"",
1525 errhint(
"Rename the trigger on the partitioned table \"%s\" instead.",
1534 if (targetrel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1538 for (
int i = 0;
i < partdesc->
nparts;
i++)
1540 Oid partitionId = partdesc->
oids[
i];
1550 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1551 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1578 const char *newname,
const char *expected_name)
1587 if (strcmp(
NameStr(tgform->tgname), newname) == 0)
1596 Anum_pg_trigger_tgrelid,
1600 Anum_pg_trigger_tgname,
1608 errmsg(
"trigger \"%s\" for relation \"%s\" already exists",
1623 if (strcmp(
NameStr(tgform->tgname), expected_name) != 0)
1625 errmsg(
"renamed trigger \"%s\" on relation \"%s\"",
1649 const char *newname,
const char *expected_name)
1661 Anum_pg_trigger_tgrelid,
1671 if (tgform->tgparentid != parentTriggerOid)
1680 if (partitionRel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1685 for (
int i = 0;
i < partdesc->
nparts;
i++)
1722 char fires_when,
bool skip_system,
bool recurse,
1737 Anum_pg_trigger_tgrelid,
1743 Anum_pg_trigger_tgname,
1754 found = changed =
false;
1760 if (
OidIsValid(tgparent) && tgparent != oldtrig->tgparentid)
1763 if (oldtrig->tgisinternal)
1770 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1771 errmsg(
"permission denied: \"%s\" is a system trigger",
1777 if (oldtrig->tgenabled != fires_when)
1783 newtrig->tgenabled = fires_when;
1802 rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
1803 (TRIGGER_FOR_ROW(oldtrig->tgtype)))
1815 fires_when, skip_system, recurse,
1829 if (tgname && !found)
1831 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1832 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1884 Anum_pg_trigger_tgrelid,
1899 if (numtrigs >= maxtrigs)
1904 build = &(triggers[numtrigs]);
1906 build->
tgoid = pg_trigger->oid;
1909 build->
tgfoid = pg_trigger->tgfoid;
1910 build->
tgtype = pg_trigger->tgtype;
1911 build->
tgenabled = pg_trigger->tgenabled;
1919 build->
tgnargs = pg_trigger->tgnargs;
1921 build->
tgnattr = pg_trigger->tgattr.dim1;
1925 memcpy(build->
tgattr, &(pg_trigger->tgattr.values),
1936 Anum_pg_trigger_tgargs,
1937 tgrel->
rd_att, &isnull));
1939 elog(
ERROR,
"tgargs is null in trigger for relation \"%s\"",
1952 datum =
fastgetattr(htup, Anum_pg_trigger_tgoldtable,
1960 datum =
fastgetattr(htup, Anum_pg_trigger_tgnewtable,
1992 for (
i = 0;
i < numtrigs;
i++)
2013 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2014 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
2016 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2017 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
2019 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2020 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_INSERT);
2022 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2023 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
2025 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2026 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
2028 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2029 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
2031 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2032 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
2034 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2035 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_UPDATE);
2037 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2038 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
2040 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2041 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
2043 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2044 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
2046 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2047 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
2049 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2050 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_DELETE);
2052 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2053 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
2055 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2056 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
2059 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2060 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_TRUNCATE);
2062 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2063 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_TRUNCATE);
2066 (TRIGGER_FOR_INSERT(tgtype) &&
2067 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgnewtable));
2069 (TRIGGER_FOR_UPDATE(tgtype) &&
2070 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgoldtable));
2072 (TRIGGER_FOR_UPDATE(tgtype) &&
2073 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgnewtable));
2075 (TRIGGER_FOR_DELETE(tgtype) &&
2076 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgoldtable));
2091 if (trigdesc == NULL || trigdesc->
numtriggers <= 0)
2098 memcpy(trigger, trigdesc->
triggers,
2110 memcpy(newattr, trigger->
tgattr,
2112 trigger->
tgattr = newattr;
2119 newargs = (
char **)
palloc(trigger->
tgnargs *
sizeof(
char *));
2122 trigger->
tgargs = newargs;
2145 if (trigdesc == NULL)
2156 while (--(trigger->
tgnargs) >= 0)
2194 if (trigdesc1 != NULL)
2196 if (trigdesc2 == NULL)
2242 else if (trig1->
tgqual == NULL || trig2->
tgqual == NULL)
2260 else if (trigdesc2 != NULL)
2274 if (trigdesc != NULL)
2379 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2380 errmsg(
"trigger function %u returned null value",
2381 fcinfo->flinfo->fn_oid)));
2402 if (trigdesc == NULL)
2412 LocTriggerData.
type = T_TriggerData;
2421 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2422 TRIGGER_TYPE_STATEMENT,
2423 TRIGGER_TYPE_BEFORE,
2424 TRIGGER_TYPE_INSERT))
2439 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2440 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2453 false, NULL, NULL,
NIL, NULL, transition_capture,
2467 LocTriggerData.
type = T_TriggerData;
2477 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2479 TRIGGER_TYPE_BEFORE,
2480 TRIGGER_TYPE_INSERT))
2497 if (newtuple == NULL)
2503 else if (newtuple != oldtuple)
2515 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2516 errmsg(
"moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported"),
2517 errdetail(
"Before executing trigger \"%s\", the row was to be in partition \"%s.%s\".",
2545 recheckIndexes, NULL,
2560 LocTriggerData.
type = T_TriggerData;
2570 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2572 TRIGGER_TYPE_INSTEAD,
2573 TRIGGER_TYPE_INSERT))
2590 if (newtuple == NULL)
2596 else if (newtuple != oldtuple)
2620 if (trigdesc == NULL)
2630 LocTriggerData.
type = T_TriggerData;
2639 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2640 TRIGGER_TYPE_STATEMENT,
2641 TRIGGER_TYPE_BEFORE,
2642 TRIGGER_TYPE_DELETE))
2657 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2658 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2671 false, NULL, NULL,
NIL, NULL, transition_capture,
2696 bool should_free =
false;
2700 if (fdw_trigtuple == NULL)
2714 if (epqslot_candidate != NULL && epqslot != NULL)
2716 *epqslot = epqslot_candidate;
2724 trigtuple = fdw_trigtuple;
2728 LocTriggerData.
type = T_TriggerData;
2738 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2740 TRIGGER_TYPE_BEFORE,
2741 TRIGGER_TYPE_DELETE))
2755 if (newtuple == NULL)
2760 if (newtuple != trigtuple)
2779 bool is_crosspart_update)
2789 if (fdw_trigtuple == NULL)
2804 true, slot, NULL,
NIL, NULL,
2806 is_crosspart_update);
2819 LocTriggerData.
type = T_TriggerData;
2832 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2834 TRIGGER_TYPE_INSTEAD,
2835 TRIGGER_TYPE_DELETE))
2849 if (rettuple == NULL)
2851 if (rettuple != trigtuple)
2867 if (trigdesc == NULL)
2882 LocTriggerData.
type = T_TriggerData;
2892 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2893 TRIGGER_TYPE_STATEMENT,
2894 TRIGGER_TYPE_BEFORE,
2895 TRIGGER_TYPE_UPDATE))
2898 updatedCols, NULL, NULL))
2910 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2911 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2927 false, NULL, NULL,
NIL,
2946 bool should_free_trig =
false;
2947 bool should_free_new =
false;
2957 if (fdw_trigtuple == NULL)
2963 lockmode, oldslot, &epqslot_candidate,
2976 if (epqslot_candidate != NULL)
2989 if (
unlikely(newslot != epqslot_clean))
3014 trigtuple = fdw_trigtuple;
3017 LocTriggerData.
type = T_TriggerData;
3029 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3031 TRIGGER_TYPE_BEFORE,
3032 TRIGGER_TYPE_UPDATE))
3035 updatedCols, oldslot, newslot))
3052 if (newtuple == NULL)
3054 if (should_free_trig)
3056 if (should_free_new)
3060 else if (newtuple != oldtuple)
3070 if (should_free_trig && newtuple == trigtuple)
3073 if (should_free_new)
3080 if (should_free_trig)
3103 List *recheckIndexes,
3105 bool is_crosspart_update)
3110 (transition_capture &&
3123 Assert((src_partinfo != NULL && dst_partinfo != NULL) ||
3124 !is_crosspart_update);
3126 tupsrc = src_partinfo ? src_partinfo : relinfo;
3139 else if (fdw_trigtuple != NULL)
3145 src_partinfo, dst_partinfo,
3148 oldslot, newslot, recheckIndexes,
3151 is_crosspart_update);
3166 LocTriggerData.
type = T_TriggerData;
3179 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3181 TRIGGER_TYPE_INSTEAD,
3182 TRIGGER_TYPE_UPDATE))
3185 NULL, oldslot, newslot))
3202 if (newtuple == NULL)
3206 else if (newtuple != oldtuple)
3230 if (trigdesc == NULL)
3235 LocTriggerData.
type = T_TriggerData;
3245 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3246 TRIGGER_TYPE_STATEMENT,
3247 TRIGGER_TYPE_BEFORE,
3248 TRIGGER_TYPE_TRUNCATE))
3263 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
3264 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
3277 false, NULL, NULL,
NIL, NULL, NULL,
3298 if (epqslot != NULL)
3307 Assert(epqstate != NULL);
3340 (
errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
3341 errmsg(
"tuple to be updated was already modified by an operation triggered by the current command"),
3342 errhint(
"Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
3383 errmsg(
"could not serialize access due to concurrent update")));
3384 elog(
ERROR,
"unexpected table_tuple_lock status: %u",
test);
3391 errmsg(
"could not serialize access due to concurrent delete")));
3396 elog(
ERROR,
"attempted to lock invisible tuple");
3400 elog(
ERROR,
"unrecognized table_tuple_lock status: %u",
test);
3412 elog(
ERROR,
"failed to fetch tuple for trigger");
3486 if (*predicate == NULL)
3513 if (!
ExecQual(*predicate, econtext))
3619 #define AFTER_TRIGGER_OFFSET 0x07FFFFFF
3620 #define AFTER_TRIGGER_DONE 0x80000000
3621 #define AFTER_TRIGGER_IN_PROGRESS 0x40000000
3623 #define AFTER_TRIGGER_FDW_REUSE 0x00000000
3624 #define AFTER_TRIGGER_FDW_FETCH 0x20000000
3625 #define AFTER_TRIGGER_1CTID 0x10000000
3626 #define AFTER_TRIGGER_2CTID 0x30000000
3627 #define AFTER_TRIGGER_CP_UPDATE 0x08000000
3628 #define AFTER_TRIGGER_TUP_BITS 0x38000000
3679 #define SizeofTriggerEvent(evt) \
3680 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_CP_UPDATE ? \
3681 sizeof(AfterTriggerEventData) : \
3682 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \
3683 sizeof(AfterTriggerEventDataNoOids) : \
3684 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \
3685 sizeof(AfterTriggerEventDataOneCtid) : \
3686 sizeof(AfterTriggerEventDataZeroCtids))))
3688 #define GetTriggerSharedData(evt) \
3689 ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
3707 #define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
3718 #define for_each_chunk(cptr, evtlist) \
3719 for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
3720 #define for_each_event(eptr, cptr) \
3721 for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
3722 (char *) eptr < (cptr)->freeptr; \
3723 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3725 #define for_each_event_chunk(eptr, cptr, evtlist) \
3726 for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
3729 #define for_each_chunk_from(cptr) \
3730 for (; cptr != NULL; cptr = cptr->next)
3731 #define for_each_event_from(eptr, cptr) \
3733 (char *) eptr < (cptr)->freeptr; \
3734 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3909 Oid tgoid,
bool tgisdeferred);
3974 for (
i = 0;
i <
state->numstates;
i++)
3976 if (
state->trigstates[
i].sct_tgoid == tgoid)
3977 return state->trigstates[
i].sct_tgisdeferred;
3981 if (
state->all_isset)
3982 return state->all_isdeferred;
4011 "AfterTriggerEvents",
4044 chunk = events->
tail;
4045 if (chunk == NULL ||
4046 chunk->endfree - chunk->freeptr < needed)
4054 "AfterTriggerEvents",
4072 #define MIN_CHUNK_SIZE 1024
4073 #define MAX_CHUNK_SIZE (1024*1024)
4075 #if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
4076 #error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
4084 chunksize = chunk->endptr - (
char *) chunk;
4086 if ((chunk->endptr - chunk->endfree) <=
4096 chunk->endptr = chunk->endfree = (
char *) chunk + chunksize;
4097 Assert(chunk->endfree - chunk->freeptr >= needed);
4099 if (events->
head == NULL)
4100 events->
head = chunk;
4103 events->
tail = chunk;
4112 (
char *) newshared >= chunk->endfree;
4122 if ((
char *) newshared < chunk->endfree)
4124 *newshared = *evtshared;
4126 chunk->endfree = (
char *) newshared;
4131 memcpy(newevent, event, eventsize);
4134 newevent->
ate_flags |= (
char *) newshared - (
char *) newevent;
4136 chunk->freeptr += eventsize;
4151 while ((chunk = events->
head) != NULL)
4156 events->
tail = NULL;
4174 if (old_events->
tail == NULL)
4181 *events = *old_events;
4183 for (chunk = events->
tail->
next; chunk != NULL; chunk = next_chunk)
4185 next_chunk = chunk->
next;
4289 bool should_free_trig =
false;
4290 bool should_free_new =
false;
4295 for (tgindx = 0; tgindx < trigdesc->
numtriggers; tgindx++)
4304 elog(
ERROR,
"could not find trigger %u", tgoid);
4324 elog(
ERROR,
"failed to fetch tuple1 for AFTER trigger");
4330 elog(
ERROR,
"failed to fetch tuple2 for AFTER trigger");
4351 LocTriggerData.
tg_newslot = trig_tuple_slot2;
4371 elog(
ERROR,
"failed to fetch tuple1 for AFTER trigger");
4377 if (src_relInfo != relInfo)
4413 elog(
ERROR,
"failed to fetch tuple2 for AFTER trigger");
4420 if (dst_relInfo != relInfo)
4477 LocTriggerData.
type = T_TriggerData;
4495 if (rettuple != NULL &&
4503 if (should_free_trig)
4505 if (should_free_new)
4509 if (trig_tuple_slot1 == NULL)
4543 bool immediate_only)
4546 bool deferred_found =
false;
4553 bool defer_it =
false;
4580 if (defer_it && move_list != NULL)
4582 deferred_found =
true;
4597 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4598 errmsg(
"cannot fire deferred trigger within security-restricted operation")));
4630 bool all_fired =
true;
4633 bool local_estate =
false;
4646 local_estate =
true;
4652 "AfterTriggerTupleContext",
4658 bool all_fired_in_chunk =
true;
4691 slot1 = slot2 = NULL;
4693 if (rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4700 if (trigdesc == NULL)
4701 elog(
ERROR,
"relation %u has no triggers",
4722 src_rInfo = dst_rInfo = rInfo;
4730 src_rInfo, dst_rInfo,
4731 trigdesc, finfo, instr,
4732 per_tuple_context, slot1, slot2);
4743 all_fired = all_fired_in_chunk =
false;
4748 if (delete_ok && all_fired_in_chunk)
4759 if (chunk == events->
tail)
4811 if (table->
relid == relid && table->
cmdType == cmdType &&
4819 table->
relid = relid;
4893 if (trigdesc == NULL)
4900 need_old_upd = need_old_del = need_new_upd =
false;
4906 need_old_del = need_new_ins =
false;
4910 need_old_upd = need_new_upd = need_new_ins =
false;
4919 elog(
ERROR,
"unexpected CmdType: %d", (
int) cmdType);
4921 need_old_upd = need_new_upd = need_old_del = need_new_ins =
false;
4924 if (!need_old_upd && !need_new_upd && !need_new_ins && !need_old_del)
4929 elog(
ERROR,
"MakeTransitionCaptureState() called outside of query");
4972 state->tcs_private = table;
5200 bool snap_pushed =
false;
5211 if (events->
head != NULL)
5509 if (tuplestore == NULL)
5512 if (original_insert_tuple)
5600 state->numalloc = numalloc;
5630 Oid tgoid,
bool tgisdeferred)
5634 int newalloc =
state->numalloc * 2;
5636 newalloc =
Max(newalloc, 8);
5641 state->numalloc = newalloc;
5645 state->trigstates[
state->numstates].sct_tgoid = tgoid;
5646 state->trigstates[
state->numstates].sct_tgisdeferred = tgisdeferred;
5718 foreach(lc,
stmt->constraints)
5722 List *namespacelist;
5729 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5730 errmsg(
"cross-database references are not implemented: \"%s.%s.%s\"",
5753 foreach(nslc, namespacelist)
5761 Anum_pg_constraint_conname,
5765 Anum_pg_constraint_connamespace,
5770 true, NULL, 2, skey);
5776 if (con->condeferrable)
5778 else if (
stmt->deferred)
5780 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
5781 errmsg(
"constraint \"%s\" is not deferrable",
5803 (
errcode(ERRCODE_UNDEFINED_OBJECT),
5804 errmsg(
"constraint \"%s\" does not exist",
5814 foreach(lc, conoidlist)
5822 Anum_pg_constraint_conparentid,
5846 foreach(lc, conoidlist)
5854 Anum_pg_trigger_tgconstraint,
5871 if (pg_trigger->tgdeferrable)
5872 tgoidlist =
lappend_oid(tgoidlist, pg_trigger->oid);
5884 foreach(lc, tgoidlist)
5891 for (
i = 0;
i <
state->numstates;
i++)
5893 if (
state->trigstates[
i].sct_tgoid == tgoid)
5895 state->trigstates[
i].sct_tgisdeferred =
stmt->deferred;
5919 if (!
stmt->deferred)
5922 bool snapshot_set =
false;
5940 snapshot_set =
true;
6064 int event,
bool row_trigger,
6068 bool is_crosspart_update)
6074 char relkind = rel->
rd_rel->relkind;
6086 elog(
ERROR,
"AfterTriggerSaveEvent() called outside of query");
6096 if (row_trigger && transition_capture != NULL)
6111 transition_capture);
6113 oldslot, NULL, old_tuplestore);
6127 transition_capture);
6129 newslot, original_insert_tuple, new_tuplestore);
6139 if (trigdesc == NULL ||
6155 rel->
rd_rel->relkind != RELKIND_PARTITIONED_TABLE ||
6156 (is_crosspart_update &&
6158 src_partinfo != NULL && dst_partinfo != NULL));
6175 tgtype_event = TRIGGER_TYPE_INSERT;
6194 tgtype_event = TRIGGER_TYPE_DELETE;
6213 tgtype_event = TRIGGER_TYPE_UPDATE;
6225 if (rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6227 Assert(src_partinfo != NULL && dst_partinfo != NULL);
6245 tgtype_event = TRIGGER_TYPE_TRUNCATE;
6252 elog(
ERROR,
"invalid after-trigger event code: %d", event);
6258 if (!(relkind == RELKIND_FOREIGN_TABLE && row_trigger))
6262 if (relkind == RELKIND_PARTITIONED_TABLE)
6273 tgtype_level = (row_trigger ? TRIGGER_TYPE_ROW : TRIGGER_TYPE_STATEMENT);
6280 if (row_trigger && rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6308 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
6314 modifiedCols, oldslot, newslot))
6317 if (relkind == RELKIND_FOREIGN_TABLE && row_trigger)
6319 if (fdw_tuplestore == NULL)
6351 if (is_crosspart_update &&
6378 if (rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
6398 rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6409 if (trigger->
tgfoid == F_UNIQUE_KEY_RECHECK)
6429 transition_capture != NULL)
6436 &new_event, &new_shared);
6446 if (oldslot != NULL)
6448 if (newslot != NULL)
6465 elog(
ERROR,
"before_stmt_triggers_fired() called outside of query");
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
#define InvalidAttrNumber
bool bms_is_member(int x, const Bitmapset *a)
Bitmapset * bms_copy(const Bitmapset *a)
static Datum values[MAXATTR]
#define CStringGetTextDatum(s)
#define TextDatumGetCString(d)
#define FLEXIBLE_ARRAY_MEMBER
#define OidIsValid(objectId)
bool IsSystemRelation(Relation relation)
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
char * get_database_name(Oid dbid)
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
@ DEPENDENCY_PARTITION_PRI
@ DEPENDENCY_PARTITION_SEC
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
ExprState * ExecPrepareQual(List *qual, EState *estate)
LockTupleMode ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo)
TupleTableSlot * EvalPlanQual(EPQState *epqstate, Relation relation, Index rti, TupleTableSlot *inputslot)
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
void ExecCloseResultRelations(EState *estate)
ResultRelInfo * ExecGetTriggerResultRel(EState *estate, Oid relid, ResultRelInfo *rootRelInfo)
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
const TupleTableSlotOps TTSOpsVirtual
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
const TupleTableSlotOps TTSOpsMinimalTuple
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
Bitmapset * ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
TupleTableSlot * ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
EState * CreateExecutorState(void)
TupleTableSlot * ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
void FreeExecutorState(EState *estate)
TupleConversionMap * ExecGetChildToRootMap(ResultRelInfo *resultRelInfo)
#define GetPerTupleExprContext(estate)
#define GetPerTupleMemoryContext(estate)
static bool ExecQual(ExprState *state, ExprContext *econtext)
void fmgr_info(Oid functionId, FmgrInfo *finfo)
#define DatumGetByteaPP(X)
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
#define DirectFunctionCall1(func, arg1)
#define LOCAL_FCINFO(name, nargs)
#define FunctionCallInvoke(fcinfo)
#define PG_RETURN_INT32(x)
void systable_endscan(SysScanDesc sysscan)
HeapTuple systable_getnext(SysScanDesc sysscan)
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
bool allowSystemTableMods
HeapTuple heap_copytuple(HeapTuple tuple)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
void InstrStartNode(Instrumentation *instr)
void InstrStopNode(Instrumentation *instr, double nTuples)
int2vector * buildint2vector(const int16 *int2s, int n)
void CacheInvalidateRelcache(Relation relation)
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
static void ItemPointerSetInvalid(ItemPointerData *pointer)
static void ItemPointerCopy(const ItemPointerData *fromPointer, ItemPointerData *toPointer)
static bool ItemPointerIsValid(const ItemPointerData *pointer)
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
List * lappend_oid(List *list, Oid datum)
void list_free(List *list)
bool list_member_oid(const List *list, Oid datum)
void list_free_deep(List *list)
void LockRelationOid(Oid relid, LOCKMODE lockmode)
#define AccessExclusiveLock
#define ShareRowExclusiveLock
char * get_namespace_name(Oid nspid)
char get_rel_relkind(Oid relid)
char * get_rel_name(Oid relid)
Oid get_func_rettype(Oid funcid)
Alias * makeAlias(const char *aliasname, List *colnames)
List * make_ands_implicit(Expr *clause)
void MemoryContextReset(MemoryContext context)
MemoryContext TopTransactionContext
char * pstrdup(const char *in)
void pfree(void *pointer)
void * palloc0(Size size)
void * MemoryContextAllocZero(MemoryContext context, Size size)
MemoryContext CurTransactionContext
MemoryContext CurrentMemoryContext
void * repalloc(void *pointer, Size size)
void * MemoryContextAlloc(MemoryContext context, Size size)
MemoryContext CacheMemoryContext
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define ALLOCSET_SMALL_SIZES
bool InSecurityRestrictedOperation(void)
Datum nameout(PG_FUNCTION_ARGS)
void namestrcpy(Name name, const char *str)
Datum namein(PG_FUNCTION_ARGS)
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
List * fetch_search_path(bool includeImplicit)
char * NameListToString(const List *names)
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
#define RangeVarGetRelid(relation, lockmode, missing_ok)
TupleTableSlot * ExecGetUpdateNewTuple(ResultRelInfo *relinfo, TupleTableSlot *planSlot, TupleTableSlot *oldSlot)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
ObjectType get_relkind_objtype(char relkind)
#define ObjectAddressSet(addr, class_id, object_id)
char * nodeToString(const void *obj)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
void assign_expr_collations(ParseState *pstate, Node *expr)
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
void free_parsestate(ParseState *pstate)
int parser_errposition(ParseState *pstate, int location)
ParseState * make_parsestate(ParseState *parentParseState)
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
int attnameAttNum(Relation rd, const char *attname, bool sysColOK)
PartitionDesc RelationGetPartitionDesc(Relation rel, bool omit_detached)
List * map_partition_varattnos(List *expr, int fromrel_varno, Relation to_rel, Relation from_rel)
Oid get_partition_parent(Oid relid, bool even_if_detached)
int errdetail_relkind_not_supported(char relkind)
FormData_pg_class * Form_pg_class
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isValidated, Oid parentConstrId, Oid relId, const int16 *constraintKey, int constraintNKeys, int constraintNTotalKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, const int16 *fkDeleteSetCols, int numFkDeleteSetCols, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, bool conIsLocal, int conInhCount, bool conNoInherit, bool conPeriod, bool is_internal)
FormData_pg_constraint * Form_pg_constraint
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
bool has_superclass(Oid relationId)
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define list_make1_oid(x1)
FormData_pg_trigger * Form_pg_trigger
#define ERRCODE_T_R_SERIALIZATION_FAILURE
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
void ResetPlanCache(void)
static Datum PointerGetDatum(const void *X)
static char * DatumGetCString(Datum X)
static Datum Int16GetDatum(int16 X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static Datum NameGetDatum(const NameData *X)
static Pointer DatumGetPointer(Datum X)
static Datum CStringGetDatum(const char *X)
void * stringToNode(const char *str)
#define RelationHasReferenceCountZero(relation)
#define RelationGetRelid(relation)
#define RelationGetDescr(relation)
#define RelationGetRelationName(relation)
#define RelationGetNamespace(relation)
ResourceOwner CurrentResourceOwner
ResourceOwner CurTransactionResourceOwner
void ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot)
bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot)
int RI_FKey_trigger_type(Oid tgfoid)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Snapshot GetTransactionSnapshot(void)
void PushActiveSnapshot(Snapshot snapshot)
void PopActiveSnapshot(void)
void relation_close(Relation relation, LOCKMODE lockmode)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
#define BTEqualStrategyNumber
#define ERRCODE_DUPLICATE_OBJECT
struct AfterTriggerEventChunk * next
ItemPointerData ate_ctid1
ItemPointerData ate_ctid2
ItemPointerData ate_ctid1
ItemPointerData ate_ctid2
ItemPointerData ate_ctid1
AfterTriggerEventChunk * head
AfterTriggerEventChunk * tail
struct AfterTriggersTableData * ats_table
Bitmapset * ats_modifiedcols
AfterTriggersQueryData * query_stack
AfterTriggersTransData * trans_stack
AfterTriggerEventList events
Tuplestorestate * fdw_tuplestore
AfterTriggerEventList events
TupleTableSlot * storeslot
Tuplestorestate * old_upd_tuplestore
Tuplestorestate * new_upd_tuplestore
Tuplestorestate * old_del_tuplestore
Tuplestorestate * new_ins_tuplestore
AfterTriggerEventList after_trig_events
AfterTriggerEventList events
PlannedStmt * es_plannedstmt
MemoryContext es_query_cxt
TupleTableSlot * ecxt_innertuple
TupleTableSlot * ecxt_outertuple
const char * p_sourcetext
struct ResultRelInfo * ri_RootResultRelInfo
Instrumentation * ri_TrigInstrument
TriggerDesc * ri_TrigDesc
ExprState ** ri_TrigWhenExprs
FmgrInfo * ri_TrigFunctions
SetConstraintTriggerData trigstates[FLEXIBLE_ARRAY_MEMBER]
struct AfterTriggersTableData * tcs_private
TupleTableSlot * tcs_original_insert_tuple
bool tcs_update_new_table
bool tcs_delete_old_table
bool tcs_insert_new_table
bool tcs_update_old_table
Tuplestorestate * tg_oldtable
const Bitmapset * tg_updatedcols
Tuplestorestate * tg_newtable
TupleTableSlot * tg_trigslot
TupleTableSlot * tg_newslot
bool trig_delete_before_row
bool trig_update_instead_row
bool trig_delete_instead_row
bool trig_update_after_row
bool trig_insert_instead_row
bool trig_update_new_table
bool trig_insert_after_row
bool trig_update_after_statement
bool trig_update_before_row
bool trig_truncate_before_statement
bool trig_insert_new_table
bool trig_update_before_statement
bool trig_truncate_after_statement
bool trig_insert_before_statement
bool trig_delete_old_table
bool trig_delete_after_row
bool trig_insert_before_row
bool trig_delete_after_statement
bool trig_delete_before_statement
bool trig_update_old_table
bool trig_insert_after_statement
#define FirstLowInvalidHeapAttributeNumber
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
#define SearchSysCacheCopy1(cacheId, key1)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode)
static TM_Result table_tuple_lock(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot, CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy, uint8 flags, TM_FailureData *tmfd)
#define TUPLE_LOCK_FLAG_FIND_LAST_VERSION
static bool table_tuple_fetch_row_version(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot)
static SetConstraintState SetConstraintStateCopy(SetConstraintState origstate)
struct AfterTriggerSharedData AfterTriggerSharedData
static void cancel_prior_stmt_triggers(Oid relid, CmdType cmdType, int tgevent)
static AfterTriggersData afterTriggers
#define AFTER_TRIGGER_FDW_FETCH
bool ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *newslot, TM_Result *tmresult, TM_FailureData *tmfd)
struct AfterTriggerEventData AfterTriggerEventData
static SetConstraintState SetConstraintStateAddItem(SetConstraintState state, Oid tgoid, bool tgisdeferred)
#define AFTER_TRIGGER_IN_PROGRESS
static void renametrig_internal(Relation tgrel, Relation targetrel, HeapTuple trigtup, const char *newname, const char *expected_name)
#define AFTER_TRIGGER_OFFSET
void AfterTriggerBeginXact(void)
void ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TransitionCaptureState *transition_capture, bool is_crosspart_update)
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
static void afterTriggerDeleteHeadEventChunk(AfterTriggersQueryData *qs)
static AfterTriggersTableData * GetAfterTriggersTableData(Oid relid, CmdType cmdType)
#define CHUNK_DATA_START(cptr)
static void RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
void AfterTriggerEndSubXact(bool isCommit)
static Tuplestorestate * GetCurrentFDWTuplestore(void)
void ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
#define AFTER_TRIGGER_TUP_BITS
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, TupleTableSlot *oldslot, TupleTableSlot *newslot)
void FreeTriggerDesc(TriggerDesc *trigdesc)
bool ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple)
#define AFTER_TRIGGER_1CTID
Datum pg_trigger_depth(PG_FUNCTION_ARGS)
static Bitmapset * afterTriggerCopyBitmap(Bitmapset *src)
void ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
void EnableDisableTrigger(Relation rel, const char *tgname, Oid tgparent, char fires_when, bool skip_system, bool recurse, LOCKMODE lockmode)
static void AfterTriggerFreeQuery(AfterTriggersQueryData *qs)
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
static void afterTriggerFreeEventList(AfterTriggerEventList *events)
bool ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
#define GetTriggerSharedData(evt)
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
static int MyTriggerDepth
#define for_each_chunk_from(cptr)
static bool afterTriggerMarkEvents(AfterTriggerEventList *events, AfterTriggerEventList *move_list, bool immediate_only)
static Tuplestorestate * GetAfterTriggersTransitionTable(int event, TupleTableSlot *oldslot, TupleTableSlot *newslot, TransitionCaptureState *transition_capture)
void ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
static bool afterTriggerInvokeEvents(AfterTriggerEventList *events, CommandId firing_id, EState *estate, bool delete_ok)
const char * FindTriggerIncompatibleWithInheritance(TriggerDesc *trigdesc)
void ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, ResultRelInfo *src_partinfo, ResultRelInfo *dst_partinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *newslot, List *recheckIndexes, TransitionCaptureState *transition_capture, bool is_crosspart_update)
struct AfterTriggerSharedData * AfterTriggerShared
void AfterTriggerSetState(ConstraintsSetStmt *stmt)
Oid get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
ObjectAddress CreateTrigger(CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, Oid funcoid, Oid parentTriggerOid, Node *whenClause, bool isInternal, bool in_partition)
static bool before_stmt_triggers_fired(Oid relid, CmdType cmdType)
static void afterTriggerAddEvent(AfterTriggerEventList *events, AfterTriggerEvent event, AfterTriggerShared evtshared)
struct SetConstraintTriggerData * SetConstraintTrigger
struct AfterTriggersData AfterTriggersData
struct AfterTriggerEventDataNoOids AfterTriggerEventDataNoOids
#define AFTER_TRIGGER_2CTID
#define SizeofTriggerEvent(evt)
int SessionReplicationRole
static bool afterTriggerCheckState(AfterTriggerShared evtshared)
struct AfterTriggerEventChunk AfterTriggerEventChunk
static void AfterTriggerExecute(EState *estate, AfterTriggerEvent event, ResultRelInfo *relInfo, ResultRelInfo *src_relInfo, ResultRelInfo *dst_relInfo, TriggerDesc *trigdesc, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context, TupleTableSlot *trig_tuple_slot1, TupleTableSlot *trig_tuple_slot2)
void ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
static SetConstraintState SetConstraintStateCreate(int numalloc)
void ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
bool ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot **epqslot, TM_Result *tmresult, TM_FailureData *tmfd)
ObjectAddress renametrig(RenameStmt *stmt)
void AfterTriggerFireDeferred(void)
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
struct SetConstraintTriggerData SetConstraintTriggerData
void TriggerSetParentTrigger(Relation trigRel, Oid childTrigId, Oid parentTrigId, Oid childTableId)
static void afterTriggerRestoreEventList(AfterTriggerEventList *events, const AfterTriggerEventList *old_events)
static void SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger)
#define for_each_event_from(eptr, cptr)
static void TransitionTableAddTuple(EState *estate, TransitionCaptureState *transition_capture, ResultRelInfo *relinfo, TupleTableSlot *slot, TupleTableSlot *original_insert_tuple, Tuplestorestate *tuplestore)
static void renametrig_partition(Relation tgrel, Oid partitionId, Oid parentTriggerOid, const char *newname, const char *expected_name)
struct AfterTriggerEventDataZeroCtids AfterTriggerEventDataZeroCtids
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
ObjectAddress CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, Oid funcoid, Oid parentTriggerOid, Node *whenClause, bool isInternal, bool in_partition, char trigger_fires_when)
void assign_session_replication_role(int newval, void *extra)
bool ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple, TupleTableSlot *newslot)
void AfterTriggerEndXact(bool isCommit)
struct AfterTriggerEventDataOneCtid AfterTriggerEventDataOneCtid
bool AfterTriggerPendingOnRel(Oid relid)
struct SetConstraintStateData SetConstraintStateData
#define AFTER_TRIGGER_FDW_REUSE
void RelationBuildTriggers(Relation relation)
void AfterTriggerBeginSubXact(void)
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, ResultRelInfo *src_partinfo, ResultRelInfo *dst_partinfo, int event, bool row_trigger, TupleTableSlot *oldslot, TupleTableSlot *newslot, List *recheckIndexes, Bitmapset *modifiedCols, TransitionCaptureState *transition_capture, bool is_crosspart_update)
static bool GetTupleForTrigger(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tid, LockTupleMode lockmode, TupleTableSlot *oldslot, TupleTableSlot **epqslot, TM_Result *tmresultp, TM_FailureData *tmfdp)
struct AfterTriggerEventList AfterTriggerEventList
static TupleTableSlot * GetAfterTriggersStoreSlot(AfterTriggersTableData *table, TupleDesc tupdesc)
#define AFTER_TRIGGER_CP_UPDATE
void AfterTriggerEndQuery(EState *estate)
void RemoveTriggerById(Oid trigOid)
#define AFTER_TRIGGER_DONE
#define for_each_event_chunk(eptr, cptr, evtlist)
SetConstraintStateData * SetConstraintState
static void AfterTriggerEnlargeQueryState(void)
#define for_each_event(eptr, cptr)
struct AfterTriggerEventData * AfterTriggerEvent
#define for_each_chunk(cptr, evtlist)
void ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
void AfterTriggerBeginQuery(void)
#define AFTER_TRIGGER_DEFERRABLE
#define TRIGGER_FIRED_FOR_STATEMENT(event)
#define TRIGGER_EVENT_UPDATE
#define TRIGGER_FIRED_BY_DELETE(event)
#define SESSION_REPLICATION_ROLE_REPLICA
#define TRIGGER_EVENT_DELETE
#define TRIGGER_FIRES_ON_ORIGIN
#define TRIGGER_EVENT_OPMASK
#define TRIGGER_FIRES_ON_REPLICA
#define AFTER_TRIGGER_INITDEFERRED
#define TRIGGER_EVENT_INSTEAD
#define TRIGGER_EVENT_ROW
#define TRIGGER_FIRED_AFTER(event)
#define TRIGGER_EVENT_BEFORE
#define TRIGGER_FIRED_BY_INSERT(event)
#define SESSION_REPLICATION_ROLE_ORIGIN
#define TRIGGER_EVENT_INSERT
#define TRIGGER_FIRED_BY_UPDATE(event)
#define TRIGGER_EVENT_TRUNCATE
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
#define TupleDescAttr(tupdesc, i)
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
void tuplestore_end(Tuplestorestate *state)
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
static void ExecMaterializeSlot(TupleTableSlot *slot)
List * pull_var_clause(Node *node, int flags)
Datum byteain(PG_FUNCTION_ARGS)
int GetCurrentTransactionNestLevel(void)
void CommandCounterIncrement(void)
bool IsSubTransaction(void)
#define IsolationUsesXactSnapshot()