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 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1524 errmsg(
"cannot rename trigger \"%s\" on table \"%s\"",
1526 errhint(
"Rename the trigger on the partitioned table \"%s\" instead.",
1535 if (targetrel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1539 for (
int i = 0;
i < partdesc->
nparts;
i++)
1541 Oid partitionId = partdesc->
oids[
i];
1551 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1552 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1579 const char *newname,
const char *expected_name)
1588 if (strcmp(
NameStr(tgform->tgname), newname) == 0)
1597 Anum_pg_trigger_tgrelid,
1601 Anum_pg_trigger_tgname,
1609 errmsg(
"trigger \"%s\" for relation \"%s\" already exists",
1624 if (strcmp(
NameStr(tgform->tgname), expected_name) != 0)
1626 errmsg(
"renamed trigger \"%s\" on relation \"%s\"",
1650 const char *newname,
const char *expected_name)
1662 Anum_pg_trigger_tgrelid,
1672 if (tgform->tgparentid != parentTriggerOid)
1681 if (partitionRel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1686 for (
int i = 0;
i < partdesc->
nparts;
i++)
1723 char fires_when,
bool skip_system,
bool recurse,
1738 Anum_pg_trigger_tgrelid,
1744 Anum_pg_trigger_tgname,
1755 found = changed =
false;
1761 if (
OidIsValid(tgparent) && tgparent != oldtrig->tgparentid)
1764 if (oldtrig->tgisinternal)
1771 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1772 errmsg(
"permission denied: \"%s\" is a system trigger",
1778 if (oldtrig->tgenabled != fires_when)
1784 newtrig->tgenabled = fires_when;
1803 rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
1804 (TRIGGER_FOR_ROW(oldtrig->tgtype)))
1816 fires_when, skip_system, recurse,
1830 if (tgname && !found)
1832 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1833 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1885 Anum_pg_trigger_tgrelid,
1900 if (numtrigs >= maxtrigs)
1905 build = &(triggers[numtrigs]);
1907 build->
tgoid = pg_trigger->oid;
1910 build->
tgfoid = pg_trigger->tgfoid;
1911 build->
tgtype = pg_trigger->tgtype;
1912 build->
tgenabled = pg_trigger->tgenabled;
1920 build->
tgnargs = pg_trigger->tgnargs;
1922 build->
tgnattr = pg_trigger->tgattr.dim1;
1926 memcpy(build->
tgattr, &(pg_trigger->tgattr.values),
1937 Anum_pg_trigger_tgargs,
1938 tgrel->
rd_att, &isnull));
1940 elog(
ERROR,
"tgargs is null in trigger for relation \"%s\"",
1953 datum =
fastgetattr(htup, Anum_pg_trigger_tgoldtable,
1961 datum =
fastgetattr(htup, Anum_pg_trigger_tgnewtable,
1993 for (
i = 0;
i < numtrigs;
i++)
2014 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2015 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
2017 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2018 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
2020 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2021 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_INSERT);
2023 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2024 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
2026 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2027 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
2029 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2030 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
2032 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2033 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
2035 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2036 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_UPDATE);
2038 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2039 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
2041 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2042 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
2044 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2045 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
2047 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2048 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
2050 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2051 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_DELETE);
2053 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2054 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
2056 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2057 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
2060 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2061 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_TRUNCATE);
2063 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2064 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_TRUNCATE);
2067 (TRIGGER_FOR_INSERT(tgtype) &&
2068 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgnewtable));
2070 (TRIGGER_FOR_UPDATE(tgtype) &&
2071 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgoldtable));
2073 (TRIGGER_FOR_UPDATE(tgtype) &&
2074 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgnewtable));
2076 (TRIGGER_FOR_DELETE(tgtype) &&
2077 TRIGGER_USES_TRANSITION_TABLE(trigger->
tgoldtable));
2092 if (trigdesc == NULL || trigdesc->
numtriggers <= 0)
2099 memcpy(trigger, trigdesc->
triggers,
2111 memcpy(newattr, trigger->
tgattr,
2113 trigger->
tgattr = newattr;
2120 newargs = (
char **)
palloc(trigger->
tgnargs *
sizeof(
char *));
2123 trigger->
tgargs = newargs;
2146 if (trigdesc == NULL)
2157 while (--(trigger->
tgnargs) >= 0)
2195 if (trigdesc1 != NULL)
2197 if (trigdesc2 == NULL)
2243 else if (trig1->
tgqual == NULL || trig2->
tgqual == NULL)
2261 else if (trigdesc2 != NULL)
2275 if (trigdesc != NULL)
2380 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2381 errmsg(
"trigger function %u returned null value",
2382 fcinfo->flinfo->fn_oid)));
2403 if (trigdesc == NULL)
2413 LocTriggerData.
type = T_TriggerData;
2422 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2423 TRIGGER_TYPE_STATEMENT,
2424 TRIGGER_TYPE_BEFORE,
2425 TRIGGER_TYPE_INSERT))
2440 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2441 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2454 false, NULL, NULL,
NIL, NULL, transition_capture,
2468 LocTriggerData.
type = T_TriggerData;
2478 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2480 TRIGGER_TYPE_BEFORE,
2481 TRIGGER_TYPE_INSERT))
2498 if (newtuple == NULL)
2504 else if (newtuple != oldtuple)
2516 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2517 errmsg(
"moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported"),
2518 errdetail(
"Before executing trigger \"%s\", the row was to be in partition \"%s.%s\".",
2546 recheckIndexes, NULL,
2561 LocTriggerData.
type = T_TriggerData;
2571 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2573 TRIGGER_TYPE_INSTEAD,
2574 TRIGGER_TYPE_INSERT))
2591 if (newtuple == NULL)
2597 else if (newtuple != oldtuple)
2621 if (trigdesc == NULL)
2631 LocTriggerData.
type = T_TriggerData;
2640 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2641 TRIGGER_TYPE_STATEMENT,
2642 TRIGGER_TYPE_BEFORE,
2643 TRIGGER_TYPE_DELETE))
2658 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2659 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2672 false, NULL, NULL,
NIL, NULL, transition_capture,
2697 bool should_free =
false;
2701 if (fdw_trigtuple == NULL)
2715 if (epqslot_candidate != NULL && epqslot != NULL)
2717 *epqslot = epqslot_candidate;
2725 trigtuple = fdw_trigtuple;
2729 LocTriggerData.
type = T_TriggerData;
2739 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2741 TRIGGER_TYPE_BEFORE,
2742 TRIGGER_TYPE_DELETE))
2756 if (newtuple == NULL)
2761 if (newtuple != trigtuple)
2780 bool is_crosspart_update)
2790 if (fdw_trigtuple == NULL)
2805 true, slot, NULL,
NIL, NULL,
2807 is_crosspart_update);
2820 LocTriggerData.
type = T_TriggerData;
2833 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2835 TRIGGER_TYPE_INSTEAD,
2836 TRIGGER_TYPE_DELETE))
2850 if (rettuple == NULL)
2852 if (rettuple != trigtuple)
2868 if (trigdesc == NULL)
2883 LocTriggerData.
type = T_TriggerData;
2893 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
2894 TRIGGER_TYPE_STATEMENT,
2895 TRIGGER_TYPE_BEFORE,
2896 TRIGGER_TYPE_UPDATE))
2899 updatedCols, NULL, NULL))
2911 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2912 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2928 false, NULL, NULL,
NIL,
2947 bool should_free_trig =
false;
2948 bool should_free_new =
false;
2958 if (fdw_trigtuple == NULL)
2964 lockmode, oldslot, &epqslot_candidate,
2977 if (epqslot_candidate != NULL)
2990 if (
unlikely(newslot != epqslot_clean))
3015 trigtuple = fdw_trigtuple;
3018 LocTriggerData.
type = T_TriggerData;
3030 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3032 TRIGGER_TYPE_BEFORE,
3033 TRIGGER_TYPE_UPDATE))
3036 updatedCols, oldslot, newslot))
3053 if (newtuple == NULL)
3055 if (should_free_trig)
3057 if (should_free_new)
3061 else if (newtuple != oldtuple)
3071 if (should_free_trig && newtuple == trigtuple)
3074 if (should_free_new)
3081 if (should_free_trig)
3104 List *recheckIndexes,
3106 bool is_crosspart_update)
3111 (transition_capture &&
3124 Assert((src_partinfo != NULL && dst_partinfo != NULL) ||
3125 !is_crosspart_update);
3127 tupsrc = src_partinfo ? src_partinfo : relinfo;
3140 else if (fdw_trigtuple != NULL)
3146 src_partinfo, dst_partinfo,
3149 oldslot, newslot, recheckIndexes,
3152 is_crosspart_update);
3167 LocTriggerData.
type = T_TriggerData;
3180 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3182 TRIGGER_TYPE_INSTEAD,
3183 TRIGGER_TYPE_UPDATE))
3186 NULL, oldslot, newslot))
3203 if (newtuple == NULL)
3207 else if (newtuple != oldtuple)
3231 if (trigdesc == NULL)
3236 LocTriggerData.
type = T_TriggerData;
3246 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
3247 TRIGGER_TYPE_STATEMENT,
3248 TRIGGER_TYPE_BEFORE,
3249 TRIGGER_TYPE_TRUNCATE))
3264 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
3265 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
3278 false, NULL, NULL,
NIL, NULL, NULL,
3299 if (epqslot != NULL)
3308 Assert(epqstate != NULL);
3341 (
errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
3342 errmsg(
"tuple to be updated was already modified by an operation triggered by the current command"),
3343 errhint(
"Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
3384 errmsg(
"could not serialize access due to concurrent update")));
3385 elog(
ERROR,
"unexpected table_tuple_lock status: %u",
test);
3392 errmsg(
"could not serialize access due to concurrent delete")));
3397 elog(
ERROR,
"attempted to lock invisible tuple");
3401 elog(
ERROR,
"unrecognized table_tuple_lock status: %u",
test);
3413 elog(
ERROR,
"failed to fetch tuple for trigger");
3487 if (*predicate == NULL)
3514 if (!
ExecQual(*predicate, econtext))
3620#define AFTER_TRIGGER_OFFSET 0x07FFFFFF
3621#define AFTER_TRIGGER_DONE 0x80000000
3622#define AFTER_TRIGGER_IN_PROGRESS 0x40000000
3624#define AFTER_TRIGGER_FDW_REUSE 0x00000000
3625#define AFTER_TRIGGER_FDW_FETCH 0x20000000
3626#define AFTER_TRIGGER_1CTID 0x10000000
3627#define AFTER_TRIGGER_2CTID 0x30000000
3628#define AFTER_TRIGGER_CP_UPDATE 0x08000000
3629#define AFTER_TRIGGER_TUP_BITS 0x38000000
3680#define SizeofTriggerEvent(evt) \
3681 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_CP_UPDATE ? \
3682 sizeof(AfterTriggerEventData) : \
3683 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \
3684 sizeof(AfterTriggerEventDataNoOids) : \
3685 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \
3686 sizeof(AfterTriggerEventDataOneCtid) : \
3687 sizeof(AfterTriggerEventDataZeroCtids))))
3689#define GetTriggerSharedData(evt) \
3690 ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
3708#define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
3719#define for_each_chunk(cptr, evtlist) \
3720 for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
3721#define for_each_event(eptr, cptr) \
3722 for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
3723 (char *) eptr < (cptr)->freeptr; \
3724 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3726#define for_each_event_chunk(eptr, cptr, evtlist) \
3727 for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
3730#define for_each_chunk_from(cptr) \
3731 for (; cptr != NULL; cptr = cptr->next)
3732#define for_each_event_from(eptr, cptr) \
3734 (char *) eptr < (cptr)->freeptr; \
3735 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3910 Oid tgoid,
bool tgisdeferred);
3975 for (
i = 0;
i <
state->numstates;
i++)
3977 if (
state->trigstates[
i].sct_tgoid == tgoid)
3978 return state->trigstates[
i].sct_tgisdeferred;
3982 if (
state->all_isset)
3983 return state->all_isdeferred;
4012 "AfterTriggerEvents",
4046 if (
chunk == NULL ||
4055 "AfterTriggerEvents",
4073#define MIN_CHUNK_SIZE 1024
4074#define MAX_CHUNK_SIZE (1024*1024)
4076#if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
4077#error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
4100 if (events->
tail == NULL)
4116 (
char *) newshared >=
chunk->endfree;
4126 if ((
char *) newshared < chunk->endfree)
4128 *newshared = *evtshared;
4130 chunk->endfree = (
char *) newshared;
4135 memcpy(newevent, event, eventsize);
4137 newevent->
ate_flags &= ~AFTER_TRIGGER_OFFSET;
4138 newevent->
ate_flags |= (
char *) newshared - (
char *) newevent;
4140 chunk->freeptr += eventsize;
4160 events->
tail = NULL;
4178 if (old_events->
tail == NULL)
4185 *events = *old_events;
4189 next_chunk =
chunk->next;
4293 bool should_free_trig =
false;
4294 bool should_free_new =
false;
4301 if (trigdesc == NULL)
4303 for (tgindx = 0; tgindx < trigdesc->
numtriggers; tgindx++)
4332 elog(
ERROR,
"failed to fetch tuple1 for AFTER trigger");
4338 elog(
ERROR,
"failed to fetch tuple2 for AFTER trigger");
4359 LocTriggerData.
tg_newslot = trig_tuple_slot2;
4379 elog(
ERROR,
"failed to fetch tuple1 for AFTER trigger");
4385 if (src_relInfo != relInfo)
4421 elog(
ERROR,
"failed to fetch tuple2 for AFTER trigger");
4428 if (dst_relInfo != relInfo)
4485 LocTriggerData.
type = T_TriggerData;
4503 if (rettuple != NULL &&
4511 if (should_free_trig)
4513 if (should_free_new)
4517 if (trig_tuple_slot1 == NULL)
4551 bool immediate_only)
4554 bool deferred_found =
false;
4561 bool defer_it =
false;
4588 if (defer_it && move_list != NULL)
4590 deferred_found =
true;
4605 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4606 errmsg(
"cannot fire deferred trigger within security-restricted operation")));
4638 bool all_fired =
true;
4641 bool local_estate =
false;
4654 local_estate =
true;
4660 "AfterTriggerTupleContext",
4666 bool all_fired_in_chunk =
true;
4700 slot1 = slot2 = NULL;
4702 if (rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4728 src_rInfo = dst_rInfo = rInfo;
4736 src_rInfo, dst_rInfo,
4737 trigdesc, finfo, instr,
4738 per_tuple_context, slot1, slot2);
4743 event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
4749 all_fired = all_fired_in_chunk =
false;
4754 if (delete_ok && all_fired_in_chunk)
4817 if (table->
relid == relid && table->
cmdType == cmdType &&
4825 table->
relid = relid;
4899 if (trigdesc == NULL)
4906 need_old_upd = need_old_del = need_new_upd =
false;
4912 need_old_del = need_new_ins =
false;
4916 need_old_upd = need_new_upd = need_new_ins =
false;
4925 elog(
ERROR,
"unexpected CmdType: %d", (
int) cmdType);
4927 need_old_upd = need_new_upd = need_old_del = need_new_ins =
false;
4930 if (!need_old_upd && !need_new_upd && !need_new_ins && !need_old_del)
4935 elog(
ERROR,
"MakeTransitionCaptureState() called outside of query");
4978 state->tcs_private = table;
5206 bool snap_pushed =
false;
5217 if (events->
head != NULL)
5515 if (tuplestore == NULL)
5518 if (original_insert_tuple)
5606 state->numalloc = numalloc;
5636 Oid tgoid,
bool tgisdeferred)
5640 int newalloc =
state->numalloc * 2;
5642 newalloc =
Max(newalloc, 8);
5647 state->numalloc = newalloc;
5651 state->trigstates[
state->numstates].sct_tgoid = tgoid;
5652 state->trigstates[
state->numstates].sct_tgisdeferred = tgisdeferred;
5724 foreach(lc,
stmt->constraints)
5728 List *namespacelist;
5735 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5736 errmsg(
"cross-database references are not implemented: \"%s.%s.%s\"",
5759 foreach(nslc, namespacelist)
5767 Anum_pg_constraint_conname,
5771 Anum_pg_constraint_connamespace,
5776 true, NULL, 2, skey);
5782 if (con->condeferrable)
5784 else if (
stmt->deferred)
5786 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
5787 errmsg(
"constraint \"%s\" is not deferrable",
5809 (
errcode(ERRCODE_UNDEFINED_OBJECT),
5810 errmsg(
"constraint \"%s\" does not exist",
5820 foreach(lc, conoidlist)
5828 Anum_pg_constraint_conparentid,
5852 foreach(lc, conoidlist)
5860 Anum_pg_trigger_tgconstraint,
5877 if (pg_trigger->tgdeferrable)
5878 tgoidlist =
lappend_oid(tgoidlist, pg_trigger->oid);
5890 foreach(lc, tgoidlist)
5897 for (
i = 0;
i <
state->numstates;
i++)
5899 if (
state->trigstates[
i].sct_tgoid == tgoid)
5901 state->trigstates[
i].sct_tgisdeferred =
stmt->deferred;
5925 if (!
stmt->deferred)
5928 bool snapshot_set =
false;
5946 snapshot_set =
true;
6070 int event,
bool row_trigger,
6074 bool is_crosspart_update)
6080 char relkind = rel->
rd_rel->relkind;
6092 elog(
ERROR,
"AfterTriggerSaveEvent() called outside of query");
6102 if (row_trigger && transition_capture != NULL)
6117 transition_capture);
6119 oldslot, NULL, old_tuplestore);
6133 transition_capture);
6135 newslot, original_insert_tuple, new_tuplestore);
6145 if (trigdesc == NULL ||
6161 rel->
rd_rel->relkind != RELKIND_PARTITIONED_TABLE ||
6162 (is_crosspart_update &&
6164 src_partinfo != NULL && dst_partinfo != NULL));
6181 tgtype_event = TRIGGER_TYPE_INSERT;
6200 tgtype_event = TRIGGER_TYPE_DELETE;
6219 tgtype_event = TRIGGER_TYPE_UPDATE;
6231 if (rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6233 Assert(src_partinfo != NULL && dst_partinfo != NULL);
6251 tgtype_event = TRIGGER_TYPE_TRUNCATE;
6258 elog(
ERROR,
"invalid after-trigger event code: %d", event);
6264 if (!(relkind == RELKIND_FOREIGN_TABLE && row_trigger))
6268 if (relkind == RELKIND_PARTITIONED_TABLE)
6279 tgtype_level = (row_trigger ? TRIGGER_TYPE_ROW : TRIGGER_TYPE_STATEMENT);
6286 if (row_trigger && rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6314 if (!TRIGGER_TYPE_MATCHES(trigger->
tgtype,
6320 modifiedCols, oldslot, newslot))
6323 if (relkind == RELKIND_FOREIGN_TABLE && row_trigger)
6325 if (fdw_tuplestore == NULL)
6357 if (is_crosspart_update &&
6384 if (rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
6404 rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6415 if (trigger->
tgfoid == F_UNIQUE_KEY_RECHECK)
6435 transition_capture != NULL)
6442 &new_event, &new_shared);
6452 if (oldslot != NULL)
6454 if (newslot != NULL)
6471 elog(
ERROR,
"before_stmt_triggers_fired() called outside of query");
6567 event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
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 Assert(condition)
#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)
ResultRelInfo * ExecGetTriggerResultRel(EState *estate, Oid relid, ResultRelInfo *rootRelInfo)
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
TupleTableSlot * EvalPlanQual(EPQState *epqstate, Relation relation, Index rti, TupleTableSlot *inputslot)
void ExecCloseResultRelations(EState *estate)
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
const TupleTableSlotOps TTSOpsVirtual
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
const TupleTableSlotOps TTSOpsMinimalTuple
void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
TupleTableSlot * ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
TupleConversionMap * ExecGetChildToRootMap(ResultRelInfo *resultRelInfo)
TupleTableSlot * ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
void FreeExecutorState(EState *estate)
Bitmapset * ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
EState * CreateExecutorState(void)
#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)
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_rel_name(Oid relid)
char get_rel_relkind(Oid relid)
char * get_namespace_name(Oid nspid)
Oid get_func_rettype(Oid funcid)
Alias * makeAlias(const char *aliasname, List *colnames)
List * make_ands_implicit(Expr *clause)
void * MemoryContextAlloc(MemoryContext context, Size size)
void MemoryContextReset(MemoryContext context)
void * MemoryContextAllocZero(MemoryContext context, Size size)
MemoryContext TopTransactionContext
char * pstrdup(const char *in)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurTransactionContext
MemoryContext CurrentMemoryContext
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)
char * NameListToString(const List *names)
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
List * fetch_search_path(bool includeImplicit)
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)
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, int16 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 Datum Int16GetDatum(int16 X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static char * DatumGetCString(Datum X)
static Datum NameGetDatum(const NameData *X)
static Pointer DatumGetPointer(Datum X)
static Datum CStringGetDatum(const char *X)
MemoryContextSwitchTo(old_ctx)
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)
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
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)
static Bitmapset * afterTriggerCopyBitmap(Bitmapset *src)
#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)
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)
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)
const char * FindTriggerIncompatibleWithInheritance(TriggerDesc *trigdesc)
bool ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
#define GetTriggerSharedData(evt)
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)
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
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
static Tuplestorestate * GetCurrentFDWTuplestore(void)
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)
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
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)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int 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()