1 /*------------------------------------------------------------------------- 2 * 3 * trigger.c 4 * PostgreSQL TRIGGERs support code. 5 * 6 * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group 7 * Portions Copyright (c) 1994, Regents of the University of California 8 * 9 * IDENTIFICATION 10 * src/backend/commands/trigger.c 11 * 12 *------------------------------------------------------------------------- 13 */ 14 #include "postgres.h" 15 16 #include "access/genam.h" 17 #include "access/heapam.h" 18 #include "access/sysattr.h" 19 #include "access/htup_details.h" 20 #include "access/xact.h" 21 #include "catalog/catalog.h" 22 #include "catalog/dependency.h" 23 #include "catalog/index.h" 24 #include "catalog/indexing.h" 25 #include "catalog/objectaccess.h" 26 #include "catalog/partition.h" 27 #include "catalog/pg_constraint.h" 28 #include "catalog/pg_inherits.h" 29 #include "catalog/pg_proc.h" 30 #include "catalog/pg_trigger.h" 31 #include "catalog/pg_type.h" 32 #include "commands/dbcommands.h" 33 #include "commands/defrem.h" 34 #include "commands/trigger.h" 35 #include "executor/executor.h" 36 #include "miscadmin.h" 37 #include "nodes/bitmapset.h" 38 #include "nodes/makefuncs.h" 39 #include "optimizer/clauses.h" 40 #include "optimizer/var.h" 41 #include "parser/parse_clause.h" 42 #include "parser/parse_collate.h" 43 #include "parser/parse_func.h" 44 #include "parser/parse_relation.h" 45 #include "parser/parsetree.h" 46 #include "pgstat.h" 47 #include "rewrite/rewriteManip.h" 48 #include "storage/bufmgr.h" 49 #include "storage/lmgr.h" 50 #include "tcop/utility.h" 51 #include "utils/acl.h" 52 #include "utils/builtins.h" 53 #include "utils/bytea.h" 54 #include "utils/fmgroids.h" 55 #include "utils/inval.h" 56 #include "utils/lsyscache.h" 57 #include "utils/memutils.h" 58 #include "utils/rel.h" 59 #include "utils/snapmgr.h" 60 #include "utils/syscache.h" 61 #include "utils/tqual.h" 62 #include "utils/tuplestore.h" 63 64 65 /* GUC variables */ 66 int SessionReplicationRole = SESSION_REPLICATION_ROLE_ORIGIN; 67 68 /* How many levels deep into trigger execution are we? */ 69 static int MyTriggerDepth = 0; 70 71 /* Local function prototypes */ 72 static void ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid); 73 static void SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger); 74 static HeapTuple GetTupleForTrigger(EState *estate, 75 EPQState *epqstate, 76 ResultRelInfo *relinfo, 77 ItemPointer tid, 78 LockTupleMode lockmode, 79 TupleTableSlot **newSlot); 80 static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, 81 Trigger *trigger, TriggerEvent event, 82 Bitmapset *modifiedCols, 83 HeapTuple oldtup, HeapTuple newtup); 84 static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, 85 int tgindx, 86 FmgrInfo *finfo, 87 Instrumentation *instr, 88 MemoryContext per_tuple_context); 89 static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, 90 int event, bool row_trigger, 91 HeapTuple oldtup, HeapTuple newtup, 92 List *recheckIndexes, Bitmapset *modifiedCols, 93 TransitionCaptureState *transition_capture); 94 static void AfterTriggerEnlargeQueryState(void); 95 static bool before_stmt_triggers_fired(Oid relid, CmdType cmdType); 96 97 98 /* 99 * Create a trigger. Returns the address of the created trigger. 100 * 101 * queryString is the source text of the CREATE TRIGGER command. 102 * This must be supplied if a whenClause is specified, else it can be NULL. 103 * 104 * relOid, if nonzero, is the relation on which the trigger should be 105 * created. If zero, the name provided in the statement will be looked up. 106 * 107 * refRelOid, if nonzero, is the relation to which the constraint trigger 108 * refers. If zero, the constraint relation name provided in the statement 109 * will be looked up as needed. 110 * 111 * constraintOid, if nonzero, says that this trigger is being created 112 * internally to implement that constraint. A suitable pg_depend entry will 113 * be made to link the trigger to that constraint. constraintOid is zero when 114 * executing a user-entered CREATE TRIGGER command. (For CREATE CONSTRAINT 115 * TRIGGER, we build a pg_constraint entry internally.) 116 * 117 * indexOid, if nonzero, is the OID of an index associated with the constraint. 118 * We do nothing with this except store it into pg_trigger.tgconstrindid; 119 * but when creating a trigger for a deferrable unique constraint on a 120 * partitioned table, its children are looked up. Note we don't cope with 121 * invalid indexes in that case. 122 * 123 * funcoid, if nonzero, is the OID of the function to invoke. When this is 124 * given, stmt->funcname is ignored. 125 * 126 * parentTriggerOid, if nonzero, is a trigger that begets this one; so that 127 * if that trigger is dropped, this one should be too. (This is passed as 128 * Invalid by most callers; it's set here when recursing on a partition.) 129 * 130 * If whenClause is passed, it is an already-transformed expression for 131 * WHEN. In this case, we ignore any that may come in stmt->whenClause. 132 * 133 * If isInternal is true then this is an internally-generated trigger. 134 * This argument sets the tgisinternal field of the pg_trigger entry, and 135 * if true causes us to modify the given trigger name to ensure uniqueness. 136 * 137 * When isInternal is not true we require ACL_TRIGGER permissions on the 138 * relation, as well as ACL_EXECUTE on the trigger function. For internal 139 * triggers the caller must apply any required permission checks. 140 * 141 * When called on partitioned tables, this function recurses to create the 142 * trigger on all the partitions, except if isInternal is true, in which 143 * case caller is expected to execute recursion on its own. 144 * 145 * Note: can return InvalidObjectAddress if we decided to not create a trigger 146 * at all, but a foreign-key constraint. This is a kluge for backwards 147 * compatibility. 148 */ 149 ObjectAddress 150 CreateTrigger(CreateTrigStmt *stmt, const char *queryString, 151 Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, 152 Oid funcoid, Oid parentTriggerOid, Node *whenClause, 153 bool isInternal, bool in_partition) 154 { 155 return 156 CreateTriggerFiringOn(stmt, queryString, relOid, refRelOid, 157 constraintOid, indexOid, funcoid, 158 parentTriggerOid, whenClause, isInternal, 159 in_partition, TRIGGER_FIRES_ON_ORIGIN); 160 } 161 162 /* 163 * Like the above; additionally the firing condition 164 * (always/origin/replica/disabled) can be specified. 165 */ 166 ObjectAddress 167 CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, 168 Oid relOid, Oid refRelOid, Oid constraintOid, 169 Oid indexOid, Oid funcoid, Oid parentTriggerOid, 170 Node *whenClause, bool isInternal, bool in_partition, 171 char trigger_fires_when) 172 { 173 int16 tgtype; 174 int ncolumns; 175 int16 *columns; 176 int2vector *tgattr; 177 List *whenRtable; 178 char *qual; 179 Datum values[Natts_pg_trigger]; 180 bool nulls[Natts_pg_trigger]; 181 Relation rel; 182 AclResult aclresult; 183 Relation tgrel; 184 SysScanDesc tgscan; 185 ScanKeyData key; 186 Relation pgrel; 187 HeapTuple tuple; 188 Oid fargtypes[1]; /* dummy */ 189 Oid funcrettype; 190 Oid trigoid; 191 char internaltrigname[NAMEDATALEN]; 192 char *trigname; 193 Oid constrrelid = InvalidOid; 194 ObjectAddress myself, 195 referenced; 196 char *oldtablename = NULL; 197 char *newtablename = NULL; 198 bool partition_recurse; 199 200 if (OidIsValid(relOid)) 201 rel = heap_open(relOid, ShareRowExclusiveLock); 202 else 203 rel = heap_openrv(stmt->relation, ShareRowExclusiveLock); 204 205 /* 206 * Triggers must be on tables or views, and there are additional 207 * relation-type-specific restrictions. 208 */ 209 if (rel->rd_rel->relkind == RELKIND_RELATION) 210 { 211 /* Tables can't have INSTEAD OF triggers */ 212 if (stmt->timing != TRIGGER_TYPE_BEFORE && 213 stmt->timing != TRIGGER_TYPE_AFTER) 214 ereport(ERROR, 215 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 216 errmsg("\"%s\" is a table", 217 RelationGetRelationName(rel)), 218 errdetail("Tables cannot have INSTEAD OF triggers."))); 219 } 220 else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) 221 { 222 /* Partitioned tables can't have INSTEAD OF triggers */ 223 if (stmt->timing != TRIGGER_TYPE_BEFORE && 224 stmt->timing != TRIGGER_TYPE_AFTER) 225 ereport(ERROR, 226 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 227 errmsg("\"%s\" is a table", 228 RelationGetRelationName(rel)), 229 errdetail("Tables cannot have INSTEAD OF triggers."))); 230 231 /* 232 * FOR EACH ROW triggers have further restrictions 233 */ 234 if (stmt->row) 235 { 236 /* 237 * BEFORE triggers FOR EACH ROW are forbidden, because they would 238 * allow the user to direct the row to another partition, which 239 * isn't implemented in the executor. 240 */ 241 if (stmt->timing != TRIGGER_TYPE_AFTER) 242 ereport(ERROR, 243 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 244 errmsg("\"%s\" is a partitioned table", 245 RelationGetRelationName(rel)), 246 errdetail("Partitioned tables cannot have BEFORE / FOR EACH ROW triggers."))); 247 248 /* 249 * Disallow use of transition tables. 250 * 251 * Note that we have another restriction about transition tables 252 * in partitions; search for 'has_superclass' below for an 253 * explanation. The check here is just to protect from the fact 254 * that if we allowed it here, the creation would succeed for a 255 * partitioned table with no partitions, but would be blocked by 256 * the other restriction when the first partition was created, 257 * which is very unfriendly behavior. 258 */ 259 if (stmt->transitionRels != NIL) 260 ereport(ERROR, 261 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 262 errmsg("\"%s\" is a partitioned table", 263 RelationGetRelationName(rel)), 264 errdetail("Triggers on partitioned tables cannot have transition tables."))); 265 } 266 } 267 else if (rel->rd_rel->relkind == RELKIND_VIEW) 268 { 269 /* 270 * Views can have INSTEAD OF triggers (which we check below are 271 * row-level), or statement-level BEFORE/AFTER triggers. 272 */ 273 if (stmt->timing != TRIGGER_TYPE_INSTEAD && stmt->row) 274 ereport(ERROR, 275 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 276 errmsg("\"%s\" is a view", 277 RelationGetRelationName(rel)), 278 errdetail("Views cannot have row-level BEFORE or AFTER triggers."))); 279 /* Disallow TRUNCATE triggers on VIEWs */ 280 if (TRIGGER_FOR_TRUNCATE(stmt->events)) 281 ereport(ERROR, 282 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 283 errmsg("\"%s\" is a view", 284 RelationGetRelationName(rel)), 285 errdetail("Views cannot have TRUNCATE triggers."))); 286 } 287 else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE) 288 { 289 if (stmt->timing != TRIGGER_TYPE_BEFORE && 290 stmt->timing != TRIGGER_TYPE_AFTER) 291 ereport(ERROR, 292 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 293 errmsg("\"%s\" is a foreign table", 294 RelationGetRelationName(rel)), 295 errdetail("Foreign tables cannot have INSTEAD OF triggers."))); 296 297 if (TRIGGER_FOR_TRUNCATE(stmt->events)) 298 ereport(ERROR, 299 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 300 errmsg("\"%s\" is a foreign table", 301 RelationGetRelationName(rel)), 302 errdetail("Foreign tables cannot have TRUNCATE triggers."))); 303 304 /* 305 * We disallow constraint triggers to protect the assumption that 306 * triggers on FKs can't be deferred. See notes with AfterTriggers 307 * data structures, below. 308 */ 309 if (stmt->isconstraint) 310 ereport(ERROR, 311 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 312 errmsg("\"%s\" is a foreign table", 313 RelationGetRelationName(rel)), 314 errdetail("Foreign tables cannot have constraint triggers."))); 315 } 316 else 317 ereport(ERROR, 318 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 319 errmsg("\"%s\" is not a table or view", 320 RelationGetRelationName(rel)))); 321 322 if (!allowSystemTableMods && IsSystemRelation(rel)) 323 ereport(ERROR, 324 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), 325 errmsg("permission denied: \"%s\" is a system catalog", 326 RelationGetRelationName(rel)))); 327 328 if (stmt->isconstraint) 329 { 330 /* 331 * We must take a lock on the target relation to protect against 332 * concurrent drop. It's not clear that AccessShareLock is strong 333 * enough, but we certainly need at least that much... otherwise, we 334 * might end up creating a pg_constraint entry referencing a 335 * nonexistent table. 336 */ 337 if (OidIsValid(refRelOid)) 338 { 339 LockRelationOid(refRelOid, AccessShareLock); 340 constrrelid = refRelOid; 341 } 342 else if (stmt->constrrel != NULL) 343 constrrelid = RangeVarGetRelid(stmt->constrrel, AccessShareLock, 344 false); 345 } 346 347 /* permission checks */ 348 if (!isInternal) 349 { 350 aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(), 351 ACL_TRIGGER); 352 if (aclresult != ACLCHECK_OK) 353 aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind), 354 RelationGetRelationName(rel)); 355 356 if (OidIsValid(constrrelid)) 357 { 358 aclresult = pg_class_aclcheck(constrrelid, GetUserId(), 359 ACL_TRIGGER); 360 if (aclresult != ACLCHECK_OK) 361 aclcheck_error(aclresult, get_relkind_objtype(get_rel_relkind(constrrelid)), 362 get_rel_name(constrrelid)); 363 } 364 } 365 366 /* 367 * When called on a partitioned table to create a FOR EACH ROW trigger 368 * that's not internal, we create one trigger for each partition, too. 369 * 370 * For that, we'd better hold lock on all of them ahead of time. 371 */ 372 partition_recurse = !isInternal && stmt->row && 373 rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE; 374 if (partition_recurse) 375 list_free(find_all_inheritors(RelationGetRelid(rel), 376 ShareRowExclusiveLock, NULL)); 377 378 /* Compute tgtype */ 379 TRIGGER_CLEAR_TYPE(tgtype); 380 if (stmt->row) 381 TRIGGER_SETT_ROW(tgtype); 382 tgtype |= stmt->timing; 383 tgtype |= stmt->events; 384 385 /* Disallow ROW-level TRUNCATE triggers */ 386 if (TRIGGER_FOR_ROW(tgtype) && TRIGGER_FOR_TRUNCATE(tgtype)) 387 ereport(ERROR, 388 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 389 errmsg("TRUNCATE FOR EACH ROW triggers are not supported"))); 390 391 /* INSTEAD triggers must be row-level, and can't have WHEN or columns */ 392 if (TRIGGER_FOR_INSTEAD(tgtype)) 393 { 394 if (!TRIGGER_FOR_ROW(tgtype)) 395 ereport(ERROR, 396 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 397 errmsg("INSTEAD OF triggers must be FOR EACH ROW"))); 398 if (stmt->whenClause) 399 ereport(ERROR, 400 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 401 errmsg("INSTEAD OF triggers cannot have WHEN conditions"))); 402 if (stmt->columns != NIL) 403 ereport(ERROR, 404 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 405 errmsg("INSTEAD OF triggers cannot have column lists"))); 406 } 407 408 /* 409 * We don't yet support naming ROW transition variables, but the parser 410 * recognizes the syntax so we can give a nicer message here. 411 * 412 * Per standard, REFERENCING TABLE names are only allowed on AFTER 413 * triggers. Per standard, REFERENCING ROW names are not allowed with FOR 414 * EACH STATEMENT. Per standard, each OLD/NEW, ROW/TABLE permutation is 415 * only allowed once. Per standard, OLD may not be specified when 416 * creating a trigger only for INSERT, and NEW may not be specified when 417 * creating a trigger only for DELETE. 418 * 419 * Notice that the standard allows an AFTER ... FOR EACH ROW trigger to 420 * reference both ROW and TABLE transition data. 421 */ 422 if (stmt->transitionRels != NIL) 423 { 424 List *varList = stmt->transitionRels; 425 ListCell *lc; 426 427 foreach(lc, varList) 428 { 429 TriggerTransition *tt = lfirst_node(TriggerTransition, lc); 430 431 if (!(tt->isTable)) 432 ereport(ERROR, 433 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 434 errmsg("ROW variable naming in the REFERENCING clause is not supported"), 435 errhint("Use OLD TABLE or NEW TABLE for naming transition tables."))); 436 437 /* 438 * Because of the above test, we omit further ROW-related testing 439 * below. If we later allow naming OLD and NEW ROW variables, 440 * adjustments will be needed below. 441 */ 442 443 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE) 444 ereport(ERROR, 445 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 446 errmsg("\"%s\" is a foreign table", 447 RelationGetRelationName(rel)), 448 errdetail("Triggers on foreign tables cannot have transition tables."))); 449 450 if (rel->rd_rel->relkind == RELKIND_VIEW) 451 ereport(ERROR, 452 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 453 errmsg("\"%s\" is a view", 454 RelationGetRelationName(rel)), 455 errdetail("Triggers on views cannot have transition tables."))); 456 457 /* 458 * We currently don't allow row-level triggers with transition 459 * tables on partition or inheritance children. Such triggers 460 * would somehow need to see tuples converted to the format of the 461 * table they're attached to, and it's not clear which subset of 462 * tuples each child should see. See also the prohibitions in 463 * ATExecAttachPartition() and ATExecAddInherit(). 464 */ 465 if (TRIGGER_FOR_ROW(tgtype) && has_superclass(rel->rd_id)) 466 { 467 /* Use appropriate error message. */ 468 if (rel->rd_rel->relispartition) 469 ereport(ERROR, 470 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 471 errmsg("ROW triggers with transition tables are not supported on partitions"))); 472 else 473 ereport(ERROR, 474 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 475 errmsg("ROW triggers with transition tables are not supported on inheritance children"))); 476 } 477 478 if (stmt->timing != TRIGGER_TYPE_AFTER) 479 ereport(ERROR, 480 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), 481 errmsg("transition table name can only be specified for an AFTER trigger"))); 482 483 if (TRIGGER_FOR_TRUNCATE(tgtype)) 484 ereport(ERROR, 485 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 486 errmsg("TRUNCATE triggers with transition tables are not supported"))); 487 488 /* 489 * We currently don't allow multi-event triggers ("INSERT OR 490 * UPDATE") with transition tables, because it's not clear how to 491 * handle INSERT ... ON CONFLICT statements which can fire both 492 * INSERT and UPDATE triggers. We show the inserted tuples to 493 * INSERT triggers and the updated tuples to UPDATE triggers, but 494 * it's not yet clear what INSERT OR UPDATE trigger should see. 495 * This restriction could be lifted if we can decide on the right 496 * semantics in a later release. 497 */ 498 if (((TRIGGER_FOR_INSERT(tgtype) ? 1 : 0) + 499 (TRIGGER_FOR_UPDATE(tgtype) ? 1 : 0) + 500 (TRIGGER_FOR_DELETE(tgtype) ? 1 : 0)) != 1) 501 ereport(ERROR, 502 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 503 errmsg("transition tables cannot be specified for triggers with more than one event"))); 504 505 /* 506 * We currently don't allow column-specific triggers with 507 * transition tables. Per spec, that seems to require 508 * accumulating separate transition tables for each combination of 509 * columns, which is a lot of work for a rather marginal feature. 510 */ 511 if (stmt->columns != NIL) 512 ereport(ERROR, 513 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 514 errmsg("transition tables cannot be specified for triggers with column lists"))); 515 516 /* 517 * We disallow constraint triggers with transition tables, to 518 * protect the assumption that such triggers can't be deferred. 519 * See notes with AfterTriggers data structures, below. 520 * 521 * Currently this is enforced by the grammar, so just Assert here. 522 */ 523 Assert(!stmt->isconstraint); 524 525 if (tt->isNew) 526 { 527 if (!(TRIGGER_FOR_INSERT(tgtype) || 528 TRIGGER_FOR_UPDATE(tgtype))) 529 ereport(ERROR, 530 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), 531 errmsg("NEW TABLE can only be specified for an INSERT or UPDATE trigger"))); 532 533 if (newtablename != NULL) 534 ereport(ERROR, 535 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), 536 errmsg("NEW TABLE cannot be specified multiple times"))); 537 538 newtablename = tt->name; 539 } 540 else 541 { 542 if (!(TRIGGER_FOR_DELETE(tgtype) || 543 TRIGGER_FOR_UPDATE(tgtype))) 544 ereport(ERROR, 545 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), 546 errmsg("OLD TABLE can only be specified for a DELETE or UPDATE trigger"))); 547 548 if (oldtablename != NULL) 549 ereport(ERROR, 550 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), 551 errmsg("OLD TABLE cannot be specified multiple times"))); 552 553 oldtablename = tt->name; 554 } 555 } 556 557 if (newtablename != NULL && oldtablename != NULL && 558 strcmp(newtablename, oldtablename) == 0) 559 ereport(ERROR, 560 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), 561 errmsg("OLD TABLE name and NEW TABLE name cannot be the same"))); 562 } 563 564 /* 565 * Parse the WHEN clause, if any and we weren't passed an already 566 * transformed one. 567 * 568 * Note that as a side effect, we fill whenRtable when parsing. If we got 569 * an already parsed clause, this does not occur, which is what we want -- 570 * no point in adding redundant dependencies below. 571 */ 572 if (!whenClause && stmt->whenClause) 573 { 574 ParseState *pstate; 575 RangeTblEntry *rte; 576 List *varList; 577 ListCell *lc; 578 579 /* Set up a pstate to parse with */ 580 pstate = make_parsestate(NULL); 581 pstate->p_sourcetext = queryString; 582 583 /* 584 * Set up RTEs for OLD and NEW references. 585 * 586 * 'OLD' must always have varno equal to 1 and 'NEW' equal to 2. 587 */ 588 rte = addRangeTableEntryForRelation(pstate, rel, 589 makeAlias("old", NIL), 590 false, false); 591 addRTEtoQuery(pstate, rte, false, true, true); 592 rte = addRangeTableEntryForRelation(pstate, rel, 593 makeAlias("new", NIL), 594 false, false); 595 addRTEtoQuery(pstate, rte, false, true, true); 596 597 /* Transform expression. Copy to be sure we don't modify original */ 598 whenClause = transformWhereClause(pstate, 599 copyObject(stmt->whenClause), 600 EXPR_KIND_TRIGGER_WHEN, 601 "WHEN"); 602 /* we have to fix its collations too */ 603 assign_expr_collations(pstate, whenClause); 604 605 /* 606 * Check for disallowed references to OLD/NEW. 607 * 608 * NB: pull_var_clause is okay here only because we don't allow 609 * subselects in WHEN clauses; it would fail to examine the contents 610 * of subselects. 611 */ 612 varList = pull_var_clause(whenClause, 0); 613 foreach(lc, varList) 614 { 615 Var *var = (Var *) lfirst(lc); 616 617 switch (var->varno) 618 { 619 case PRS2_OLD_VARNO: 620 if (!TRIGGER_FOR_ROW(tgtype)) 621 ereport(ERROR, 622 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), 623 errmsg("statement trigger's WHEN condition cannot reference column values"), 624 parser_errposition(pstate, var->location))); 625 if (TRIGGER_FOR_INSERT(tgtype)) 626 ereport(ERROR, 627 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), 628 errmsg("INSERT trigger's WHEN condition cannot reference OLD values"), 629 parser_errposition(pstate, var->location))); 630 /* system columns are okay here */ 631 break; 632 case PRS2_NEW_VARNO: 633 if (!TRIGGER_FOR_ROW(tgtype)) 634 ereport(ERROR, 635 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), 636 errmsg("statement trigger's WHEN condition cannot reference column values"), 637 parser_errposition(pstate, var->location))); 638 if (TRIGGER_FOR_DELETE(tgtype)) 639 ereport(ERROR, 640 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), 641 errmsg("DELETE trigger's WHEN condition cannot reference NEW values"), 642 parser_errposition(pstate, var->location))); 643 if (var->varattno < 0 && TRIGGER_FOR_BEFORE(tgtype)) 644 ereport(ERROR, 645 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 646 errmsg("BEFORE trigger's WHEN condition cannot reference NEW system columns"), 647 parser_errposition(pstate, var->location))); 648 break; 649 default: 650 /* can't happen without add_missing_from, so just elog */ 651 elog(ERROR, "trigger WHEN condition cannot contain references to other relations"); 652 break; 653 } 654 } 655 656 /* we'll need the rtable for recordDependencyOnExpr */ 657 whenRtable = pstate->p_rtable; 658 659 qual = nodeToString(whenClause); 660 661 free_parsestate(pstate); 662 } 663 else if (!whenClause) 664 { 665 whenClause = NULL; 666 whenRtable = NIL; 667 qual = NULL; 668 } 669 else 670 { 671 qual = nodeToString(whenClause); 672 whenRtable = NIL; 673 } 674 675 /* 676 * Find and validate the trigger function. 677 */ 678 if (!OidIsValid(funcoid)) 679 funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false); 680 if (!isInternal) 681 { 682 aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE); 683 if (aclresult != ACLCHECK_OK) 684 aclcheck_error(aclresult, OBJECT_FUNCTION, 685 NameListToString(stmt->funcname)); 686 } 687 funcrettype = get_func_rettype(funcoid); 688 if (funcrettype != TRIGGEROID) 689 { 690 /* 691 * We allow OPAQUE just so we can load old dump files. When we see a 692 * trigger function declared OPAQUE, change it to TRIGGER. 693 */ 694 if (funcrettype == OPAQUEOID) 695 { 696 ereport(WARNING, 697 (errmsg("changing return type of function %s from %s to %s", 698 NameListToString(stmt->funcname), 699 "opaque", "trigger"))); 700 SetFunctionReturnType(funcoid, TRIGGEROID); 701 } 702 else 703 ereport(ERROR, 704 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), 705 errmsg("function %s must return type %s", 706 NameListToString(stmt->funcname), "trigger"))); 707 } 708 709 /* 710 * If the command is a user-entered CREATE CONSTRAINT TRIGGER command that 711 * references one of the built-in RI_FKey trigger functions, assume it is 712 * from a dump of a pre-7.3 foreign key constraint, and take steps to 713 * convert this legacy representation into a regular foreign key 714 * constraint. Ugly, but necessary for loading old dump files. 715 */ 716 if (stmt->isconstraint && !isInternal && 717 list_length(stmt->args) >= 6 && 718 (list_length(stmt->args) % 2) == 0 && 719 RI_FKey_trigger_type(funcoid) != RI_TRIGGER_NONE) 720 { 721 /* Keep lock on target rel until end of xact */ 722 heap_close(rel, NoLock); 723 724 ConvertTriggerToFK(stmt, funcoid); 725 726 return InvalidObjectAddress; 727 } 728 729 /* 730 * If it's a user-entered CREATE CONSTRAINT TRIGGER command, make a 731 * corresponding pg_constraint entry. 732 */ 733 if (stmt->isconstraint && !OidIsValid(constraintOid)) 734 { 735 /* Internal callers should have made their own constraints */ 736 Assert(!isInternal); 737 constraintOid = CreateConstraintEntry(stmt->trigname, 738 RelationGetNamespace(rel), 739 CONSTRAINT_TRIGGER, 740 stmt->deferrable, 741 stmt->initdeferred, 742 true, 743 InvalidOid, /* no parent */ 744 RelationGetRelid(rel), 745 NULL, /* no conkey */ 746 0, 747 0, 748 InvalidOid, /* no domain */ 749 InvalidOid, /* no index */ 750 InvalidOid, /* no foreign key */ 751 NULL, 752 NULL, 753 NULL, 754 NULL, 755 0, 756 ' ', 757 ' ', 758 ' ', 759 NULL, /* no exclusion */ 760 NULL, /* no check constraint */ 761 NULL, 762 NULL, 763 true, /* islocal */ 764 0, /* inhcount */ 765 true, /* isnoinherit */ 766 isInternal); /* is_internal */ 767 } 768 769 /* 770 * Generate the trigger's OID now, so that we can use it in the name if 771 * needed. 772 */ 773 tgrel = heap_open(TriggerRelationId, RowExclusiveLock); 774 775 trigoid = GetNewOid(tgrel); 776 777 /* 778 * If trigger is internally generated, modify the provided trigger name to 779 * ensure uniqueness by appending the trigger OID. (Callers will usually 780 * supply a simple constant trigger name in these cases.) 781 */ 782 if (isInternal) 783 { 784 snprintf(internaltrigname, sizeof(internaltrigname), 785 "%s_%u", stmt->trigname, trigoid); 786 trigname = internaltrigname; 787 } 788 else 789 { 790 /* user-defined trigger; use the specified trigger name as-is */ 791 trigname = stmt->trigname; 792 } 793 794 /* 795 * Scan pg_trigger for existing triggers on relation. We do this only to 796 * give a nice error message if there's already a trigger of the same 797 * name. (The unique index on tgrelid/tgname would complain anyway.) We 798 * can skip this for internally generated triggers, since the name 799 * modification above should be sufficient. 800 * 801 * NOTE that this is cool only because we have ShareRowExclusiveLock on 802 * the relation, so the trigger set won't be changing underneath us. 803 */ 804 if (!isInternal) 805 { 806 ScanKeyInit(&key, 807 Anum_pg_trigger_tgrelid, 808 BTEqualStrategyNumber, F_OIDEQ, 809 ObjectIdGetDatum(RelationGetRelid(rel))); 810 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true, 811 NULL, 1, &key); 812 while (HeapTupleIsValid(tuple = systable_getnext(tgscan))) 813 { 814 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple); 815 816 if (namestrcmp(&(pg_trigger->tgname), trigname) == 0) 817 ereport(ERROR, 818 (errcode(ERRCODE_DUPLICATE_OBJECT), 819 errmsg("trigger \"%s\" for relation \"%s\" already exists", 820 trigname, RelationGetRelationName(rel)))); 821 } 822 systable_endscan(tgscan); 823 } 824 825 /* 826 * Build the new pg_trigger tuple. 827 * 828 * When we're creating a trigger in a partition, we mark it as internal, 829 * even though we don't do the isInternal magic in this function. This 830 * makes the triggers in partitions identical to the ones in the 831 * partitioned tables, except that they are marked internal. 832 */ 833 memset(nulls, false, sizeof(nulls)); 834 835 values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel)); 836 values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein, 837 CStringGetDatum(trigname)); 838 values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid); 839 values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype); 840 values[Anum_pg_trigger_tgenabled - 1] = trigger_fires_when; 841 values[Anum_pg_trigger_tgisinternal - 1] = BoolGetDatum(isInternal || in_partition); 842 values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid); 843 values[Anum_pg_trigger_tgconstrindid - 1] = ObjectIdGetDatum(indexOid); 844 values[Anum_pg_trigger_tgconstraint - 1] = ObjectIdGetDatum(constraintOid); 845 values[Anum_pg_trigger_tgdeferrable - 1] = BoolGetDatum(stmt->deferrable); 846 values[Anum_pg_trigger_tginitdeferred - 1] = BoolGetDatum(stmt->initdeferred); 847 848 if (stmt->args) 849 { 850 ListCell *le; 851 char *args; 852 int16 nargs = list_length(stmt->args); 853 int len = 0; 854 855 foreach(le, stmt->args) 856 { 857 char *ar = strVal(lfirst(le)); 858 859 len += strlen(ar) + 4; 860 for (; *ar; ar++) 861 { 862 if (*ar == '\\') 863 len++; 864 } 865 } 866 args = (char *) palloc(len + 1); 867 args[0] = '\0'; 868 foreach(le, stmt->args) 869 { 870 char *s = strVal(lfirst(le)); 871 char *d = args + strlen(args); 872 873 while (*s) 874 { 875 if (*s == '\\') 876 *d++ = '\\'; 877 *d++ = *s++; 878 } 879 strcpy(d, "\\000"); 880 } 881 values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs); 882 values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain, 883 CStringGetDatum(args)); 884 } 885 else 886 { 887 values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0); 888 values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain, 889 CStringGetDatum("")); 890 } 891 892 /* build column number array if it's a column-specific trigger */ 893 ncolumns = list_length(stmt->columns); 894 if (ncolumns == 0) 895 columns = NULL; 896 else 897 { 898 ListCell *cell; 899 int i = 0; 900 901 columns = (int16 *) palloc(ncolumns * sizeof(int16)); 902 foreach(cell, stmt->columns) 903 { 904 char *name = strVal(lfirst(cell)); 905 int16 attnum; 906 int j; 907 908 /* Lookup column name. System columns are not allowed */ 909 attnum = attnameAttNum(rel, name, false); 910 if (attnum == InvalidAttrNumber) 911 ereport(ERROR, 912 (errcode(ERRCODE_UNDEFINED_COLUMN), 913 errmsg("column \"%s\" of relation \"%s\" does not exist", 914 name, RelationGetRelationName(rel)))); 915 916 /* Check for duplicates */ 917 for (j = i - 1; j >= 0; j--) 918 { 919 if (columns[j] == attnum) 920 ereport(ERROR, 921 (errcode(ERRCODE_DUPLICATE_COLUMN), 922 errmsg("column \"%s\" specified more than once", 923 name))); 924 } 925 926 columns[i++] = attnum; 927 } 928 } 929 tgattr = buildint2vector(columns, ncolumns); 930 values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr); 931 932 /* set tgqual if trigger has WHEN clause */ 933 if (qual) 934 values[Anum_pg_trigger_tgqual - 1] = CStringGetTextDatum(qual); 935 else 936 nulls[Anum_pg_trigger_tgqual - 1] = true; 937 938 if (oldtablename) 939 values[Anum_pg_trigger_tgoldtable - 1] = DirectFunctionCall1(namein, 940 CStringGetDatum(oldtablename)); 941 else 942 nulls[Anum_pg_trigger_tgoldtable - 1] = true; 943 if (newtablename) 944 values[Anum_pg_trigger_tgnewtable - 1] = DirectFunctionCall1(namein, 945 CStringGetDatum(newtablename)); 946 else 947 nulls[Anum_pg_trigger_tgnewtable - 1] = true; 948 949 tuple = heap_form_tuple(tgrel->rd_att, values, nulls); 950 951 /* force tuple to have the desired OID */ 952 HeapTupleSetOid(tuple, trigoid); 953 954 /* 955 * Insert tuple into pg_trigger. 956 */ 957 CatalogTupleInsert(tgrel, tuple); 958 959 heap_freetuple(tuple); 960 heap_close(tgrel, RowExclusiveLock); 961 962 pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1])); 963 pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1])); 964 pfree(DatumGetPointer(values[Anum_pg_trigger_tgattr - 1])); 965 if (oldtablename) 966 pfree(DatumGetPointer(values[Anum_pg_trigger_tgoldtable - 1])); 967 if (newtablename) 968 pfree(DatumGetPointer(values[Anum_pg_trigger_tgnewtable - 1])); 969 970 /* 971 * Update relation's pg_class entry; if necessary; and if not, send an SI 972 * message to make other backends (and this one) rebuild relcache entries. 973 */ 974 pgrel = heap_open(RelationRelationId, RowExclusiveLock); 975 tuple = SearchSysCacheCopy1(RELOID, 976 ObjectIdGetDatum(RelationGetRelid(rel))); 977 if (!HeapTupleIsValid(tuple)) 978 elog(ERROR, "cache lookup failed for relation %u", 979 RelationGetRelid(rel)); 980 if (!((Form_pg_class) GETSTRUCT(tuple))->relhastriggers) 981 { 982 ((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true; 983 984 CatalogTupleUpdate(pgrel, &tuple->t_self, tuple); 985 986 CommandCounterIncrement(); 987 } 988 else 989 CacheInvalidateRelcacheByTuple(tuple); 990 991 heap_freetuple(tuple); 992 heap_close(pgrel, RowExclusiveLock); 993 994 /* 995 * Record dependencies for trigger. Always place a normal dependency on 996 * the function. 997 */ 998 myself.classId = TriggerRelationId; 999 myself.objectId = trigoid; 1000 myself.objectSubId = 0; 1001 1002 referenced.classId = ProcedureRelationId; 1003 referenced.objectId = funcoid; 1004 referenced.objectSubId = 0; 1005 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); 1006 1007 if (isInternal && OidIsValid(constraintOid)) 1008 { 1009 /* 1010 * Internally-generated trigger for a constraint, so make it an 1011 * internal dependency of the constraint. We can skip depending on 1012 * the relation(s), as there'll be an indirect dependency via the 1013 * constraint. 1014 */ 1015 referenced.classId = ConstraintRelationId; 1016 referenced.objectId = constraintOid; 1017 referenced.objectSubId = 0; 1018 recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL); 1019 } 1020 else 1021 { 1022 /* 1023 * User CREATE TRIGGER, so place dependencies. We make trigger be 1024 * auto-dropped if its relation is dropped or if the FK relation is 1025 * dropped. (Auto drop is compatible with our pre-7.3 behavior.) 1026 * 1027 * Exception: if this trigger comes from a parent partitioned table, 1028 * then it's not separately drop-able, but goes away if the partition 1029 * does. 1030 */ 1031 referenced.classId = RelationRelationId; 1032 referenced.objectId = RelationGetRelid(rel); 1033 referenced.objectSubId = 0; 1034 recordDependencyOn(&myself, &referenced, OidIsValid(parentTriggerOid) ? 1035 DEPENDENCY_INTERNAL_AUTO : 1036 DEPENDENCY_AUTO); 1037 1038 if (OidIsValid(constrrelid)) 1039 { 1040 referenced.classId = RelationRelationId; 1041 referenced.objectId = constrrelid; 1042 referenced.objectSubId = 0; 1043 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO); 1044 } 1045 /* Not possible to have an index dependency in this case */ 1046 Assert(!OidIsValid(indexOid)); 1047 1048 /* 1049 * If it's a user-specified constraint trigger, make the constraint 1050 * internally dependent on the trigger instead of vice versa. 1051 */ 1052 if (OidIsValid(constraintOid)) 1053 { 1054 referenced.classId = ConstraintRelationId; 1055 referenced.objectId = constraintOid; 1056 referenced.objectSubId = 0; 1057 recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL); 1058 } 1059 1060 /* Depends on the parent trigger, if there is one. */ 1061 if (OidIsValid(parentTriggerOid)) 1062 { 1063 ObjectAddressSet(referenced, TriggerRelationId, parentTriggerOid); 1064 recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL_AUTO); 1065 } 1066 } 1067 1068 /* If column-specific trigger, add normal dependencies on columns */ 1069 if (columns != NULL) 1070 { 1071 int i; 1072 1073 referenced.classId = RelationRelationId; 1074 referenced.objectId = RelationGetRelid(rel); 1075 for (i = 0; i < ncolumns; i++) 1076 { 1077 referenced.objectSubId = columns[i]; 1078 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); 1079 } 1080 } 1081 1082 /* 1083 * If it has a WHEN clause, add dependencies on objects mentioned in the 1084 * expression (eg, functions, as well as any columns used). 1085 */ 1086 if (whenRtable != NIL) 1087 recordDependencyOnExpr(&myself, whenClause, whenRtable, 1088 DEPENDENCY_NORMAL); 1089 1090 /* Post creation hook for new trigger */ 1091 InvokeObjectPostCreateHookArg(TriggerRelationId, trigoid, 0, 1092 isInternal); 1093 1094 /* 1095 * Lastly, create the trigger on child relations, if needed. 1096 */ 1097 if (partition_recurse) 1098 { 1099 PartitionDesc partdesc = RelationGetPartitionDesc(rel); 1100 List *idxs = NIL; 1101 List *childTbls = NIL; 1102 ListCell *l; 1103 int i; 1104 MemoryContext oldcxt, 1105 perChildCxt; 1106 1107 perChildCxt = AllocSetContextCreate(CurrentMemoryContext, 1108 "part trig clone", 1109 ALLOCSET_SMALL_SIZES); 1110 1111 /* 1112 * When a trigger is being created associated with an index, we'll 1113 * need to associate the trigger in each child partition with the 1114 * corresponding index on it. 1115 */ 1116 if (OidIsValid(indexOid)) 1117 { 1118 ListCell *l; 1119 List *idxs = NIL; 1120 1121 idxs = find_inheritance_children(indexOid, ShareRowExclusiveLock); 1122 foreach(l, idxs) 1123 childTbls = lappend_oid(childTbls, 1124 IndexGetRelation(lfirst_oid(l), 1125 false)); 1126 } 1127 1128 oldcxt = MemoryContextSwitchTo(perChildCxt); 1129 1130 /* Iterate to create the trigger on each existing partition */ 1131 for (i = 0; i < partdesc->nparts; i++) 1132 { 1133 Oid indexOnChild = InvalidOid; 1134 ListCell *l2; 1135 CreateTrigStmt *childStmt; 1136 Relation childTbl; 1137 Node *qual; 1138 bool found_whole_row; 1139 1140 childTbl = heap_open(partdesc->oids[i], ShareRowExclusiveLock); 1141 1142 /* Find which of the child indexes is the one on this partition */ 1143 if (OidIsValid(indexOid)) 1144 { 1145 forboth(l, idxs, l2, childTbls) 1146 { 1147 if (lfirst_oid(l2) == partdesc->oids[i]) 1148 { 1149 indexOnChild = lfirst_oid(l); 1150 break; 1151 } 1152 } 1153 if (!OidIsValid(indexOnChild)) 1154 elog(ERROR, "failed to find index matching index \"%s\" in partition \"%s\"", 1155 get_rel_name(indexOid), 1156 get_rel_name(partdesc->oids[i])); 1157 } 1158 1159 /* 1160 * Initialize our fabricated parse node by copying the original 1161 * one, then resetting fields that we pass separately. 1162 */ 1163 childStmt = (CreateTrigStmt *) copyObject(stmt); 1164 childStmt->funcname = NIL; 1165 childStmt->whenClause = NULL; 1166 1167 /* If there is a WHEN clause, create a modified copy of it */ 1168 qual = copyObject(whenClause); 1169 qual = (Node *) 1170 map_partition_varattnos((List *) qual, PRS2_OLD_VARNO, 1171 childTbl, rel, 1172 &found_whole_row); 1173 if (found_whole_row) 1174 elog(ERROR, "unexpected whole-row reference found in trigger WHEN clause"); 1175 qual = (Node *) 1176 map_partition_varattnos((List *) qual, PRS2_NEW_VARNO, 1177 childTbl, rel, 1178 &found_whole_row); 1179 if (found_whole_row) 1180 elog(ERROR, "unexpected whole-row reference found in trigger WHEN clause"); 1181 1182 CreateTriggerFiringOn(childStmt, queryString, 1183 partdesc->oids[i], refRelOid, 1184 InvalidOid, indexOnChild, 1185 funcoid, trigoid, qual, 1186 isInternal, true, trigger_fires_when); 1187 1188 heap_close(childTbl, NoLock); 1189 1190 MemoryContextReset(perChildCxt); 1191 } 1192 1193 MemoryContextSwitchTo(oldcxt); 1194 MemoryContextDelete(perChildCxt); 1195 list_free(idxs); 1196 list_free(childTbls); 1197 } 1198 1199 /* Keep lock on target rel until end of xact */ 1200 heap_close(rel, NoLock); 1201 1202 return myself; 1203 } 1204 1205 1206 /* 1207 * Convert legacy (pre-7.3) CREATE CONSTRAINT TRIGGER commands into 1208 * full-fledged foreign key constraints. 1209 * 1210 * The conversion is complex because a pre-7.3 foreign key involved three 1211 * separate triggers, which were reported separately in dumps. While the 1212 * single trigger on the referencing table adds no new information, we need 1213 * to know the trigger functions of both of the triggers on the referenced 1214 * table to build the constraint declaration. Also, due to lack of proper 1215 * dependency checking pre-7.3, it is possible that the source database had 1216 * an incomplete set of triggers resulting in an only partially enforced 1217 * FK constraint. (This would happen if one of the tables had been dropped 1218 * and re-created, but only if the DB had been affected by a 7.0 pg_dump bug 1219 * that caused loss of tgconstrrelid information.) We choose to translate to 1220 * an FK constraint only when we've seen all three triggers of a set. This is 1221 * implemented by storing unmatched items in a list in TopMemoryContext. 1222 * We match triggers together by comparing the trigger arguments (which 1223 * include constraint name, table and column names, so should be good enough). 1224 */ 1225 typedef struct 1226 { 1227 List *args; /* list of (T_String) Values or NIL */ 1228 Oid funcoids[3]; /* OIDs of trigger functions */ 1229 /* The three function OIDs are stored in the order update, delete, child */ 1230 } OldTriggerInfo; 1231 1232 static void 1233 ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid) 1234 { 1235 static List *info_list = NIL; 1236 1237 static const char *const funcdescr[3] = { 1238 gettext_noop("Found referenced table's UPDATE trigger."), 1239 gettext_noop("Found referenced table's DELETE trigger."), 1240 gettext_noop("Found referencing table's trigger.") 1241 }; 1242 1243 char *constr_name; 1244 char *fk_table_name; 1245 char *pk_table_name; 1246 char fk_matchtype = FKCONSTR_MATCH_SIMPLE; 1247 List *fk_attrs = NIL; 1248 List *pk_attrs = NIL; 1249 StringInfoData buf; 1250 int funcnum; 1251 OldTriggerInfo *info = NULL; 1252 ListCell *l; 1253 int i; 1254 1255 /* Parse out the trigger arguments */ 1256 constr_name = strVal(linitial(stmt->args)); 1257 fk_table_name = strVal(lsecond(stmt->args)); 1258 pk_table_name = strVal(lthird(stmt->args)); 1259 i = 0; 1260 foreach(l, stmt->args) 1261 { 1262 Value *arg = (Value *) lfirst(l); 1263 1264 i++; 1265 if (i < 4) /* skip constraint and table names */ 1266 continue; 1267 if (i == 4) /* handle match type */ 1268 { 1269 if (strcmp(strVal(arg), "FULL") == 0) 1270 fk_matchtype = FKCONSTR_MATCH_FULL; 1271 else 1272 fk_matchtype = FKCONSTR_MATCH_SIMPLE; 1273 continue; 1274 } 1275 if (i % 2) 1276 fk_attrs = lappend(fk_attrs, arg); 1277 else 1278 pk_attrs = lappend(pk_attrs, arg); 1279 } 1280 1281 /* Prepare description of constraint for use in messages */ 1282 initStringInfo(&buf); 1283 appendStringInfo(&buf, "FOREIGN KEY %s(", 1284 quote_identifier(fk_table_name)); 1285 i = 0; 1286 foreach(l, fk_attrs) 1287 { 1288 Value *arg = (Value *) lfirst(l); 1289 1290 if (i++ > 0) 1291 appendStringInfoChar(&buf, ','); 1292 appendStringInfoString(&buf, quote_identifier(strVal(arg))); 1293 } 1294 appendStringInfo(&buf, ") REFERENCES %s(", 1295 quote_identifier(pk_table_name)); 1296 i = 0; 1297 foreach(l, pk_attrs) 1298 { 1299 Value *arg = (Value *) lfirst(l); 1300 1301 if (i++ > 0) 1302 appendStringInfoChar(&buf, ','); 1303 appendStringInfoString(&buf, quote_identifier(strVal(arg))); 1304 } 1305 appendStringInfoChar(&buf, ')'); 1306 1307 /* Identify class of trigger --- update, delete, or referencing-table */ 1308 switch (funcoid) 1309 { 1310 case F_RI_FKEY_CASCADE_UPD: 1311 case F_RI_FKEY_RESTRICT_UPD: 1312 case F_RI_FKEY_SETNULL_UPD: 1313 case F_RI_FKEY_SETDEFAULT_UPD: 1314 case F_RI_FKEY_NOACTION_UPD: 1315 funcnum = 0; 1316 break; 1317 1318 case F_RI_FKEY_CASCADE_DEL: 1319 case F_RI_FKEY_RESTRICT_DEL: 1320 case F_RI_FKEY_SETNULL_DEL: 1321 case F_RI_FKEY_SETDEFAULT_DEL: 1322 case F_RI_FKEY_NOACTION_DEL: 1323 funcnum = 1; 1324 break; 1325 1326 default: 1327 funcnum = 2; 1328 break; 1329 } 1330 1331 /* See if we have a match to this trigger */ 1332 foreach(l, info_list) 1333 { 1334 info = (OldTriggerInfo *) lfirst(l); 1335 if (info->funcoids[funcnum] == InvalidOid && 1336 equal(info->args, stmt->args)) 1337 { 1338 info->funcoids[funcnum] = funcoid; 1339 break; 1340 } 1341 } 1342 1343 if (l == NULL) 1344 { 1345 /* First trigger of set, so create a new list entry */ 1346 MemoryContext oldContext; 1347 1348 ereport(NOTICE, 1349 (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s", 1350 constr_name, buf.data), 1351 errdetail_internal("%s", _(funcdescr[funcnum])))); 1352 oldContext = MemoryContextSwitchTo(TopMemoryContext); 1353 info = (OldTriggerInfo *) palloc0(sizeof(OldTriggerInfo)); 1354 info->args = copyObject(stmt->args); 1355 info->funcoids[funcnum] = funcoid; 1356 info_list = lappend(info_list, info); 1357 MemoryContextSwitchTo(oldContext); 1358 } 1359 else if (info->funcoids[0] == InvalidOid || 1360 info->funcoids[1] == InvalidOid || 1361 info->funcoids[2] == InvalidOid) 1362 { 1363 /* Second trigger of set */ 1364 ereport(NOTICE, 1365 (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s", 1366 constr_name, buf.data), 1367 errdetail_internal("%s", _(funcdescr[funcnum])))); 1368 } 1369 else 1370 { 1371 /* OK, we have a set, so make the FK constraint ALTER TABLE cmd */ 1372 AlterTableStmt *atstmt = makeNode(AlterTableStmt); 1373 AlterTableCmd *atcmd = makeNode(AlterTableCmd); 1374 Constraint *fkcon = makeNode(Constraint); 1375 PlannedStmt *wrapper = makeNode(PlannedStmt); 1376 1377 ereport(NOTICE, 1378 (errmsg("converting trigger group into constraint \"%s\" %s", 1379 constr_name, buf.data), 1380 errdetail_internal("%s", _(funcdescr[funcnum])))); 1381 fkcon->contype = CONSTR_FOREIGN; 1382 fkcon->location = -1; 1383 if (funcnum == 2) 1384 { 1385 /* This trigger is on the FK table */ 1386 atstmt->relation = stmt->relation; 1387 if (stmt->constrrel) 1388 fkcon->pktable = stmt->constrrel; 1389 else 1390 { 1391 /* Work around ancient pg_dump bug that omitted constrrel */ 1392 fkcon->pktable = makeRangeVar(NULL, pk_table_name, -1); 1393 } 1394 } 1395 else 1396 { 1397 /* This trigger is on the PK table */ 1398 fkcon->pktable = stmt->relation; 1399 if (stmt->constrrel) 1400 atstmt->relation = stmt->constrrel; 1401 else 1402 { 1403 /* Work around ancient pg_dump bug that omitted constrrel */ 1404 atstmt->relation = makeRangeVar(NULL, fk_table_name, -1); 1405 } 1406 } 1407 atstmt->cmds = list_make1(atcmd); 1408 atstmt->relkind = OBJECT_TABLE; 1409 atcmd->subtype = AT_AddConstraint; 1410 atcmd->def = (Node *) fkcon; 1411 if (strcmp(constr_name, "<unnamed>") == 0) 1412 fkcon->conname = NULL; 1413 else 1414 fkcon->conname = constr_name; 1415 fkcon->fk_attrs = fk_attrs; 1416 fkcon->pk_attrs = pk_attrs; 1417 fkcon->fk_matchtype = fk_matchtype; 1418 switch (info->funcoids[0]) 1419 { 1420 case F_RI_FKEY_NOACTION_UPD: 1421 fkcon->fk_upd_action = FKCONSTR_ACTION_NOACTION; 1422 break; 1423 case F_RI_FKEY_CASCADE_UPD: 1424 fkcon->fk_upd_action = FKCONSTR_ACTION_CASCADE; 1425 break; 1426 case F_RI_FKEY_RESTRICT_UPD: 1427 fkcon->fk_upd_action = FKCONSTR_ACTION_RESTRICT; 1428 break; 1429 case F_RI_FKEY_SETNULL_UPD: 1430 fkcon->fk_upd_action = FKCONSTR_ACTION_SETNULL; 1431 break; 1432 case F_RI_FKEY_SETDEFAULT_UPD: 1433 fkcon->fk_upd_action = FKCONSTR_ACTION_SETDEFAULT; 1434 break; 1435 default: 1436 /* can't get here because of earlier checks */ 1437 elog(ERROR, "confused about RI update function"); 1438 } 1439 switch (info->funcoids[1]) 1440 { 1441 case F_RI_FKEY_NOACTION_DEL: 1442 fkcon->fk_del_action = FKCONSTR_ACTION_NOACTION; 1443 break; 1444 case F_RI_FKEY_CASCADE_DEL: 1445 fkcon->fk_del_action = FKCONSTR_ACTION_CASCADE; 1446 break; 1447 case F_RI_FKEY_RESTRICT_DEL: 1448 fkcon->fk_del_action = FKCONSTR_ACTION_RESTRICT; 1449 break; 1450 case F_RI_FKEY_SETNULL_DEL: 1451 fkcon->fk_del_action = FKCONSTR_ACTION_SETNULL; 1452 break; 1453 case F_RI_FKEY_SETDEFAULT_DEL: 1454 fkcon->fk_del_action = FKCONSTR_ACTION_SETDEFAULT; 1455 break; 1456 default: 1457 /* can't get here because of earlier checks */ 1458 elog(ERROR, "confused about RI delete function"); 1459 } 1460 fkcon->deferrable = stmt->deferrable; 1461 fkcon->initdeferred = stmt->initdeferred; 1462 fkcon->skip_validation = false; 1463 fkcon->initially_valid = true; 1464 1465 /* finally, wrap it in a dummy PlannedStmt */ 1466 wrapper->commandType = CMD_UTILITY; 1467 wrapper->canSetTag = false; 1468 wrapper->utilityStmt = (Node *) atstmt; 1469 wrapper->stmt_location = -1; 1470 wrapper->stmt_len = -1; 1471 1472 /* ... and execute it */ 1473 ProcessUtility(wrapper, 1474 "(generated ALTER TABLE ADD FOREIGN KEY command)", 1475 PROCESS_UTILITY_SUBCOMMAND, NULL, NULL, 1476 None_Receiver, NULL); 1477 1478 /* Remove the matched item from the list */ 1479 info_list = list_delete_ptr(info_list, info); 1480 pfree(info); 1481 /* We leak the copied args ... not worth worrying about */ 1482 } 1483 } 1484 1485 /* 1486 * Guts of trigger deletion. 1487 */ 1488 void 1489 RemoveTriggerById(Oid trigOid) 1490 { 1491 Relation tgrel; 1492 SysScanDesc tgscan; 1493 ScanKeyData skey[1]; 1494 HeapTuple tup; 1495 Oid relid; 1496 Relation rel; 1497 1498 tgrel = heap_open(TriggerRelationId, RowExclusiveLock); 1499 1500 /* 1501 * Find the trigger to delete. 1502 */ 1503 ScanKeyInit(&skey[0], 1504 ObjectIdAttributeNumber, 1505 BTEqualStrategyNumber, F_OIDEQ, 1506 ObjectIdGetDatum(trigOid)); 1507 1508 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true, 1509 NULL, 1, skey); 1510 1511 tup = systable_getnext(tgscan); 1512 if (!HeapTupleIsValid(tup)) 1513 elog(ERROR, "could not find tuple for trigger %u", trigOid); 1514 1515 /* 1516 * Open and exclusive-lock the relation the trigger belongs to. 1517 */ 1518 relid = ((Form_pg_trigger) GETSTRUCT(tup))->tgrelid; 1519 1520 rel = heap_open(relid, AccessExclusiveLock); 1521 1522 if (rel->rd_rel->relkind != RELKIND_RELATION && 1523 rel->rd_rel->relkind != RELKIND_VIEW && 1524 rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE && 1525 rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) 1526 ereport(ERROR, 1527 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 1528 errmsg("\"%s\" is not a table, view, or foreign table", 1529 RelationGetRelationName(rel)))); 1530 1531 if (!allowSystemTableMods && IsSystemRelation(rel)) 1532 ereport(ERROR, 1533 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), 1534 errmsg("permission denied: \"%s\" is a system catalog", 1535 RelationGetRelationName(rel)))); 1536 1537 /* 1538 * Delete the pg_trigger tuple. 1539 */ 1540 CatalogTupleDelete(tgrel, &tup->t_self); 1541 1542 systable_endscan(tgscan); 1543 heap_close(tgrel, RowExclusiveLock); 1544 1545 /* 1546 * We do not bother to try to determine whether any other triggers remain, 1547 * which would be needed in order to decide whether it's safe to clear the 1548 * relation's relhastriggers. (In any case, there might be a concurrent 1549 * process adding new triggers.) Instead, just force a relcache inval to 1550 * make other backends (and this one too!) rebuild their relcache entries. 1551 * There's no great harm in leaving relhastriggers true even if there are 1552 * no triggers left. 1553 */ 1554 CacheInvalidateRelcache(rel); 1555 1556 /* Keep lock on trigger's rel until end of xact */ 1557 heap_close(rel, NoLock); 1558 } 1559 1560 /* 1561 * get_trigger_oid - Look up a trigger by name to find its OID. 1562 * 1563 * If missing_ok is false, throw an error if trigger not found. If 1564 * true, just return InvalidOid. 1565 */ 1566 Oid 1567 get_trigger_oid(Oid relid, const char *trigname, bool missing_ok) 1568 { 1569 Relation tgrel; 1570 ScanKeyData skey[2]; 1571 SysScanDesc tgscan; 1572 HeapTuple tup; 1573 Oid oid; 1574 1575 /* 1576 * Find the trigger, verify permissions, set up object address 1577 */ 1578 tgrel = heap_open(TriggerRelationId, AccessShareLock); 1579 1580 ScanKeyInit(&skey[0], 1581 Anum_pg_trigger_tgrelid, 1582 BTEqualStrategyNumber, F_OIDEQ, 1583 ObjectIdGetDatum(relid)); 1584 ScanKeyInit(&skey[1], 1585 Anum_pg_trigger_tgname, 1586 BTEqualStrategyNumber, F_NAMEEQ, 1587 CStringGetDatum(trigname)); 1588 1589 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true, 1590 NULL, 2, skey); 1591 1592 tup = systable_getnext(tgscan); 1593 1594 if (!HeapTupleIsValid(tup)) 1595 { 1596 if (!missing_ok) 1597 ereport(ERROR, 1598 (errcode(ERRCODE_UNDEFINED_OBJECT), 1599 errmsg("trigger \"%s\" for table \"%s\" does not exist", 1600 trigname, get_rel_name(relid)))); 1601 oid = InvalidOid; 1602 } 1603 else 1604 { 1605 oid = HeapTupleGetOid(tup); 1606 } 1607 1608 systable_endscan(tgscan); 1609 heap_close(tgrel, AccessShareLock); 1610 return oid; 1611 } 1612 1613 /* 1614 * Perform permissions and integrity checks before acquiring a relation lock. 1615 */ 1616 static void 1617 RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid, 1618 void *arg) 1619 { 1620 HeapTuple tuple; 1621 Form_pg_class form; 1622 1623 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); 1624 if (!HeapTupleIsValid(tuple)) 1625 return; /* concurrently dropped */ 1626 form = (Form_pg_class) GETSTRUCT(tuple); 1627 1628 /* only tables and views can have triggers */ 1629 if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW && 1630 form->relkind != RELKIND_FOREIGN_TABLE && 1631 form->relkind != RELKIND_PARTITIONED_TABLE) 1632 ereport(ERROR, 1633 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 1634 errmsg("\"%s\" is not a table, view, or foreign table", 1635 rv->relname))); 1636 1637 /* you must own the table to rename one of its triggers */ 1638 if (!pg_class_ownercheck(relid, GetUserId())) 1639 aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(get_rel_relkind(relid)), rv->relname); 1640 if (!allowSystemTableMods && IsSystemClass(relid, form)) 1641 ereport(ERROR, 1642 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), 1643 errmsg("permission denied: \"%s\" is a system catalog", 1644 rv->relname))); 1645 1646 ReleaseSysCache(tuple); 1647 } 1648 1649 /* 1650 * renametrig - changes the name of a trigger on a relation 1651 * 1652 * trigger name is changed in trigger catalog. 1653 * No record of the previous name is kept. 1654 * 1655 * get proper relrelation from relation catalog (if not arg) 1656 * scan trigger catalog 1657 * for name conflict (within rel) 1658 * for original trigger (if not arg) 1659 * modify tgname in trigger tuple 1660 * update row in catalog 1661 */ 1662 ObjectAddress 1663 renametrig(RenameStmt *stmt) 1664 { 1665 Oid tgoid; 1666 Relation targetrel; 1667 Relation tgrel; 1668 HeapTuple tuple; 1669 SysScanDesc tgscan; 1670 ScanKeyData key[2]; 1671 Oid relid; 1672 ObjectAddress address; 1673 1674 /* 1675 * Look up name, check permissions, and acquire lock (which we will NOT 1676 * release until end of transaction). 1677 */ 1678 relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock, 1679 0, 1680 RangeVarCallbackForRenameTrigger, 1681 NULL); 1682 1683 /* Have lock already, so just need to build relcache entry. */ 1684 targetrel = relation_open(relid, NoLock); 1685 1686 /* 1687 * Scan pg_trigger twice for existing triggers on relation. We do this in 1688 * order to ensure a trigger does not exist with newname (The unique index 1689 * on tgrelid/tgname would complain anyway) and to ensure a trigger does 1690 * exist with oldname. 1691 * 1692 * NOTE that this is cool only because we have AccessExclusiveLock on the 1693 * relation, so the trigger set won't be changing underneath us. 1694 */ 1695 tgrel = heap_open(TriggerRelationId, RowExclusiveLock); 1696 1697 /* 1698 * First pass -- look for name conflict 1699 */ 1700 ScanKeyInit(&key[0], 1701 Anum_pg_trigger_tgrelid, 1702 BTEqualStrategyNumber, F_OIDEQ, 1703 ObjectIdGetDatum(relid)); 1704 ScanKeyInit(&key[1], 1705 Anum_pg_trigger_tgname, 1706 BTEqualStrategyNumber, F_NAMEEQ, 1707 PointerGetDatum(stmt->newname)); 1708 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true, 1709 NULL, 2, key); 1710 if (HeapTupleIsValid(tuple = systable_getnext(tgscan))) 1711 ereport(ERROR, 1712 (errcode(ERRCODE_DUPLICATE_OBJECT), 1713 errmsg("trigger \"%s\" for relation \"%s\" already exists", 1714 stmt->newname, RelationGetRelationName(targetrel)))); 1715 systable_endscan(tgscan); 1716 1717 /* 1718 * Second pass -- look for trigger existing with oldname and update 1719 */ 1720 ScanKeyInit(&key[0], 1721 Anum_pg_trigger_tgrelid, 1722 BTEqualStrategyNumber, F_OIDEQ, 1723 ObjectIdGetDatum(relid)); 1724 ScanKeyInit(&key[1], 1725 Anum_pg_trigger_tgname, 1726 BTEqualStrategyNumber, F_NAMEEQ, 1727 PointerGetDatum(stmt->subname)); 1728 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true, 1729 NULL, 2, key); 1730 if (HeapTupleIsValid(tuple = systable_getnext(tgscan))) 1731 { 1732 tgoid = HeapTupleGetOid(tuple); 1733 1734 /* 1735 * Update pg_trigger tuple with new tgname. 1736 */ 1737 tuple = heap_copytuple(tuple); /* need a modifiable copy */ 1738 1739 namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname, 1740 stmt->newname); 1741 1742 CatalogTupleUpdate(tgrel, &tuple->t_self, tuple); 1743 1744 InvokeObjectPostAlterHook(TriggerRelationId, 1745 HeapTupleGetOid(tuple), 0); 1746 1747 /* 1748 * Invalidate relation's relcache entry so that other backends (and 1749 * this one too!) are sent SI message to make them rebuild relcache 1750 * entries. (Ideally this should happen automatically...) 1751 */ 1752 CacheInvalidateRelcache(targetrel); 1753 } 1754 else 1755 { 1756 ereport(ERROR, 1757 (errcode(ERRCODE_UNDEFINED_OBJECT), 1758 errmsg("trigger \"%s\" for table \"%s\" does not exist", 1759 stmt->subname, RelationGetRelationName(targetrel)))); 1760 } 1761 1762 ObjectAddressSet(address, TriggerRelationId, tgoid); 1763 1764 systable_endscan(tgscan); 1765 1766 heap_close(tgrel, RowExclusiveLock); 1767 1768 /* 1769 * Close rel, but keep exclusive lock! 1770 */ 1771 relation_close(targetrel, NoLock); 1772 1773 return address; 1774 } 1775 1776 1777 /* 1778 * EnableDisableTrigger() 1779 * 1780 * Called by ALTER TABLE ENABLE/DISABLE [ REPLICA | ALWAYS ] TRIGGER 1781 * to change 'tgenabled' field for the specified trigger(s) 1782 * 1783 * rel: relation to process (caller must hold suitable lock on it) 1784 * tgname: trigger to process, or NULL to scan all triggers 1785 * fires_when: new value for tgenabled field. In addition to generic 1786 * enablement/disablement, this also defines when the trigger 1787 * should be fired in session replication roles. 1788 * skip_system: if true, skip "system" triggers (constraint triggers) 1789 * 1790 * Caller should have checked permissions for the table; here we also 1791 * enforce that superuser privilege is required to alter the state of 1792 * system triggers 1793 */ 1794 void 1795 EnableDisableTrigger(Relation rel, const char *tgname, 1796 char fires_when, bool skip_system, LOCKMODE lockmode) 1797 { 1798 Relation tgrel; 1799 int nkeys; 1800 ScanKeyData keys[2]; 1801 SysScanDesc tgscan; 1802 HeapTuple tuple; 1803 bool found; 1804 bool changed; 1805 1806 /* Scan the relevant entries in pg_triggers */ 1807 tgrel = heap_open(TriggerRelationId, RowExclusiveLock); 1808 1809 ScanKeyInit(&keys[0], 1810 Anum_pg_trigger_tgrelid, 1811 BTEqualStrategyNumber, F_OIDEQ, 1812 ObjectIdGetDatum(RelationGetRelid(rel))); 1813 if (tgname) 1814 { 1815 ScanKeyInit(&keys[1], 1816 Anum_pg_trigger_tgname, 1817 BTEqualStrategyNumber, F_NAMEEQ, 1818 CStringGetDatum(tgname)); 1819 nkeys = 2; 1820 } 1821 else 1822 nkeys = 1; 1823 1824 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true, 1825 NULL, nkeys, keys); 1826 1827 found = changed = false; 1828 1829 while (HeapTupleIsValid(tuple = systable_getnext(tgscan))) 1830 { 1831 Form_pg_trigger oldtrig = (Form_pg_trigger) GETSTRUCT(tuple); 1832 1833 if (oldtrig->tgisinternal) 1834 { 1835 /* system trigger ... ok to process? */ 1836 if (skip_system) 1837 continue; 1838 if (!superuser()) 1839 ereport(ERROR, 1840 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), 1841 errmsg("permission denied: \"%s\" is a system trigger", 1842 NameStr(oldtrig->tgname)))); 1843 } 1844 1845 found = true; 1846 1847 if (oldtrig->tgenabled != fires_when) 1848 { 1849 /* need to change this one ... make a copy to scribble on */ 1850 HeapTuple newtup = heap_copytuple(tuple); 1851 Form_pg_trigger newtrig = (Form_pg_trigger) GETSTRUCT(newtup); 1852 1853 newtrig->tgenabled = fires_when; 1854 1855 CatalogTupleUpdate(tgrel, &newtup->t_self, newtup); 1856 1857 heap_freetuple(newtup); 1858 1859 changed = true; 1860 } 1861 1862 InvokeObjectPostAlterHook(TriggerRelationId, 1863 HeapTupleGetOid(tuple), 0); 1864 } 1865 1866 systable_endscan(tgscan); 1867 1868 heap_close(tgrel, RowExclusiveLock); 1869 1870 if (tgname && !found) 1871 ereport(ERROR, 1872 (errcode(ERRCODE_UNDEFINED_OBJECT), 1873 errmsg("trigger \"%s\" for table \"%s\" does not exist", 1874 tgname, RelationGetRelationName(rel)))); 1875 1876 /* 1877 * If we changed anything, broadcast a SI inval message to force each 1878 * backend (including our own!) to rebuild relation's relcache entry. 1879 * Otherwise they will fail to apply the change promptly. 1880 */ 1881 if (changed) 1882 CacheInvalidateRelcache(rel); 1883 } 1884 1885 1886 /* 1887 * Build trigger data to attach to the given relcache entry. 1888 * 1889 * Note that trigger data attached to a relcache entry must be stored in 1890 * CacheMemoryContext to ensure it survives as long as the relcache entry. 1891 * But we should be running in a less long-lived working context. To avoid 1892 * leaking cache memory if this routine fails partway through, we build a 1893 * temporary TriggerDesc in working memory and then copy the completed 1894 * structure into cache memory. 1895 */ 1896 void 1897 RelationBuildTriggers(Relation relation) 1898 { 1899 TriggerDesc *trigdesc; 1900 int numtrigs; 1901 int maxtrigs; 1902 Trigger *triggers; 1903 Relation tgrel; 1904 ScanKeyData skey; 1905 SysScanDesc tgscan; 1906 HeapTuple htup; 1907 MemoryContext oldContext; 1908 int i; 1909 1910 /* 1911 * Allocate a working array to hold the triggers (the array is extended if 1912 * necessary) 1913 */ 1914 maxtrigs = 16; 1915 triggers = (Trigger *) palloc(maxtrigs * sizeof(Trigger)); 1916 numtrigs = 0; 1917 1918 /* 1919 * Note: since we scan the triggers using TriggerRelidNameIndexId, we will 1920 * be reading the triggers in name order, except possibly during 1921 * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn 1922 * ensures that triggers will be fired in name order. 1923 */ 1924 ScanKeyInit(&skey, 1925 Anum_pg_trigger_tgrelid, 1926 BTEqualStrategyNumber, F_OIDEQ, 1927 ObjectIdGetDatum(RelationGetRelid(relation))); 1928 1929 tgrel = heap_open(TriggerRelationId, AccessShareLock); 1930 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true, 1931 NULL, 1, &skey); 1932 1933 while (HeapTupleIsValid(htup = systable_getnext(tgscan))) 1934 { 1935 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup); 1936 Trigger *build; 1937 Datum datum; 1938 bool isnull; 1939 1940 if (numtrigs >= maxtrigs) 1941 { 1942 maxtrigs *= 2; 1943 triggers = (Trigger *) repalloc(triggers, maxtrigs * sizeof(Trigger)); 1944 } 1945 build = &(triggers[numtrigs]); 1946 1947 build->tgoid = HeapTupleGetOid(htup); 1948 build->tgname = DatumGetCString(DirectFunctionCall1(nameout, 1949 NameGetDatum(&pg_trigger->tgname))); 1950 build->tgfoid = pg_trigger->tgfoid; 1951 build->tgtype = pg_trigger->tgtype; 1952 build->tgenabled = pg_trigger->tgenabled; 1953 build->tgisinternal = pg_trigger->tgisinternal; 1954 build->tgconstrrelid = pg_trigger->tgconstrrelid; 1955 build->tgconstrindid = pg_trigger->tgconstrindid; 1956 build->tgconstraint = pg_trigger->tgconstraint; 1957 build->tgdeferrable = pg_trigger->tgdeferrable; 1958 build->tginitdeferred = pg_trigger->tginitdeferred; 1959 build->tgnargs = pg_trigger->tgnargs; 1960 /* tgattr is first var-width field, so OK to access directly */ 1961 build->tgnattr = pg_trigger->tgattr.dim1; 1962 if (build->tgnattr > 0) 1963 { 1964 build->tgattr = (int16 *) palloc(build->tgnattr * sizeof(int16)); 1965 memcpy(build->tgattr, &(pg_trigger->tgattr.values), 1966 build->tgnattr * sizeof(int16)); 1967 } 1968 else 1969 build->tgattr = NULL; 1970 if (build->tgnargs > 0) 1971 { 1972 bytea *val; 1973 char *p; 1974 1975 val = DatumGetByteaPP(fastgetattr(htup, 1976 Anum_pg_trigger_tgargs, 1977 tgrel->rd_att, &isnull)); 1978 if (isnull) 1979 elog(ERROR, "tgargs is null in trigger for relation \"%s\"", 1980 RelationGetRelationName(relation)); 1981 p = (char *) VARDATA_ANY(val); 1982 build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *)); 1983 for (i = 0; i < build->tgnargs; i++) 1984 { 1985 build->tgargs[i] = pstrdup(p); 1986 p += strlen(p) + 1; 1987 } 1988 } 1989 else 1990 build->tgargs = NULL; 1991 1992 datum = fastgetattr(htup, Anum_pg_trigger_tgoldtable, 1993 tgrel->rd_att, &isnull); 1994 if (!isnull) 1995 build->tgoldtable = 1996 DatumGetCString(DirectFunctionCall1(nameout, datum)); 1997 else 1998 build->tgoldtable = NULL; 1999 2000 datum = fastgetattr(htup, Anum_pg_trigger_tgnewtable, 2001 tgrel->rd_att, &isnull); 2002 if (!isnull) 2003 build->tgnewtable = 2004 DatumGetCString(DirectFunctionCall1(nameout, datum)); 2005 else 2006 build->tgnewtable = NULL; 2007 2008 datum = fastgetattr(htup, Anum_pg_trigger_tgqual, 2009 tgrel->rd_att, &isnull); 2010 if (!isnull) 2011 build->tgqual = TextDatumGetCString(datum); 2012 else 2013 build->tgqual = NULL; 2014 2015 numtrigs++; 2016 } 2017 2018 systable_endscan(tgscan); 2019 heap_close(tgrel, AccessShareLock); 2020 2021 /* There might not be any triggers */ 2022 if (numtrigs == 0) 2023 { 2024 pfree(triggers); 2025 return; 2026 } 2027 2028 /* Build trigdesc */ 2029 trigdesc = (TriggerDesc *) palloc0(sizeof(TriggerDesc)); 2030 trigdesc->triggers = triggers; 2031 trigdesc->numtriggers = numtrigs; 2032 for (i = 0; i < numtrigs; i++) 2033 SetTriggerFlags(trigdesc, &(triggers[i])); 2034 2035 /* Copy completed trigdesc into cache storage */ 2036 oldContext = MemoryContextSwitchTo(CacheMemoryContext); 2037 relation->trigdesc = CopyTriggerDesc(trigdesc); 2038 MemoryContextSwitchTo(oldContext); 2039 2040 /* Release working memory */ 2041 FreeTriggerDesc(trigdesc); 2042 } 2043 2044 /* 2045 * Update the TriggerDesc's hint flags to include the specified trigger 2046 */ 2047 static void 2048 SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger) 2049 { 2050 int16 tgtype = trigger->tgtype; 2051 2052 trigdesc->trig_insert_before_row |= 2053 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW, 2054 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT); 2055 trigdesc->trig_insert_after_row |= 2056 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW, 2057 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT); 2058 trigdesc->trig_insert_instead_row |= 2059 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW, 2060 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_INSERT); 2061 trigdesc->trig_insert_before_statement |= 2062 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT, 2063 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT); 2064 trigdesc->trig_insert_after_statement |= 2065 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT, 2066 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT); 2067 trigdesc->trig_update_before_row |= 2068 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW, 2069 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE); 2070 trigdesc->trig_update_after_row |= 2071 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW, 2072 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE); 2073 trigdesc->trig_update_instead_row |= 2074 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW, 2075 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_UPDATE); 2076 trigdesc->trig_update_before_statement |= 2077 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT, 2078 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE); 2079 trigdesc->trig_update_after_statement |= 2080 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT, 2081 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE); 2082 trigdesc->trig_delete_before_row |= 2083 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW, 2084 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE); 2085 trigdesc->trig_delete_after_row |= 2086 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW, 2087 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE); 2088 trigdesc->trig_delete_instead_row |= 2089 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW, 2090 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_DELETE); 2091 trigdesc->trig_delete_before_statement |= 2092 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT, 2093 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE); 2094 trigdesc->trig_delete_after_statement |= 2095 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT, 2096 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE); 2097 /* there are no row-level truncate triggers */ 2098 trigdesc->trig_truncate_before_statement |= 2099 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT, 2100 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_TRUNCATE); 2101 trigdesc->trig_truncate_after_statement |= 2102 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT, 2103 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_TRUNCATE); 2104 2105 trigdesc->trig_insert_new_table |= 2106 (TRIGGER_FOR_INSERT(tgtype) && 2107 TRIGGER_USES_TRANSITION_TABLE(trigger->tgnewtable)); 2108 trigdesc->trig_update_old_table |= 2109 (TRIGGER_FOR_UPDATE(tgtype) && 2110 TRIGGER_USES_TRANSITION_TABLE(trigger->tgoldtable)); 2111 trigdesc->trig_update_new_table |= 2112 (TRIGGER_FOR_UPDATE(tgtype) && 2113 TRIGGER_USES_TRANSITION_TABLE(trigger->tgnewtable)); 2114 trigdesc->trig_delete_old_table |= 2115 (TRIGGER_FOR_DELETE(tgtype) && 2116 TRIGGER_USES_TRANSITION_TABLE(trigger->tgoldtable)); 2117 } 2118 2119 /* 2120 * Copy a TriggerDesc data structure. 2121 * 2122 * The copy is allocated in the current memory context. 2123 */ 2124 TriggerDesc * 2125 CopyTriggerDesc(TriggerDesc *trigdesc) 2126 { 2127 TriggerDesc *newdesc; 2128 Trigger *trigger; 2129 int i; 2130 2131 if (trigdesc == NULL || trigdesc->numtriggers <= 0) 2132 return NULL; 2133 2134 newdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc)); 2135 memcpy(newdesc, trigdesc, sizeof(TriggerDesc)); 2136 2137 trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger)); 2138 memcpy(trigger, trigdesc->triggers, 2139 trigdesc->numtriggers * sizeof(Trigger)); 2140 newdesc->triggers = trigger; 2141 2142 for (i = 0; i < trigdesc->numtriggers; i++) 2143 { 2144 trigger->tgname = pstrdup(trigger->tgname); 2145 if (trigger->tgnattr > 0) 2146 { 2147 int16 *newattr; 2148 2149 newattr = (int16 *) palloc(trigger->tgnattr * sizeof(int16)); 2150 memcpy(newattr, trigger->tgattr, 2151 trigger->tgnattr * sizeof(int16)); 2152 trigger->tgattr = newattr; 2153 } 2154 if (trigger->tgnargs > 0) 2155 { 2156 char **newargs; 2157 int16 j; 2158 2159 newargs = (char **) palloc(trigger->tgnargs * sizeof(char *)); 2160 for (j = 0; j < trigger->tgnargs; j++) 2161 newargs[j] = pstrdup(trigger->tgargs[j]); 2162 trigger->tgargs = newargs; 2163 } 2164 if (trigger->tgqual) 2165 trigger->tgqual = pstrdup(trigger->tgqual); 2166 if (trigger->tgoldtable) 2167 trigger->tgoldtable = pstrdup(trigger->tgoldtable); 2168 if (trigger->tgnewtable) 2169 trigger->tgnewtable = pstrdup(trigger->tgnewtable); 2170 trigger++; 2171 } 2172 2173 return newdesc; 2174 } 2175 2176 /* 2177 * Free a TriggerDesc data structure. 2178 */ 2179 void 2180 FreeTriggerDesc(TriggerDesc *trigdesc) 2181 { 2182 Trigger *trigger; 2183 int i; 2184 2185 if (trigdesc == NULL) 2186 return; 2187 2188 trigger = trigdesc->triggers; 2189 for (i = 0; i < trigdesc->numtriggers; i++) 2190 { 2191 pfree(trigger->tgname); 2192 if (trigger->tgnattr > 0) 2193 pfree(trigger->tgattr); 2194 if (trigger->tgnargs > 0) 2195 { 2196 while (--(trigger->tgnargs) >= 0) 2197 pfree(trigger->tgargs[trigger->tgnargs]); 2198 pfree(trigger->tgargs); 2199 } 2200 if (trigger->tgqual) 2201 pfree(trigger->tgqual); 2202 if (trigger->tgoldtable) 2203 pfree(trigger->tgoldtable); 2204 if (trigger->tgnewtable) 2205 pfree(trigger->tgnewtable); 2206 trigger++; 2207 } 2208 pfree(trigdesc->triggers); 2209 pfree(trigdesc); 2210 } 2211 2212 /* 2213 * Compare two TriggerDesc structures for logical equality. 2214 */ 2215 #ifdef NOT_USED 2216 bool 2217 equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2) 2218 { 2219 int i, 2220 j; 2221 2222 /* 2223 * We need not examine the hint flags, just the trigger array itself; if 2224 * we have the same triggers with the same types, the flags should match. 2225 * 2226 * As of 7.3 we assume trigger set ordering is significant in the 2227 * comparison; so we just compare corresponding slots of the two sets. 2228 * 2229 * Note: comparing the stringToNode forms of the WHEN clauses means that 2230 * parse column locations will affect the result. This is okay as long as 2231 * this function is only used for detecting exact equality, as for example 2232 * in checking for staleness of a cache entry. 2233 */ 2234 if (trigdesc1 != NULL) 2235 { 2236 if (trigdesc2 == NULL) 2237 return false; 2238 if (trigdesc1->numtriggers != trigdesc2->numtriggers) 2239 return false; 2240 for (i = 0; i < trigdesc1->numtriggers; i++) 2241 { 2242 Trigger *trig1 = trigdesc1->triggers + i; 2243 Trigger *trig2 = trigdesc2->triggers + i; 2244 2245 if (trig1->tgoid != trig2->tgoid) 2246 return false; 2247 if (strcmp(trig1->tgname, trig2->tgname) != 0) 2248 return false; 2249 if (trig1->tgfoid != trig2->tgfoid) 2250 return false; 2251 if (trig1->tgtype != trig2->tgtype) 2252 return false; 2253 if (trig1->tgenabled != trig2->tgenabled) 2254 return false; 2255 if (trig1->tgisinternal != trig2->tgisinternal) 2256 return false; 2257 if (trig1->tgconstrrelid != trig2->tgconstrrelid) 2258 return false; 2259 if (trig1->tgconstrindid != trig2->tgconstrindid) 2260 return false; 2261 if (trig1->tgconstraint != trig2->tgconstraint) 2262 return false; 2263 if (trig1->tgdeferrable != trig2->tgdeferrable) 2264 return false; 2265 if (trig1->tginitdeferred != trig2->tginitdeferred) 2266 return false; 2267 if (trig1->tgnargs != trig2->tgnargs) 2268 return false; 2269 if (trig1->tgnattr != trig2->tgnattr) 2270 return false; 2271 if (trig1->tgnattr > 0 && 2272 memcmp(trig1->tgattr, trig2->tgattr, 2273 trig1->tgnattr * sizeof(int16)) != 0) 2274 return false; 2275 for (j = 0; j < trig1->tgnargs; j++) 2276 if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0) 2277 return false; 2278 if (trig1->tgqual == NULL && trig2->tgqual == NULL) 2279 /* ok */ ; 2280 else if (trig1->tgqual == NULL || trig2->tgqual == NULL) 2281 return false; 2282 else if (strcmp(trig1->tgqual, trig2->tgqual) != 0) 2283 return false; 2284 if (trig1->tgoldtable == NULL && trig2->tgoldtable == NULL) 2285 /* ok */ ; 2286 else if (trig1->tgoldtable == NULL || trig2->tgoldtable == NULL) 2287 return false; 2288 else if (strcmp(trig1->tgoldtable, trig2->tgoldtable) != 0) 2289 return false; 2290 if (trig1->tgnewtable == NULL && trig2->tgnewtable == NULL) 2291 /* ok */ ; 2292 else if (trig1->tgnewtable == NULL || trig2->tgnewtable == NULL) 2293 return false; 2294 else if (strcmp(trig1->tgnewtable, trig2->tgnewtable) != 0) 2295 return false; 2296 } 2297 } 2298 else if (trigdesc2 != NULL) 2299 return false; 2300 return true; 2301 } 2302 #endif /* NOT_USED */ 2303 2304 /* 2305 * Check if there is a row-level trigger with transition tables that prevents 2306 * a table from becoming an inheritance child or partition. Return the name 2307 * of the first such incompatible trigger, or NULL if there is none. 2308 */ 2309 const char * 2310 FindTriggerIncompatibleWithInheritance(TriggerDesc *trigdesc) 2311 { 2312 if (trigdesc != NULL) 2313 { 2314 int i; 2315 2316 for (i = 0; i < trigdesc->numtriggers; ++i) 2317 { 2318 Trigger *trigger = &trigdesc->triggers[i]; 2319 2320 if (trigger->tgoldtable != NULL || trigger->tgnewtable != NULL) 2321 return trigger->tgname; 2322 } 2323 } 2324 2325 return NULL; 2326 } 2327 2328 /* 2329 * Call a trigger function. 2330 * 2331 * trigdata: trigger descriptor. 2332 * tgindx: trigger's index in finfo and instr arrays. 2333 * finfo: array of cached trigger function call information. 2334 * instr: optional array of EXPLAIN ANALYZE instrumentation state. 2335 * per_tuple_context: memory context to execute the function in. 2336 * 2337 * Returns the tuple (or NULL) as returned by the function. 2338 */ 2339 static HeapTuple 2340 ExecCallTriggerFunc(TriggerData *trigdata, 2341 int tgindx, 2342 FmgrInfo *finfo, 2343 Instrumentation *instr, 2344 MemoryContext per_tuple_context) 2345 { 2346 FunctionCallInfoData fcinfo; 2347 PgStat_FunctionCallUsage fcusage; 2348 Datum result; 2349 MemoryContext oldContext; 2350 2351 /* 2352 * Protect against code paths that may fail to initialize transition table 2353 * info. 2354 */ 2355 Assert(((TRIGGER_FIRED_BY_INSERT(trigdata->tg_event) || 2356 TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event) || 2357 TRIGGER_FIRED_BY_DELETE(trigdata->tg_event)) && 2358 TRIGGER_FIRED_AFTER(trigdata->tg_event) && 2359 !(trigdata->tg_event & AFTER_TRIGGER_DEFERRABLE) && 2360 !(trigdata->tg_event & AFTER_TRIGGER_INITDEFERRED)) || 2361 (trigdata->tg_oldtable == NULL && trigdata->tg_newtable == NULL)); 2362 2363 finfo += tgindx; 2364 2365 /* 2366 * We cache fmgr lookup info, to avoid making the lookup again on each 2367 * call. 2368 */ 2369 if (finfo->fn_oid == InvalidOid) 2370 fmgr_info(trigdata->tg_trigger->tgfoid, finfo); 2371 2372 Assert(finfo->fn_oid == trigdata->tg_trigger->tgfoid); 2373 2374 /* 2375 * If doing EXPLAIN ANALYZE, start charging time to this trigger. 2376 */ 2377 if (instr) 2378 InstrStartNode(instr + tgindx); 2379 2380 /* 2381 * Do the function evaluation in the per-tuple memory context, so that 2382 * leaked memory will be reclaimed once per tuple. Note in particular that 2383 * any new tuple created by the trigger function will live till the end of 2384 * the tuple cycle. 2385 */ 2386 oldContext = MemoryContextSwitchTo(per_tuple_context); 2387 2388 /* 2389 * Call the function, passing no arguments but setting a context. 2390 */ 2391 InitFunctionCallInfoData(fcinfo, finfo, 0, 2392 InvalidOid, (Node *) trigdata, NULL); 2393 2394 pgstat_init_function_usage(&fcinfo, &fcusage); 2395 2396 MyTriggerDepth++; 2397 PG_TRY(); 2398 { 2399 result = FunctionCallInvoke(&fcinfo); 2400 } 2401 PG_CATCH(); 2402 { 2403 MyTriggerDepth--; 2404 PG_RE_THROW(); 2405 } 2406 PG_END_TRY(); 2407 MyTriggerDepth--; 2408 2409 pgstat_end_function_usage(&fcusage, true); 2410 2411 MemoryContextSwitchTo(oldContext); 2412 2413 /* 2414 * Trigger protocol allows function to return a null pointer, but NOT to 2415 * set the isnull result flag. 2416 */ 2417 if (fcinfo.isnull) 2418 ereport(ERROR, 2419 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), 2420 errmsg("trigger function %u returned null value", 2421 fcinfo.flinfo->fn_oid))); 2422 2423 /* 2424 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count 2425 * one "tuple returned" (really the number of firings). 2426 */ 2427 if (instr) 2428 InstrStopNode(instr + tgindx, 1); 2429 2430 return (HeapTuple) DatumGetPointer(result); 2431 } 2432 2433 void 2434 ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo) 2435 { 2436 TriggerDesc *trigdesc; 2437 int i; 2438 TriggerData LocTriggerData; 2439 2440 trigdesc = relinfo->ri_TrigDesc; 2441 2442 if (trigdesc == NULL) 2443 return; 2444 if (!trigdesc->trig_insert_before_statement) 2445 return; 2446 2447 /* no-op if we already fired BS triggers in this context */ 2448 if (before_stmt_triggers_fired(RelationGetRelid(relinfo->ri_RelationDesc), 2449 CMD_INSERT)) 2450 return; 2451 2452 LocTriggerData.type = T_TriggerData; 2453 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT | 2454 TRIGGER_EVENT_BEFORE; 2455 LocTriggerData.tg_relation = relinfo->ri_RelationDesc; 2456 LocTriggerData.tg_trigtuple = NULL; 2457 LocTriggerData.tg_newtuple = NULL; 2458 LocTriggerData.tg_oldtable = NULL; 2459 LocTriggerData.tg_newtable = NULL; 2460 LocTriggerData.tg_trigtuplebuf = InvalidBuffer; 2461 LocTriggerData.tg_newtuplebuf = InvalidBuffer; 2462 for (i = 0; i < trigdesc->numtriggers; i++) 2463 { 2464 Trigger *trigger = &trigdesc->triggers[i]; 2465 HeapTuple newtuple; 2466 2467 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype, 2468 TRIGGER_TYPE_STATEMENT, 2469 TRIGGER_TYPE_BEFORE, 2470 TRIGGER_TYPE_INSERT)) 2471 continue; 2472 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event, 2473 NULL, NULL, NULL)) 2474 continue; 2475 2476 LocTriggerData.tg_trigger = trigger; 2477 newtuple = ExecCallTriggerFunc(&LocTriggerData, 2478 i, 2479 relinfo->ri_TrigFunctions, 2480 relinfo->ri_TrigInstrument, 2481 GetPerTupleMemoryContext(estate)); 2482 2483 if (newtuple) 2484 ereport(ERROR, 2485 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), 2486 errmsg("BEFORE STATEMENT trigger cannot return a value"))); 2487 } 2488 } 2489 2490 void 2491 ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, 2492 TransitionCaptureState *transition_capture) 2493 { 2494 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 2495 2496 if (trigdesc && trigdesc->trig_insert_after_statement) 2497 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_INSERT, 2498 false, NULL, NULL, NIL, NULL, transition_capture); 2499 } 2500 2501 TupleTableSlot * 2502 ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, 2503 TupleTableSlot *slot) 2504 { 2505 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 2506 HeapTuple slottuple = ExecMaterializeSlot(slot); 2507 HeapTuple newtuple = slottuple; 2508 HeapTuple oldtuple; 2509 TriggerData LocTriggerData; 2510 int i; 2511 2512 LocTriggerData.type = T_TriggerData; 2513 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT | 2514 TRIGGER_EVENT_ROW | 2515 TRIGGER_EVENT_BEFORE; 2516 LocTriggerData.tg_relation = relinfo->ri_RelationDesc; 2517 LocTriggerData.tg_newtuple = NULL; 2518 LocTriggerData.tg_oldtable = NULL; 2519 LocTriggerData.tg_newtable = NULL; 2520 LocTriggerData.tg_newtuplebuf = InvalidBuffer; 2521 for (i = 0; i < trigdesc->numtriggers; i++) 2522 { 2523 Trigger *trigger = &trigdesc->triggers[i]; 2524 2525 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype, 2526 TRIGGER_TYPE_ROW, 2527 TRIGGER_TYPE_BEFORE, 2528 TRIGGER_TYPE_INSERT)) 2529 continue; 2530 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event, 2531 NULL, NULL, newtuple)) 2532 continue; 2533 2534 LocTriggerData.tg_trigtuple = oldtuple = newtuple; 2535 LocTriggerData.tg_trigtuplebuf = InvalidBuffer; 2536 LocTriggerData.tg_trigger = trigger; 2537 newtuple = ExecCallTriggerFunc(&LocTriggerData, 2538 i, 2539 relinfo->ri_TrigFunctions, 2540 relinfo->ri_TrigInstrument, 2541 GetPerTupleMemoryContext(estate)); 2542 if (oldtuple != newtuple && oldtuple != slottuple) 2543 heap_freetuple(oldtuple); 2544 if (newtuple == NULL) 2545 return NULL; /* "do nothing" */ 2546 } 2547 2548 if (newtuple != slottuple) 2549 { 2550 /* 2551 * Return the modified tuple using the es_trig_tuple_slot. We assume 2552 * the tuple was allocated in per-tuple memory context, and therefore 2553 * will go away by itself. The tuple table slot should not try to 2554 * clear it. 2555 */ 2556 TupleTableSlot *newslot = estate->es_trig_tuple_slot; 2557 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc); 2558 2559 if (newslot->tts_tupleDescriptor != tupdesc) 2560 ExecSetSlotDescriptor(newslot, tupdesc); 2561 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false); 2562 slot = newslot; 2563 } 2564 return slot; 2565 } 2566 2567 void 2568 ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, 2569 HeapTuple trigtuple, List *recheckIndexes, 2570 TransitionCaptureState *transition_capture) 2571 { 2572 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 2573 2574 if ((trigdesc && trigdesc->trig_insert_after_row) || 2575 (transition_capture && transition_capture->tcs_insert_new_table)) 2576 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_INSERT, 2577 true, NULL, trigtuple, 2578 recheckIndexes, NULL, 2579 transition_capture); 2580 } 2581 2582 TupleTableSlot * 2583 ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, 2584 TupleTableSlot *slot) 2585 { 2586 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 2587 HeapTuple slottuple = ExecMaterializeSlot(slot); 2588 HeapTuple newtuple = slottuple; 2589 HeapTuple oldtuple; 2590 TriggerData LocTriggerData; 2591 int i; 2592 2593 LocTriggerData.type = T_TriggerData; 2594 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT | 2595 TRIGGER_EVENT_ROW | 2596 TRIGGER_EVENT_INSTEAD; 2597 LocTriggerData.tg_relation = relinfo->ri_RelationDesc; 2598 LocTriggerData.tg_newtuple = NULL; 2599 LocTriggerData.tg_oldtable = NULL; 2600 LocTriggerData.tg_newtable = NULL; 2601 LocTriggerData.tg_newtuplebuf = InvalidBuffer; 2602 for (i = 0; i < trigdesc->numtriggers; i++) 2603 { 2604 Trigger *trigger = &trigdesc->triggers[i]; 2605 2606 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype, 2607 TRIGGER_TYPE_ROW, 2608 TRIGGER_TYPE_INSTEAD, 2609 TRIGGER_TYPE_INSERT)) 2610 continue; 2611 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event, 2612 NULL, NULL, newtuple)) 2613 continue; 2614 2615 LocTriggerData.tg_trigtuple = oldtuple = newtuple; 2616 LocTriggerData.tg_trigtuplebuf = InvalidBuffer; 2617 LocTriggerData.tg_trigger = trigger; 2618 newtuple = ExecCallTriggerFunc(&LocTriggerData, 2619 i, 2620 relinfo->ri_TrigFunctions, 2621 relinfo->ri_TrigInstrument, 2622 GetPerTupleMemoryContext(estate)); 2623 if (oldtuple != newtuple && oldtuple != slottuple) 2624 heap_freetuple(oldtuple); 2625 if (newtuple == NULL) 2626 return NULL; /* "do nothing" */ 2627 } 2628 2629 if (newtuple != slottuple) 2630 { 2631 /* 2632 * Return the modified tuple using the es_trig_tuple_slot. We assume 2633 * the tuple was allocated in per-tuple memory context, and therefore 2634 * will go away by itself. The tuple table slot should not try to 2635 * clear it. 2636 */ 2637 TupleTableSlot *newslot = estate->es_trig_tuple_slot; 2638 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc); 2639 2640 if (newslot->tts_tupleDescriptor != tupdesc) 2641 ExecSetSlotDescriptor(newslot, tupdesc); 2642 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false); 2643 slot = newslot; 2644 } 2645 return slot; 2646 } 2647 2648 void 2649 ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo) 2650 { 2651 TriggerDesc *trigdesc; 2652 int i; 2653 TriggerData LocTriggerData; 2654 2655 trigdesc = relinfo->ri_TrigDesc; 2656 2657 if (trigdesc == NULL) 2658 return; 2659 if (!trigdesc->trig_delete_before_statement) 2660 return; 2661 2662 /* no-op if we already fired BS triggers in this context */ 2663 if (before_stmt_triggers_fired(RelationGetRelid(relinfo->ri_RelationDesc), 2664 CMD_DELETE)) 2665 return; 2666 2667 LocTriggerData.type = T_TriggerData; 2668 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE | 2669 TRIGGER_EVENT_BEFORE; 2670 LocTriggerData.tg_relation = relinfo->ri_RelationDesc; 2671 LocTriggerData.tg_trigtuple = NULL; 2672 LocTriggerData.tg_newtuple = NULL; 2673 LocTriggerData.tg_oldtable = NULL; 2674 LocTriggerData.tg_newtable = NULL; 2675 LocTriggerData.tg_trigtuplebuf = InvalidBuffer; 2676 LocTriggerData.tg_newtuplebuf = InvalidBuffer; 2677 for (i = 0; i < trigdesc->numtriggers; i++) 2678 { 2679 Trigger *trigger = &trigdesc->triggers[i]; 2680 HeapTuple newtuple; 2681 2682 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype, 2683 TRIGGER_TYPE_STATEMENT, 2684 TRIGGER_TYPE_BEFORE, 2685 TRIGGER_TYPE_DELETE)) 2686 continue; 2687 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event, 2688 NULL, NULL, NULL)) 2689 continue; 2690 2691 LocTriggerData.tg_trigger = trigger; 2692 newtuple = ExecCallTriggerFunc(&LocTriggerData, 2693 i, 2694 relinfo->ri_TrigFunctions, 2695 relinfo->ri_TrigInstrument, 2696 GetPerTupleMemoryContext(estate)); 2697 2698 if (newtuple) 2699 ereport(ERROR, 2700 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), 2701 errmsg("BEFORE STATEMENT trigger cannot return a value"))); 2702 } 2703 } 2704 2705 void 2706 ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo, 2707 TransitionCaptureState *transition_capture) 2708 { 2709 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 2710 2711 if (trigdesc && trigdesc->trig_delete_after_statement) 2712 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_DELETE, 2713 false, NULL, NULL, NIL, NULL, transition_capture); 2714 } 2715 2716 /* 2717 * Execute BEFORE ROW DELETE triggers. 2718 * 2719 * True indicates caller can proceed with the delete. False indicates caller 2720 * need to suppress the delete and additionally if requested, we need to pass 2721 * back the concurrently updated tuple if any. 2722 */ 2723 bool 2724 ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, 2725 ResultRelInfo *relinfo, 2726 ItemPointer tupleid, 2727 HeapTuple fdw_trigtuple, 2728 TupleTableSlot **epqslot) 2729 { 2730 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 2731 bool result = true; 2732 TriggerData LocTriggerData; 2733 HeapTuple trigtuple; 2734 HeapTuple newtuple; 2735 TupleTableSlot *newSlot; 2736 int i; 2737 2738 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid)); 2739 if (fdw_trigtuple == NULL) 2740 { 2741 trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid, 2742 LockTupleExclusive, &newSlot); 2743 if (trigtuple == NULL) 2744 return false; 2745 2746 /* 2747 * If the tuple was concurrently updated and the caller of this 2748 * function requested for the updated tuple, skip the trigger 2749 * execution. 2750 */ 2751 if (newSlot != NULL && epqslot != NULL) 2752 { 2753 *epqslot = newSlot; 2754 heap_freetuple(trigtuple); 2755 return false; 2756 } 2757 } 2758 else 2759 trigtuple = fdw_trigtuple; 2760 2761 LocTriggerData.type = T_TriggerData; 2762 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE | 2763 TRIGGER_EVENT_ROW | 2764 TRIGGER_EVENT_BEFORE; 2765 LocTriggerData.tg_relation = relinfo->ri_RelationDesc; 2766 LocTriggerData.tg_newtuple = NULL; 2767 LocTriggerData.tg_oldtable = NULL; 2768 LocTriggerData.tg_newtable = NULL; 2769 LocTriggerData.tg_newtuplebuf = InvalidBuffer; 2770 for (i = 0; i < trigdesc->numtriggers; i++) 2771 { 2772 Trigger *trigger = &trigdesc->triggers[i]; 2773 2774 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype, 2775 TRIGGER_TYPE_ROW, 2776 TRIGGER_TYPE_BEFORE, 2777 TRIGGER_TYPE_DELETE)) 2778 continue; 2779 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event, 2780 NULL, trigtuple, NULL)) 2781 continue; 2782 2783 LocTriggerData.tg_trigtuple = trigtuple; 2784 LocTriggerData.tg_trigtuplebuf = InvalidBuffer; 2785 LocTriggerData.tg_trigger = trigger; 2786 newtuple = ExecCallTriggerFunc(&LocTriggerData, 2787 i, 2788 relinfo->ri_TrigFunctions, 2789 relinfo->ri_TrigInstrument, 2790 GetPerTupleMemoryContext(estate)); 2791 if (newtuple == NULL) 2792 { 2793 result = false; /* tell caller to suppress delete */ 2794 break; 2795 } 2796 if (newtuple != trigtuple) 2797 heap_freetuple(newtuple); 2798 } 2799 if (trigtuple != fdw_trigtuple) 2800 heap_freetuple(trigtuple); 2801 2802 return result; 2803 } 2804 2805 void 2806 ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, 2807 ItemPointer tupleid, 2808 HeapTuple fdw_trigtuple, 2809 TransitionCaptureState *transition_capture) 2810 { 2811 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 2812 2813 if ((trigdesc && trigdesc->trig_delete_after_row) || 2814 (transition_capture && transition_capture->tcs_delete_old_table)) 2815 { 2816 HeapTuple trigtuple; 2817 2818 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid)); 2819 if (fdw_trigtuple == NULL) 2820 trigtuple = GetTupleForTrigger(estate, 2821 NULL, 2822 relinfo, 2823 tupleid, 2824 LockTupleExclusive, 2825 NULL); 2826 else 2827 trigtuple = fdw_trigtuple; 2828 2829 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_DELETE, 2830 true, trigtuple, NULL, NIL, NULL, 2831 transition_capture); 2832 if (trigtuple != fdw_trigtuple) 2833 heap_freetuple(trigtuple); 2834 } 2835 } 2836 2837 bool 2838 ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo, 2839 HeapTuple trigtuple) 2840 { 2841 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 2842 TriggerData LocTriggerData; 2843 HeapTuple rettuple; 2844 int i; 2845 2846 LocTriggerData.type = T_TriggerData; 2847 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE | 2848 TRIGGER_EVENT_ROW | 2849 TRIGGER_EVENT_INSTEAD; 2850 LocTriggerData.tg_relation = relinfo->ri_RelationDesc; 2851 LocTriggerData.tg_newtuple = NULL; 2852 LocTriggerData.tg_oldtable = NULL; 2853 LocTriggerData.tg_newtable = NULL; 2854 LocTriggerData.tg_newtuplebuf = InvalidBuffer; 2855 for (i = 0; i < trigdesc->numtriggers; i++) 2856 { 2857 Trigger *trigger = &trigdesc->triggers[i]; 2858 2859 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype, 2860 TRIGGER_TYPE_ROW, 2861 TRIGGER_TYPE_INSTEAD, 2862 TRIGGER_TYPE_DELETE)) 2863 continue; 2864 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event, 2865 NULL, trigtuple, NULL)) 2866 continue; 2867 2868 LocTriggerData.tg_trigtuple = trigtuple; 2869 LocTriggerData.tg_trigtuplebuf = InvalidBuffer; 2870 LocTriggerData.tg_trigger = trigger; 2871 rettuple = ExecCallTriggerFunc(&LocTriggerData, 2872 i, 2873 relinfo->ri_TrigFunctions, 2874 relinfo->ri_TrigInstrument, 2875 GetPerTupleMemoryContext(estate)); 2876 if (rettuple == NULL) 2877 return false; /* Delete was suppressed */ 2878 if (rettuple != trigtuple) 2879 heap_freetuple(rettuple); 2880 } 2881 return true; 2882 } 2883 2884 void 2885 ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo) 2886 { 2887 TriggerDesc *trigdesc; 2888 int i; 2889 TriggerData LocTriggerData; 2890 Bitmapset *updatedCols; 2891 2892 trigdesc = relinfo->ri_TrigDesc; 2893 2894 if (trigdesc == NULL) 2895 return; 2896 if (!trigdesc->trig_update_before_statement) 2897 return; 2898 2899 /* no-op if we already fired BS triggers in this context */ 2900 if (before_stmt_triggers_fired(RelationGetRelid(relinfo->ri_RelationDesc), 2901 CMD_UPDATE)) 2902 return; 2903 2904 updatedCols = ExecGetUpdatedCols(relinfo, estate); 2905 2906 LocTriggerData.type = T_TriggerData; 2907 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE | 2908 TRIGGER_EVENT_BEFORE; 2909 LocTriggerData.tg_relation = relinfo->ri_RelationDesc; 2910 LocTriggerData.tg_trigtuple = NULL; 2911 LocTriggerData.tg_newtuple = NULL; 2912 LocTriggerData.tg_oldtable = NULL; 2913 LocTriggerData.tg_newtable = NULL; 2914 LocTriggerData.tg_trigtuplebuf = InvalidBuffer; 2915 LocTriggerData.tg_newtuplebuf = InvalidBuffer; 2916 for (i = 0; i < trigdesc->numtriggers; i++) 2917 { 2918 Trigger *trigger = &trigdesc->triggers[i]; 2919 HeapTuple newtuple; 2920 2921 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype, 2922 TRIGGER_TYPE_STATEMENT, 2923 TRIGGER_TYPE_BEFORE, 2924 TRIGGER_TYPE_UPDATE)) 2925 continue; 2926 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event, 2927 updatedCols, NULL, NULL)) 2928 continue; 2929 2930 LocTriggerData.tg_trigger = trigger; 2931 newtuple = ExecCallTriggerFunc(&LocTriggerData, 2932 i, 2933 relinfo->ri_TrigFunctions, 2934 relinfo->ri_TrigInstrument, 2935 GetPerTupleMemoryContext(estate)); 2936 2937 if (newtuple) 2938 ereport(ERROR, 2939 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), 2940 errmsg("BEFORE STATEMENT trigger cannot return a value"))); 2941 } 2942 } 2943 2944 void 2945 ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo, 2946 TransitionCaptureState *transition_capture) 2947 { 2948 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 2949 2950 /* statement-level triggers operate on the parent table */ 2951 Assert(relinfo->ri_RootResultRelInfo == NULL); 2952 2953 if (trigdesc && trigdesc->trig_update_after_statement) 2954 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE, 2955 false, NULL, NULL, NIL, 2956 ExecGetUpdatedCols(relinfo, estate), 2957 transition_capture); 2958 } 2959 2960 TupleTableSlot * 2961 ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, 2962 ResultRelInfo *relinfo, 2963 ItemPointer tupleid, 2964 HeapTuple fdw_trigtuple, 2965 TupleTableSlot *slot) 2966 { 2967 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 2968 HeapTuple slottuple = ExecMaterializeSlot(slot); 2969 HeapTuple newtuple = slottuple; 2970 TriggerData LocTriggerData; 2971 HeapTuple trigtuple; 2972 HeapTuple oldtuple; 2973 TupleTableSlot *newSlot; 2974 int i; 2975 Bitmapset *updatedCols; 2976 LockTupleMode lockmode; 2977 2978 /* Determine lock mode to use */ 2979 lockmode = ExecUpdateLockMode(estate, relinfo); 2980 2981 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid)); 2982 if (fdw_trigtuple == NULL) 2983 { 2984 /* get a copy of the on-disk tuple we are planning to update */ 2985 trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid, 2986 lockmode, &newSlot); 2987 if (trigtuple == NULL) 2988 return NULL; /* cancel the update action */ 2989 } 2990 else 2991 { 2992 trigtuple = fdw_trigtuple; 2993 newSlot = NULL; 2994 } 2995 2996 /* 2997 * In READ COMMITTED isolation level it's possible that target tuple was 2998 * changed due to concurrent update. In that case we have a raw subplan 2999 * output tuple in newSlot, and need to run it through the junk filter to 3000 * produce an insertable tuple. 3001 * 3002 * Caution: more than likely, the passed-in slot is the same as the 3003 * junkfilter's output slot, so we are clobbering the original value of 3004 * slottuple by doing the filtering. This is OK since neither we nor our 3005 * caller have any more interest in the prior contents of that slot. 3006 */ 3007 if (newSlot != NULL) 3008 { 3009 slot = ExecFilterJunk(relinfo->ri_junkFilter, newSlot); 3010 slottuple = ExecMaterializeSlot(slot); 3011 newtuple = slottuple; 3012 } 3013 3014 3015 LocTriggerData.type = T_TriggerData; 3016 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE | 3017 TRIGGER_EVENT_ROW | 3018 TRIGGER_EVENT_BEFORE; 3019 LocTriggerData.tg_relation = relinfo->ri_RelationDesc; 3020 LocTriggerData.tg_oldtable = NULL; 3021 LocTriggerData.tg_newtable = NULL; 3022 updatedCols = ExecGetUpdatedCols(relinfo, estate); 3023 for (i = 0; i < trigdesc->numtriggers; i++) 3024 { 3025 Trigger *trigger = &trigdesc->triggers[i]; 3026 3027 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype, 3028 TRIGGER_TYPE_ROW, 3029 TRIGGER_TYPE_BEFORE, 3030 TRIGGER_TYPE_UPDATE)) 3031 continue; 3032 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event, 3033 updatedCols, trigtuple, newtuple)) 3034 continue; 3035 3036 LocTriggerData.tg_trigtuple = trigtuple; 3037 LocTriggerData.tg_newtuple = oldtuple = newtuple; 3038 LocTriggerData.tg_trigtuplebuf = InvalidBuffer; 3039 LocTriggerData.tg_newtuplebuf = InvalidBuffer; 3040 LocTriggerData.tg_trigger = trigger; 3041 newtuple = ExecCallTriggerFunc(&LocTriggerData, 3042 i, 3043 relinfo->ri_TrigFunctions, 3044 relinfo->ri_TrigInstrument, 3045 GetPerTupleMemoryContext(estate)); 3046 if (oldtuple != newtuple && 3047 oldtuple != slottuple && 3048 oldtuple != trigtuple) 3049 heap_freetuple(oldtuple); 3050 if (newtuple == NULL) 3051 { 3052 if (trigtuple != fdw_trigtuple) 3053 heap_freetuple(trigtuple); 3054 return NULL; /* "do nothing" */ 3055 } 3056 } 3057 if (trigtuple != fdw_trigtuple && trigtuple != newtuple) 3058 heap_freetuple(trigtuple); 3059 3060 if (newtuple != slottuple) 3061 { 3062 /* 3063 * Return the modified tuple using the es_trig_tuple_slot. We assume 3064 * the tuple was allocated in per-tuple memory context, and therefore 3065 * will go away by itself. The tuple table slot should not try to 3066 * clear it. 3067 */ 3068 TupleTableSlot *newslot = estate->es_trig_tuple_slot; 3069 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc); 3070 3071 if (newslot->tts_tupleDescriptor != tupdesc) 3072 ExecSetSlotDescriptor(newslot, tupdesc); 3073 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false); 3074 slot = newslot; 3075 } 3076 return slot; 3077 } 3078 3079 void 3080 ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, 3081 ItemPointer tupleid, 3082 HeapTuple fdw_trigtuple, 3083 HeapTuple newtuple, 3084 List *recheckIndexes, 3085 TransitionCaptureState *transition_capture) 3086 { 3087 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 3088 3089 if ((trigdesc && trigdesc->trig_update_after_row) || 3090 (transition_capture && 3091 (transition_capture->tcs_update_old_table || 3092 transition_capture->tcs_update_new_table))) 3093 { 3094 HeapTuple trigtuple; 3095 3096 /* 3097 * Note: if the UPDATE is converted into a DELETE+INSERT as part of 3098 * update-partition-key operation, then this function is also called 3099 * separately for DELETE and INSERT to capture transition table rows. 3100 * In such case, either old tuple or new tuple can be NULL. 3101 */ 3102 if (fdw_trigtuple == NULL && ItemPointerIsValid(tupleid)) 3103 trigtuple = GetTupleForTrigger(estate, 3104 NULL, 3105 relinfo, 3106 tupleid, 3107 LockTupleExclusive, 3108 NULL); 3109 else 3110 trigtuple = fdw_trigtuple; 3111 3112 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE, 3113 true, trigtuple, newtuple, recheckIndexes, 3114 ExecGetUpdatedCols(relinfo, estate), 3115 transition_capture); 3116 if (trigtuple != fdw_trigtuple) 3117 heap_freetuple(trigtuple); 3118 } 3119 } 3120 3121 TupleTableSlot * 3122 ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, 3123 HeapTuple trigtuple, TupleTableSlot *slot) 3124 { 3125 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 3126 HeapTuple slottuple = ExecMaterializeSlot(slot); 3127 HeapTuple newtuple = slottuple; 3128 TriggerData LocTriggerData; 3129 HeapTuple oldtuple; 3130 int i; 3131 3132 LocTriggerData.type = T_TriggerData; 3133 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE | 3134 TRIGGER_EVENT_ROW | 3135 TRIGGER_EVENT_INSTEAD; 3136 LocTriggerData.tg_relation = relinfo->ri_RelationDesc; 3137 LocTriggerData.tg_oldtable = NULL; 3138 LocTriggerData.tg_newtable = NULL; 3139 for (i = 0; i < trigdesc->numtriggers; i++) 3140 { 3141 Trigger *trigger = &trigdesc->triggers[i]; 3142 3143 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype, 3144 TRIGGER_TYPE_ROW, 3145 TRIGGER_TYPE_INSTEAD, 3146 TRIGGER_TYPE_UPDATE)) 3147 continue; 3148 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event, 3149 NULL, trigtuple, newtuple)) 3150 continue; 3151 3152 LocTriggerData.tg_trigtuple = trigtuple; 3153 LocTriggerData.tg_newtuple = oldtuple = newtuple; 3154 LocTriggerData.tg_trigtuplebuf = InvalidBuffer; 3155 LocTriggerData.tg_newtuplebuf = InvalidBuffer; 3156 LocTriggerData.tg_trigger = trigger; 3157 newtuple = ExecCallTriggerFunc(&LocTriggerData, 3158 i, 3159 relinfo->ri_TrigFunctions, 3160 relinfo->ri_TrigInstrument, 3161 GetPerTupleMemoryContext(estate)); 3162 if (oldtuple != newtuple && oldtuple != slottuple) 3163 heap_freetuple(oldtuple); 3164 if (newtuple == NULL) 3165 return NULL; /* "do nothing" */ 3166 } 3167 3168 if (newtuple != slottuple) 3169 { 3170 /* 3171 * Return the modified tuple using the es_trig_tuple_slot. We assume 3172 * the tuple was allocated in per-tuple memory context, and therefore 3173 * will go away by itself. The tuple table slot should not try to 3174 * clear it. 3175 */ 3176 TupleTableSlot *newslot = estate->es_trig_tuple_slot; 3177 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc); 3178 3179 if (newslot->tts_tupleDescriptor != tupdesc) 3180 ExecSetSlotDescriptor(newslot, tupdesc); 3181 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false); 3182 slot = newslot; 3183 } 3184 return slot; 3185 } 3186 3187 void 3188 ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo) 3189 { 3190 TriggerDesc *trigdesc; 3191 int i; 3192 TriggerData LocTriggerData; 3193 3194 trigdesc = relinfo->ri_TrigDesc; 3195 3196 if (trigdesc == NULL) 3197 return; 3198 if (!trigdesc->trig_truncate_before_statement) 3199 return; 3200 3201 LocTriggerData.type = T_TriggerData; 3202 LocTriggerData.tg_event = TRIGGER_EVENT_TRUNCATE | 3203 TRIGGER_EVENT_BEFORE; 3204 LocTriggerData.tg_relation = relinfo->ri_RelationDesc; 3205 LocTriggerData.tg_trigtuple = NULL; 3206 LocTriggerData.tg_newtuple = NULL; 3207 LocTriggerData.tg_oldtable = NULL; 3208 LocTriggerData.tg_newtable = NULL; 3209 LocTriggerData.tg_trigtuplebuf = InvalidBuffer; 3210 LocTriggerData.tg_newtuplebuf = InvalidBuffer; 3211 for (i = 0; i < trigdesc->numtriggers; i++) 3212 { 3213 Trigger *trigger = &trigdesc->triggers[i]; 3214 HeapTuple newtuple; 3215 3216 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype, 3217 TRIGGER_TYPE_STATEMENT, 3218 TRIGGER_TYPE_BEFORE, 3219 TRIGGER_TYPE_TRUNCATE)) 3220 continue; 3221 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event, 3222 NULL, NULL, NULL)) 3223 continue; 3224 3225 LocTriggerData.tg_trigger = trigger; 3226 newtuple = ExecCallTriggerFunc(&LocTriggerData, 3227 i, 3228 relinfo->ri_TrigFunctions, 3229 relinfo->ri_TrigInstrument, 3230 GetPerTupleMemoryContext(estate)); 3231 3232 if (newtuple) 3233 ereport(ERROR, 3234 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), 3235 errmsg("BEFORE STATEMENT trigger cannot return a value"))); 3236 } 3237 } 3238 3239 void 3240 ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo) 3241 { 3242 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 3243 3244 if (trigdesc && trigdesc->trig_truncate_after_statement) 3245 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_TRUNCATE, 3246 false, NULL, NULL, NIL, NULL, NULL); 3247 } 3248 3249 3250 static HeapTuple 3251 GetTupleForTrigger(EState *estate, 3252 EPQState *epqstate, 3253 ResultRelInfo *relinfo, 3254 ItemPointer tid, 3255 LockTupleMode lockmode, 3256 TupleTableSlot **newSlot) 3257 { 3258 Relation relation = relinfo->ri_RelationDesc; 3259 HeapTupleData tuple; 3260 HeapTuple result; 3261 Buffer buffer; 3262 3263 if (newSlot != NULL) 3264 { 3265 HTSU_Result test; 3266 HeapUpdateFailureData hufd; 3267 3268 *newSlot = NULL; 3269 3270 /* caller must pass an epqstate if EvalPlanQual is possible */ 3271 Assert(epqstate != NULL); 3272 3273 /* 3274 * lock tuple for update 3275 */ 3276 ltrmark:; 3277 tuple.t_self = *tid; 3278 test = heap_lock_tuple(relation, &tuple, 3279 estate->es_output_cid, 3280 lockmode, LockWaitBlock, 3281 false, &buffer, &hufd); 3282 switch (test) 3283 { 3284 case HeapTupleSelfUpdated: 3285 3286 /* 3287 * The target tuple was already updated or deleted by the 3288 * current command, or by a later command in the current 3289 * transaction. We ignore the tuple in the former case, and 3290 * throw error in the latter case, for the same reasons 3291 * enumerated in ExecUpdate and ExecDelete in 3292 * nodeModifyTable.c. 3293 */ 3294 if (hufd.cmax != estate->es_output_cid) 3295 ereport(ERROR, 3296 (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION), 3297 errmsg("tuple to be updated was already modified by an operation triggered by the current command"), 3298 errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows."))); 3299 3300 /* treat it as deleted; do not process */ 3301 ReleaseBuffer(buffer); 3302 return NULL; 3303 3304 case HeapTupleMayBeUpdated: 3305 break; 3306 3307 case HeapTupleUpdated: 3308 ReleaseBuffer(buffer); 3309 if (IsolationUsesXactSnapshot()) 3310 ereport(ERROR, 3311 (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), 3312 errmsg("could not serialize access due to concurrent update"))); 3313 if (ItemPointerIndicatesMovedPartitions(&hufd.ctid)) 3314 ereport(ERROR, 3315 (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), 3316 errmsg("tuple to be locked was already moved to another partition due to concurrent update"))); 3317 3318 if (!ItemPointerEquals(&hufd.ctid, &tuple.t_self)) 3319 { 3320 /* it was updated, so look at the updated version */ 3321 TupleTableSlot *epqslot; 3322 3323 epqslot = EvalPlanQual(estate, 3324 epqstate, 3325 relation, 3326 relinfo->ri_RangeTableIndex, 3327 lockmode, 3328 &hufd.ctid, 3329 hufd.xmax); 3330 if (!TupIsNull(epqslot)) 3331 { 3332 *tid = hufd.ctid; 3333 *newSlot = epqslot; 3334 3335 /* 3336 * EvalPlanQual already locked the tuple, but we 3337 * re-call heap_lock_tuple anyway as an easy way of 3338 * re-fetching the correct tuple. Speed is hardly a 3339 * criterion in this path anyhow. 3340 */ 3341 goto ltrmark; 3342 } 3343 } 3344 3345 /* 3346 * if tuple was deleted or PlanQual failed for updated tuple - 3347 * we must not process this tuple! 3348 */ 3349 return NULL; 3350 3351 case HeapTupleInvisible: 3352 elog(ERROR, "attempted to lock invisible tuple"); 3353 break; 3354 3355 default: 3356 ReleaseBuffer(buffer); 3357 elog(ERROR, "unrecognized heap_lock_tuple status: %u", test); 3358 return NULL; /* keep compiler quiet */ 3359 } 3360 } 3361 else 3362 { 3363 Page page; 3364 ItemId lp; 3365 3366 buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid)); 3367 3368 /* 3369 * Although we already know this tuple is valid, we must lock the 3370 * buffer to ensure that no one has a buffer cleanup lock; otherwise 3371 * they might move the tuple while we try to copy it. But we can 3372 * release the lock before actually doing the heap_copytuple call, 3373 * since holding pin is sufficient to prevent anyone from getting a 3374 * cleanup lock they don't already hold. 3375 */ 3376 LockBuffer(buffer, BUFFER_LOCK_SHARE); 3377 3378 page = BufferGetPage(buffer); 3379 lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid)); 3380 3381 Assert(ItemIdIsNormal(lp)); 3382 3383 tuple.t_data = (HeapTupleHeader) PageGetItem(page, lp); 3384 tuple.t_len = ItemIdGetLength(lp); 3385 tuple.t_self = *tid; 3386 tuple.t_tableOid = RelationGetRelid(relation); 3387 3388 LockBuffer(buffer, BUFFER_LOCK_UNLOCK); 3389 } 3390 3391 /* 3392 * While this is not necessary anymore after 297d627e, as a defense 3393 * against C code that has not recompiled for minor releases after the 3394 * fix, continue to expand the tuple. 3395 */ 3396 if (HeapTupleHeaderGetNatts(tuple.t_data) < relation->rd_att->natts) 3397 result = heap_expand_tuple(&tuple, relation->rd_att); 3398 else 3399 result = heap_copytuple(&tuple); 3400 ReleaseBuffer(buffer); 3401 3402 return result; 3403 } 3404 3405 /* 3406 * Is trigger enabled to fire? 3407 */ 3408 static bool 3409 TriggerEnabled(EState *estate, ResultRelInfo *relinfo, 3410 Trigger *trigger, TriggerEvent event, 3411 Bitmapset *modifiedCols, 3412 HeapTuple oldtup, HeapTuple newtup) 3413 { 3414 /* Check replication-role-dependent enable state */ 3415 if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA) 3416 { 3417 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN || 3418 trigger->tgenabled == TRIGGER_DISABLED) 3419 return false; 3420 } 3421 else /* ORIGIN or LOCAL role */ 3422 { 3423 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA || 3424 trigger->tgenabled == TRIGGER_DISABLED) 3425 return false; 3426 } 3427 3428 /* 3429 * Check for column-specific trigger (only possible for UPDATE, and in 3430 * fact we *must* ignore tgattr for other event types) 3431 */ 3432 if (trigger->tgnattr > 0 && TRIGGER_FIRED_BY_UPDATE(event)) 3433 { 3434 int i; 3435 bool modified; 3436 3437 modified = false; 3438 for (i = 0; i < trigger->tgnattr; i++) 3439 { 3440 if (bms_is_member(trigger->tgattr[i] - FirstLowInvalidHeapAttributeNumber, 3441 modifiedCols)) 3442 { 3443 modified = true; 3444 break; 3445 } 3446 } 3447 if (!modified) 3448 return false; 3449 } 3450 3451 /* Check for WHEN clause */ 3452 if (trigger->tgqual) 3453 { 3454 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc); 3455 ExprState **predicate; 3456 ExprContext *econtext; 3457 TupleTableSlot *oldslot = NULL; 3458 TupleTableSlot *newslot = NULL; 3459 MemoryContext oldContext; 3460 int i; 3461 3462 Assert(estate != NULL); 3463 3464 /* 3465 * trigger is an element of relinfo->ri_TrigDesc->triggers[]; find the 3466 * matching element of relinfo->ri_TrigWhenExprs[] 3467 */ 3468 i = trigger - relinfo->ri_TrigDesc->triggers; 3469 predicate = &relinfo->ri_TrigWhenExprs[i]; 3470 3471 /* 3472 * If first time through for this WHEN expression, build expression 3473 * nodetrees for it. Keep them in the per-query memory context so 3474 * they'll survive throughout the query. 3475 */ 3476 if (*predicate == NULL) 3477 { 3478 Node *tgqual; 3479 3480 oldContext = MemoryContextSwitchTo(estate->es_query_cxt); 3481 tgqual = stringToNode(trigger->tgqual); 3482 /* Change references to OLD and NEW to INNER_VAR and OUTER_VAR */ 3483 ChangeVarNodes(tgqual, PRS2_OLD_VARNO, INNER_VAR, 0); 3484 ChangeVarNodes(tgqual, PRS2_NEW_VARNO, OUTER_VAR, 0); 3485 /* ExecPrepareQual wants implicit-AND form */ 3486 tgqual = (Node *) make_ands_implicit((Expr *) tgqual); 3487 *predicate = ExecPrepareQual((List *) tgqual, estate); 3488 MemoryContextSwitchTo(oldContext); 3489 } 3490 3491 /* 3492 * We will use the EState's per-tuple context for evaluating WHEN 3493 * expressions (creating it if it's not already there). 3494 */ 3495 econtext = GetPerTupleExprContext(estate); 3496 3497 /* 3498 * Put OLD and NEW tuples into tupleslots for expression evaluation. 3499 * These slots can be shared across the whole estate, but be careful 3500 * that they have the current resultrel's tupdesc. 3501 */ 3502 if (HeapTupleIsValid(oldtup)) 3503 { 3504 if (estate->es_trig_oldtup_slot == NULL) 3505 { 3506 oldContext = MemoryContextSwitchTo(estate->es_query_cxt); 3507 estate->es_trig_oldtup_slot = 3508 ExecInitExtraTupleSlot(estate, NULL); 3509 MemoryContextSwitchTo(oldContext); 3510 } 3511 oldslot = estate->es_trig_oldtup_slot; 3512 if (oldslot->tts_tupleDescriptor != tupdesc) 3513 ExecSetSlotDescriptor(oldslot, tupdesc); 3514 ExecStoreTuple(oldtup, oldslot, InvalidBuffer, false); 3515 } 3516 if (HeapTupleIsValid(newtup)) 3517 { 3518 if (estate->es_trig_newtup_slot == NULL) 3519 { 3520 oldContext = MemoryContextSwitchTo(estate->es_query_cxt); 3521 estate->es_trig_newtup_slot = 3522 ExecInitExtraTupleSlot(estate, NULL); 3523 MemoryContextSwitchTo(oldContext); 3524 } 3525 newslot = estate->es_trig_newtup_slot; 3526 if (newslot->tts_tupleDescriptor != tupdesc) 3527 ExecSetSlotDescriptor(newslot, tupdesc); 3528 ExecStoreTuple(newtup, newslot, InvalidBuffer, false); 3529 } 3530 3531 /* 3532 * Finally evaluate the expression, making the old and/or new tuples 3533 * available as INNER_VAR/OUTER_VAR respectively. 3534 */ 3535 econtext->ecxt_innertuple = oldslot; 3536 econtext->ecxt_outertuple = newslot; 3537 if (!ExecQual(*predicate, econtext)) 3538 return false; 3539 } 3540 3541 return true; 3542 } 3543 3544 3545 /* ---------- 3546 * After-trigger stuff 3547 * 3548 * The AfterTriggersData struct holds data about pending AFTER trigger events 3549 * during the current transaction tree. (BEFORE triggers are fired 3550 * immediately so we don't need any persistent state about them.) The struct 3551 * and most of its subsidiary data are kept in TopTransactionContext; however 3552 * some data that can be discarded sooner appears in the CurTransactionContext 3553 * of the relevant subtransaction. Also, the individual event records are 3554 * kept in a separate sub-context of TopTransactionContext. This is done 3555 * mainly so that it's easy to tell from a memory context dump how much space 3556 * is being eaten by trigger events. 3557 * 3558 * Because the list of pending events can grow large, we go to some 3559 * considerable effort to minimize per-event memory consumption. The event 3560 * records are grouped into chunks and common data for similar events in the 3561 * same chunk is only stored once. 3562 * 3563 * XXX We need to be able to save the per-event data in a file if it grows too 3564 * large. 3565 * ---------- 3566 */ 3567 3568 /* Per-trigger SET CONSTRAINT status */ 3569 typedef struct SetConstraintTriggerData 3570 { 3571 Oid sct_tgoid; 3572 bool sct_tgisdeferred; 3573 } SetConstraintTriggerData; 3574 3575 typedef struct SetConstraintTriggerData *SetConstraintTrigger; 3576 3577 /* 3578 * SET CONSTRAINT intra-transaction status. 3579 * 3580 * We make this a single palloc'd object so it can be copied and freed easily. 3581 * 3582 * all_isset and all_isdeferred are used to keep track 3583 * of SET CONSTRAINTS ALL {DEFERRED, IMMEDIATE}. 3584 * 3585 * trigstates[] stores per-trigger tgisdeferred settings. 3586 */ 3587 typedef struct SetConstraintStateData 3588 { 3589 bool all_isset; 3590 bool all_isdeferred; 3591 int numstates; /* number of trigstates[] entries in use */ 3592 int numalloc; /* allocated size of trigstates[] */ 3593 SetConstraintTriggerData trigstates[FLEXIBLE_ARRAY_MEMBER]; 3594 } SetConstraintStateData; 3595 3596 typedef SetConstraintStateData *SetConstraintState; 3597 3598 3599 /* 3600 * Per-trigger-event data 3601 * 3602 * The actual per-event data, AfterTriggerEventData, includes DONE/IN_PROGRESS 3603 * status bits and up to two tuple CTIDs. Each event record also has an 3604 * associated AfterTriggerSharedData that is shared across all instances of 3605 * similar events within a "chunk". 3606 * 3607 * For row-level triggers, we arrange not to waste storage on unneeded ctid 3608 * fields. Updates of regular tables use two; inserts and deletes of regular 3609 * tables use one; foreign tables always use zero and save the tuple(s) to a 3610 * tuplestore. AFTER_TRIGGER_FDW_FETCH directs AfterTriggerExecute() to 3611 * retrieve a fresh tuple or pair of tuples from that tuplestore, while 3612 * AFTER_TRIGGER_FDW_REUSE directs it to use the most-recently-retrieved 3613 * tuple(s). This permits storing tuples once regardless of the number of 3614 * row-level triggers on a foreign table. 3615 * 3616 * Note that we need triggers on foreign tables to be fired in exactly the 3617 * order they were queued, so that the tuples come out of the tuplestore in 3618 * the right order. To ensure that, we forbid deferrable (constraint) 3619 * triggers on foreign tables. This also ensures that such triggers do not 3620 * get deferred into outer trigger query levels, meaning that it's okay to 3621 * destroy the tuplestore at the end of the query level. 3622 * 3623 * Statement-level triggers always bear AFTER_TRIGGER_1CTID, though they 3624 * require no ctid field. We lack the flag bit space to neatly represent that 3625 * distinct case, and it seems unlikely to be worth much trouble. 3626 * 3627 * Note: ats_firing_id is initially zero and is set to something else when 3628 * AFTER_TRIGGER_IN_PROGRESS is set. It indicates which trigger firing 3629 * cycle the trigger will be fired in (or was fired in, if DONE is set). 3630 * Although this is mutable state, we can keep it in AfterTriggerSharedData 3631 * because all instances of the same type of event in a given event list will 3632 * be fired at the same time, if they were queued between the same firing 3633 * cycles. So we need only ensure that ats_firing_id is zero when attaching 3634 * a new event to an existing AfterTriggerSharedData record. 3635 */ 3636 typedef uint32 TriggerFlags; 3637 3638 #define AFTER_TRIGGER_OFFSET 0x0FFFFFFF /* must be low-order bits */ 3639 #define AFTER_TRIGGER_DONE 0x10000000 3640 #define AFTER_TRIGGER_IN_PROGRESS 0x20000000 3641 /* bits describing the size and tuple sources of this event */ 3642 #define AFTER_TRIGGER_FDW_REUSE 0x00000000 3643 #define AFTER_TRIGGER_FDW_FETCH 0x80000000 3644 #define AFTER_TRIGGER_1CTID 0x40000000 3645 #define AFTER_TRIGGER_2CTID 0xC0000000 3646 #define AFTER_TRIGGER_TUP_BITS 0xC0000000 3647 3648 typedef struct AfterTriggerSharedData *AfterTriggerShared; 3649 3650 typedef struct AfterTriggerSharedData 3651 { 3652 TriggerEvent ats_event; /* event type indicator, see trigger.h */ 3653 Oid ats_tgoid; /* the trigger's ID */ 3654 Oid ats_relid; /* the relation it's on */ 3655 CommandId ats_firing_id; /* ID for firing cycle */ 3656 struct AfterTriggersTableData *ats_table; /* transition table access */ 3657 } AfterTriggerSharedData; 3658 3659 typedef struct AfterTriggerEventData *AfterTriggerEvent; 3660 3661 typedef struct AfterTriggerEventData 3662 { 3663 TriggerFlags ate_flags; /* status bits and offset to shared data */ 3664 ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */ 3665 ItemPointerData ate_ctid2; /* new updated tuple */ 3666 } AfterTriggerEventData; 3667 3668 /* AfterTriggerEventData, minus ate_ctid2 */ 3669 typedef struct AfterTriggerEventDataOneCtid 3670 { 3671 TriggerFlags ate_flags; /* status bits and offset to shared data */ 3672 ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */ 3673 } AfterTriggerEventDataOneCtid; 3674 3675 /* AfterTriggerEventData, minus ate_ctid1 and ate_ctid2 */ 3676 typedef struct AfterTriggerEventDataZeroCtids 3677 { 3678 TriggerFlags ate_flags; /* status bits and offset to shared data */ 3679 } AfterTriggerEventDataZeroCtids; 3680 3681 #define SizeofTriggerEvent(evt) \ 3682 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \ 3683 sizeof(AfterTriggerEventData) : \ 3684 ((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \ 3685 sizeof(AfterTriggerEventDataOneCtid) : \ 3686 sizeof(AfterTriggerEventDataZeroCtids)) 3687 3688 #define GetTriggerSharedData(evt) \ 3689 ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET))) 3690 3691 /* 3692 * To avoid palloc overhead, we keep trigger events in arrays in successively- 3693 * larger chunks (a slightly more sophisticated version of an expansible 3694 * array). The space between CHUNK_DATA_START and freeptr is occupied by 3695 * AfterTriggerEventData records; the space between endfree and endptr is 3696 * occupied by AfterTriggerSharedData records. 3697 */ 3698 typedef struct AfterTriggerEventChunk 3699 { 3700 struct AfterTriggerEventChunk *next; /* list link */ 3701 char *freeptr; /* start of free space in chunk */ 3702 char *endfree; /* end of free space in chunk */ 3703 char *endptr; /* end of chunk */ 3704 /* event data follows here */ 3705 } AfterTriggerEventChunk; 3706 3707 #define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk))) 3708 3709 /* A list of events */ 3710 typedef struct AfterTriggerEventList 3711 { 3712 AfterTriggerEventChunk *head; 3713 AfterTriggerEventChunk *tail; 3714 char *tailfree; /* freeptr of tail chunk */ 3715 } AfterTriggerEventList; 3716 3717 /* Macros to help in iterating over a list of events */ 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))) 3724 /* Use this if no special per-chunk processing is needed */ 3725 #define for_each_event_chunk(eptr, cptr, evtlist) \ 3726 for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr) 3727 3728 /* Macros for iterating from a start point that might not be list start */ 3729 #define for_each_chunk_from(cptr) \ 3730 for (; cptr != NULL; cptr = cptr->next) 3731 #define for_each_event_from(eptr, cptr) \ 3732 for (; \ 3733 (char *) eptr < (cptr)->freeptr; \ 3734 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr))) 3735 3736 3737 /* 3738 * All per-transaction data for the AFTER TRIGGERS module. 3739 * 3740 * AfterTriggersData has the following fields: 3741 * 3742 * firing_counter is incremented for each call of afterTriggerInvokeEvents. 3743 * We mark firable events with the current firing cycle's ID so that we can 3744 * tell which ones to work on. This ensures sane behavior if a trigger 3745 * function chooses to do SET CONSTRAINTS: the inner SET CONSTRAINTS will 3746 * only fire those events that weren't already scheduled for firing. 3747 * 3748 * state keeps track of the transaction-local effects of SET CONSTRAINTS. 3749 * This is saved and restored across failed subtransactions. 3750 * 3751 * events is the current list of deferred events. This is global across 3752 * all subtransactions of the current transaction. In a subtransaction 3753 * abort, we know that the events added by the subtransaction are at the 3754 * end of the list, so it is relatively easy to discard them. The event 3755 * list chunks themselves are stored in event_cxt. 3756 * 3757 * query_depth is the current depth of nested AfterTriggerBeginQuery calls 3758 * (-1 when the stack is empty). 3759 * 3760 * query_stack[query_depth] is the per-query-level data, including these fields: 3761 * 3762 * events is a list of AFTER trigger events queued by the current query. 3763 * None of these are valid until the matching AfterTriggerEndQuery call 3764 * occurs. At that point we fire immediate-mode triggers, and append any 3765 * deferred events to the main events list. 3766 * 3767 * fdw_tuplestore is a tuplestore containing the foreign-table tuples 3768 * needed by events queued by the current query. (Note: we use just one 3769 * tuplestore even though more than one foreign table might be involved. 3770 * This is okay because tuplestores don't really care what's in the tuples 3771 * they store; but it's possible that someday it'd break.) 3772 * 3773 * tables is a List of AfterTriggersTableData structs for target tables 3774 * of the current query (see below). 3775 * 3776 * maxquerydepth is just the allocated length of query_stack. 3777 * 3778 * trans_stack holds per-subtransaction data, including these fields: 3779 * 3780 * state is NULL or a pointer to a saved copy of the SET CONSTRAINTS 3781 * state data. Each subtransaction level that modifies that state first 3782 * saves a copy, which we use to restore the state if we abort. 3783 * 3784 * events is a copy of the events head/tail pointers, 3785 * which we use to restore those values during subtransaction abort. 3786 * 3787 * query_depth is the subtransaction-start-time value of query_depth, 3788 * which we similarly use to clean up at subtransaction abort. 3789 * 3790 * firing_counter is the subtransaction-start-time value of firing_counter. 3791 * We use this to recognize which deferred triggers were fired (or marked 3792 * for firing) within an aborted subtransaction. 3793 * 3794 * We use GetCurrentTransactionNestLevel() to determine the correct array 3795 * index in trans_stack. maxtransdepth is the number of allocated entries in 3796 * trans_stack. (By not keeping our own stack pointer, we can avoid trouble 3797 * in cases where errors during subxact abort cause multiple invocations 3798 * of AfterTriggerEndSubXact() at the same nesting depth.) 3799 * 3800 * We create an AfterTriggersTableData struct for each target table of the 3801 * current query, and each operation mode (INSERT/UPDATE/DELETE), that has 3802 * either transition tables or statement-level triggers. This is used to 3803 * hold the relevant transition tables, as well as info tracking whether 3804 * we already queued the statement triggers. (We use that info to prevent 3805 * firing the same statement triggers more than once per statement, or really 3806 * once per transition table set.) These structs, along with the transition 3807 * table tuplestores, live in the (sub)transaction's CurTransactionContext. 3808 * That's sufficient lifespan because we don't allow transition tables to be 3809 * used by deferrable triggers, so they only need to survive until 3810 * AfterTriggerEndQuery. 3811 */ 3812 typedef struct AfterTriggersQueryData AfterTriggersQueryData; 3813 typedef struct AfterTriggersTransData AfterTriggersTransData; 3814 typedef struct AfterTriggersTableData AfterTriggersTableData; 3815 3816 typedef struct AfterTriggersData 3817 { 3818 CommandId firing_counter; /* next firing ID to assign */ 3819 SetConstraintState state; /* the active S C state */ 3820 AfterTriggerEventList events; /* deferred-event list */ 3821 MemoryContext event_cxt; /* memory context for events, if any */ 3822 3823 /* per-query-level data: */ 3824 AfterTriggersQueryData *query_stack; /* array of structs shown below */ 3825 int query_depth; /* current index in above array */ 3826 int maxquerydepth; /* allocated len of above array */ 3827 3828 /* per-subtransaction-level data: */ 3829 AfterTriggersTransData *trans_stack; /* array of structs shown below */ 3830 int maxtransdepth; /* allocated len of above array */ 3831 } AfterTriggersData; 3832 3833 struct AfterTriggersQueryData 3834 { 3835 AfterTriggerEventList events; /* events pending from this query */ 3836 Tuplestorestate *fdw_tuplestore; /* foreign tuples for said events */ 3837 List *tables; /* list of AfterTriggersTableData, see below */ 3838 }; 3839 3840 struct AfterTriggersTransData 3841 { 3842 /* these fields are just for resetting at subtrans abort: */ 3843 SetConstraintState state; /* saved S C state, or NULL if not yet saved */ 3844 AfterTriggerEventList events; /* saved list pointer */ 3845 int query_depth; /* saved query_depth */ 3846 CommandId firing_counter; /* saved firing_counter */ 3847 }; 3848 3849 struct AfterTriggersTableData 3850 { 3851 /* relid + cmdType form the lookup key for these structs: */ 3852 Oid relid; /* target table's OID */ 3853 CmdType cmdType; /* event type, CMD_INSERT/UPDATE/DELETE */ 3854 bool closed; /* true when no longer OK to add tuples */ 3855 bool before_trig_done; /* did we already queue BS triggers? */ 3856 bool after_trig_done; /* did we already queue AS triggers? */ 3857 AfterTriggerEventList after_trig_events; /* if so, saved list pointer */ 3858 Tuplestorestate *old_tuplestore; /* "old" transition table, if any */ 3859 Tuplestorestate *new_tuplestore; /* "new" transition table, if any */ 3860 }; 3861 3862 static AfterTriggersData afterTriggers; 3863 3864 static void AfterTriggerExecute(AfterTriggerEvent event, 3865 Relation rel, TriggerDesc *trigdesc, 3866 FmgrInfo *finfo, 3867 Instrumentation *instr, 3868 MemoryContext per_tuple_context, 3869 TupleTableSlot *trig_tuple_slot1, 3870 TupleTableSlot *trig_tuple_slot2); 3871 static AfterTriggersTableData *GetAfterTriggersTableData(Oid relid, 3872 CmdType cmdType); 3873 static void AfterTriggerFreeQuery(AfterTriggersQueryData *qs); 3874 static SetConstraintState SetConstraintStateCreate(int numalloc); 3875 static SetConstraintState SetConstraintStateCopy(SetConstraintState state); 3876 static SetConstraintState SetConstraintStateAddItem(SetConstraintState state, 3877 Oid tgoid, bool tgisdeferred); 3878 static void cancel_prior_stmt_triggers(Oid relid, CmdType cmdType, int tgevent); 3879 3880 3881 /* 3882 * Get the FDW tuplestore for the current trigger query level, creating it 3883 * if necessary. 3884 */ 3885 static Tuplestorestate * 3886 GetCurrentFDWTuplestore(void) 3887 { 3888 Tuplestorestate *ret; 3889 3890 ret = afterTriggers.query_stack[afterTriggers.query_depth].fdw_tuplestore; 3891 if (ret == NULL) 3892 { 3893 MemoryContext oldcxt; 3894 ResourceOwner saveResourceOwner; 3895 3896 /* 3897 * Make the tuplestore valid until end of subtransaction. We really 3898 * only need it until AfterTriggerEndQuery(). 3899 */ 3900 oldcxt = MemoryContextSwitchTo(CurTransactionContext); 3901 saveResourceOwner = CurrentResourceOwner; 3902 CurrentResourceOwner = CurTransactionResourceOwner; 3903 3904 ret = tuplestore_begin_heap(false, false, work_mem); 3905 3906 CurrentResourceOwner = saveResourceOwner; 3907 MemoryContextSwitchTo(oldcxt); 3908 3909 afterTriggers.query_stack[afterTriggers.query_depth].fdw_tuplestore = ret; 3910 } 3911 3912 return ret; 3913 } 3914 3915 /* ---------- 3916 * afterTriggerCheckState() 3917 * 3918 * Returns true if the trigger event is actually in state DEFERRED. 3919 * ---------- 3920 */ 3921 static bool 3922 afterTriggerCheckState(AfterTriggerShared evtshared) 3923 { 3924 Oid tgoid = evtshared->ats_tgoid; 3925 SetConstraintState state = afterTriggers.state; 3926 int i; 3927 3928 /* 3929 * For not-deferrable triggers (i.e. normal AFTER ROW triggers and 3930 * constraints declared NOT DEFERRABLE), the state is always false. 3931 */ 3932 if ((evtshared->ats_event & AFTER_TRIGGER_DEFERRABLE) == 0) 3933 return false; 3934 3935 /* 3936 * If constraint state exists, SET CONSTRAINTS might have been executed 3937 * either for this trigger or for all triggers. 3938 */ 3939 if (state != NULL) 3940 { 3941 /* Check for SET CONSTRAINTS for this specific trigger. */ 3942 for (i = 0; i < state->numstates; i++) 3943 { 3944 if (state->trigstates[i].sct_tgoid == tgoid) 3945 return state->trigstates[i].sct_tgisdeferred; 3946 } 3947 3948 /* Check for SET CONSTRAINTS ALL. */ 3949 if (state->all_isset) 3950 return state->all_isdeferred; 3951 } 3952 3953 /* 3954 * Otherwise return the default state for the trigger. 3955 */ 3956 return ((evtshared->ats_event & AFTER_TRIGGER_INITDEFERRED) != 0); 3957 } 3958 3959 3960 /* ---------- 3961 * afterTriggerAddEvent() 3962 * 3963 * Add a new trigger event to the specified queue. 3964 * The passed-in event data is copied. 3965 * ---------- 3966 */ 3967 static void 3968 afterTriggerAddEvent(AfterTriggerEventList *events, 3969 AfterTriggerEvent event, AfterTriggerShared evtshared) 3970 { 3971 Size eventsize = SizeofTriggerEvent(event); 3972 Size needed = eventsize + sizeof(AfterTriggerSharedData); 3973 AfterTriggerEventChunk *chunk; 3974 AfterTriggerShared newshared; 3975 AfterTriggerEvent newevent; 3976 3977 /* 3978 * If empty list or not enough room in the tail chunk, make a new chunk. 3979 * We assume here that a new shared record will always be needed. 3980 */ 3981 chunk = events->tail; 3982 if (chunk == NULL || 3983 chunk->endfree - chunk->freeptr < needed) 3984 { 3985 Size chunksize; 3986 3987 /* Create event context if we didn't already */ 3988 if (afterTriggers.event_cxt == NULL) 3989 afterTriggers.event_cxt = 3990 AllocSetContextCreate(TopTransactionContext, 3991 "AfterTriggerEvents", 3992 ALLOCSET_DEFAULT_SIZES); 3993 3994 /* 3995 * Chunk size starts at 1KB and is allowed to increase up to 1MB. 3996 * These numbers are fairly arbitrary, though there is a hard limit at 3997 * AFTER_TRIGGER_OFFSET; else we couldn't link event records to their 3998 * shared records using the available space in ate_flags. Another 3999 * constraint is that if the chunk size gets too huge, the search loop 4000 * below would get slow given a (not too common) usage pattern with 4001 * many distinct event types in a chunk. Therefore, we double the 4002 * preceding chunk size only if there weren't too many shared records 4003 * in the preceding chunk; otherwise we halve it. This gives us some 4004 * ability to adapt to the actual usage pattern of the current query 4005 * while still having large chunk sizes in typical usage. All chunk 4006 * sizes used should be MAXALIGN multiples, to ensure that the shared 4007 * records will be aligned safely. 4008 */ 4009 #define MIN_CHUNK_SIZE 1024 4010 #define MAX_CHUNK_SIZE (1024*1024) 4011 4012 #if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1) 4013 #error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET 4014 #endif 4015 4016 if (chunk == NULL) 4017 chunksize = MIN_CHUNK_SIZE; 4018 else 4019 { 4020 /* preceding chunk size... */ 4021 chunksize = chunk->endptr - (char *) chunk; 4022 /* check number of shared records in preceding chunk */ 4023 if ((chunk->endptr - chunk->endfree) <= 4024 (100 * sizeof(AfterTriggerSharedData))) 4025 chunksize *= 2; /* okay, double it */ 4026 else 4027 chunksize /= 2; /* too many shared records */ 4028 chunksize = Min(chunksize, MAX_CHUNK_SIZE); 4029 } 4030 chunk = MemoryContextAlloc(afterTriggers.event_cxt, chunksize); 4031 chunk->next = NULL; 4032 chunk->freeptr = CHUNK_DATA_START(chunk); 4033 chunk->endptr = chunk->endfree = (char *) chunk + chunksize; 4034 Assert(chunk->endfree - chunk->freeptr >= needed); 4035 4036 if (events->head == NULL) 4037 events->head = chunk; 4038 else 4039 events->tail->next = chunk; 4040 events->tail = chunk; 4041 /* events->tailfree is now out of sync, but we'll fix it below */ 4042 } 4043 4044 /* 4045 * Try to locate a matching shared-data record already in the chunk. If 4046 * none, make a new one. 4047 */ 4048 for (newshared = ((AfterTriggerShared) chunk->endptr) - 1; 4049 (char *) newshared >= chunk->endfree; 4050 newshared--) 4051 { 4052 if (newshared->ats_tgoid == evtshared->ats_tgoid && 4053 newshared->ats_relid == evtshared->ats_relid && 4054 newshared->ats_event == evtshared->ats_event && 4055 newshared->ats_table == evtshared->ats_table && 4056 newshared->ats_firing_id == 0) 4057 break; 4058 } 4059 if ((char *) newshared < chunk->endfree) 4060 { 4061 *newshared = *evtshared; 4062 newshared->ats_firing_id = 0; /* just to be sure */ 4063 chunk->endfree = (char *) newshared; 4064 } 4065 4066 /* Insert the data */ 4067 newevent = (AfterTriggerEvent) chunk->freeptr; 4068 memcpy(newevent, event, eventsize); 4069 /* ... and link the new event to its shared record */ 4070 newevent->ate_flags &= ~AFTER_TRIGGER_OFFSET; 4071 newevent->ate_flags |= (char *) newshared - (char *) newevent; 4072 4073 chunk->freeptr += eventsize; 4074 events->tailfree = chunk->freeptr; 4075 } 4076 4077 /* ---------- 4078 * afterTriggerFreeEventList() 4079 * 4080 * Free all the event storage in the given list. 4081 * ---------- 4082 */ 4083 static void 4084 afterTriggerFreeEventList(AfterTriggerEventList *events) 4085 { 4086 AfterTriggerEventChunk *chunk; 4087 4088 while ((chunk = events->head) != NULL) 4089 { 4090 events->head = chunk->next; 4091 pfree(chunk); 4092 } 4093 events->tail = NULL; 4094 events->tailfree = NULL; 4095 } 4096 4097 /* ---------- 4098 * afterTriggerRestoreEventList() 4099 * 4100 * Restore an event list to its prior length, removing all the events 4101 * added since it had the value old_events. 4102 * ---------- 4103 */ 4104 static void 4105 afterTriggerRestoreEventList(AfterTriggerEventList *events, 4106 const AfterTriggerEventList *old_events) 4107 { 4108 AfterTriggerEventChunk *chunk; 4109 AfterTriggerEventChunk *next_chunk; 4110 4111 if (old_events->tail == NULL) 4112 { 4113 /* restoring to a completely empty state, so free everything */ 4114 afterTriggerFreeEventList(events); 4115 } 4116 else 4117 { 4118 *events = *old_events; 4119 /* free any chunks after the last one we want to keep */ 4120 for (chunk = events->tail->next; chunk != NULL; chunk = next_chunk) 4121 { 4122 next_chunk = chunk->next; 4123 pfree(chunk); 4124 } 4125 /* and clean up the tail chunk to be the right length */ 4126 events->tail->next = NULL; 4127 events->tail->freeptr = events->tailfree; 4128 4129 /* 4130 * We don't make any effort to remove now-unused shared data records. 4131 * They might still be useful, anyway. 4132 */ 4133 } 4134 } 4135 4136 /* ---------- 4137 * afterTriggerDeleteHeadEventChunk() 4138 * 4139 * Remove the first chunk of events from the query level's event list. 4140 * Keep any event list pointers elsewhere in the query level's data 4141 * structures in sync. 4142 * ---------- 4143 */ 4144 static void 4145 afterTriggerDeleteHeadEventChunk(AfterTriggersQueryData *qs) 4146 { 4147 AfterTriggerEventChunk *target = qs->events.head; 4148 ListCell *lc; 4149 4150 Assert(target && target->next); 4151 4152 /* 4153 * First, update any pointers in the per-table data, so that they won't be 4154 * dangling. Resetting obsoleted pointers to NULL will make 4155 * cancel_prior_stmt_triggers start from the list head, which is fine. 4156 */ 4157 foreach(lc, qs->tables) 4158 { 4159 AfterTriggersTableData *table = (AfterTriggersTableData *) lfirst(lc); 4160 4161 if (table->after_trig_done && 4162 table->after_trig_events.tail == target) 4163 { 4164 table->after_trig_events.head = NULL; 4165 table->after_trig_events.tail = NULL; 4166 table->after_trig_events.tailfree = NULL; 4167 } 4168 } 4169 4170 /* Now we can flush the head chunk */ 4171 qs->events.head = target->next; 4172 pfree(target); 4173 } 4174 4175 4176 /* ---------- 4177 * AfterTriggerExecute() 4178 * 4179 * Fetch the required tuples back from the heap and fire one 4180 * single trigger function. 4181 * 4182 * Frequently, this will be fired many times in a row for triggers of 4183 * a single relation. Therefore, we cache the open relation and provide 4184 * fmgr lookup cache space at the caller level. (For triggers fired at 4185 * the end of a query, we can even piggyback on the executor's state.) 4186 * 4187 * event: event currently being fired. 4188 * rel: open relation for event. 4189 * trigdesc: working copy of rel's trigger info. 4190 * finfo: array of fmgr lookup cache entries (one per trigger in trigdesc). 4191 * instr: array of EXPLAIN ANALYZE instrumentation nodes (one per trigger), 4192 * or NULL if no instrumentation is wanted. 4193 * per_tuple_context: memory context to call trigger function in. 4194 * trig_tuple_slot1: scratch slot for tg_trigtuple (foreign tables only) 4195 * trig_tuple_slot2: scratch slot for tg_newtuple (foreign tables only) 4196 * ---------- 4197 */ 4198 static void 4199 AfterTriggerExecute(AfterTriggerEvent event, 4200 Relation rel, TriggerDesc *trigdesc, 4201 FmgrInfo *finfo, Instrumentation *instr, 4202 MemoryContext per_tuple_context, 4203 TupleTableSlot *trig_tuple_slot1, 4204 TupleTableSlot *trig_tuple_slot2) 4205 { 4206 AfterTriggerShared evtshared = GetTriggerSharedData(event); 4207 Oid tgoid = evtshared->ats_tgoid; 4208 TriggerData LocTriggerData; 4209 HeapTupleData tuple1; 4210 HeapTupleData tuple2; 4211 HeapTuple rettuple; 4212 Buffer buffer1 = InvalidBuffer; 4213 Buffer buffer2 = InvalidBuffer; 4214 int tgindx; 4215 4216 /* 4217 * Locate trigger in trigdesc. 4218 */ 4219 LocTriggerData.tg_trigger = NULL; 4220 for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++) 4221 { 4222 if (trigdesc->triggers[tgindx].tgoid == tgoid) 4223 { 4224 LocTriggerData.tg_trigger = &(trigdesc->triggers[tgindx]); 4225 break; 4226 } 4227 } 4228 if (LocTriggerData.tg_trigger == NULL) 4229 elog(ERROR, "could not find trigger %u", tgoid); 4230 4231 /* 4232 * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want 4233 * to include time spent re-fetching tuples in the trigger cost. 4234 */ 4235 if (instr) 4236 InstrStartNode(instr + tgindx); 4237 4238 /* 4239 * Fetch the required tuple(s). 4240 */ 4241 switch (event->ate_flags & AFTER_TRIGGER_TUP_BITS) 4242 { 4243 case AFTER_TRIGGER_FDW_FETCH: 4244 { 4245 Tuplestorestate *fdw_tuplestore = GetCurrentFDWTuplestore(); 4246 4247 if (!tuplestore_gettupleslot(fdw_tuplestore, true, false, 4248 trig_tuple_slot1)) 4249 elog(ERROR, "failed to fetch tuple1 for AFTER trigger"); 4250 4251 if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) == 4252 TRIGGER_EVENT_UPDATE && 4253 !tuplestore_gettupleslot(fdw_tuplestore, true, false, 4254 trig_tuple_slot2)) 4255 elog(ERROR, "failed to fetch tuple2 for AFTER trigger"); 4256 } 4257 /* fall through */ 4258 case AFTER_TRIGGER_FDW_REUSE: 4259 4260 /* 4261 * Using ExecMaterializeSlot() rather than ExecFetchSlotTuple() 4262 * ensures that tg_trigtuple does not reference tuplestore memory. 4263 * (It is formally possible for the trigger function to queue 4264 * trigger events that add to the same tuplestore, which can push 4265 * other tuples out of memory.) The distinction is academic, 4266 * because we start with a minimal tuple that ExecFetchSlotTuple() 4267 * must materialize anyway. 4268 */ 4269 LocTriggerData.tg_trigtuple = 4270 ExecMaterializeSlot(trig_tuple_slot1); 4271 LocTriggerData.tg_trigtuplebuf = InvalidBuffer; 4272 4273 LocTriggerData.tg_newtuple = 4274 ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) == 4275 TRIGGER_EVENT_UPDATE) ? 4276 ExecMaterializeSlot(trig_tuple_slot2) : NULL; 4277 LocTriggerData.tg_newtuplebuf = InvalidBuffer; 4278 4279 break; 4280 4281 default: 4282 if (ItemPointerIsValid(&(event->ate_ctid1))) 4283 { 4284 ItemPointerCopy(&(event->ate_ctid1), &(tuple1.t_self)); 4285 if (!heap_fetch(rel, SnapshotAny, &tuple1, &buffer1, false, NULL)) 4286 elog(ERROR, "failed to fetch tuple1 for AFTER trigger"); 4287 LocTriggerData.tg_trigtuple = &tuple1; 4288 LocTriggerData.tg_trigtuplebuf = buffer1; 4289 } 4290 else 4291 { 4292 LocTriggerData.tg_trigtuple = NULL; 4293 LocTriggerData.tg_trigtuplebuf = InvalidBuffer; 4294 } 4295 4296 /* don't touch ctid2 if not there */ 4297 if ((event->ate_flags & AFTER_TRIGGER_TUP_BITS) == 4298 AFTER_TRIGGER_2CTID && 4299 ItemPointerIsValid(&(event->ate_ctid2))) 4300 { 4301 ItemPointerCopy(&(event->ate_ctid2), &(tuple2.t_self)); 4302 if (!heap_fetch(rel, SnapshotAny, &tuple2, &buffer2, false, NULL)) 4303 elog(ERROR, "failed to fetch tuple2 for AFTER trigger"); 4304 LocTriggerData.tg_newtuple = &tuple2; 4305 LocTriggerData.tg_newtuplebuf = buffer2; 4306 } 4307 else 4308 { 4309 LocTriggerData.tg_newtuple = NULL; 4310 LocTriggerData.tg_newtuplebuf = InvalidBuffer; 4311 } 4312 } 4313 4314 /* 4315 * Set up the tuplestore information to let the trigger have access to 4316 * transition tables. When we first make a transition table available to 4317 * a trigger, mark it "closed" so that it cannot change anymore. If any 4318 * additional events of the same type get queued in the current trigger 4319 * query level, they'll go into new transition tables. 4320 */ 4321 LocTriggerData.tg_oldtable = LocTriggerData.tg_newtable = NULL; 4322 if (evtshared->ats_table) 4323 { 4324 if (LocTriggerData.tg_trigger->tgoldtable) 4325 { 4326 LocTriggerData.tg_oldtable = evtshared->ats_table->old_tuplestore; 4327 evtshared->ats_table->closed = true; 4328 } 4329 4330 if (LocTriggerData.tg_trigger->tgnewtable) 4331 { 4332 LocTriggerData.tg_newtable = evtshared->ats_table->new_tuplestore; 4333 evtshared->ats_table->closed = true; 4334 } 4335 } 4336 4337 /* 4338 * Setup the remaining trigger information 4339 */ 4340 LocTriggerData.type = T_TriggerData; 4341 LocTriggerData.tg_event = 4342 evtshared->ats_event & (TRIGGER_EVENT_OPMASK | TRIGGER_EVENT_ROW); 4343 LocTriggerData.tg_relation = rel; 4344 4345 MemoryContextReset(per_tuple_context); 4346 4347 /* 4348 * Call the trigger and throw away any possibly returned updated tuple. 4349 * (Don't let ExecCallTriggerFunc measure EXPLAIN time.) 4350 */ 4351 rettuple = ExecCallTriggerFunc(&LocTriggerData, 4352 tgindx, 4353 finfo, 4354 NULL, 4355 per_tuple_context); 4356 if (rettuple != NULL && 4357 rettuple != LocTriggerData.tg_trigtuple && 4358 rettuple != LocTriggerData.tg_newtuple) 4359 heap_freetuple(rettuple); 4360 4361 /* 4362 * Release buffers 4363 */ 4364 if (buffer1 != InvalidBuffer) 4365 ReleaseBuffer(buffer1); 4366 if (buffer2 != InvalidBuffer) 4367 ReleaseBuffer(buffer2); 4368 4369 /* 4370 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count 4371 * one "tuple returned" (really the number of firings). 4372 */ 4373 if (instr) 4374 InstrStopNode(instr + tgindx, 1); 4375 } 4376 4377 4378 /* 4379 * afterTriggerMarkEvents() 4380 * 4381 * Scan the given event list for not yet invoked events. Mark the ones 4382 * that can be invoked now with the current firing ID. 4383 * 4384 * If move_list isn't NULL, events that are not to be invoked now are 4385 * transferred to move_list. 4386 * 4387 * When immediate_only is true, do not invoke currently-deferred triggers. 4388 * (This will be false only at main transaction exit.) 4389 * 4390 * Returns true if any invokable events were found. 4391 */ 4392 static bool 4393 afterTriggerMarkEvents(AfterTriggerEventList *events, 4394 AfterTriggerEventList *move_list, 4395 bool immediate_only) 4396 { 4397 bool found = false; 4398 bool deferred_found = false; 4399 AfterTriggerEvent event; 4400 AfterTriggerEventChunk *chunk; 4401 4402 for_each_event_chunk(event, chunk, *events) 4403 { 4404 AfterTriggerShared evtshared = GetTriggerSharedData(event); 4405 bool defer_it = false; 4406 4407 if (!(event->ate_flags & 4408 (AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS))) 4409 { 4410 /* 4411 * This trigger hasn't been called or scheduled yet. Check if we 4412 * should call it now. 4413 */ 4414 if (immediate_only && afterTriggerCheckState(evtshared)) 4415 { 4416 defer_it = true; 4417 } 4418 else 4419 { 4420 /* 4421 * Mark it as to be fired in this firing cycle. 4422 */ 4423 evtshared->ats_firing_id = afterTriggers.firing_counter; 4424 event->ate_flags |= AFTER_TRIGGER_IN_PROGRESS; 4425 found = true; 4426 } 4427 } 4428 4429 /* 4430 * If it's deferred, move it to move_list, if requested. 4431 */ 4432 if (defer_it && move_list != NULL) 4433 { 4434 deferred_found = true; 4435 /* add it to move_list */ 4436 afterTriggerAddEvent(move_list, event, evtshared); 4437 /* mark original copy "done" so we don't do it again */ 4438 event->ate_flags |= AFTER_TRIGGER_DONE; 4439 } 4440 } 4441 4442 /* 4443 * We could allow deferred triggers if, before the end of the 4444 * security-restricted operation, we were to verify that a SET CONSTRAINTS 4445 * ... IMMEDIATE has fired all such triggers. For now, don't bother. 4446 */ 4447 if (deferred_found && InSecurityRestrictedOperation()) 4448 ereport(ERROR, 4449 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), 4450 errmsg("cannot fire deferred trigger within security-restricted operation"))); 4451 4452 return found; 4453 } 4454 4455 /* 4456 * afterTriggerInvokeEvents() 4457 * 4458 * Scan the given event list for events that are marked as to be fired 4459 * in the current firing cycle, and fire them. 4460 * 4461 * If estate isn't NULL, we use its result relation info to avoid repeated 4462 * openings and closing of trigger target relations. If it is NULL, we 4463 * make one locally to cache the info in case there are multiple trigger 4464 * events per rel. 4465 * 4466 * When delete_ok is true, it's safe to delete fully-processed events. 4467 * (We are not very tense about that: we simply reset a chunk to be empty 4468 * if all its events got fired. The objective here is just to avoid useless 4469 * rescanning of events when a trigger queues new events during transaction 4470 * end, so it's not necessary to worry much about the case where only 4471 * some events are fired.) 4472 * 4473 * Returns true if no unfired events remain in the list (this allows us 4474 * to avoid repeating afterTriggerMarkEvents). 4475 */ 4476 static bool 4477 afterTriggerInvokeEvents(AfterTriggerEventList *events, 4478 CommandId firing_id, 4479 EState *estate, 4480 bool delete_ok) 4481 { 4482 bool all_fired = true; 4483 AfterTriggerEventChunk *chunk; 4484 MemoryContext per_tuple_context; 4485 bool local_estate = false; 4486 Relation rel = NULL; 4487 TriggerDesc *trigdesc = NULL; 4488 FmgrInfo *finfo = NULL; 4489 Instrumentation *instr = NULL; 4490 TupleTableSlot *slot1 = NULL, 4491 *slot2 = NULL; 4492 4493 /* Make a local EState if need be */ 4494 if (estate == NULL) 4495 { 4496 estate = CreateExecutorState(); 4497 local_estate = true; 4498 } 4499 4500 /* Make a per-tuple memory context for trigger function calls */ 4501 per_tuple_context = 4502 AllocSetContextCreate(CurrentMemoryContext, 4503 "AfterTriggerTupleContext", 4504 ALLOCSET_DEFAULT_SIZES); 4505 4506 for_each_chunk(chunk, *events) 4507 { 4508 AfterTriggerEvent event; 4509 bool all_fired_in_chunk = true; 4510 4511 for_each_event(event, chunk) 4512 { 4513 AfterTriggerShared evtshared = GetTriggerSharedData(event); 4514 4515 /* 4516 * Is it one for me to fire? 4517 */ 4518 if ((event->ate_flags & AFTER_TRIGGER_IN_PROGRESS) && 4519 evtshared->ats_firing_id == firing_id) 4520 { 4521 /* 4522 * So let's fire it... but first, find the correct relation if 4523 * this is not the same relation as before. 4524 */ 4525 if (rel == NULL || RelationGetRelid(rel) != evtshared->ats_relid) 4526 { 4527 ResultRelInfo *rInfo; 4528 4529 rInfo = ExecGetTriggerResultRel(estate, evtshared->ats_relid); 4530 rel = rInfo->ri_RelationDesc; 4531 trigdesc = rInfo->ri_TrigDesc; 4532 finfo = rInfo->ri_TrigFunctions; 4533 instr = rInfo->ri_TrigInstrument; 4534 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE) 4535 { 4536 if (slot1 != NULL) 4537 { 4538 ExecDropSingleTupleTableSlot(slot1); 4539 ExecDropSingleTupleTableSlot(slot2); 4540 } 4541 slot1 = MakeSingleTupleTableSlot(rel->rd_att); 4542 slot2 = MakeSingleTupleTableSlot(rel->rd_att); 4543 } 4544 if (trigdesc == NULL) /* should not happen */ 4545 elog(ERROR, "relation %u has no triggers", 4546 evtshared->ats_relid); 4547 } 4548 4549 /* 4550 * Fire it. Note that the AFTER_TRIGGER_IN_PROGRESS flag is 4551 * still set, so recursive examinations of the event list 4552 * won't try to re-fire it. 4553 */ 4554 AfterTriggerExecute(event, rel, trigdesc, finfo, instr, 4555 per_tuple_context, slot1, slot2); 4556 4557 /* 4558 * Mark the event as done. 4559 */ 4560 event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS; 4561 event->ate_flags |= AFTER_TRIGGER_DONE; 4562 } 4563 else if (!(event->ate_flags & AFTER_TRIGGER_DONE)) 4564 { 4565 /* something remains to be done */ 4566 all_fired = all_fired_in_chunk = false; 4567 } 4568 } 4569 4570 /* Clear the chunk if delete_ok and nothing left of interest */ 4571 if (delete_ok && all_fired_in_chunk) 4572 { 4573 chunk->freeptr = CHUNK_DATA_START(chunk); 4574 chunk->endfree = chunk->endptr; 4575 4576 /* 4577 * If it's last chunk, must sync event list's tailfree too. Note 4578 * that delete_ok must NOT be passed as true if there could be 4579 * additional AfterTriggerEventList values pointing at this event 4580 * list, since we'd fail to fix their copies of tailfree. 4581 */ 4582 if (chunk == events->tail) 4583 events->tailfree = chunk->freeptr; 4584 } 4585 } 4586 if (slot1 != NULL) 4587 { 4588 ExecDropSingleTupleTableSlot(slot1); 4589 ExecDropSingleTupleTableSlot(slot2); 4590 } 4591 4592 /* Release working resources */ 4593 MemoryContextDelete(per_tuple_context); 4594 4595 if (local_estate) 4596 { 4597 ExecCleanUpTriggerState(estate); 4598 FreeExecutorState(estate); 4599 } 4600 4601 return all_fired; 4602 } 4603 4604 4605 /* 4606 * GetAfterTriggersTableData 4607 * 4608 * Find or create an AfterTriggersTableData struct for the specified 4609 * trigger event (relation + operation type). Ignore existing structs 4610 * marked "closed"; we don't want to put any additional tuples into them, 4611 * nor change their stmt-triggers-fired state. 4612 * 4613 * Note: the AfterTriggersTableData list is allocated in the current 4614 * (sub)transaction's CurTransactionContext. This is OK because 4615 * we don't need it to live past AfterTriggerEndQuery. 4616 */ 4617 static AfterTriggersTableData * 4618 GetAfterTriggersTableData(Oid relid, CmdType cmdType) 4619 { 4620 AfterTriggersTableData *table; 4621 AfterTriggersQueryData *qs; 4622 MemoryContext oldcxt; 4623 ListCell *lc; 4624 4625 /* Caller should have ensured query_depth is OK. */ 4626 Assert(afterTriggers.query_depth >= 0 && 4627 afterTriggers.query_depth < afterTriggers.maxquerydepth); 4628 qs = &afterTriggers.query_stack[afterTriggers.query_depth]; 4629 4630 foreach(lc, qs->tables) 4631 { 4632 table = (AfterTriggersTableData *) lfirst(lc); 4633 if (table->relid == relid && table->cmdType == cmdType && 4634 !table->closed) 4635 return table; 4636 } 4637 4638 oldcxt = MemoryContextSwitchTo(CurTransactionContext); 4639 4640 table = (AfterTriggersTableData *) palloc0(sizeof(AfterTriggersTableData)); 4641 table->relid = relid; 4642 table->cmdType = cmdType; 4643 qs->tables = lappend(qs->tables, table); 4644 4645 MemoryContextSwitchTo(oldcxt); 4646 4647 return table; 4648 } 4649 4650 4651 /* 4652 * MakeTransitionCaptureState 4653 * 4654 * Make a TransitionCaptureState object for the given TriggerDesc, target 4655 * relation, and operation type. The TCS object holds all the state needed 4656 * to decide whether to capture tuples in transition tables. 4657 * 4658 * If there are no triggers in 'trigdesc' that request relevant transition 4659 * tables, then return NULL. 4660 * 4661 * The resulting object can be passed to the ExecAR* functions. The caller 4662 * should set tcs_map or tcs_original_insert_tuple as appropriate when dealing 4663 * with child tables. 4664 * 4665 * Note that we copy the flags from a parent table into this struct (rather 4666 * than subsequently using the relation's TriggerDesc directly) so that we can 4667 * use it to control collection of transition tuples from child tables. 4668 * 4669 * Per SQL spec, all operations of the same kind (INSERT/UPDATE/DELETE) 4670 * on the same table during one query should share one transition table. 4671 * Therefore, the Tuplestores are owned by an AfterTriggersTableData struct 4672 * looked up using the table OID + CmdType, and are merely referenced by 4673 * the TransitionCaptureState objects we hand out to callers. 4674 */ 4675 TransitionCaptureState * 4676 MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType) 4677 { 4678 TransitionCaptureState *state; 4679 bool need_old, 4680 need_new; 4681 AfterTriggersTableData *table; 4682 MemoryContext oldcxt; 4683 ResourceOwner saveResourceOwner; 4684 4685 if (trigdesc == NULL) 4686 return NULL; 4687 4688 /* Detect which table(s) we need. */ 4689 switch (cmdType) 4690 { 4691 case CMD_INSERT: 4692 need_old = false; 4693 need_new = trigdesc->trig_insert_new_table; 4694 break; 4695 case CMD_UPDATE: 4696 need_old = trigdesc->trig_update_old_table; 4697 need_new = trigdesc->trig_update_new_table; 4698 break; 4699 case CMD_DELETE: 4700 need_old = trigdesc->trig_delete_old_table; 4701 need_new = false; 4702 break; 4703 default: 4704 elog(ERROR, "unexpected CmdType: %d", (int) cmdType); 4705 need_old = need_new = false; /* keep compiler quiet */ 4706 break; 4707 } 4708 if (!need_old && !need_new) 4709 return NULL; 4710 4711 /* Check state, like AfterTriggerSaveEvent. */ 4712 if (afterTriggers.query_depth < 0) 4713 elog(ERROR, "MakeTransitionCaptureState() called outside of query"); 4714 4715 /* Be sure we have enough space to record events at this query depth. */ 4716 if (afterTriggers.query_depth >= afterTriggers.maxquerydepth) 4717 AfterTriggerEnlargeQueryState(); 4718 4719 /* 4720 * Find or create an AfterTriggersTableData struct to hold the 4721 * tuplestore(s). If there's a matching struct but it's marked closed, 4722 * ignore it; we need a newer one. 4723 * 4724 * Note: the AfterTriggersTableData list, as well as the tuplestores, are 4725 * allocated in the current (sub)transaction's CurTransactionContext, and 4726 * the tuplestores are managed by the (sub)transaction's resource owner. 4727 * This is sufficient lifespan because we do not allow triggers using 4728 * transition tables to be deferrable; they will be fired during 4729 * AfterTriggerEndQuery, after which it's okay to delete the data. 4730 */ 4731 table = GetAfterTriggersTableData(relid, cmdType); 4732 4733 /* Now create required tuplestore(s), if we don't have them already. */ 4734 oldcxt = MemoryContextSwitchTo(CurTransactionContext); 4735 saveResourceOwner = CurrentResourceOwner; 4736 CurrentResourceOwner = CurTransactionResourceOwner; 4737 4738 if (need_old && table->old_tuplestore == NULL) 4739 table->old_tuplestore = tuplestore_begin_heap(false, false, work_mem); 4740 if (need_new && table->new_tuplestore == NULL) 4741 table->new_tuplestore = tuplestore_begin_heap(false, false, work_mem); 4742 4743 CurrentResourceOwner = saveResourceOwner; 4744 MemoryContextSwitchTo(oldcxt); 4745 4746 /* Now build the TransitionCaptureState struct, in caller's context */ 4747 state = (TransitionCaptureState *) palloc0(sizeof(TransitionCaptureState)); 4748 state->tcs_delete_old_table = trigdesc->trig_delete_old_table; 4749 state->tcs_update_old_table = trigdesc->trig_update_old_table; 4750 state->tcs_update_new_table = trigdesc->trig_update_new_table; 4751 state->tcs_insert_new_table = trigdesc->trig_insert_new_table; 4752 state->tcs_private = table; 4753 4754 return state; 4755 } 4756 4757 4758 /* ---------- 4759 * AfterTriggerBeginXact() 4760 * 4761 * Called at transaction start (either BEGIN or implicit for single 4762 * statement outside of transaction block). 4763 * ---------- 4764 */ 4765 void 4766 AfterTriggerBeginXact(void) 4767 { 4768 /* 4769 * Initialize after-trigger state structure to empty 4770 */ 4771 afterTriggers.firing_counter = (CommandId) 1; /* mustn't be 0 */ 4772 afterTriggers.query_depth = -1; 4773 4774 /* 4775 * Verify that there is no leftover state remaining. If these assertions 4776 * trip, it means that AfterTriggerEndXact wasn't called or didn't clean 4777 * up properly. 4778 */ 4779 Assert(afterTriggers.state == NULL); 4780 Assert(afterTriggers.query_stack == NULL); 4781 Assert(afterTriggers.maxquerydepth == 0); 4782 Assert(afterTriggers.event_cxt == NULL); 4783 Assert(afterTriggers.events.head == NULL); 4784 Assert(afterTriggers.trans_stack == NULL); 4785 Assert(afterTriggers.maxtransdepth == 0); 4786 } 4787 4788 4789 /* ---------- 4790 * AfterTriggerBeginQuery() 4791 * 4792 * Called just before we start processing a single query within a 4793 * transaction (or subtransaction). Most of the real work gets deferred 4794 * until somebody actually tries to queue a trigger event. 4795 * ---------- 4796 */ 4797 void 4798 AfterTriggerBeginQuery(void) 4799 { 4800 /* Increase the query stack depth */ 4801 afterTriggers.query_depth++; 4802 } 4803 4804 4805 /* ---------- 4806 * AfterTriggerEndQuery() 4807 * 4808 * Called after one query has been completely processed. At this time 4809 * we invoke all AFTER IMMEDIATE trigger events queued by the query, and 4810 * transfer deferred trigger events to the global deferred-trigger list. 4811 * 4812 * Note that this must be called BEFORE closing down the executor 4813 * with ExecutorEnd, because we make use of the EState's info about 4814 * target relations. Normally it is called from ExecutorFinish. 4815 * ---------- 4816 */ 4817 void 4818 AfterTriggerEndQuery(EState *estate) 4819 { 4820 AfterTriggersQueryData *qs; 4821 4822 /* Must be inside a query, too */ 4823 Assert(afterTriggers.query_depth >= 0); 4824 4825 /* 4826 * If we never even got as far as initializing the event stack, there 4827 * certainly won't be any events, so exit quickly. 4828 */ 4829 if (afterTriggers.query_depth >= afterTriggers.maxquerydepth) 4830 { 4831 afterTriggers.query_depth--; 4832 return; 4833 } 4834 4835 /* 4836 * Process all immediate-mode triggers queued by the query, and move the 4837 * deferred ones to the main list of deferred events. 4838 * 4839 * Notice that we decide which ones will be fired, and put the deferred 4840 * ones on the main list, before anything is actually fired. This ensures 4841 * reasonably sane behavior if a trigger function does SET CONSTRAINTS ... 4842 * IMMEDIATE: all events we have decided to defer will be available for it 4843 * to fire. 4844 * 4845 * We loop in case a trigger queues more events at the same query level. 4846 * Ordinary trigger functions, including all PL/pgSQL trigger functions, 4847 * will instead fire any triggers in a dedicated query level. Foreign key 4848 * enforcement triggers do add to the current query level, thanks to their 4849 * passing fire_triggers = false to SPI_execute_snapshot(). Other 4850 * C-language triggers might do likewise. 4851 * 4852 * If we find no firable events, we don't have to increment 4853 * firing_counter. 4854 */ 4855 qs = &afterTriggers.query_stack[afterTriggers.query_depth]; 4856 4857 for (;;) 4858 { 4859 if (afterTriggerMarkEvents(&qs->events, &afterTriggers.events, true)) 4860 { 4861 CommandId firing_id = afterTriggers.firing_counter++; 4862 AfterTriggerEventChunk *oldtail = qs->events.tail; 4863 4864 if (afterTriggerInvokeEvents(&qs->events, firing_id, estate, false)) 4865 break; /* all fired */ 4866 4867 /* 4868 * Firing a trigger could result in query_stack being repalloc'd, 4869 * so we must recalculate qs after each afterTriggerInvokeEvents 4870 * call. Furthermore, it's unsafe to pass delete_ok = true here, 4871 * because that could cause afterTriggerInvokeEvents to try to 4872 * access qs->events after the stack has been repalloc'd. 4873 */ 4874 qs = &afterTriggers.query_stack[afterTriggers.query_depth]; 4875 4876 /* 4877 * We'll need to scan the events list again. To reduce the cost 4878 * of doing so, get rid of completely-fired chunks. We know that 4879 * all events were marked IN_PROGRESS or DONE at the conclusion of 4880 * afterTriggerMarkEvents, so any still-interesting events must 4881 * have been added after that, and so must be in the chunk that 4882 * was then the tail chunk, or in later chunks. So, zap all 4883 * chunks before oldtail. This is approximately the same set of 4884 * events we would have gotten rid of by passing delete_ok = true. 4885 */ 4886 Assert(oldtail != NULL); 4887 while (qs->events.head != oldtail) 4888 afterTriggerDeleteHeadEventChunk(qs); 4889 } 4890 else 4891 break; 4892 } 4893 4894 /* Release query-level-local storage, including tuplestores if any */ 4895 AfterTriggerFreeQuery(&afterTriggers.query_stack[afterTriggers.query_depth]); 4896 4897 afterTriggers.query_depth--; 4898 } 4899 4900 4901 /* 4902 * AfterTriggerFreeQuery 4903 * Release subsidiary storage for a trigger query level. 4904 * This includes closing down tuplestores. 4905 * Note: it's important for this to be safe if interrupted by an error 4906 * and then called again for the same query level. 4907 */ 4908 static void 4909 AfterTriggerFreeQuery(AfterTriggersQueryData *qs) 4910 { 4911 Tuplestorestate *ts; 4912 List *tables; 4913 ListCell *lc; 4914 4915 /* Drop the trigger events */ 4916 afterTriggerFreeEventList(&qs->events); 4917 4918 /* Drop FDW tuplestore if any */ 4919 ts = qs->fdw_tuplestore; 4920 qs->fdw_tuplestore = NULL; 4921 if (ts) 4922 tuplestore_end(ts); 4923 4924 /* Release per-table subsidiary storage */ 4925 tables = qs->tables; 4926 foreach(lc, tables) 4927 { 4928 AfterTriggersTableData *table = (AfterTriggersTableData *) lfirst(lc); 4929 4930 ts = table->old_tuplestore; 4931 table->old_tuplestore = NULL; 4932 if (ts) 4933 tuplestore_end(ts); 4934 ts = table->new_tuplestore; 4935 table->new_tuplestore = NULL; 4936 if (ts) 4937 tuplestore_end(ts); 4938 } 4939 4940 /* 4941 * Now free the AfterTriggersTableData structs and list cells. Reset list 4942 * pointer first; if list_free_deep somehow gets an error, better to leak 4943 * that storage than have an infinite loop. 4944 */ 4945 qs->tables = NIL; 4946 list_free_deep(tables); 4947 } 4948 4949 4950 /* ---------- 4951 * AfterTriggerFireDeferred() 4952 * 4953 * Called just before the current transaction is committed. At this 4954 * time we invoke all pending DEFERRED triggers. 4955 * 4956 * It is possible for other modules to queue additional deferred triggers 4957 * during pre-commit processing; therefore xact.c may have to call this 4958 * multiple times. 4959 * ---------- 4960 */ 4961 void 4962 AfterTriggerFireDeferred(void) 4963 { 4964 AfterTriggerEventList *events; 4965 bool snap_pushed = false; 4966 4967 /* Must not be inside a query */ 4968 Assert(afterTriggers.query_depth == -1); 4969 4970 /* 4971 * If there are any triggers to fire, make sure we have set a snapshot for 4972 * them to use. (Since PortalRunUtility doesn't set a snap for COMMIT, we 4973 * can't assume ActiveSnapshot is valid on entry.) 4974 */ 4975 events = &afterTriggers.events; 4976 if (events->head != NULL) 4977 { 4978 PushActiveSnapshot(GetTransactionSnapshot()); 4979 snap_pushed = true; 4980 } 4981 4982 /* 4983 * Run all the remaining triggers. Loop until they are all gone, in case 4984 * some trigger queues more for us to do. 4985 */ 4986 while (afterTriggerMarkEvents(events, NULL, false)) 4987 { 4988 CommandId firing_id = afterTriggers.firing_counter++; 4989 4990 if (afterTriggerInvokeEvents(events, firing_id, NULL, true)) 4991 break; /* all fired */ 4992 } 4993 4994 /* 4995 * We don't bother freeing the event list, since it will go away anyway 4996 * (and more efficiently than via pfree) in AfterTriggerEndXact. 4997 */ 4998 4999 if (snap_pushed) 5000 PopActiveSnapshot(); 5001 } 5002 5003 5004 /* ---------- 5005 * AfterTriggerEndXact() 5006 * 5007 * The current transaction is finishing. 5008 * 5009 * Any unfired triggers are canceled so we simply throw 5010 * away anything we know. 5011 * 5012 * Note: it is possible for this to be called repeatedly in case of 5013 * error during transaction abort; therefore, do not complain if 5014 * already closed down. 5015 * ---------- 5016 */ 5017 void 5018 AfterTriggerEndXact(bool isCommit) 5019 { 5020 /* 5021 * Forget the pending-events list. 5022 * 5023 * Since all the info is in TopTransactionContext or children thereof, we 5024 * don't really need to do anything to reclaim memory. However, the 5025 * pending-events list could be large, and so it's useful to discard it as 5026 * soon as possible --- especially if we are aborting because we ran out 5027 * of memory for the list! 5028 */ 5029 if (afterTriggers.event_cxt) 5030 { 5031 MemoryContextDelete(afterTriggers.event_cxt); 5032 afterTriggers.event_cxt = NULL; 5033 afterTriggers.events.head = NULL; 5034 afterTriggers.events.tail = NULL; 5035 afterTriggers.events.tailfree = NULL; 5036 } 5037 5038 /* 5039 * Forget any subtransaction state as well. Since this can't be very 5040 * large, we let the eventual reset of TopTransactionContext free the 5041 * memory instead of doing it here. 5042 */ 5043 afterTriggers.trans_stack = NULL; 5044 afterTriggers.maxtransdepth = 0; 5045 5046 5047 /* 5048 * Forget the query stack and constraint-related state information. As 5049 * with the subtransaction state information, we don't bother freeing the 5050 * memory here. 5051 */ 5052 afterTriggers.query_stack = NULL; 5053 afterTriggers.maxquerydepth = 0; 5054 afterTriggers.state = NULL; 5055 5056 /* No more afterTriggers manipulation until next transaction starts. */ 5057 afterTriggers.query_depth = -1; 5058 } 5059 5060 /* 5061 * AfterTriggerBeginSubXact() 5062 * 5063 * Start a subtransaction. 5064 */ 5065 void 5066 AfterTriggerBeginSubXact(void) 5067 { 5068 int my_level = GetCurrentTransactionNestLevel(); 5069 5070 /* 5071 * Allocate more space in the trans_stack if needed. (Note: because the 5072 * minimum nest level of a subtransaction is 2, we waste the first couple 5073 * entries of the array; not worth the notational effort to avoid it.) 5074 */ 5075 while (my_level >= afterTriggers.maxtransdepth) 5076 { 5077 if (afterTriggers.maxtransdepth == 0) 5078 { 5079 /* Arbitrarily initialize for max of 8 subtransaction levels */ 5080 afterTriggers.trans_stack = (AfterTriggersTransData *) 5081 MemoryContextAlloc(TopTransactionContext, 5082 8 * sizeof(AfterTriggersTransData)); 5083 afterTriggers.maxtransdepth = 8; 5084 } 5085 else 5086 { 5087 /* repalloc will keep the stack in the same context */ 5088 int new_alloc = afterTriggers.maxtransdepth * 2; 5089 5090 afterTriggers.trans_stack = (AfterTriggersTransData *) 5091 repalloc(afterTriggers.trans_stack, 5092 new_alloc * sizeof(AfterTriggersTransData)); 5093 afterTriggers.maxtransdepth = new_alloc; 5094 } 5095 } 5096 5097 /* 5098 * Push the current information into the stack. The SET CONSTRAINTS state 5099 * is not saved until/unless changed. Likewise, we don't make a 5100 * per-subtransaction event context until needed. 5101 */ 5102 afterTriggers.trans_stack[my_level].state = NULL; 5103 afterTriggers.trans_stack[my_level].events = afterTriggers.events; 5104 afterTriggers.trans_stack[my_level].query_depth = afterTriggers.query_depth; 5105 afterTriggers.trans_stack[my_level].firing_counter = afterTriggers.firing_counter; 5106 } 5107 5108 /* 5109 * AfterTriggerEndSubXact() 5110 * 5111 * The current subtransaction is ending. 5112 */ 5113 void 5114 AfterTriggerEndSubXact(bool isCommit) 5115 { 5116 int my_level = GetCurrentTransactionNestLevel(); 5117 SetConstraintState state; 5118 AfterTriggerEvent event; 5119 AfterTriggerEventChunk *chunk; 5120 CommandId subxact_firing_id; 5121 5122 /* 5123 * Pop the prior state if needed. 5124 */ 5125 if (isCommit) 5126 { 5127 Assert(my_level < afterTriggers.maxtransdepth); 5128 /* If we saved a prior state, we don't need it anymore */ 5129 state = afterTriggers.trans_stack[my_level].state; 5130 if (state != NULL) 5131 pfree(state); 5132 /* this avoids double pfree if error later: */ 5133 afterTriggers.trans_stack[my_level].state = NULL; 5134 Assert(afterTriggers.query_depth == 5135 afterTriggers.trans_stack[my_level].query_depth); 5136 } 5137 else 5138 { 5139 /* 5140 * Aborting. It is possible subxact start failed before calling 5141 * AfterTriggerBeginSubXact, in which case we mustn't risk touching 5142 * trans_stack levels that aren't there. 5143 */ 5144 if (my_level >= afterTriggers.maxtransdepth) 5145 return; 5146 5147 /* 5148 * Release query-level storage for queries being aborted, and restore 5149 * query_depth to its pre-subxact value. This assumes that a 5150 * subtransaction will not add events to query levels started in a 5151 * earlier transaction state. 5152 */ 5153 while (afterTriggers.query_depth > afterTriggers.trans_stack[my_level].query_depth) 5154 { 5155 if (afterTriggers.query_depth < afterTriggers.maxquerydepth) 5156 AfterTriggerFreeQuery(&afterTriggers.query_stack[afterTriggers.query_depth]); 5157 afterTriggers.query_depth--; 5158 } 5159 Assert(afterTriggers.query_depth == 5160 afterTriggers.trans_stack[my_level].query_depth); 5161 5162 /* 5163 * Restore the global deferred-event list to its former length, 5164 * discarding any events queued by the subxact. 5165 */ 5166 afterTriggerRestoreEventList(&afterTriggers.events, 5167 &afterTriggers.trans_stack[my_level].events); 5168 5169 /* 5170 * Restore the trigger state. If the saved state is NULL, then this 5171 * subxact didn't save it, so it doesn't need restoring. 5172 */ 5173 state = afterTriggers.trans_stack[my_level].state; 5174 if (state != NULL) 5175 { 5176 pfree(afterTriggers.state); 5177 afterTriggers.state = state; 5178 } 5179 /* this avoids double pfree if error later: */ 5180 afterTriggers.trans_stack[my_level].state = NULL; 5181 5182 /* 5183 * Scan for any remaining deferred events that were marked DONE or IN 5184 * PROGRESS by this subxact or a child, and un-mark them. We can 5185 * recognize such events because they have a firing ID greater than or 5186 * equal to the firing_counter value we saved at subtransaction start. 5187 * (This essentially assumes that the current subxact includes all 5188 * subxacts started after it.) 5189 */ 5190 subxact_firing_id = afterTriggers.trans_stack[my_level].firing_counter; 5191 for_each_event_chunk(event, chunk, afterTriggers.events) 5192 { 5193 AfterTriggerShared evtshared = GetTriggerSharedData(event); 5194 5195 if (event->ate_flags & 5196 (AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS)) 5197 { 5198 if (evtshared->ats_firing_id >= subxact_firing_id) 5199 event->ate_flags &= 5200 ~(AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS); 5201 } 5202 } 5203 } 5204 } 5205 5206 /* ---------- 5207 * AfterTriggerEnlargeQueryState() 5208 * 5209 * Prepare the necessary state so that we can record AFTER trigger events 5210 * queued by a query. It is allowed to have nested queries within a 5211 * (sub)transaction, so we need to have separate state for each query 5212 * nesting level. 5213 * ---------- 5214 */ 5215 static void 5216 AfterTriggerEnlargeQueryState(void) 5217 { 5218 int init_depth = afterTriggers.maxquerydepth; 5219 5220 Assert(afterTriggers.query_depth >= afterTriggers.maxquerydepth); 5221 5222 if (afterTriggers.maxquerydepth == 0) 5223 { 5224 int new_alloc = Max(afterTriggers.query_depth + 1, 8); 5225 5226 afterTriggers.query_stack = (AfterTriggersQueryData *) 5227 MemoryContextAlloc(TopTransactionContext, 5228 new_alloc * sizeof(AfterTriggersQueryData)); 5229 afterTriggers.maxquerydepth = new_alloc; 5230 } 5231 else 5232 { 5233 /* repalloc will keep the stack in the same context */ 5234 int old_alloc = afterTriggers.maxquerydepth; 5235 int new_alloc = Max(afterTriggers.query_depth + 1, 5236 old_alloc * 2); 5237 5238 afterTriggers.query_stack = (AfterTriggersQueryData *) 5239 repalloc(afterTriggers.query_stack, 5240 new_alloc * sizeof(AfterTriggersQueryData)); 5241 afterTriggers.maxquerydepth = new_alloc; 5242 } 5243 5244 /* Initialize new array entries to empty */ 5245 while (init_depth < afterTriggers.maxquerydepth) 5246 { 5247 AfterTriggersQueryData *qs = &afterTriggers.query_stack[init_depth]; 5248 5249 qs->events.head = NULL; 5250 qs->events.tail = NULL; 5251 qs->events.tailfree = NULL; 5252 qs->fdw_tuplestore = NULL; 5253 qs->tables = NIL; 5254 5255 ++init_depth; 5256 } 5257 } 5258 5259 /* 5260 * Create an empty SetConstraintState with room for numalloc trigstates 5261 */ 5262 static SetConstraintState 5263 SetConstraintStateCreate(int numalloc) 5264 { 5265 SetConstraintState state; 5266 5267 /* Behave sanely with numalloc == 0 */ 5268 if (numalloc <= 0) 5269 numalloc = 1; 5270 5271 /* 5272 * We assume that zeroing will correctly initialize the state values. 5273 */ 5274 state = (SetConstraintState) 5275 MemoryContextAllocZero(TopTransactionContext, 5276 offsetof(SetConstraintStateData, trigstates) + 5277 numalloc * sizeof(SetConstraintTriggerData)); 5278 5279 state->numalloc = numalloc; 5280 5281 return state; 5282 } 5283 5284 /* 5285 * Copy a SetConstraintState 5286 */ 5287 static SetConstraintState 5288 SetConstraintStateCopy(SetConstraintState origstate) 5289 { 5290 SetConstraintState state; 5291 5292 state = SetConstraintStateCreate(origstate->numstates); 5293 5294 state->all_isset = origstate->all_isset; 5295 state->all_isdeferred = origstate->all_isdeferred; 5296 state->numstates = origstate->numstates; 5297 memcpy(state->trigstates, origstate->trigstates, 5298 origstate->numstates * sizeof(SetConstraintTriggerData)); 5299 5300 return state; 5301 } 5302 5303 /* 5304 * Add a per-trigger item to a SetConstraintState. Returns possibly-changed 5305 * pointer to the state object (it will change if we have to repalloc). 5306 */ 5307 static SetConstraintState 5308 SetConstraintStateAddItem(SetConstraintState state, 5309 Oid tgoid, bool tgisdeferred) 5310 { 5311 if (state->numstates >= state->numalloc) 5312 { 5313 int newalloc = state->numalloc * 2; 5314 5315 newalloc = Max(newalloc, 8); /* in case original has size 0 */ 5316 state = (SetConstraintState) 5317 repalloc(state, 5318 offsetof(SetConstraintStateData, trigstates) + 5319 newalloc * sizeof(SetConstraintTriggerData)); 5320 state->numalloc = newalloc; 5321 Assert(state->numstates < state->numalloc); 5322 } 5323 5324 state->trigstates[state->numstates].sct_tgoid = tgoid; 5325 state->trigstates[state->numstates].sct_tgisdeferred = tgisdeferred; 5326 state->numstates++; 5327 5328 return state; 5329 } 5330 5331 /* ---------- 5332 * AfterTriggerSetState() 5333 * 5334 * Execute the SET CONSTRAINTS ... utility command. 5335 * ---------- 5336 */ 5337 void 5338 AfterTriggerSetState(ConstraintsSetStmt *stmt) 5339 { 5340 int my_level = GetCurrentTransactionNestLevel(); 5341 5342 /* If we haven't already done so, initialize our state. */ 5343 if (afterTriggers.state == NULL) 5344 afterTriggers.state = SetConstraintStateCreate(8); 5345 5346 /* 5347 * If in a subtransaction, and we didn't save the current state already, 5348 * save it so it can be restored if the subtransaction aborts. 5349 */ 5350 if (my_level > 1 && 5351 afterTriggers.trans_stack[my_level].state == NULL) 5352 { 5353 afterTriggers.trans_stack[my_level].state = 5354 SetConstraintStateCopy(afterTriggers.state); 5355 } 5356 5357 /* 5358 * Handle SET CONSTRAINTS ALL ... 5359 */ 5360 if (stmt->constraints == NIL) 5361 { 5362 /* 5363 * Forget any previous SET CONSTRAINTS commands in this transaction. 5364 */ 5365 afterTriggers.state->numstates = 0; 5366 5367 /* 5368 * Set the per-transaction ALL state to known. 5369 */ 5370 afterTriggers.state->all_isset = true; 5371 afterTriggers.state->all_isdeferred = stmt->deferred; 5372 } 5373 else 5374 { 5375 Relation conrel; 5376 Relation tgrel; 5377 List *conoidlist = NIL; 5378 List *tgoidlist = NIL; 5379 ListCell *lc; 5380 5381 /* 5382 * Handle SET CONSTRAINTS constraint-name [, ...] 5383 * 5384 * First, identify all the named constraints and make a list of their 5385 * OIDs. Since, unlike the SQL spec, we allow multiple constraints of 5386 * the same name within a schema, the specifications are not 5387 * necessarily unique. Our strategy is to target all matching 5388 * constraints within the first search-path schema that has any 5389 * matches, but disregard matches in schemas beyond the first match. 5390 * (This is a bit odd but it's the historical behavior.) 5391 * 5392 * A constraint in a partitioned table may have corresponding 5393 * constraints in the partitions. Grab those too. 5394 */ 5395 conrel = heap_open(ConstraintRelationId, AccessShareLock); 5396 5397 foreach(lc, stmt->constraints) 5398 { 5399 RangeVar *constraint = lfirst(lc); 5400 bool found; 5401 List *namespacelist; 5402 ListCell *nslc; 5403 5404 if (constraint->catalogname) 5405 { 5406 if (strcmp(constraint->catalogname, get_database_name(MyDatabaseId)) != 0) 5407 ereport(ERROR, 5408 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 5409 errmsg("cross-database references are not implemented: \"%s.%s.%s\"", 5410 constraint->catalogname, constraint->schemaname, 5411 constraint->relname))); 5412 } 5413 5414 /* 5415 * If we're given the schema name with the constraint, look only 5416 * in that schema. If given a bare constraint name, use the 5417 * search path to find the first matching constraint. 5418 */ 5419 if (constraint->schemaname) 5420 { 5421 Oid namespaceId = LookupExplicitNamespace(constraint->schemaname, 5422 false); 5423 5424 namespacelist = list_make1_oid(namespaceId); 5425 } 5426 else 5427 { 5428 namespacelist = fetch_search_path(true); 5429 } 5430 5431 found = false; 5432 foreach(nslc, namespacelist) 5433 { 5434 Oid namespaceId = lfirst_oid(nslc); 5435 SysScanDesc conscan; 5436 ScanKeyData skey[2]; 5437 HeapTuple tup; 5438 5439 ScanKeyInit(&skey[0], 5440 Anum_pg_constraint_conname, 5441 BTEqualStrategyNumber, F_NAMEEQ, 5442 CStringGetDatum(constraint->relname)); 5443 ScanKeyInit(&skey[1], 5444 Anum_pg_constraint_connamespace, 5445 BTEqualStrategyNumber, F_OIDEQ, 5446 ObjectIdGetDatum(namespaceId)); 5447 5448 conscan = systable_beginscan(conrel, ConstraintNameNspIndexId, 5449 true, NULL, 2, skey); 5450 5451 while (HeapTupleIsValid(tup = systable_getnext(conscan))) 5452 { 5453 Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup); 5454 5455 if (con->condeferrable) 5456 conoidlist = lappend_oid(conoidlist, 5457 HeapTupleGetOid(tup)); 5458 else if (stmt->deferred) 5459 ereport(ERROR, 5460 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 5461 errmsg("constraint \"%s\" is not deferrable", 5462 constraint->relname))); 5463 found = true; 5464 } 5465 5466 systable_endscan(conscan); 5467 5468 /* 5469 * Once we've found a matching constraint we do not search 5470 * later parts of the search path. 5471 */ 5472 if (found) 5473 break; 5474 } 5475 5476 list_free(namespacelist); 5477 5478 /* 5479 * Not found ? 5480 */ 5481 if (!found) 5482 ereport(ERROR, 5483 (errcode(ERRCODE_UNDEFINED_OBJECT), 5484 errmsg("constraint \"%s\" does not exist", 5485 constraint->relname))); 5486 } 5487 5488 /* 5489 * Scan for any possible descendants of the constraints. We append 5490 * whatever we find to the same list that we're scanning; this has the 5491 * effect that we create new scans for those, too, so if there are 5492 * further descendents, we'll also catch them. 5493 */ 5494 foreach(lc, conoidlist) 5495 { 5496 Oid parent = lfirst_oid(lc); 5497 ScanKeyData key; 5498 SysScanDesc scan; 5499 HeapTuple tuple; 5500 5501 ScanKeyInit(&key, 5502 Anum_pg_constraint_conparentid, 5503 BTEqualStrategyNumber, F_OIDEQ, 5504 ObjectIdGetDatum(parent)); 5505 5506 scan = systable_beginscan(conrel, ConstraintParentIndexId, true, NULL, 1, &key); 5507 5508 while (HeapTupleIsValid(tuple = systable_getnext(scan))) 5509 conoidlist = lappend_oid(conoidlist, HeapTupleGetOid(tuple)); 5510 5511 systable_endscan(scan); 5512 } 5513 5514 heap_close(conrel, AccessShareLock); 5515 5516 /* 5517 * Now, locate the trigger(s) implementing each of these constraints, 5518 * and make a list of their OIDs. 5519 */ 5520 tgrel = heap_open(TriggerRelationId, AccessShareLock); 5521 5522 foreach(lc, conoidlist) 5523 { 5524 Oid conoid = lfirst_oid(lc); 5525 ScanKeyData skey; 5526 SysScanDesc tgscan; 5527 HeapTuple htup; 5528 5529 ScanKeyInit(&skey, 5530 Anum_pg_trigger_tgconstraint, 5531 BTEqualStrategyNumber, F_OIDEQ, 5532 ObjectIdGetDatum(conoid)); 5533 5534 tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true, 5535 NULL, 1, &skey); 5536 5537 while (HeapTupleIsValid(htup = systable_getnext(tgscan))) 5538 { 5539 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup); 5540 5541 /* 5542 * Silently skip triggers that are marked as non-deferrable in 5543 * pg_trigger. This is not an error condition, since a 5544 * deferrable RI constraint may have some non-deferrable 5545 * actions. 5546 */ 5547 if (pg_trigger->tgdeferrable) 5548 tgoidlist = lappend_oid(tgoidlist, 5549 HeapTupleGetOid(htup)); 5550 } 5551 5552 systable_endscan(tgscan); 5553 } 5554 5555 heap_close(tgrel, AccessShareLock); 5556 5557 /* 5558 * Now we can set the trigger states of individual triggers for this 5559 * xact. 5560 */ 5561 foreach(lc, tgoidlist) 5562 { 5563 Oid tgoid = lfirst_oid(lc); 5564 SetConstraintState state = afterTriggers.state; 5565 bool found = false; 5566 int i; 5567 5568 for (i = 0; i < state->numstates; i++) 5569 { 5570 if (state->trigstates[i].sct_tgoid == tgoid) 5571 { 5572 state->trigstates[i].sct_tgisdeferred = stmt->deferred; 5573 found = true; 5574 break; 5575 } 5576 } 5577 if (!found) 5578 { 5579 afterTriggers.state = 5580 SetConstraintStateAddItem(state, tgoid, stmt->deferred); 5581 } 5582 } 5583 } 5584 5585 /* 5586 * SQL99 requires that when a constraint is set to IMMEDIATE, any deferred 5587 * checks against that constraint must be made when the SET CONSTRAINTS 5588 * command is executed -- i.e. the effects of the SET CONSTRAINTS command 5589 * apply retroactively. We've updated the constraints state, so scan the 5590 * list of previously deferred events to fire any that have now become 5591 * immediate. 5592 * 5593 * Obviously, if this was SET ... DEFERRED then it can't have converted 5594 * any unfired events to immediate, so we need do nothing in that case. 5595 */ 5596 if (!stmt->deferred) 5597 { 5598 AfterTriggerEventList *events = &afterTriggers.events; 5599 bool snapshot_set = false; 5600 5601 while (afterTriggerMarkEvents(events, NULL, true)) 5602 { 5603 CommandId firing_id = afterTriggers.firing_counter++; 5604 5605 /* 5606 * Make sure a snapshot has been established in case trigger 5607 * functions need one. Note that we avoid setting a snapshot if 5608 * we don't find at least one trigger that has to be fired now. 5609 * This is so that BEGIN; SET CONSTRAINTS ...; SET TRANSACTION 5610 * ISOLATION LEVEL SERIALIZABLE; ... works properly. (If we are 5611 * at the start of a transaction it's not possible for any trigger 5612 * events to be queued yet.) 5613 */ 5614 if (!snapshot_set) 5615 { 5616 PushActiveSnapshot(GetTransactionSnapshot()); 5617 snapshot_set = true; 5618 } 5619 5620 /* 5621 * We can delete fired events if we are at top transaction level, 5622 * but we'd better not if inside a subtransaction, since the 5623 * subtransaction could later get rolled back. 5624 */ 5625 if (afterTriggerInvokeEvents(events, firing_id, NULL, 5626 !IsSubTransaction())) 5627 break; /* all fired */ 5628 } 5629 5630 if (snapshot_set) 5631 PopActiveSnapshot(); 5632 } 5633 } 5634 5635 /* ---------- 5636 * AfterTriggerPendingOnRel() 5637 * Test to see if there are any pending after-trigger events for rel. 5638 * 5639 * This is used by TRUNCATE, CLUSTER, ALTER TABLE, etc to detect whether 5640 * it is unsafe to perform major surgery on a relation. Note that only 5641 * local pending events are examined. We assume that having exclusive lock 5642 * on a rel guarantees there are no unserviced events in other backends --- 5643 * but having a lock does not prevent there being such events in our own. 5644 * 5645 * In some scenarios it'd be reasonable to remove pending events (more 5646 * specifically, mark them DONE by the current subxact) but without a lot 5647 * of knowledge of the trigger semantics we can't do this in general. 5648 * ---------- 5649 */ 5650 bool 5651 AfterTriggerPendingOnRel(Oid relid) 5652 { 5653 AfterTriggerEvent event; 5654 AfterTriggerEventChunk *chunk; 5655 int depth; 5656 5657 /* Scan queued events */ 5658 for_each_event_chunk(event, chunk, afterTriggers.events) 5659 { 5660 AfterTriggerShared evtshared = GetTriggerSharedData(event); 5661 5662 /* 5663 * We can ignore completed events. (Even if a DONE flag is rolled 5664 * back by subxact abort, it's OK because the effects of the TRUNCATE 5665 * or whatever must get rolled back too.) 5666 */ 5667 if (event->ate_flags & AFTER_TRIGGER_DONE) 5668 continue; 5669 5670 if (evtshared->ats_relid == relid) 5671 return true; 5672 } 5673 5674 /* 5675 * Also scan events queued by incomplete queries. This could only matter 5676 * if TRUNCATE/etc is executed by a function or trigger within an updating 5677 * query on the same relation, which is pretty perverse, but let's check. 5678 */ 5679 for (depth = 0; depth <= afterTriggers.query_depth && depth < afterTriggers.maxquerydepth; depth++) 5680 { 5681 for_each_event_chunk(event, chunk, afterTriggers.query_stack[depth].events) 5682 { 5683 AfterTriggerShared evtshared = GetTriggerSharedData(event); 5684 5685 if (event->ate_flags & AFTER_TRIGGER_DONE) 5686 continue; 5687 5688 if (evtshared->ats_relid == relid) 5689 return true; 5690 } 5691 } 5692 5693 return false; 5694 } 5695 5696 5697 /* ---------- 5698 * AfterTriggerSaveEvent() 5699 * 5700 * Called by ExecA[RS]...Triggers() to queue up the triggers that should 5701 * be fired for an event. 5702 * 5703 * NOTE: this is called whenever there are any triggers associated with 5704 * the event (even if they are disabled). This function decides which 5705 * triggers actually need to be queued. It is also called after each row, 5706 * even if there are no triggers for that event, if there are any AFTER 5707 * STATEMENT triggers for the statement which use transition tables, so that 5708 * the transition tuplestores can be built. Furthermore, if the transition 5709 * capture is happening for UPDATEd rows being moved to another partition due 5710 * to the partition-key being changed, then this function is called once when 5711 * the row is deleted (to capture OLD row), and once when the row is inserted 5712 * into another partition (to capture NEW row). This is done separately because 5713 * DELETE and INSERT happen on different tables. 5714 * 5715 * Transition tuplestores are built now, rather than when events are pulled 5716 * off of the queue because AFTER ROW triggers are allowed to select from the 5717 * transition tables for the statement. 5718 * ---------- 5719 */ 5720 static void 5721 AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, 5722 int event, bool row_trigger, 5723 HeapTuple oldtup, HeapTuple newtup, 5724 List *recheckIndexes, Bitmapset *modifiedCols, 5725 TransitionCaptureState *transition_capture) 5726 { 5727 Relation rel = relinfo->ri_RelationDesc; 5728 TriggerDesc *trigdesc = relinfo->ri_TrigDesc; 5729 AfterTriggerEventData new_event; 5730 AfterTriggerSharedData new_shared; 5731 char relkind = rel->rd_rel->relkind; 5732 int tgtype_event; 5733 int tgtype_level; 5734 int i; 5735 Tuplestorestate *fdw_tuplestore = NULL; 5736 5737 /* 5738 * Check state. We use a normal test not Assert because it is possible to 5739 * reach here in the wrong state given misconfigured RI triggers, in 5740 * particular deferring a cascade action trigger. 5741 */ 5742 if (afterTriggers.query_depth < 0) 5743 elog(ERROR, "AfterTriggerSaveEvent() called outside of query"); 5744 5745 /* Be sure we have enough space to record events at this query depth. */ 5746 if (afterTriggers.query_depth >= afterTriggers.maxquerydepth) 5747 AfterTriggerEnlargeQueryState(); 5748 5749 /* 5750 * If the directly named relation has any triggers with transition tables, 5751 * then we need to capture transition tuples. 5752 */ 5753 if (row_trigger && transition_capture != NULL) 5754 { 5755 HeapTuple original_insert_tuple = transition_capture->tcs_original_insert_tuple; 5756 TupleConversionMap *map = transition_capture->tcs_map; 5757 bool delete_old_table = transition_capture->tcs_delete_old_table; 5758 bool update_old_table = transition_capture->tcs_update_old_table; 5759 bool update_new_table = transition_capture->tcs_update_new_table; 5760 bool insert_new_table = transition_capture->tcs_insert_new_table; 5761 5762 /* 5763 * For INSERT events newtup should be non-NULL, for DELETE events 5764 * oldtup should be non-NULL, whereas for UPDATE events normally both 5765 * oldtup and newtup are non-NULL. But for UPDATE events fired for 5766 * capturing transition tuples during UPDATE partition-key row 5767 * movement, oldtup is NULL when the event is for a row being 5768 * inserted, whereas newtup is NULL when the event is for a row being 5769 * deleted. 5770 */ 5771 Assert(!(event == TRIGGER_EVENT_DELETE && delete_old_table && 5772 oldtup == NULL)); 5773 Assert(!(event == TRIGGER_EVENT_INSERT && insert_new_table && 5774 newtup == NULL)); 5775 5776 if (oldtup != NULL && 5777 ((event == TRIGGER_EVENT_DELETE && delete_old_table) || 5778 (event == TRIGGER_EVENT_UPDATE && update_old_table))) 5779 { 5780 Tuplestorestate *old_tuplestore; 5781 5782 old_tuplestore = transition_capture->tcs_private->old_tuplestore; 5783 5784 if (map != NULL) 5785 { 5786 HeapTuple converted = do_convert_tuple(oldtup, map); 5787 5788 tuplestore_puttuple(old_tuplestore, converted); 5789 pfree(converted); 5790 } 5791 else 5792 tuplestore_puttuple(old_tuplestore, oldtup); 5793 } 5794 if (newtup != NULL && 5795 ((event == TRIGGER_EVENT_INSERT && insert_new_table) || 5796 (event == TRIGGER_EVENT_UPDATE && update_new_table))) 5797 { 5798 Tuplestorestate *new_tuplestore; 5799 5800 new_tuplestore = transition_capture->tcs_private->new_tuplestore; 5801 5802 if (original_insert_tuple != NULL) 5803 tuplestore_puttuple(new_tuplestore, original_insert_tuple); 5804 else if (map != NULL) 5805 { 5806 HeapTuple converted = do_convert_tuple(newtup, map); 5807 5808 tuplestore_puttuple(new_tuplestore, converted); 5809 pfree(converted); 5810 } 5811 else 5812 tuplestore_puttuple(new_tuplestore, newtup); 5813 } 5814 5815 /* 5816 * If transition tables are the only reason we're here, return. As 5817 * mentioned above, we can also be here during update tuple routing in 5818 * presence of transition tables, in which case this function is 5819 * called separately for oldtup and newtup, so we expect exactly one 5820 * of them to be NULL. 5821 */ 5822 if (trigdesc == NULL || 5823 (event == TRIGGER_EVENT_DELETE && !trigdesc->trig_delete_after_row) || 5824 (event == TRIGGER_EVENT_INSERT && !trigdesc->trig_insert_after_row) || 5825 (event == TRIGGER_EVENT_UPDATE && !trigdesc->trig_update_after_row) || 5826 (event == TRIGGER_EVENT_UPDATE && ((oldtup == NULL) ^ (newtup == NULL)))) 5827 return; 5828 } 5829 5830 /* 5831 * Validate the event code and collect the associated tuple CTIDs. 5832 * 5833 * The event code will be used both as a bitmask and an array offset, so 5834 * validation is important to make sure we don't walk off the edge of our 5835 * arrays. 5836 * 5837 * Also, if we're considering statement-level triggers, check whether we 5838 * already queued a set of them for this event, and cancel the prior set 5839 * if so. This preserves the behavior that statement-level triggers fire 5840 * just once per statement and fire after row-level triggers. 5841 */ 5842 switch (event) 5843 { 5844 case TRIGGER_EVENT_INSERT: 5845 tgtype_event = TRIGGER_TYPE_INSERT; 5846 if (row_trigger) 5847 { 5848 Assert(oldtup == NULL); 5849 Assert(newtup != NULL); 5850 ItemPointerCopy(&(newtup->t_self), &(new_event.ate_ctid1)); 5851 ItemPointerSetInvalid(&(new_event.ate_ctid2)); 5852 } 5853 else 5854 { 5855 Assert(oldtup == NULL); 5856 Assert(newtup == NULL); 5857 ItemPointerSetInvalid(&(new_event.ate_ctid1)); 5858 ItemPointerSetInvalid(&(new_event.ate_ctid2)); 5859 cancel_prior_stmt_triggers(RelationGetRelid(rel), 5860 CMD_INSERT, event); 5861 } 5862 break; 5863 case TRIGGER_EVENT_DELETE: 5864 tgtype_event = TRIGGER_TYPE_DELETE; 5865 if (row_trigger) 5866 { 5867 Assert(oldtup != NULL); 5868 Assert(newtup == NULL); 5869 ItemPointerCopy(&(oldtup->t_self), &(new_event.ate_ctid1)); 5870 ItemPointerSetInvalid(&(new_event.ate_ctid2)); 5871 } 5872 else 5873 { 5874 Assert(oldtup == NULL); 5875 Assert(newtup == NULL); 5876 ItemPointerSetInvalid(&(new_event.ate_ctid1)); 5877 ItemPointerSetInvalid(&(new_event.ate_ctid2)); 5878 cancel_prior_stmt_triggers(RelationGetRelid(rel), 5879 CMD_DELETE, event); 5880 } 5881 break; 5882 case TRIGGER_EVENT_UPDATE: 5883 tgtype_event = TRIGGER_TYPE_UPDATE; 5884 if (row_trigger) 5885 { 5886 Assert(oldtup != NULL); 5887 Assert(newtup != NULL); 5888 ItemPointerCopy(&(oldtup->t_self), &(new_event.ate_ctid1)); 5889 ItemPointerCopy(&(newtup->t_self), &(new_event.ate_ctid2)); 5890 } 5891 else 5892 { 5893 Assert(oldtup == NULL); 5894 Assert(newtup == NULL); 5895 ItemPointerSetInvalid(&(new_event.ate_ctid1)); 5896 ItemPointerSetInvalid(&(new_event.ate_ctid2)); 5897 cancel_prior_stmt_triggers(RelationGetRelid(rel), 5898 CMD_UPDATE, event); 5899 } 5900 break; 5901 case TRIGGER_EVENT_TRUNCATE: 5902 tgtype_event = TRIGGER_TYPE_TRUNCATE; 5903 Assert(oldtup == NULL); 5904 Assert(newtup == NULL); 5905 ItemPointerSetInvalid(&(new_event.ate_ctid1)); 5906 ItemPointerSetInvalid(&(new_event.ate_ctid2)); 5907 break; 5908 default: 5909 elog(ERROR, "invalid after-trigger event code: %d", event); 5910 tgtype_event = 0; /* keep compiler quiet */ 5911 break; 5912 } 5913 5914 if (!(relkind == RELKIND_FOREIGN_TABLE && row_trigger)) 5915 new_event.ate_flags = (row_trigger && event == TRIGGER_EVENT_UPDATE) ? 5916 AFTER_TRIGGER_2CTID : AFTER_TRIGGER_1CTID; 5917 /* else, we'll initialize ate_flags for each trigger */ 5918 5919 tgtype_level = (row_trigger ? TRIGGER_TYPE_ROW : TRIGGER_TYPE_STATEMENT); 5920 5921 for (i = 0; i < trigdesc->numtriggers; i++) 5922 { 5923 Trigger *trigger = &trigdesc->triggers[i]; 5924 5925 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype, 5926 tgtype_level, 5927 TRIGGER_TYPE_AFTER, 5928 tgtype_event)) 5929 continue; 5930 if (!TriggerEnabled(estate, relinfo, trigger, event, 5931 modifiedCols, oldtup, newtup)) 5932 continue; 5933 5934 if (relkind == RELKIND_FOREIGN_TABLE && row_trigger) 5935 { 5936 if (fdw_tuplestore == NULL) 5937 { 5938 fdw_tuplestore = GetCurrentFDWTuplestore(); 5939 new_event.ate_flags = AFTER_TRIGGER_FDW_FETCH; 5940 } 5941 else 5942 /* subsequent event for the same tuple */ 5943 new_event.ate_flags = AFTER_TRIGGER_FDW_REUSE; 5944 } 5945 5946 /* 5947 * If the trigger is a foreign key enforcement trigger, there are 5948 * certain cases where we can skip queueing the event because we can 5949 * tell by inspection that the FK constraint will still pass. 5950 */ 5951 if (TRIGGER_FIRED_BY_UPDATE(event)) 5952 { 5953 switch (RI_FKey_trigger_type(trigger->tgfoid)) 5954 { 5955 case RI_TRIGGER_PK: 5956 /* Update on trigger's PK table */ 5957 if (!RI_FKey_pk_upd_check_required(trigger, rel, 5958 oldtup, newtup)) 5959 { 5960 /* skip queuing this event */ 5961 continue; 5962 } 5963 break; 5964 5965 case RI_TRIGGER_FK: 5966 /* Update on trigger's FK table */ 5967 if (!RI_FKey_fk_upd_check_required(trigger, rel, 5968 oldtup, newtup)) 5969 { 5970 /* skip queuing this event */ 5971 continue; 5972 } 5973 break; 5974 5975 case RI_TRIGGER_NONE: 5976 /* Not an FK trigger */ 5977 break; 5978 } 5979 } 5980 5981 /* 5982 * If the trigger is a deferred unique constraint check trigger, only 5983 * queue it if the unique constraint was potentially violated, which 5984 * we know from index insertion time. 5985 */ 5986 if (trigger->tgfoid == F_UNIQUE_KEY_RECHECK) 5987 { 5988 if (!list_member_oid(recheckIndexes, trigger->tgconstrindid)) 5989 continue; /* Uniqueness definitely not violated */ 5990 } 5991 5992 /* 5993 * Fill in event structure and add it to the current query's queue. 5994 * Note we set ats_table to NULL whenever this trigger doesn't use 5995 * transition tables, to improve sharability of the shared event data. 5996 */ 5997 new_shared.ats_event = 5998 (event & TRIGGER_EVENT_OPMASK) | 5999 (row_trigger ? TRIGGER_EVENT_ROW : 0) | 6000 (trigger->tgdeferrable ? AFTER_TRIGGER_DEFERRABLE : 0) | 6001 (trigger->tginitdeferred ? AFTER_TRIGGER_INITDEFERRED : 0); 6002 new_shared.ats_tgoid = trigger->tgoid; 6003 new_shared.ats_relid = RelationGetRelid(rel); 6004 new_shared.ats_firing_id = 0; 6005 if ((trigger->tgoldtable || trigger->tgnewtable) && 6006 transition_capture != NULL) 6007 new_shared.ats_table = transition_capture->tcs_private; 6008 else 6009 new_shared.ats_table = NULL; 6010 6011 afterTriggerAddEvent(&afterTriggers.query_stack[afterTriggers.query_depth].events, 6012 &new_event, &new_shared); 6013 } 6014 6015 /* 6016 * Finally, spool any foreign tuple(s). The tuplestore squashes them to 6017 * minimal tuples, so this loses any system columns. The executor lost 6018 * those columns before us, for an unrelated reason, so this is fine. 6019 */ 6020 if (fdw_tuplestore) 6021 { 6022 if (oldtup != NULL) 6023 tuplestore_puttuple(fdw_tuplestore, oldtup); 6024 if (newtup != NULL) 6025 tuplestore_puttuple(fdw_tuplestore, newtup); 6026 } 6027 } 6028 6029 /* 6030 * Detect whether we already queued BEFORE STATEMENT triggers for the given 6031 * relation + operation, and set the flag so the next call will report "true". 6032 */ 6033 static bool 6034 before_stmt_triggers_fired(Oid relid, CmdType cmdType) 6035 { 6036 bool result; 6037 AfterTriggersTableData *table; 6038 6039 /* Check state, like AfterTriggerSaveEvent. */ 6040 if (afterTriggers.query_depth < 0) 6041 elog(ERROR, "before_stmt_triggers_fired() called outside of query"); 6042 6043 /* Be sure we have enough space to record events at this query depth. */ 6044 if (afterTriggers.query_depth >= afterTriggers.maxquerydepth) 6045 AfterTriggerEnlargeQueryState(); 6046 6047 /* 6048 * We keep this state in the AfterTriggersTableData that also holds 6049 * transition tables for the relation + operation. In this way, if we are 6050 * forced to make a new set of transition tables because more tuples get 6051 * entered after we've already fired triggers, we will allow a new set of 6052 * statement triggers to get queued. 6053 */ 6054 table = GetAfterTriggersTableData(relid, cmdType); 6055 result = table->before_trig_done; 6056 table->before_trig_done = true; 6057 return result; 6058 } 6059 6060 /* 6061 * If we previously queued a set of AFTER STATEMENT triggers for the given 6062 * relation + operation, and they've not been fired yet, cancel them. The 6063 * caller will queue a fresh set that's after any row-level triggers that may 6064 * have been queued by the current sub-statement, preserving (as much as 6065 * possible) the property that AFTER ROW triggers fire before AFTER STATEMENT 6066 * triggers, and that the latter only fire once. This deals with the 6067 * situation where several FK enforcement triggers sequentially queue triggers 6068 * for the same table into the same trigger query level. We can't fully 6069 * prevent odd behavior though: if there are AFTER ROW triggers taking 6070 * transition tables, we don't want to change the transition tables once the 6071 * first such trigger has seen them. In such a case, any additional events 6072 * will result in creating new transition tables and allowing new firings of 6073 * statement triggers. 6074 * 6075 * This also saves the current event list location so that a later invocation 6076 * of this function can cheaply find the triggers we're about to queue and 6077 * cancel them. 6078 */ 6079 static void 6080 cancel_prior_stmt_triggers(Oid relid, CmdType cmdType, int tgevent) 6081 { 6082 AfterTriggersTableData *table; 6083 AfterTriggersQueryData *qs = &afterTriggers.query_stack[afterTriggers.query_depth]; 6084 6085 /* 6086 * We keep this state in the AfterTriggersTableData that also holds 6087 * transition tables for the relation + operation. In this way, if we are 6088 * forced to make a new set of transition tables because more tuples get 6089 * entered after we've already fired triggers, we will allow a new set of 6090 * statement triggers to get queued without canceling the old ones. 6091 */ 6092 table = GetAfterTriggersTableData(relid, cmdType); 6093 6094 if (table->after_trig_done) 6095 { 6096 /* 6097 * We want to start scanning from the tail location that existed just 6098 * before we inserted any statement triggers. But the events list 6099 * might've been entirely empty then, in which case scan from the 6100 * current head. 6101 */ 6102 AfterTriggerEvent event; 6103 AfterTriggerEventChunk *chunk; 6104 6105 if (table->after_trig_events.tail) 6106 { 6107 chunk = table->after_trig_events.tail; 6108 event = (AfterTriggerEvent) table->after_trig_events.tailfree; 6109 } 6110 else 6111 { 6112 chunk = qs->events.head; 6113 event = NULL; 6114 } 6115 6116 for_each_chunk_from(chunk) 6117 { 6118 if (event == NULL) 6119 event = (AfterTriggerEvent) CHUNK_DATA_START(chunk); 6120 for_each_event_from(event, chunk) 6121 { 6122 AfterTriggerShared evtshared = GetTriggerSharedData(event); 6123 6124 /* 6125 * Exit loop when we reach events that aren't AS triggers for 6126 * the target relation. 6127 */ 6128 if (evtshared->ats_relid != relid) 6129 goto done; 6130 if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) != tgevent) 6131 goto done; 6132 if (!TRIGGER_FIRED_FOR_STATEMENT(evtshared->ats_event)) 6133 goto done; 6134 if (!TRIGGER_FIRED_AFTER(evtshared->ats_event)) 6135 goto done; 6136 /* OK, mark it DONE */ 6137 event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS; 6138 event->ate_flags |= AFTER_TRIGGER_DONE; 6139 } 6140 /* signal we must reinitialize event ptr for next chunk */ 6141 event = NULL; 6142 } 6143 } 6144 done: 6145 6146 /* In any case, save current insertion point for next time */ 6147 table->after_trig_done = true; 6148 table->after_trig_events = qs->events; 6149 } 6150 6151 /* 6152 * SQL function pg_trigger_depth() 6153 */ 6154 Datum 6155 pg_trigger_depth(PG_FUNCTION_ARGS) 6156 { 6157 PG_RETURN_INT32(MyTriggerDepth); 6158 } 6159