Header And Logo

PostgreSQL
| The world's most advanced open source database.

trigger.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * trigger.c
00004  *    PostgreSQL TRIGGERs support code.
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  * IDENTIFICATION
00010  *    src/backend/commands/trigger.c
00011  *
00012  *-------------------------------------------------------------------------
00013  */
00014 #include "postgres.h"
00015 
00016 #include "access/genam.h"
00017 #include "access/heapam.h"
00018 #include "access/sysattr.h"
00019 #include "access/htup_details.h"
00020 #include "access/xact.h"
00021 #include "catalog/catalog.h"
00022 #include "catalog/dependency.h"
00023 #include "catalog/indexing.h"
00024 #include "catalog/objectaccess.h"
00025 #include "catalog/pg_constraint.h"
00026 #include "catalog/pg_proc.h"
00027 #include "catalog/pg_trigger.h"
00028 #include "catalog/pg_type.h"
00029 #include "commands/dbcommands.h"
00030 #include "commands/defrem.h"
00031 #include "commands/trigger.h"
00032 #include "executor/executor.h"
00033 #include "miscadmin.h"
00034 #include "nodes/bitmapset.h"
00035 #include "nodes/makefuncs.h"
00036 #include "optimizer/clauses.h"
00037 #include "optimizer/var.h"
00038 #include "parser/parse_clause.h"
00039 #include "parser/parse_collate.h"
00040 #include "parser/parse_func.h"
00041 #include "parser/parse_relation.h"
00042 #include "parser/parsetree.h"
00043 #include "pgstat.h"
00044 #include "rewrite/rewriteManip.h"
00045 #include "storage/bufmgr.h"
00046 #include "tcop/utility.h"
00047 #include "utils/acl.h"
00048 #include "utils/builtins.h"
00049 #include "utils/bytea.h"
00050 #include "utils/fmgroids.h"
00051 #include "utils/inval.h"
00052 #include "utils/lsyscache.h"
00053 #include "utils/memutils.h"
00054 #include "utils/rel.h"
00055 #include "utils/snapmgr.h"
00056 #include "utils/syscache.h"
00057 #include "utils/tqual.h"
00058 
00059 
00060 /* GUC variables */
00061 int         SessionReplicationRole = SESSION_REPLICATION_ROLE_ORIGIN;
00062 
00063 /* How many levels deep into trigger execution are we? */
00064 static int  MyTriggerDepth = 0;
00065 
00066 #define GetModifiedColumns(relinfo, estate) \
00067     (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->modifiedCols)
00068 
00069 /* Local function prototypes */
00070 static void ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid);
00071 static void SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger);
00072 static HeapTuple GetTupleForTrigger(EState *estate,
00073                    EPQState *epqstate,
00074                    ResultRelInfo *relinfo,
00075                    ItemPointer tid,
00076                    LockTupleMode lockmode,
00077                    TupleTableSlot **newSlot);
00078 static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
00079                Trigger *trigger, TriggerEvent event,
00080                Bitmapset *modifiedCols,
00081                HeapTuple oldtup, HeapTuple newtup);
00082 static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
00083                     int tgindx,
00084                     FmgrInfo *finfo,
00085                     Instrumentation *instr,
00086                     MemoryContext per_tuple_context);
00087 static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
00088                       int event, bool row_trigger,
00089                       HeapTuple oldtup, HeapTuple newtup,
00090                       List *recheckIndexes, Bitmapset *modifiedCols);
00091 
00092 
00093 /*
00094  * Create a trigger.  Returns the OID of the created trigger.
00095  *
00096  * queryString is the source text of the CREATE TRIGGER command.
00097  * This must be supplied if a whenClause is specified, else it can be NULL.
00098  *
00099  * constraintOid, if nonzero, says that this trigger is being created
00100  * internally to implement that constraint.  A suitable pg_depend entry will
00101  * be made to link the trigger to that constraint.  constraintOid is zero when
00102  * executing a user-entered CREATE TRIGGER command.  (For CREATE CONSTRAINT
00103  * TRIGGER, we build a pg_constraint entry internally.)
00104  *
00105  * indexOid, if nonzero, is the OID of an index associated with the constraint.
00106  * We do nothing with this except store it into pg_trigger.tgconstrindid.
00107  *
00108  * If isInternal is true then this is an internally-generated trigger.
00109  * This argument sets the tgisinternal field of the pg_trigger entry, and
00110  * if TRUE causes us to modify the given trigger name to ensure uniqueness.
00111  *
00112  * When isInternal is not true we require ACL_TRIGGER permissions on the
00113  * relation, as well as ACL_EXECUTE on the trigger function.  For internal
00114  * triggers the caller must apply any required permission checks.
00115  *
00116  * Note: can return InvalidOid if we decided to not create a trigger at all,
00117  * but a foreign-key constraint.  This is a kluge for backwards compatibility.
00118  */
00119 Oid
00120 CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
00121               Oid constraintOid, Oid indexOid,
00122               bool isInternal)
00123 {
00124     int16       tgtype;
00125     int         ncolumns;
00126     int16      *columns;
00127     int2vector *tgattr;
00128     Node       *whenClause;
00129     List       *whenRtable;
00130     char       *qual;
00131     Datum       values[Natts_pg_trigger];
00132     bool        nulls[Natts_pg_trigger];
00133     Relation    rel;
00134     AclResult   aclresult;
00135     Relation    tgrel;
00136     SysScanDesc tgscan;
00137     ScanKeyData key;
00138     Relation    pgrel;
00139     HeapTuple   tuple;
00140     Oid         fargtypes[1];   /* dummy */
00141     Oid         funcoid;
00142     Oid         funcrettype;
00143     Oid         trigoid;
00144     char        internaltrigname[NAMEDATALEN];
00145     char       *trigname;
00146     Oid         constrrelid = InvalidOid;
00147     ObjectAddress myself,
00148                 referenced;
00149 
00150     rel = heap_openrv(stmt->relation, AccessExclusiveLock);
00151 
00152     /*
00153      * Triggers must be on tables or views, and there are additional
00154      * relation-type-specific restrictions.
00155      */
00156     if (rel->rd_rel->relkind == RELKIND_RELATION)
00157     {
00158         /* Tables can't have INSTEAD OF triggers */
00159         if (stmt->timing != TRIGGER_TYPE_BEFORE &&
00160             stmt->timing != TRIGGER_TYPE_AFTER)
00161             ereport(ERROR,
00162                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00163                      errmsg("\"%s\" is a table",
00164                             RelationGetRelationName(rel)),
00165                      errdetail("Tables cannot have INSTEAD OF triggers.")));
00166     }
00167     else if (rel->rd_rel->relkind == RELKIND_VIEW)
00168     {
00169         /*
00170          * Views can have INSTEAD OF triggers (which we check below are
00171          * row-level), or statement-level BEFORE/AFTER triggers.
00172          */
00173         if (stmt->timing != TRIGGER_TYPE_INSTEAD && stmt->row)
00174             ereport(ERROR,
00175                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00176                      errmsg("\"%s\" is a view",
00177                             RelationGetRelationName(rel)),
00178                      errdetail("Views cannot have row-level BEFORE or AFTER triggers.")));
00179         /* Disallow TRUNCATE triggers on VIEWs */
00180         if (TRIGGER_FOR_TRUNCATE(stmt->events))
00181             ereport(ERROR,
00182                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00183                      errmsg("\"%s\" is a view",
00184                             RelationGetRelationName(rel)),
00185                      errdetail("Views cannot have TRUNCATE triggers.")));
00186     }
00187     else
00188         ereport(ERROR,
00189                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00190                  errmsg("\"%s\" is not a table or view",
00191                         RelationGetRelationName(rel))));
00192 
00193     if (!allowSystemTableMods && IsSystemRelation(rel))
00194         ereport(ERROR,
00195                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00196                  errmsg("permission denied: \"%s\" is a system catalog",
00197                         RelationGetRelationName(rel))));
00198 
00199     if (stmt->isconstraint && stmt->constrrel != NULL)
00200     {
00201         /*
00202          * We must take a lock on the target relation to protect against
00203          * concurrent drop.  It's not clear that AccessShareLock is strong
00204          * enough, but we certainly need at least that much... otherwise, we
00205          * might end up creating a pg_constraint entry referencing a
00206          * nonexistent table.
00207          */
00208         constrrelid = RangeVarGetRelid(stmt->constrrel, AccessShareLock, false);
00209     }
00210 
00211     /* permission checks */
00212     if (!isInternal)
00213     {
00214         aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
00215                                       ACL_TRIGGER);
00216         if (aclresult != ACLCHECK_OK)
00217             aclcheck_error(aclresult, ACL_KIND_CLASS,
00218                            RelationGetRelationName(rel));
00219 
00220         if (OidIsValid(constrrelid))
00221         {
00222             aclresult = pg_class_aclcheck(constrrelid, GetUserId(),
00223                                           ACL_TRIGGER);
00224             if (aclresult != ACLCHECK_OK)
00225                 aclcheck_error(aclresult, ACL_KIND_CLASS,
00226                                get_rel_name(constrrelid));
00227         }
00228     }
00229 
00230     /* Compute tgtype */
00231     TRIGGER_CLEAR_TYPE(tgtype);
00232     if (stmt->row)
00233         TRIGGER_SETT_ROW(tgtype);
00234     tgtype |= stmt->timing;
00235     tgtype |= stmt->events;
00236 
00237     /* Disallow ROW-level TRUNCATE triggers */
00238     if (TRIGGER_FOR_ROW(tgtype) && TRIGGER_FOR_TRUNCATE(tgtype))
00239         ereport(ERROR,
00240                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00241                  errmsg("TRUNCATE FOR EACH ROW triggers are not supported")));
00242 
00243     /* INSTEAD triggers must be row-level, and can't have WHEN or columns */
00244     if (TRIGGER_FOR_INSTEAD(tgtype))
00245     {
00246         if (!TRIGGER_FOR_ROW(tgtype))
00247             ereport(ERROR,
00248                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00249                      errmsg("INSTEAD OF triggers must be FOR EACH ROW")));
00250         if (stmt->whenClause)
00251             ereport(ERROR,
00252                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00253                  errmsg("INSTEAD OF triggers cannot have WHEN conditions")));
00254         if (stmt->columns != NIL)
00255             ereport(ERROR,
00256                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00257                      errmsg("INSTEAD OF triggers cannot have column lists")));
00258     }
00259 
00260     /*
00261      * Parse the WHEN clause, if any
00262      */
00263     if (stmt->whenClause)
00264     {
00265         ParseState *pstate;
00266         RangeTblEntry *rte;
00267         List       *varList;
00268         ListCell   *lc;
00269 
00270         /* Set up a pstate to parse with */
00271         pstate = make_parsestate(NULL);
00272         pstate->p_sourcetext = queryString;
00273 
00274         /*
00275          * Set up RTEs for OLD and NEW references.
00276          *
00277          * 'OLD' must always have varno equal to 1 and 'NEW' equal to 2.
00278          */
00279         rte = addRangeTableEntryForRelation(pstate, rel,
00280                                             makeAlias("old", NIL),
00281                                             false, false);
00282         addRTEtoQuery(pstate, rte, false, true, true);
00283         rte = addRangeTableEntryForRelation(pstate, rel,
00284                                             makeAlias("new", NIL),
00285                                             false, false);
00286         addRTEtoQuery(pstate, rte, false, true, true);
00287 
00288         /* Transform expression.  Copy to be sure we don't modify original */
00289         whenClause = transformWhereClause(pstate,
00290                                           copyObject(stmt->whenClause),
00291                                           EXPR_KIND_TRIGGER_WHEN,
00292                                           "WHEN");
00293         /* we have to fix its collations too */
00294         assign_expr_collations(pstate, whenClause);
00295 
00296         /*
00297          * Check for disallowed references to OLD/NEW.
00298          *
00299          * NB: pull_var_clause is okay here only because we don't allow
00300          * subselects in WHEN clauses; it would fail to examine the contents
00301          * of subselects.
00302          */
00303         varList = pull_var_clause(whenClause,
00304                                   PVC_REJECT_AGGREGATES,
00305                                   PVC_REJECT_PLACEHOLDERS);
00306         foreach(lc, varList)
00307         {
00308             Var        *var = (Var *) lfirst(lc);
00309 
00310             switch (var->varno)
00311             {
00312                 case PRS2_OLD_VARNO:
00313                     if (!TRIGGER_FOR_ROW(tgtype))
00314                         ereport(ERROR,
00315                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00316                                  errmsg("statement trigger's WHEN condition cannot reference column values"),
00317                                  parser_errposition(pstate, var->location)));
00318                     if (TRIGGER_FOR_INSERT(tgtype))
00319                         ereport(ERROR,
00320                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00321                                  errmsg("INSERT trigger's WHEN condition cannot reference OLD values"),
00322                                  parser_errposition(pstate, var->location)));
00323                     /* system columns are okay here */
00324                     break;
00325                 case PRS2_NEW_VARNO:
00326                     if (!TRIGGER_FOR_ROW(tgtype))
00327                         ereport(ERROR,
00328                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00329                                  errmsg("statement trigger's WHEN condition cannot reference column values"),
00330                                  parser_errposition(pstate, var->location)));
00331                     if (TRIGGER_FOR_DELETE(tgtype))
00332                         ereport(ERROR,
00333                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00334                                  errmsg("DELETE trigger's WHEN condition cannot reference NEW values"),
00335                                  parser_errposition(pstate, var->location)));
00336                     if (var->varattno < 0 && TRIGGER_FOR_BEFORE(tgtype))
00337                         ereport(ERROR,
00338                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00339                                  errmsg("BEFORE trigger's WHEN condition cannot reference NEW system columns"),
00340                                  parser_errposition(pstate, var->location)));
00341                     break;
00342                 default:
00343                     /* can't happen without add_missing_from, so just elog */
00344                     elog(ERROR, "trigger WHEN condition cannot contain references to other relations");
00345                     break;
00346             }
00347         }
00348 
00349         /* we'll need the rtable for recordDependencyOnExpr */
00350         whenRtable = pstate->p_rtable;
00351 
00352         qual = nodeToString(whenClause);
00353 
00354         free_parsestate(pstate);
00355     }
00356     else
00357     {
00358         whenClause = NULL;
00359         whenRtable = NIL;
00360         qual = NULL;
00361     }
00362 
00363     /*
00364      * Find and validate the trigger function.
00365      */
00366     funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
00367     if (!isInternal)
00368     {
00369         aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
00370         if (aclresult != ACLCHECK_OK)
00371             aclcheck_error(aclresult, ACL_KIND_PROC,
00372                            NameListToString(stmt->funcname));
00373     }
00374     funcrettype = get_func_rettype(funcoid);
00375     if (funcrettype != TRIGGEROID)
00376     {
00377         /*
00378          * We allow OPAQUE just so we can load old dump files.  When we see a
00379          * trigger function declared OPAQUE, change it to TRIGGER.
00380          */
00381         if (funcrettype == OPAQUEOID)
00382         {
00383             ereport(WARNING,
00384                     (errmsg("changing return type of function %s from \"opaque\" to \"trigger\"",
00385                             NameListToString(stmt->funcname))));
00386             SetFunctionReturnType(funcoid, TRIGGEROID);
00387         }
00388         else
00389             ereport(ERROR,
00390                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00391                      errmsg("function %s must return type \"trigger\"",
00392                             NameListToString(stmt->funcname))));
00393     }
00394 
00395     /*
00396      * If the command is a user-entered CREATE CONSTRAINT TRIGGER command that
00397      * references one of the built-in RI_FKey trigger functions, assume it is
00398      * from a dump of a pre-7.3 foreign key constraint, and take steps to
00399      * convert this legacy representation into a regular foreign key
00400      * constraint.  Ugly, but necessary for loading old dump files.
00401      */
00402     if (stmt->isconstraint && !isInternal &&
00403         list_length(stmt->args) >= 6 &&
00404         (list_length(stmt->args) % 2) == 0 &&
00405         RI_FKey_trigger_type(funcoid) != RI_TRIGGER_NONE)
00406     {
00407         /* Keep lock on target rel until end of xact */
00408         heap_close(rel, NoLock);
00409 
00410         ConvertTriggerToFK(stmt, funcoid);
00411 
00412         return InvalidOid;
00413     }
00414 
00415     /*
00416      * If it's a user-entered CREATE CONSTRAINT TRIGGER command, make a
00417      * corresponding pg_constraint entry.
00418      */
00419     if (stmt->isconstraint && !OidIsValid(constraintOid))
00420     {
00421         /* Internal callers should have made their own constraints */
00422         Assert(!isInternal);
00423         constraintOid = CreateConstraintEntry(stmt->trigname,
00424                                               RelationGetNamespace(rel),
00425                                               CONSTRAINT_TRIGGER,
00426                                               stmt->deferrable,
00427                                               stmt->initdeferred,
00428                                               true,
00429                                               RelationGetRelid(rel),
00430                                               NULL,     /* no conkey */
00431                                               0,
00432                                               InvalidOid,       /* no domain */
00433                                               InvalidOid,       /* no index */
00434                                               InvalidOid,       /* no foreign key */
00435                                               NULL,
00436                                               NULL,
00437                                               NULL,
00438                                               NULL,
00439                                               0,
00440                                               ' ',
00441                                               ' ',
00442                                               ' ',
00443                                               NULL,     /* no exclusion */
00444                                               NULL,     /* no check constraint */
00445                                               NULL,
00446                                               NULL,
00447                                               true,     /* islocal */
00448                                               0,        /* inhcount */
00449                                               true,     /* isnoinherit */
00450                                               isInternal);  /* is_internal */
00451     }
00452 
00453     /*
00454      * Generate the trigger's OID now, so that we can use it in the name if
00455      * needed.
00456      */
00457     tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
00458 
00459     trigoid = GetNewOid(tgrel);
00460 
00461     /*
00462      * If trigger is internally generated, modify the provided trigger name to
00463      * ensure uniqueness by appending the trigger OID.  (Callers will usually
00464      * supply a simple constant trigger name in these cases.)
00465      */
00466     if (isInternal)
00467     {
00468         snprintf(internaltrigname, sizeof(internaltrigname),
00469                  "%s_%u", stmt->trigname, trigoid);
00470         trigname = internaltrigname;
00471     }
00472     else
00473     {
00474         /* user-defined trigger; use the specified trigger name as-is */
00475         trigname = stmt->trigname;
00476     }
00477 
00478     /*
00479      * Scan pg_trigger for existing triggers on relation.  We do this only to
00480      * give a nice error message if there's already a trigger of the same
00481      * name.  (The unique index on tgrelid/tgname would complain anyway.) We
00482      * can skip this for internally generated triggers, since the name
00483      * modification above should be sufficient.
00484      *
00485      * NOTE that this is cool only because we have AccessExclusiveLock on the
00486      * relation, so the trigger set won't be changing underneath us.
00487      */
00488     if (!isInternal)
00489     {
00490         ScanKeyInit(&key,
00491                     Anum_pg_trigger_tgrelid,
00492                     BTEqualStrategyNumber, F_OIDEQ,
00493                     ObjectIdGetDatum(RelationGetRelid(rel)));
00494         tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
00495                                     SnapshotNow, 1, &key);
00496         while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
00497         {
00498             Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
00499 
00500             if (namestrcmp(&(pg_trigger->tgname), trigname) == 0)
00501                 ereport(ERROR,
00502                         (errcode(ERRCODE_DUPLICATE_OBJECT),
00503                   errmsg("trigger \"%s\" for relation \"%s\" already exists",
00504                          trigname, stmt->relation->relname)));
00505         }
00506         systable_endscan(tgscan);
00507     }
00508 
00509     /*
00510      * Build the new pg_trigger tuple.
00511      */
00512     memset(nulls, false, sizeof(nulls));
00513 
00514     values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
00515     values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein,
00516                                                   CStringGetDatum(trigname));
00517     values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
00518     values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
00519     values[Anum_pg_trigger_tgenabled - 1] = CharGetDatum(TRIGGER_FIRES_ON_ORIGIN);
00520     values[Anum_pg_trigger_tgisinternal - 1] = BoolGetDatum(isInternal);
00521     values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid);
00522     values[Anum_pg_trigger_tgconstrindid - 1] = ObjectIdGetDatum(indexOid);
00523     values[Anum_pg_trigger_tgconstraint - 1] = ObjectIdGetDatum(constraintOid);
00524     values[Anum_pg_trigger_tgdeferrable - 1] = BoolGetDatum(stmt->deferrable);
00525     values[Anum_pg_trigger_tginitdeferred - 1] = BoolGetDatum(stmt->initdeferred);
00526 
00527     if (stmt->args)
00528     {
00529         ListCell   *le;
00530         char       *args;
00531         int16       nargs = list_length(stmt->args);
00532         int         len = 0;
00533 
00534         foreach(le, stmt->args)
00535         {
00536             char       *ar = strVal(lfirst(le));
00537 
00538             len += strlen(ar) + 4;
00539             for (; *ar; ar++)
00540             {
00541                 if (*ar == '\\')
00542                     len++;
00543             }
00544         }
00545         args = (char *) palloc(len + 1);
00546         args[0] = '\0';
00547         foreach(le, stmt->args)
00548         {
00549             char       *s = strVal(lfirst(le));
00550             char       *d = args + strlen(args);
00551 
00552             while (*s)
00553             {
00554                 if (*s == '\\')
00555                     *d++ = '\\';
00556                 *d++ = *s++;
00557             }
00558             strcpy(d, "\\000");
00559         }
00560         values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);
00561         values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
00562                                                       CStringGetDatum(args));
00563     }
00564     else
00565     {
00566         values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0);
00567         values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
00568                                                         CStringGetDatum(""));
00569     }
00570 
00571     /* build column number array if it's a column-specific trigger */
00572     ncolumns = list_length(stmt->columns);
00573     if (ncolumns == 0)
00574         columns = NULL;
00575     else
00576     {
00577         ListCell   *cell;
00578         int         i = 0;
00579 
00580         columns = (int16 *) palloc(ncolumns * sizeof(int16));
00581         foreach(cell, stmt->columns)
00582         {
00583             char       *name = strVal(lfirst(cell));
00584             int16       attnum;
00585             int         j;
00586 
00587             /* Lookup column name.  System columns are not allowed */
00588             attnum = attnameAttNum(rel, name, false);
00589             if (attnum == InvalidAttrNumber)
00590                 ereport(ERROR,
00591                         (errcode(ERRCODE_UNDEFINED_COLUMN),
00592                     errmsg("column \"%s\" of relation \"%s\" does not exist",
00593                            name, RelationGetRelationName(rel))));
00594 
00595             /* Check for duplicates */
00596             for (j = i - 1; j >= 0; j--)
00597             {
00598                 if (columns[j] == attnum)
00599                     ereport(ERROR,
00600                             (errcode(ERRCODE_DUPLICATE_COLUMN),
00601                              errmsg("column \"%s\" specified more than once",
00602                                     name)));
00603             }
00604 
00605             columns[i++] = attnum;
00606         }
00607     }
00608     tgattr = buildint2vector(columns, ncolumns);
00609     values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
00610 
00611     /* set tgqual if trigger has WHEN clause */
00612     if (qual)
00613         values[Anum_pg_trigger_tgqual - 1] = CStringGetTextDatum(qual);
00614     else
00615         nulls[Anum_pg_trigger_tgqual - 1] = true;
00616 
00617     tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
00618 
00619     /* force tuple to have the desired OID */
00620     HeapTupleSetOid(tuple, trigoid);
00621 
00622     /*
00623      * Insert tuple into pg_trigger.
00624      */
00625     simple_heap_insert(tgrel, tuple);
00626 
00627     CatalogUpdateIndexes(tgrel, tuple);
00628 
00629     heap_freetuple(tuple);
00630     heap_close(tgrel, RowExclusiveLock);
00631 
00632     pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
00633     pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
00634     pfree(DatumGetPointer(values[Anum_pg_trigger_tgattr - 1]));
00635 
00636     /*
00637      * Update relation's pg_class entry.  Crucial side-effect: other backends
00638      * (and this one too!) are sent SI message to make them rebuild relcache
00639      * entries.
00640      */
00641     pgrel = heap_open(RelationRelationId, RowExclusiveLock);
00642     tuple = SearchSysCacheCopy1(RELOID,
00643                                 ObjectIdGetDatum(RelationGetRelid(rel)));
00644     if (!HeapTupleIsValid(tuple))
00645         elog(ERROR, "cache lookup failed for relation %u",
00646              RelationGetRelid(rel));
00647 
00648     ((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true;
00649 
00650     simple_heap_update(pgrel, &tuple->t_self, tuple);
00651 
00652     CatalogUpdateIndexes(pgrel, tuple);
00653 
00654     heap_freetuple(tuple);
00655     heap_close(pgrel, RowExclusiveLock);
00656 
00657     /*
00658      * We used to try to update the rel's relcache entry here, but that's
00659      * fairly pointless since it will happen as a byproduct of the upcoming
00660      * CommandCounterIncrement...
00661      */
00662 
00663     /*
00664      * Record dependencies for trigger.  Always place a normal dependency on
00665      * the function.
00666      */
00667     myself.classId = TriggerRelationId;
00668     myself.objectId = trigoid;
00669     myself.objectSubId = 0;
00670 
00671     referenced.classId = ProcedureRelationId;
00672     referenced.objectId = funcoid;
00673     referenced.objectSubId = 0;
00674     recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00675 
00676     if (isInternal && OidIsValid(constraintOid))
00677     {
00678         /*
00679          * Internally-generated trigger for a constraint, so make it an
00680          * internal dependency of the constraint.  We can skip depending on
00681          * the relation(s), as there'll be an indirect dependency via the
00682          * constraint.
00683          */
00684         referenced.classId = ConstraintRelationId;
00685         referenced.objectId = constraintOid;
00686         referenced.objectSubId = 0;
00687         recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
00688     }
00689     else
00690     {
00691         /*
00692          * User CREATE TRIGGER, so place dependencies.  We make trigger be
00693          * auto-dropped if its relation is dropped or if the FK relation is
00694          * dropped.  (Auto drop is compatible with our pre-7.3 behavior.)
00695          */
00696         referenced.classId = RelationRelationId;
00697         referenced.objectId = RelationGetRelid(rel);
00698         referenced.objectSubId = 0;
00699         recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
00700         if (OidIsValid(constrrelid))
00701         {
00702             referenced.classId = RelationRelationId;
00703             referenced.objectId = constrrelid;
00704             referenced.objectSubId = 0;
00705             recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
00706         }
00707         /* Not possible to have an index dependency in this case */
00708         Assert(!OidIsValid(indexOid));
00709 
00710         /*
00711          * If it's a user-specified constraint trigger, make the constraint
00712          * internally dependent on the trigger instead of vice versa.
00713          */
00714         if (OidIsValid(constraintOid))
00715         {
00716             referenced.classId = ConstraintRelationId;
00717             referenced.objectId = constraintOid;
00718             referenced.objectSubId = 0;
00719             recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
00720         }
00721     }
00722 
00723     /* If column-specific trigger, add normal dependencies on columns */
00724     if (columns != NULL)
00725     {
00726         int         i;
00727 
00728         referenced.classId = RelationRelationId;
00729         referenced.objectId = RelationGetRelid(rel);
00730         for (i = 0; i < ncolumns; i++)
00731         {
00732             referenced.objectSubId = columns[i];
00733             recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00734         }
00735     }
00736 
00737     /*
00738      * If it has a WHEN clause, add dependencies on objects mentioned in the
00739      * expression (eg, functions, as well as any columns used).
00740      */
00741     if (whenClause != NULL)
00742         recordDependencyOnExpr(&myself, whenClause, whenRtable,
00743                                DEPENDENCY_NORMAL);
00744 
00745     /* Post creation hook for new trigger */
00746     InvokeObjectPostCreateHookArg(TriggerRelationId, trigoid, 0,
00747                                   isInternal);
00748 
00749     /* Keep lock on target rel until end of xact */
00750     heap_close(rel, NoLock);
00751 
00752     return trigoid;
00753 }
00754 
00755 
00756 /*
00757  * Convert legacy (pre-7.3) CREATE CONSTRAINT TRIGGER commands into
00758  * full-fledged foreign key constraints.
00759  *
00760  * The conversion is complex because a pre-7.3 foreign key involved three
00761  * separate triggers, which were reported separately in dumps.  While the
00762  * single trigger on the referencing table adds no new information, we need
00763  * to know the trigger functions of both of the triggers on the referenced
00764  * table to build the constraint declaration.  Also, due to lack of proper
00765  * dependency checking pre-7.3, it is possible that the source database had
00766  * an incomplete set of triggers resulting in an only partially enforced
00767  * FK constraint.  (This would happen if one of the tables had been dropped
00768  * and re-created, but only if the DB had been affected by a 7.0 pg_dump bug
00769  * that caused loss of tgconstrrelid information.)  We choose to translate to
00770  * an FK constraint only when we've seen all three triggers of a set.  This is
00771  * implemented by storing unmatched items in a list in TopMemoryContext.
00772  * We match triggers together by comparing the trigger arguments (which
00773  * include constraint name, table and column names, so should be good enough).
00774  */
00775 typedef struct
00776 {
00777     List       *args;           /* list of (T_String) Values or NIL */
00778     Oid         funcoids[3];    /* OIDs of trigger functions */
00779     /* The three function OIDs are stored in the order update, delete, child */
00780 } OldTriggerInfo;
00781 
00782 static void
00783 ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
00784 {
00785     static List *info_list = NIL;
00786 
00787     static const char *const funcdescr[3] = {
00788         gettext_noop("Found referenced table's UPDATE trigger."),
00789         gettext_noop("Found referenced table's DELETE trigger."),
00790         gettext_noop("Found referencing table's trigger.")
00791     };
00792 
00793     char       *constr_name;
00794     char       *fk_table_name;
00795     char       *pk_table_name;
00796     char        fk_matchtype = FKCONSTR_MATCH_SIMPLE;
00797     List       *fk_attrs = NIL;
00798     List       *pk_attrs = NIL;
00799     StringInfoData buf;
00800     int         funcnum;
00801     OldTriggerInfo *info = NULL;
00802     ListCell   *l;
00803     int         i;
00804 
00805     /* Parse out the trigger arguments */
00806     constr_name = strVal(linitial(stmt->args));
00807     fk_table_name = strVal(lsecond(stmt->args));
00808     pk_table_name = strVal(lthird(stmt->args));
00809     i = 0;
00810     foreach(l, stmt->args)
00811     {
00812         Value      *arg = (Value *) lfirst(l);
00813 
00814         i++;
00815         if (i < 4)              /* skip constraint and table names */
00816             continue;
00817         if (i == 4)             /* handle match type */
00818         {
00819             if (strcmp(strVal(arg), "FULL") == 0)
00820                 fk_matchtype = FKCONSTR_MATCH_FULL;
00821             else
00822                 fk_matchtype = FKCONSTR_MATCH_SIMPLE;
00823             continue;
00824         }
00825         if (i % 2)
00826             fk_attrs = lappend(fk_attrs, arg);
00827         else
00828             pk_attrs = lappend(pk_attrs, arg);
00829     }
00830 
00831     /* Prepare description of constraint for use in messages */
00832     initStringInfo(&buf);
00833     appendStringInfo(&buf, "FOREIGN KEY %s(",
00834                      quote_identifier(fk_table_name));
00835     i = 0;
00836     foreach(l, fk_attrs)
00837     {
00838         Value      *arg = (Value *) lfirst(l);
00839 
00840         if (i++ > 0)
00841             appendStringInfoChar(&buf, ',');
00842         appendStringInfoString(&buf, quote_identifier(strVal(arg)));
00843     }
00844     appendStringInfo(&buf, ") REFERENCES %s(",
00845                      quote_identifier(pk_table_name));
00846     i = 0;
00847     foreach(l, pk_attrs)
00848     {
00849         Value      *arg = (Value *) lfirst(l);
00850 
00851         if (i++ > 0)
00852             appendStringInfoChar(&buf, ',');
00853         appendStringInfoString(&buf, quote_identifier(strVal(arg)));
00854     }
00855     appendStringInfoChar(&buf, ')');
00856 
00857     /* Identify class of trigger --- update, delete, or referencing-table */
00858     switch (funcoid)
00859     {
00860         case F_RI_FKEY_CASCADE_UPD:
00861         case F_RI_FKEY_RESTRICT_UPD:
00862         case F_RI_FKEY_SETNULL_UPD:
00863         case F_RI_FKEY_SETDEFAULT_UPD:
00864         case F_RI_FKEY_NOACTION_UPD:
00865             funcnum = 0;
00866             break;
00867 
00868         case F_RI_FKEY_CASCADE_DEL:
00869         case F_RI_FKEY_RESTRICT_DEL:
00870         case F_RI_FKEY_SETNULL_DEL:
00871         case F_RI_FKEY_SETDEFAULT_DEL:
00872         case F_RI_FKEY_NOACTION_DEL:
00873             funcnum = 1;
00874             break;
00875 
00876         default:
00877             funcnum = 2;
00878             break;
00879     }
00880 
00881     /* See if we have a match to this trigger */
00882     foreach(l, info_list)
00883     {
00884         info = (OldTriggerInfo *) lfirst(l);
00885         if (info->funcoids[funcnum] == InvalidOid &&
00886             equal(info->args, stmt->args))
00887         {
00888             info->funcoids[funcnum] = funcoid;
00889             break;
00890         }
00891     }
00892 
00893     if (l == NULL)
00894     {
00895         /* First trigger of set, so create a new list entry */
00896         MemoryContext oldContext;
00897 
00898         ereport(NOTICE,
00899         (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
00900                 constr_name, buf.data),
00901          errdetail_internal("%s", _(funcdescr[funcnum]))));
00902         oldContext = MemoryContextSwitchTo(TopMemoryContext);
00903         info = (OldTriggerInfo *) palloc0(sizeof(OldTriggerInfo));
00904         info->args = copyObject(stmt->args);
00905         info->funcoids[funcnum] = funcoid;
00906         info_list = lappend(info_list, info);
00907         MemoryContextSwitchTo(oldContext);
00908     }
00909     else if (info->funcoids[0] == InvalidOid ||
00910              info->funcoids[1] == InvalidOid ||
00911              info->funcoids[2] == InvalidOid)
00912     {
00913         /* Second trigger of set */
00914         ereport(NOTICE,
00915         (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
00916                 constr_name, buf.data),
00917          errdetail_internal("%s", _(funcdescr[funcnum]))));
00918     }
00919     else
00920     {
00921         /* OK, we have a set, so make the FK constraint ALTER TABLE cmd */
00922         AlterTableStmt *atstmt = makeNode(AlterTableStmt);
00923         AlterTableCmd *atcmd = makeNode(AlterTableCmd);
00924         Constraint *fkcon = makeNode(Constraint);
00925 
00926         ereport(NOTICE,
00927                 (errmsg("converting trigger group into constraint \"%s\" %s",
00928                         constr_name, buf.data),
00929                  errdetail_internal("%s", _(funcdescr[funcnum]))));
00930         fkcon->contype = CONSTR_FOREIGN;
00931         fkcon->location = -1;
00932         if (funcnum == 2)
00933         {
00934             /* This trigger is on the FK table */
00935             atstmt->relation = stmt->relation;
00936             if (stmt->constrrel)
00937                 fkcon->pktable = stmt->constrrel;
00938             else
00939             {
00940                 /* Work around ancient pg_dump bug that omitted constrrel */
00941                 fkcon->pktable = makeRangeVar(NULL, pk_table_name, -1);
00942             }
00943         }
00944         else
00945         {
00946             /* This trigger is on the PK table */
00947             fkcon->pktable = stmt->relation;
00948             if (stmt->constrrel)
00949                 atstmt->relation = stmt->constrrel;
00950             else
00951             {
00952                 /* Work around ancient pg_dump bug that omitted constrrel */
00953                 atstmt->relation = makeRangeVar(NULL, fk_table_name, -1);
00954             }
00955         }
00956         atstmt->cmds = list_make1(atcmd);
00957         atstmt->relkind = OBJECT_TABLE;
00958         atcmd->subtype = AT_AddConstraint;
00959         atcmd->def = (Node *) fkcon;
00960         if (strcmp(constr_name, "<unnamed>") == 0)
00961             fkcon->conname = NULL;
00962         else
00963             fkcon->conname = constr_name;
00964         fkcon->fk_attrs = fk_attrs;
00965         fkcon->pk_attrs = pk_attrs;
00966         fkcon->fk_matchtype = fk_matchtype;
00967         switch (info->funcoids[0])
00968         {
00969             case F_RI_FKEY_NOACTION_UPD:
00970                 fkcon->fk_upd_action = FKCONSTR_ACTION_NOACTION;
00971                 break;
00972             case F_RI_FKEY_CASCADE_UPD:
00973                 fkcon->fk_upd_action = FKCONSTR_ACTION_CASCADE;
00974                 break;
00975             case F_RI_FKEY_RESTRICT_UPD:
00976                 fkcon->fk_upd_action = FKCONSTR_ACTION_RESTRICT;
00977                 break;
00978             case F_RI_FKEY_SETNULL_UPD:
00979                 fkcon->fk_upd_action = FKCONSTR_ACTION_SETNULL;
00980                 break;
00981             case F_RI_FKEY_SETDEFAULT_UPD:
00982                 fkcon->fk_upd_action = FKCONSTR_ACTION_SETDEFAULT;
00983                 break;
00984             default:
00985                 /* can't get here because of earlier checks */
00986                 elog(ERROR, "confused about RI update function");
00987         }
00988         switch (info->funcoids[1])
00989         {
00990             case F_RI_FKEY_NOACTION_DEL:
00991                 fkcon->fk_del_action = FKCONSTR_ACTION_NOACTION;
00992                 break;
00993             case F_RI_FKEY_CASCADE_DEL:
00994                 fkcon->fk_del_action = FKCONSTR_ACTION_CASCADE;
00995                 break;
00996             case F_RI_FKEY_RESTRICT_DEL:
00997                 fkcon->fk_del_action = FKCONSTR_ACTION_RESTRICT;
00998                 break;
00999             case F_RI_FKEY_SETNULL_DEL:
01000                 fkcon->fk_del_action = FKCONSTR_ACTION_SETNULL;
01001                 break;
01002             case F_RI_FKEY_SETDEFAULT_DEL:
01003                 fkcon->fk_del_action = FKCONSTR_ACTION_SETDEFAULT;
01004                 break;
01005             default:
01006                 /* can't get here because of earlier checks */
01007                 elog(ERROR, "confused about RI delete function");
01008         }
01009         fkcon->deferrable = stmt->deferrable;
01010         fkcon->initdeferred = stmt->initdeferred;
01011         fkcon->skip_validation = false;
01012         fkcon->initially_valid = true;
01013 
01014         /* ... and execute it */
01015         ProcessUtility((Node *) atstmt,
01016                        "(generated ALTER TABLE ADD FOREIGN KEY command)",
01017                        PROCESS_UTILITY_SUBCOMMAND, NULL,
01018                        None_Receiver, NULL);
01019 
01020         /* Remove the matched item from the list */
01021         info_list = list_delete_ptr(info_list, info);
01022         pfree(info);
01023         /* We leak the copied args ... not worth worrying about */
01024     }
01025 }
01026 
01027 /*
01028  * Guts of trigger deletion.
01029  */
01030 void
01031 RemoveTriggerById(Oid trigOid)
01032 {
01033     Relation    tgrel;
01034     SysScanDesc tgscan;
01035     ScanKeyData skey[1];
01036     HeapTuple   tup;
01037     Oid         relid;
01038     Relation    rel;
01039 
01040     tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
01041 
01042     /*
01043      * Find the trigger to delete.
01044      */
01045     ScanKeyInit(&skey[0],
01046                 ObjectIdAttributeNumber,
01047                 BTEqualStrategyNumber, F_OIDEQ,
01048                 ObjectIdGetDatum(trigOid));
01049 
01050     tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
01051                                 SnapshotNow, 1, skey);
01052 
01053     tup = systable_getnext(tgscan);
01054     if (!HeapTupleIsValid(tup))
01055         elog(ERROR, "could not find tuple for trigger %u", trigOid);
01056 
01057     /*
01058      * Open and exclusive-lock the relation the trigger belongs to.
01059      */
01060     relid = ((Form_pg_trigger) GETSTRUCT(tup))->tgrelid;
01061 
01062     rel = heap_open(relid, AccessExclusiveLock);
01063 
01064     if (rel->rd_rel->relkind != RELKIND_RELATION &&
01065         rel->rd_rel->relkind != RELKIND_VIEW)
01066         ereport(ERROR,
01067                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01068                  errmsg("\"%s\" is not a table or view",
01069                         RelationGetRelationName(rel))));
01070 
01071     if (!allowSystemTableMods && IsSystemRelation(rel))
01072         ereport(ERROR,
01073                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01074                  errmsg("permission denied: \"%s\" is a system catalog",
01075                         RelationGetRelationName(rel))));
01076 
01077     /*
01078      * Delete the pg_trigger tuple.
01079      */
01080     simple_heap_delete(tgrel, &tup->t_self);
01081 
01082     systable_endscan(tgscan);
01083     heap_close(tgrel, RowExclusiveLock);
01084 
01085     /*
01086      * We do not bother to try to determine whether any other triggers remain,
01087      * which would be needed in order to decide whether it's safe to clear the
01088      * relation's relhastriggers.  (In any case, there might be a concurrent
01089      * process adding new triggers.)  Instead, just force a relcache inval to
01090      * make other backends (and this one too!) rebuild their relcache entries.
01091      * There's no great harm in leaving relhastriggers true even if there are
01092      * no triggers left.
01093      */
01094     CacheInvalidateRelcache(rel);
01095 
01096     /* Keep lock on trigger's rel until end of xact */
01097     heap_close(rel, NoLock);
01098 }
01099 
01100 /*
01101  * get_trigger_oid - Look up a trigger by name to find its OID.
01102  *
01103  * If missing_ok is false, throw an error if trigger not found.  If
01104  * true, just return InvalidOid.
01105  */
01106 Oid
01107 get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
01108 {
01109     Relation    tgrel;
01110     ScanKeyData skey[2];
01111     SysScanDesc tgscan;
01112     HeapTuple   tup;
01113     Oid         oid;
01114 
01115     /*
01116      * Find the trigger, verify permissions, set up object address
01117      */
01118     tgrel = heap_open(TriggerRelationId, AccessShareLock);
01119 
01120     ScanKeyInit(&skey[0],
01121                 Anum_pg_trigger_tgrelid,
01122                 BTEqualStrategyNumber, F_OIDEQ,
01123                 ObjectIdGetDatum(relid));
01124     ScanKeyInit(&skey[1],
01125                 Anum_pg_trigger_tgname,
01126                 BTEqualStrategyNumber, F_NAMEEQ,
01127                 CStringGetDatum(trigname));
01128 
01129     tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
01130                                 SnapshotNow, 2, skey);
01131 
01132     tup = systable_getnext(tgscan);
01133 
01134     if (!HeapTupleIsValid(tup))
01135     {
01136         if (!missing_ok)
01137             ereport(ERROR,
01138                     (errcode(ERRCODE_UNDEFINED_OBJECT),
01139                      errmsg("trigger \"%s\" for table \"%s\" does not exist",
01140                             trigname, get_rel_name(relid))));
01141         oid = InvalidOid;
01142     }
01143     else
01144     {
01145         oid = HeapTupleGetOid(tup);
01146     }
01147 
01148     systable_endscan(tgscan);
01149     heap_close(tgrel, AccessShareLock);
01150     return oid;
01151 }
01152 
01153 /*
01154  * Perform permissions and integrity checks before acquiring a relation lock.
01155  */
01156 static void
01157 RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid,
01158                                  void *arg)
01159 {
01160     HeapTuple   tuple;
01161     Form_pg_class form;
01162 
01163     tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
01164     if (!HeapTupleIsValid(tuple))
01165         return;                 /* concurrently dropped */
01166     form = (Form_pg_class) GETSTRUCT(tuple);
01167 
01168     /* only tables and views can have triggers */
01169     if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW)
01170         ereport(ERROR,
01171                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01172                  errmsg("\"%s\" is not a table or view", rv->relname)));
01173 
01174     /* you must own the table to rename one of its triggers */
01175     if (!pg_class_ownercheck(relid, GetUserId()))
01176         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, rv->relname);
01177     if (!allowSystemTableMods && IsSystemClass(form))
01178         ereport(ERROR,
01179                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01180                  errmsg("permission denied: \"%s\" is a system catalog",
01181                         rv->relname)));
01182 
01183     ReleaseSysCache(tuple);
01184 }
01185 
01186 /*
01187  *      renametrig      - changes the name of a trigger on a relation
01188  *
01189  *      trigger name is changed in trigger catalog.
01190  *      No record of the previous name is kept.
01191  *
01192  *      get proper relrelation from relation catalog (if not arg)
01193  *      scan trigger catalog
01194  *              for name conflict (within rel)
01195  *              for original trigger (if not arg)
01196  *      modify tgname in trigger tuple
01197  *      update row in catalog
01198  */
01199 Oid
01200 renametrig(RenameStmt *stmt)
01201 {
01202     Oid         tgoid;
01203     Relation    targetrel;
01204     Relation    tgrel;
01205     HeapTuple   tuple;
01206     SysScanDesc tgscan;
01207     ScanKeyData key[2];
01208     Oid         relid;
01209 
01210     /*
01211      * Look up name, check permissions, and acquire lock (which we will NOT
01212      * release until end of transaction).
01213      */
01214     relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
01215                                      false, false,
01216                                      RangeVarCallbackForRenameTrigger,
01217                                      NULL);
01218 
01219     /* Have lock already, so just need to build relcache entry. */
01220     targetrel = relation_open(relid, NoLock);
01221 
01222     /*
01223      * Scan pg_trigger twice for existing triggers on relation.  We do this in
01224      * order to ensure a trigger does not exist with newname (The unique index
01225      * on tgrelid/tgname would complain anyway) and to ensure a trigger does
01226      * exist with oldname.
01227      *
01228      * NOTE that this is cool only because we have AccessExclusiveLock on the
01229      * relation, so the trigger set won't be changing underneath us.
01230      */
01231     tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
01232 
01233     /*
01234      * First pass -- look for name conflict
01235      */
01236     ScanKeyInit(&key[0],
01237                 Anum_pg_trigger_tgrelid,
01238                 BTEqualStrategyNumber, F_OIDEQ,
01239                 ObjectIdGetDatum(relid));
01240     ScanKeyInit(&key[1],
01241                 Anum_pg_trigger_tgname,
01242                 BTEqualStrategyNumber, F_NAMEEQ,
01243                 PointerGetDatum(stmt->newname));
01244     tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
01245                                 SnapshotNow, 2, key);
01246     if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
01247         ereport(ERROR,
01248                 (errcode(ERRCODE_DUPLICATE_OBJECT),
01249                  errmsg("trigger \"%s\" for relation \"%s\" already exists",
01250                         stmt->newname, RelationGetRelationName(targetrel))));
01251     systable_endscan(tgscan);
01252 
01253     /*
01254      * Second pass -- look for trigger existing with oldname and update
01255      */
01256     ScanKeyInit(&key[0],
01257                 Anum_pg_trigger_tgrelid,
01258                 BTEqualStrategyNumber, F_OIDEQ,
01259                 ObjectIdGetDatum(relid));
01260     ScanKeyInit(&key[1],
01261                 Anum_pg_trigger_tgname,
01262                 BTEqualStrategyNumber, F_NAMEEQ,
01263                 PointerGetDatum(stmt->subname));
01264     tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
01265                                 SnapshotNow, 2, key);
01266     if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
01267     {
01268         tgoid = HeapTupleGetOid(tuple);
01269         /*
01270          * Update pg_trigger tuple with new tgname.
01271          */
01272         tuple = heap_copytuple(tuple);  /* need a modifiable copy */
01273 
01274         namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname,
01275                    stmt->newname);
01276 
01277         simple_heap_update(tgrel, &tuple->t_self, tuple);
01278 
01279         /* keep system catalog indexes current */
01280         CatalogUpdateIndexes(tgrel, tuple);
01281 
01282         InvokeObjectPostAlterHook(TriggerRelationId,
01283                                   HeapTupleGetOid(tuple), 0);
01284 
01285         /*
01286          * Invalidate relation's relcache entry so that other backends (and
01287          * this one too!) are sent SI message to make them rebuild relcache
01288          * entries.  (Ideally this should happen automatically...)
01289          */
01290         CacheInvalidateRelcache(targetrel);
01291     }
01292     else
01293     {
01294         ereport(ERROR,
01295                 (errcode(ERRCODE_UNDEFINED_OBJECT),
01296                  errmsg("trigger \"%s\" for table \"%s\" does not exist",
01297                         stmt->subname, RelationGetRelationName(targetrel))));
01298     }
01299 
01300     systable_endscan(tgscan);
01301 
01302     heap_close(tgrel, RowExclusiveLock);
01303 
01304     /*
01305      * Close rel, but keep exclusive lock!
01306      */
01307     relation_close(targetrel, NoLock);
01308 
01309     return tgoid;
01310 }
01311 
01312 
01313 /*
01314  * EnableDisableTrigger()
01315  *
01316  *  Called by ALTER TABLE ENABLE/DISABLE [ REPLICA | ALWAYS ] TRIGGER
01317  *  to change 'tgenabled' field for the specified trigger(s)
01318  *
01319  * rel: relation to process (caller must hold suitable lock on it)
01320  * tgname: trigger to process, or NULL to scan all triggers
01321  * fires_when: new value for tgenabled field. In addition to generic
01322  *             enablement/disablement, this also defines when the trigger
01323  *             should be fired in session replication roles.
01324  * skip_system: if true, skip "system" triggers (constraint triggers)
01325  *
01326  * Caller should have checked permissions for the table; here we also
01327  * enforce that superuser privilege is required to alter the state of
01328  * system triggers
01329  */
01330 void
01331 EnableDisableTrigger(Relation rel, const char *tgname,
01332                      char fires_when, bool skip_system)
01333 {
01334     Relation    tgrel;
01335     int         nkeys;
01336     ScanKeyData keys[2];
01337     SysScanDesc tgscan;
01338     HeapTuple   tuple;
01339     bool        found;
01340     bool        changed;
01341 
01342     /* Scan the relevant entries in pg_triggers */
01343     tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
01344 
01345     ScanKeyInit(&keys[0],
01346                 Anum_pg_trigger_tgrelid,
01347                 BTEqualStrategyNumber, F_OIDEQ,
01348                 ObjectIdGetDatum(RelationGetRelid(rel)));
01349     if (tgname)
01350     {
01351         ScanKeyInit(&keys[1],
01352                     Anum_pg_trigger_tgname,
01353                     BTEqualStrategyNumber, F_NAMEEQ,
01354                     CStringGetDatum(tgname));
01355         nkeys = 2;
01356     }
01357     else
01358         nkeys = 1;
01359 
01360     tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
01361                                 SnapshotNow, nkeys, keys);
01362 
01363     found = changed = false;
01364 
01365     while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
01366     {
01367         Form_pg_trigger oldtrig = (Form_pg_trigger) GETSTRUCT(tuple);
01368 
01369         if (oldtrig->tgisinternal)
01370         {
01371             /* system trigger ... ok to process? */
01372             if (skip_system)
01373                 continue;
01374             if (!superuser())
01375                 ereport(ERROR,
01376                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01377                       errmsg("permission denied: \"%s\" is a system trigger",
01378                              NameStr(oldtrig->tgname))));
01379         }
01380 
01381         found = true;
01382 
01383         if (oldtrig->tgenabled != fires_when)
01384         {
01385             /* need to change this one ... make a copy to scribble on */
01386             HeapTuple   newtup = heap_copytuple(tuple);
01387             Form_pg_trigger newtrig = (Form_pg_trigger) GETSTRUCT(newtup);
01388 
01389             newtrig->tgenabled = fires_when;
01390 
01391             simple_heap_update(tgrel, &newtup->t_self, newtup);
01392 
01393             /* Keep catalog indexes current */
01394             CatalogUpdateIndexes(tgrel, newtup);
01395 
01396             heap_freetuple(newtup);
01397 
01398             changed = true;
01399         }
01400 
01401         InvokeObjectPostAlterHook(TriggerRelationId,
01402                                   HeapTupleGetOid(tuple), 0);
01403     }
01404 
01405     systable_endscan(tgscan);
01406 
01407     heap_close(tgrel, RowExclusiveLock);
01408 
01409     if (tgname && !found)
01410         ereport(ERROR,
01411                 (errcode(ERRCODE_UNDEFINED_OBJECT),
01412                  errmsg("trigger \"%s\" for table \"%s\" does not exist",
01413                         tgname, RelationGetRelationName(rel))));
01414 
01415     /*
01416      * If we changed anything, broadcast a SI inval message to force each
01417      * backend (including our own!) to rebuild relation's relcache entry.
01418      * Otherwise they will fail to apply the change promptly.
01419      */
01420     if (changed)
01421         CacheInvalidateRelcache(rel);
01422 }
01423 
01424 
01425 /*
01426  * Build trigger data to attach to the given relcache entry.
01427  *
01428  * Note that trigger data attached to a relcache entry must be stored in
01429  * CacheMemoryContext to ensure it survives as long as the relcache entry.
01430  * But we should be running in a less long-lived working context.  To avoid
01431  * leaking cache memory if this routine fails partway through, we build a
01432  * temporary TriggerDesc in working memory and then copy the completed
01433  * structure into cache memory.
01434  */
01435 void
01436 RelationBuildTriggers(Relation relation)
01437 {
01438     TriggerDesc *trigdesc;
01439     int         numtrigs;
01440     int         maxtrigs;
01441     Trigger    *triggers;
01442     Relation    tgrel;
01443     ScanKeyData skey;
01444     SysScanDesc tgscan;
01445     HeapTuple   htup;
01446     MemoryContext oldContext;
01447     int         i;
01448 
01449     /*
01450      * Allocate a working array to hold the triggers (the array is extended if
01451      * necessary)
01452      */
01453     maxtrigs = 16;
01454     triggers = (Trigger *) palloc(maxtrigs * sizeof(Trigger));
01455     numtrigs = 0;
01456 
01457     /*
01458      * Note: since we scan the triggers using TriggerRelidNameIndexId, we will
01459      * be reading the triggers in name order, except possibly during
01460      * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
01461      * ensures that triggers will be fired in name order.
01462      */
01463     ScanKeyInit(&skey,
01464                 Anum_pg_trigger_tgrelid,
01465                 BTEqualStrategyNumber, F_OIDEQ,
01466                 ObjectIdGetDatum(RelationGetRelid(relation)));
01467 
01468     tgrel = heap_open(TriggerRelationId, AccessShareLock);
01469     tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
01470                                 SnapshotNow, 1, &skey);
01471 
01472     while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
01473     {
01474         Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
01475         Trigger    *build;
01476         Datum       datum;
01477         bool        isnull;
01478 
01479         if (numtrigs >= maxtrigs)
01480         {
01481             maxtrigs *= 2;
01482             triggers = (Trigger *) repalloc(triggers, maxtrigs * sizeof(Trigger));
01483         }
01484         build = &(triggers[numtrigs]);
01485 
01486         build->tgoid = HeapTupleGetOid(htup);
01487         build->tgname = DatumGetCString(DirectFunctionCall1(nameout,
01488                                          NameGetDatum(&pg_trigger->tgname)));
01489         build->tgfoid = pg_trigger->tgfoid;
01490         build->tgtype = pg_trigger->tgtype;
01491         build->tgenabled = pg_trigger->tgenabled;
01492         build->tgisinternal = pg_trigger->tgisinternal;
01493         build->tgconstrrelid = pg_trigger->tgconstrrelid;
01494         build->tgconstrindid = pg_trigger->tgconstrindid;
01495         build->tgconstraint = pg_trigger->tgconstraint;
01496         build->tgdeferrable = pg_trigger->tgdeferrable;
01497         build->tginitdeferred = pg_trigger->tginitdeferred;
01498         build->tgnargs = pg_trigger->tgnargs;
01499         /* tgattr is first var-width field, so OK to access directly */
01500         build->tgnattr = pg_trigger->tgattr.dim1;
01501         if (build->tgnattr > 0)
01502         {
01503             build->tgattr = (int16 *) palloc(build->tgnattr * sizeof(int16));
01504             memcpy(build->tgattr, &(pg_trigger->tgattr.values),
01505                    build->tgnattr * sizeof(int16));
01506         }
01507         else
01508             build->tgattr = NULL;
01509         if (build->tgnargs > 0)
01510         {
01511             bytea      *val;
01512             char       *p;
01513 
01514             val = DatumGetByteaP(fastgetattr(htup,
01515                                              Anum_pg_trigger_tgargs,
01516                                              tgrel->rd_att, &isnull));
01517             if (isnull)
01518                 elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
01519                      RelationGetRelationName(relation));
01520             p = (char *) VARDATA(val);
01521             build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
01522             for (i = 0; i < build->tgnargs; i++)
01523             {
01524                 build->tgargs[i] = pstrdup(p);
01525                 p += strlen(p) + 1;
01526             }
01527         }
01528         else
01529             build->tgargs = NULL;
01530         datum = fastgetattr(htup, Anum_pg_trigger_tgqual,
01531                             tgrel->rd_att, &isnull);
01532         if (!isnull)
01533             build->tgqual = TextDatumGetCString(datum);
01534         else
01535             build->tgqual = NULL;
01536 
01537         numtrigs++;
01538     }
01539 
01540     systable_endscan(tgscan);
01541     heap_close(tgrel, AccessShareLock);
01542 
01543     /* There might not be any triggers */
01544     if (numtrigs == 0)
01545     {
01546         pfree(triggers);
01547         return;
01548     }
01549 
01550     /* Build trigdesc */
01551     trigdesc = (TriggerDesc *) palloc0(sizeof(TriggerDesc));
01552     trigdesc->triggers = triggers;
01553     trigdesc->numtriggers = numtrigs;
01554     for (i = 0; i < numtrigs; i++)
01555         SetTriggerFlags(trigdesc, &(triggers[i]));
01556 
01557     /* Copy completed trigdesc into cache storage */
01558     oldContext = MemoryContextSwitchTo(CacheMemoryContext);
01559     relation->trigdesc = CopyTriggerDesc(trigdesc);
01560     MemoryContextSwitchTo(oldContext);
01561 
01562     /* Release working memory */
01563     FreeTriggerDesc(trigdesc);
01564 }
01565 
01566 /*
01567  * Update the TriggerDesc's hint flags to include the specified trigger
01568  */
01569 static void
01570 SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger)
01571 {
01572     int16       tgtype = trigger->tgtype;
01573 
01574     trigdesc->trig_insert_before_row |=
01575         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
01576                              TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
01577     trigdesc->trig_insert_after_row |=
01578         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
01579                              TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
01580     trigdesc->trig_insert_instead_row |=
01581         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
01582                              TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_INSERT);
01583     trigdesc->trig_insert_before_statement |=
01584         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
01585                              TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
01586     trigdesc->trig_insert_after_statement |=
01587         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
01588                              TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
01589     trigdesc->trig_update_before_row |=
01590         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
01591                              TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
01592     trigdesc->trig_update_after_row |=
01593         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
01594                              TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
01595     trigdesc->trig_update_instead_row |=
01596         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
01597                              TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_UPDATE);
01598     trigdesc->trig_update_before_statement |=
01599         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
01600                              TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
01601     trigdesc->trig_update_after_statement |=
01602         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
01603                              TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
01604     trigdesc->trig_delete_before_row |=
01605         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
01606                              TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
01607     trigdesc->trig_delete_after_row |=
01608         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
01609                              TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
01610     trigdesc->trig_delete_instead_row |=
01611         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
01612                              TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_DELETE);
01613     trigdesc->trig_delete_before_statement |=
01614         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
01615                              TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
01616     trigdesc->trig_delete_after_statement |=
01617         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
01618                              TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
01619     /* there are no row-level truncate triggers */
01620     trigdesc->trig_truncate_before_statement |=
01621         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
01622                              TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_TRUNCATE);
01623     trigdesc->trig_truncate_after_statement |=
01624         TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
01625                              TRIGGER_TYPE_AFTER, TRIGGER_TYPE_TRUNCATE);
01626 }
01627 
01628 /*
01629  * Copy a TriggerDesc data structure.
01630  *
01631  * The copy is allocated in the current memory context.
01632  */
01633 TriggerDesc *
01634 CopyTriggerDesc(TriggerDesc *trigdesc)
01635 {
01636     TriggerDesc *newdesc;
01637     Trigger    *trigger;
01638     int         i;
01639 
01640     if (trigdesc == NULL || trigdesc->numtriggers <= 0)
01641         return NULL;
01642 
01643     newdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc));
01644     memcpy(newdesc, trigdesc, sizeof(TriggerDesc));
01645 
01646     trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger));
01647     memcpy(trigger, trigdesc->triggers,
01648            trigdesc->numtriggers * sizeof(Trigger));
01649     newdesc->triggers = trigger;
01650 
01651     for (i = 0; i < trigdesc->numtriggers; i++)
01652     {
01653         trigger->tgname = pstrdup(trigger->tgname);
01654         if (trigger->tgnattr > 0)
01655         {
01656             int16      *newattr;
01657 
01658             newattr = (int16 *) palloc(trigger->tgnattr * sizeof(int16));
01659             memcpy(newattr, trigger->tgattr,
01660                    trigger->tgnattr * sizeof(int16));
01661             trigger->tgattr = newattr;
01662         }
01663         if (trigger->tgnargs > 0)
01664         {
01665             char      **newargs;
01666             int16       j;
01667 
01668             newargs = (char **) palloc(trigger->tgnargs * sizeof(char *));
01669             for (j = 0; j < trigger->tgnargs; j++)
01670                 newargs[j] = pstrdup(trigger->tgargs[j]);
01671             trigger->tgargs = newargs;
01672         }
01673         if (trigger->tgqual)
01674             trigger->tgqual = pstrdup(trigger->tgqual);
01675         trigger++;
01676     }
01677 
01678     return newdesc;
01679 }
01680 
01681 /*
01682  * Free a TriggerDesc data structure.
01683  */
01684 void
01685 FreeTriggerDesc(TriggerDesc *trigdesc)
01686 {
01687     Trigger    *trigger;
01688     int         i;
01689 
01690     if (trigdesc == NULL)
01691         return;
01692 
01693     trigger = trigdesc->triggers;
01694     for (i = 0; i < trigdesc->numtriggers; i++)
01695     {
01696         pfree(trigger->tgname);
01697         if (trigger->tgnattr > 0)
01698             pfree(trigger->tgattr);
01699         if (trigger->tgnargs > 0)
01700         {
01701             while (--(trigger->tgnargs) >= 0)
01702                 pfree(trigger->tgargs[trigger->tgnargs]);
01703             pfree(trigger->tgargs);
01704         }
01705         if (trigger->tgqual)
01706             pfree(trigger->tgqual);
01707         trigger++;
01708     }
01709     pfree(trigdesc->triggers);
01710     pfree(trigdesc);
01711 }
01712 
01713 /*
01714  * Compare two TriggerDesc structures for logical equality.
01715  */
01716 #ifdef NOT_USED
01717 bool
01718 equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
01719 {
01720     int         i,
01721                 j;
01722 
01723     /*
01724      * We need not examine the hint flags, just the trigger array itself; if
01725      * we have the same triggers with the same types, the flags should match.
01726      *
01727      * As of 7.3 we assume trigger set ordering is significant in the
01728      * comparison; so we just compare corresponding slots of the two sets.
01729      *
01730      * Note: comparing the stringToNode forms of the WHEN clauses means that
01731      * parse column locations will affect the result.  This is okay as long as
01732      * this function is only used for detecting exact equality, as for example
01733      * in checking for staleness of a cache entry.
01734      */
01735     if (trigdesc1 != NULL)
01736     {
01737         if (trigdesc2 == NULL)
01738             return false;
01739         if (trigdesc1->numtriggers != trigdesc2->numtriggers)
01740             return false;
01741         for (i = 0; i < trigdesc1->numtriggers; i++)
01742         {
01743             Trigger    *trig1 = trigdesc1->triggers + i;
01744             Trigger    *trig2 = trigdesc2->triggers + i;
01745 
01746             if (trig1->tgoid != trig2->tgoid)
01747                 return false;
01748             if (strcmp(trig1->tgname, trig2->tgname) != 0)
01749                 return false;
01750             if (trig1->tgfoid != trig2->tgfoid)
01751                 return false;
01752             if (trig1->tgtype != trig2->tgtype)
01753                 return false;
01754             if (trig1->tgenabled != trig2->tgenabled)
01755                 return false;
01756             if (trig1->tgisinternal != trig2->tgisinternal)
01757                 return false;
01758             if (trig1->tgconstrrelid != trig2->tgconstrrelid)
01759                 return false;
01760             if (trig1->tgconstrindid != trig2->tgconstrindid)
01761                 return false;
01762             if (trig1->tgconstraint != trig2->tgconstraint)
01763                 return false;
01764             if (trig1->tgdeferrable != trig2->tgdeferrable)
01765                 return false;
01766             if (trig1->tginitdeferred != trig2->tginitdeferred)
01767                 return false;
01768             if (trig1->tgnargs != trig2->tgnargs)
01769                 return false;
01770             if (trig1->tgnattr != trig2->tgnattr)
01771                 return false;
01772             if (trig1->tgnattr > 0 &&
01773                 memcmp(trig1->tgattr, trig2->tgattr,
01774                        trig1->tgnattr * sizeof(int16)) != 0)
01775                 return false;
01776             for (j = 0; j < trig1->tgnargs; j++)
01777                 if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)
01778                     return false;
01779             if (trig1->tgqual == NULL && trig2->tgqual == NULL)
01780                  /* ok */ ;
01781             else if (trig1->tgqual == NULL || trig2->tgqual == NULL)
01782                 return false;
01783             else if (strcmp(trig1->tgqual, trig2->tgqual) != 0)
01784                 return false;
01785         }
01786     }
01787     else if (trigdesc2 != NULL)
01788         return false;
01789     return true;
01790 }
01791 #endif   /* NOT_USED */
01792 
01793 /*
01794  * Call a trigger function.
01795  *
01796  *      trigdata: trigger descriptor.
01797  *      tgindx: trigger's index in finfo and instr arrays.
01798  *      finfo: array of cached trigger function call information.
01799  *      instr: optional array of EXPLAIN ANALYZE instrumentation state.
01800  *      per_tuple_context: memory context to execute the function in.
01801  *
01802  * Returns the tuple (or NULL) as returned by the function.
01803  */
01804 static HeapTuple
01805 ExecCallTriggerFunc(TriggerData *trigdata,
01806                     int tgindx,
01807                     FmgrInfo *finfo,
01808                     Instrumentation *instr,
01809                     MemoryContext per_tuple_context)
01810 {
01811     FunctionCallInfoData fcinfo;
01812     PgStat_FunctionCallUsage fcusage;
01813     Datum       result;
01814     MemoryContext oldContext;
01815 
01816     finfo += tgindx;
01817 
01818     /*
01819      * We cache fmgr lookup info, to avoid making the lookup again on each
01820      * call.
01821      */
01822     if (finfo->fn_oid == InvalidOid)
01823         fmgr_info(trigdata->tg_trigger->tgfoid, finfo);
01824 
01825     Assert(finfo->fn_oid == trigdata->tg_trigger->tgfoid);
01826 
01827     /*
01828      * If doing EXPLAIN ANALYZE, start charging time to this trigger.
01829      */
01830     if (instr)
01831         InstrStartNode(instr + tgindx);
01832 
01833     /*
01834      * Do the function evaluation in the per-tuple memory context, so that
01835      * leaked memory will be reclaimed once per tuple. Note in particular that
01836      * any new tuple created by the trigger function will live till the end of
01837      * the tuple cycle.
01838      */
01839     oldContext = MemoryContextSwitchTo(per_tuple_context);
01840 
01841     /*
01842      * Call the function, passing no arguments but setting a context.
01843      */
01844     InitFunctionCallInfoData(fcinfo, finfo, 0,
01845                              InvalidOid, (Node *) trigdata, NULL);
01846 
01847     pgstat_init_function_usage(&fcinfo, &fcusage);
01848 
01849     MyTriggerDepth++;
01850     PG_TRY();
01851     {
01852         result = FunctionCallInvoke(&fcinfo);
01853     }
01854     PG_CATCH();
01855     {
01856         MyTriggerDepth--;
01857         PG_RE_THROW();
01858     }
01859     PG_END_TRY();
01860     MyTriggerDepth--;
01861 
01862     pgstat_end_function_usage(&fcusage, true);
01863 
01864     MemoryContextSwitchTo(oldContext);
01865 
01866     /*
01867      * Trigger protocol allows function to return a null pointer, but NOT to
01868      * set the isnull result flag.
01869      */
01870     if (fcinfo.isnull)
01871         ereport(ERROR,
01872                 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
01873                  errmsg("trigger function %u returned null value",
01874                         fcinfo.flinfo->fn_oid)));
01875 
01876     /*
01877      * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
01878      * one "tuple returned" (really the number of firings).
01879      */
01880     if (instr)
01881         InstrStopNode(instr + tgindx, 1);
01882 
01883     return (HeapTuple) DatumGetPointer(result);
01884 }
01885 
01886 void
01887 ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
01888 {
01889     TriggerDesc *trigdesc;
01890     int         i;
01891     TriggerData LocTriggerData;
01892 
01893     trigdesc = relinfo->ri_TrigDesc;
01894 
01895     if (trigdesc == NULL)
01896         return;
01897     if (!trigdesc->trig_insert_before_statement)
01898         return;
01899 
01900     LocTriggerData.type = T_TriggerData;
01901     LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
01902         TRIGGER_EVENT_BEFORE;
01903     LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
01904     LocTriggerData.tg_trigtuple = NULL;
01905     LocTriggerData.tg_newtuple = NULL;
01906     LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
01907     LocTriggerData.tg_newtuplebuf = InvalidBuffer;
01908     for (i = 0; i < trigdesc->numtriggers; i++)
01909     {
01910         Trigger    *trigger = &trigdesc->triggers[i];
01911         HeapTuple   newtuple;
01912 
01913         if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
01914                                   TRIGGER_TYPE_STATEMENT,
01915                                   TRIGGER_TYPE_BEFORE,
01916                                   TRIGGER_TYPE_INSERT))
01917             continue;
01918         if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
01919                             NULL, NULL, NULL))
01920             continue;
01921 
01922         LocTriggerData.tg_trigger = trigger;
01923         newtuple = ExecCallTriggerFunc(&LocTriggerData,
01924                                        i,
01925                                        relinfo->ri_TrigFunctions,
01926                                        relinfo->ri_TrigInstrument,
01927                                        GetPerTupleMemoryContext(estate));
01928 
01929         if (newtuple)
01930             ereport(ERROR,
01931                     (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
01932                   errmsg("BEFORE STATEMENT trigger cannot return a value")));
01933     }
01934 }
01935 
01936 void
01937 ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo)
01938 {
01939     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
01940 
01941     if (trigdesc && trigdesc->trig_insert_after_statement)
01942         AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_INSERT,
01943                               false, NULL, NULL, NIL, NULL);
01944 }
01945 
01946 TupleTableSlot *
01947 ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
01948                      TupleTableSlot *slot)
01949 {
01950     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
01951     HeapTuple   slottuple = ExecMaterializeSlot(slot);
01952     HeapTuple   newtuple = slottuple;
01953     HeapTuple   oldtuple;
01954     TriggerData LocTriggerData;
01955     int         i;
01956 
01957     LocTriggerData.type = T_TriggerData;
01958     LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
01959         TRIGGER_EVENT_ROW |
01960         TRIGGER_EVENT_BEFORE;
01961     LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
01962     LocTriggerData.tg_newtuple = NULL;
01963     LocTriggerData.tg_newtuplebuf = InvalidBuffer;
01964     for (i = 0; i < trigdesc->numtriggers; i++)
01965     {
01966         Trigger    *trigger = &trigdesc->triggers[i];
01967 
01968         if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
01969                                   TRIGGER_TYPE_ROW,
01970                                   TRIGGER_TYPE_BEFORE,
01971                                   TRIGGER_TYPE_INSERT))
01972             continue;
01973         if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
01974                             NULL, NULL, newtuple))
01975             continue;
01976 
01977         LocTriggerData.tg_trigtuple = oldtuple = newtuple;
01978         LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
01979         LocTriggerData.tg_trigger = trigger;
01980         newtuple = ExecCallTriggerFunc(&LocTriggerData,
01981                                        i,
01982                                        relinfo->ri_TrigFunctions,
01983                                        relinfo->ri_TrigInstrument,
01984                                        GetPerTupleMemoryContext(estate));
01985         if (oldtuple != newtuple && oldtuple != slottuple)
01986             heap_freetuple(oldtuple);
01987         if (newtuple == NULL)
01988             return NULL;        /* "do nothing" */
01989     }
01990 
01991     if (newtuple != slottuple)
01992     {
01993         /*
01994          * Return the modified tuple using the es_trig_tuple_slot.  We assume
01995          * the tuple was allocated in per-tuple memory context, and therefore
01996          * will go away by itself. The tuple table slot should not try to
01997          * clear it.
01998          */
01999         TupleTableSlot *newslot = estate->es_trig_tuple_slot;
02000         TupleDesc   tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
02001 
02002         if (newslot->tts_tupleDescriptor != tupdesc)
02003             ExecSetSlotDescriptor(newslot, tupdesc);
02004         ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
02005         slot = newslot;
02006     }
02007     return slot;
02008 }
02009 
02010 void
02011 ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo,
02012                      HeapTuple trigtuple, List *recheckIndexes)
02013 {
02014     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
02015 
02016     if (trigdesc && trigdesc->trig_insert_after_row)
02017         AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_INSERT,
02018                               true, NULL, trigtuple, recheckIndexes, NULL);
02019 }
02020 
02021 TupleTableSlot *
02022 ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
02023                      TupleTableSlot *slot)
02024 {
02025     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
02026     HeapTuple   slottuple = ExecMaterializeSlot(slot);
02027     HeapTuple   newtuple = slottuple;
02028     HeapTuple   oldtuple;
02029     TriggerData LocTriggerData;
02030     int         i;
02031 
02032     LocTriggerData.type = T_TriggerData;
02033     LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
02034         TRIGGER_EVENT_ROW |
02035         TRIGGER_EVENT_INSTEAD;
02036     LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
02037     LocTriggerData.tg_newtuple = NULL;
02038     LocTriggerData.tg_newtuplebuf = InvalidBuffer;
02039     for (i = 0; i < trigdesc->numtriggers; i++)
02040     {
02041         Trigger    *trigger = &trigdesc->triggers[i];
02042 
02043         if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
02044                                   TRIGGER_TYPE_ROW,
02045                                   TRIGGER_TYPE_INSTEAD,
02046                                   TRIGGER_TYPE_INSERT))
02047             continue;
02048         if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
02049                             NULL, NULL, newtuple))
02050             continue;
02051 
02052         LocTriggerData.tg_trigtuple = oldtuple = newtuple;
02053         LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
02054         LocTriggerData.tg_trigger = trigger;
02055         newtuple = ExecCallTriggerFunc(&LocTriggerData,
02056                                        i,
02057                                        relinfo->ri_TrigFunctions,
02058                                        relinfo->ri_TrigInstrument,
02059                                        GetPerTupleMemoryContext(estate));
02060         if (oldtuple != newtuple && oldtuple != slottuple)
02061             heap_freetuple(oldtuple);
02062         if (newtuple == NULL)
02063             return NULL;        /* "do nothing" */
02064     }
02065 
02066     if (newtuple != slottuple)
02067     {
02068         /*
02069          * Return the modified tuple using the es_trig_tuple_slot.  We assume
02070          * the tuple was allocated in per-tuple memory context, and therefore
02071          * will go away by itself. The tuple table slot should not try to
02072          * clear it.
02073          */
02074         TupleTableSlot *newslot = estate->es_trig_tuple_slot;
02075         TupleDesc   tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
02076 
02077         if (newslot->tts_tupleDescriptor != tupdesc)
02078             ExecSetSlotDescriptor(newslot, tupdesc);
02079         ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
02080         slot = newslot;
02081     }
02082     return slot;
02083 }
02084 
02085 void
02086 ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
02087 {
02088     TriggerDesc *trigdesc;
02089     int         i;
02090     TriggerData LocTriggerData;
02091 
02092     trigdesc = relinfo->ri_TrigDesc;
02093 
02094     if (trigdesc == NULL)
02095         return;
02096     if (!trigdesc->trig_delete_before_statement)
02097         return;
02098 
02099     LocTriggerData.type = T_TriggerData;
02100     LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
02101         TRIGGER_EVENT_BEFORE;
02102     LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
02103     LocTriggerData.tg_trigtuple = NULL;
02104     LocTriggerData.tg_newtuple = NULL;
02105     LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
02106     LocTriggerData.tg_newtuplebuf = InvalidBuffer;
02107     for (i = 0; i < trigdesc->numtriggers; i++)
02108     {
02109         Trigger    *trigger = &trigdesc->triggers[i];
02110         HeapTuple   newtuple;
02111 
02112         if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
02113                                   TRIGGER_TYPE_STATEMENT,
02114                                   TRIGGER_TYPE_BEFORE,
02115                                   TRIGGER_TYPE_DELETE))
02116             continue;
02117         if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
02118                             NULL, NULL, NULL))
02119             continue;
02120 
02121         LocTriggerData.tg_trigger = trigger;
02122         newtuple = ExecCallTriggerFunc(&LocTriggerData,
02123                                        i,
02124                                        relinfo->ri_TrigFunctions,
02125                                        relinfo->ri_TrigInstrument,
02126                                        GetPerTupleMemoryContext(estate));
02127 
02128         if (newtuple)
02129             ereport(ERROR,
02130                     (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
02131                   errmsg("BEFORE STATEMENT trigger cannot return a value")));
02132     }
02133 }
02134 
02135 void
02136 ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
02137 {
02138     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
02139 
02140     if (trigdesc && trigdesc->trig_delete_after_statement)
02141         AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_DELETE,
02142                               false, NULL, NULL, NIL, NULL);
02143 }
02144 
02145 bool
02146 ExecBRDeleteTriggers(EState *estate, EPQState *epqstate,
02147                      ResultRelInfo *relinfo,
02148                      ItemPointer tupleid)
02149 {
02150     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
02151     bool        result = true;
02152     TriggerData LocTriggerData;
02153     HeapTuple   trigtuple;
02154     HeapTuple   newtuple;
02155     TupleTableSlot *newSlot;
02156     int         i;
02157 
02158     trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
02159                                    LockTupleExclusive, &newSlot);
02160     if (trigtuple == NULL)
02161         return false;
02162 
02163     LocTriggerData.type = T_TriggerData;
02164     LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
02165         TRIGGER_EVENT_ROW |
02166         TRIGGER_EVENT_BEFORE;
02167     LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
02168     LocTriggerData.tg_newtuple = NULL;
02169     LocTriggerData.tg_newtuplebuf = InvalidBuffer;
02170     for (i = 0; i < trigdesc->numtriggers; i++)
02171     {
02172         Trigger    *trigger = &trigdesc->triggers[i];
02173 
02174         if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
02175                                   TRIGGER_TYPE_ROW,
02176                                   TRIGGER_TYPE_BEFORE,
02177                                   TRIGGER_TYPE_DELETE))
02178             continue;
02179         if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
02180                             NULL, trigtuple, NULL))
02181             continue;
02182 
02183         LocTriggerData.tg_trigtuple = trigtuple;
02184         LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
02185         LocTriggerData.tg_trigger = trigger;
02186         newtuple = ExecCallTriggerFunc(&LocTriggerData,
02187                                        i,
02188                                        relinfo->ri_TrigFunctions,
02189                                        relinfo->ri_TrigInstrument,
02190                                        GetPerTupleMemoryContext(estate));
02191         if (newtuple == NULL)
02192         {
02193             result = false;     /* tell caller to suppress delete */
02194             break;
02195         }
02196         if (newtuple != trigtuple)
02197             heap_freetuple(newtuple);
02198     }
02199     heap_freetuple(trigtuple);
02200 
02201     return result;
02202 }
02203 
02204 void
02205 ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
02206                      ItemPointer tupleid)
02207 {
02208     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
02209 
02210     if (trigdesc && trigdesc->trig_delete_after_row)
02211     {
02212         HeapTuple   trigtuple = GetTupleForTrigger(estate, NULL, relinfo,
02213                                                    tupleid, LockTupleExclusive,
02214                                                    NULL);
02215 
02216         AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_DELETE,
02217                               true, trigtuple, NULL, NIL, NULL);
02218         heap_freetuple(trigtuple);
02219     }
02220 }
02221 
02222 bool
02223 ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
02224                      HeapTuple trigtuple)
02225 {
02226     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
02227     TriggerData LocTriggerData;
02228     HeapTuple   rettuple;
02229     int         i;
02230 
02231     LocTriggerData.type = T_TriggerData;
02232     LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
02233         TRIGGER_EVENT_ROW |
02234         TRIGGER_EVENT_INSTEAD;
02235     LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
02236     LocTriggerData.tg_newtuple = NULL;
02237     LocTriggerData.tg_newtuplebuf = InvalidBuffer;
02238     for (i = 0; i < trigdesc->numtriggers; i++)
02239     {
02240         Trigger    *trigger = &trigdesc->triggers[i];
02241 
02242         if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
02243                                   TRIGGER_TYPE_ROW,
02244                                   TRIGGER_TYPE_INSTEAD,
02245                                   TRIGGER_TYPE_DELETE))
02246             continue;
02247         if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
02248                             NULL, trigtuple, NULL))
02249             continue;
02250 
02251         LocTriggerData.tg_trigtuple = trigtuple;
02252         LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
02253         LocTriggerData.tg_trigger = trigger;
02254         rettuple = ExecCallTriggerFunc(&LocTriggerData,
02255                                        i,
02256                                        relinfo->ri_TrigFunctions,
02257                                        relinfo->ri_TrigInstrument,
02258                                        GetPerTupleMemoryContext(estate));
02259         if (rettuple == NULL)
02260             return false;       /* Delete was suppressed */
02261         if (rettuple != trigtuple)
02262             heap_freetuple(rettuple);
02263     }
02264     return true;
02265 }
02266 
02267 void
02268 ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
02269 {
02270     TriggerDesc *trigdesc;
02271     int         i;
02272     TriggerData LocTriggerData;
02273     Bitmapset  *modifiedCols;
02274 
02275     trigdesc = relinfo->ri_TrigDesc;
02276 
02277     if (trigdesc == NULL)
02278         return;
02279     if (!trigdesc->trig_update_before_statement)
02280         return;
02281 
02282     modifiedCols = GetModifiedColumns(relinfo, estate);
02283 
02284     LocTriggerData.type = T_TriggerData;
02285     LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
02286         TRIGGER_EVENT_BEFORE;
02287     LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
02288     LocTriggerData.tg_trigtuple = NULL;
02289     LocTriggerData.tg_newtuple = NULL;
02290     LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
02291     LocTriggerData.tg_newtuplebuf = InvalidBuffer;
02292     for (i = 0; i < trigdesc->numtriggers; i++)
02293     {
02294         Trigger    *trigger = &trigdesc->triggers[i];
02295         HeapTuple   newtuple;
02296 
02297         if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
02298                                   TRIGGER_TYPE_STATEMENT,
02299                                   TRIGGER_TYPE_BEFORE,
02300                                   TRIGGER_TYPE_UPDATE))
02301             continue;
02302         if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
02303                             modifiedCols, NULL, NULL))
02304             continue;
02305 
02306         LocTriggerData.tg_trigger = trigger;
02307         newtuple = ExecCallTriggerFunc(&LocTriggerData,
02308                                        i,
02309                                        relinfo->ri_TrigFunctions,
02310                                        relinfo->ri_TrigInstrument,
02311                                        GetPerTupleMemoryContext(estate));
02312 
02313         if (newtuple)
02314             ereport(ERROR,
02315                     (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
02316                   errmsg("BEFORE STATEMENT trigger cannot return a value")));
02317     }
02318 }
02319 
02320 void
02321 ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
02322 {
02323     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
02324 
02325     if (trigdesc && trigdesc->trig_update_after_statement)
02326         AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE,
02327                               false, NULL, NULL, NIL,
02328                               GetModifiedColumns(relinfo, estate));
02329 }
02330 
02331 TupleTableSlot *
02332 ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
02333                      ResultRelInfo *relinfo,
02334                      ItemPointer tupleid, TupleTableSlot *slot)
02335 {
02336     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
02337     HeapTuple   slottuple = ExecMaterializeSlot(slot);
02338     HeapTuple   newtuple = slottuple;
02339     TriggerData LocTriggerData;
02340     HeapTuple   trigtuple;
02341     HeapTuple   oldtuple;
02342     TupleTableSlot *newSlot;
02343     int         i;
02344     Bitmapset  *modifiedCols;
02345     Bitmapset  *keyCols;
02346     LockTupleMode lockmode;
02347 
02348     /*
02349      * Compute lock mode to use.  If columns that are part of the key have not
02350      * been modified, then we can use a weaker lock, allowing for better
02351      * concurrency.
02352      */
02353     modifiedCols = GetModifiedColumns(relinfo, estate);
02354     keyCols = RelationGetIndexAttrBitmap(relinfo->ri_RelationDesc, true);
02355     if (bms_overlap(keyCols, modifiedCols))
02356         lockmode = LockTupleExclusive;
02357     else
02358         lockmode = LockTupleNoKeyExclusive;
02359 
02360     /* get a copy of the on-disk tuple we are planning to update */
02361     trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
02362                                    lockmode, &newSlot);
02363     if (trigtuple == NULL)
02364         return NULL;            /* cancel the update action */
02365 
02366     /*
02367      * In READ COMMITTED isolation level it's possible that target tuple was
02368      * changed due to concurrent update.  In that case we have a raw subplan
02369      * output tuple in newSlot, and need to run it through the junk filter to
02370      * produce an insertable tuple.
02371      *
02372      * Caution: more than likely, the passed-in slot is the same as the
02373      * junkfilter's output slot, so we are clobbering the original value of
02374      * slottuple by doing the filtering.  This is OK since neither we nor our
02375      * caller have any more interest in the prior contents of that slot.
02376      */
02377     if (newSlot != NULL)
02378     {
02379         slot = ExecFilterJunk(relinfo->ri_junkFilter, newSlot);
02380         slottuple = ExecMaterializeSlot(slot);
02381         newtuple = slottuple;
02382     }
02383 
02384 
02385     LocTriggerData.type = T_TriggerData;
02386     LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
02387         TRIGGER_EVENT_ROW |
02388         TRIGGER_EVENT_BEFORE;
02389     LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
02390     for (i = 0; i < trigdesc->numtriggers; i++)
02391     {
02392         Trigger    *trigger = &trigdesc->triggers[i];
02393 
02394         if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
02395                                   TRIGGER_TYPE_ROW,
02396                                   TRIGGER_TYPE_BEFORE,
02397                                   TRIGGER_TYPE_UPDATE))
02398             continue;
02399         if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
02400                             modifiedCols, trigtuple, newtuple))
02401             continue;
02402 
02403         LocTriggerData.tg_trigtuple = trigtuple;
02404         LocTriggerData.tg_newtuple = oldtuple = newtuple;
02405         LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
02406         LocTriggerData.tg_newtuplebuf = InvalidBuffer;
02407         LocTriggerData.tg_trigger = trigger;
02408         newtuple = ExecCallTriggerFunc(&LocTriggerData,
02409                                        i,
02410                                        relinfo->ri_TrigFunctions,
02411                                        relinfo->ri_TrigInstrument,
02412                                        GetPerTupleMemoryContext(estate));
02413         if (oldtuple != newtuple && oldtuple != slottuple)
02414             heap_freetuple(oldtuple);
02415         if (newtuple == NULL)
02416         {
02417             heap_freetuple(trigtuple);
02418             return NULL;        /* "do nothing" */
02419         }
02420     }
02421     heap_freetuple(trigtuple);
02422 
02423     if (newtuple != slottuple)
02424     {
02425         /*
02426          * Return the modified tuple using the es_trig_tuple_slot.  We assume
02427          * the tuple was allocated in per-tuple memory context, and therefore
02428          * will go away by itself. The tuple table slot should not try to
02429          * clear it.
02430          */
02431         TupleTableSlot *newslot = estate->es_trig_tuple_slot;
02432         TupleDesc   tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
02433 
02434         if (newslot->tts_tupleDescriptor != tupdesc)
02435             ExecSetSlotDescriptor(newslot, tupdesc);
02436         ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
02437         slot = newslot;
02438     }
02439     return slot;
02440 }
02441 
02442 void
02443 ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
02444                      ItemPointer tupleid, HeapTuple newtuple,
02445                      List *recheckIndexes)
02446 {
02447     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
02448 
02449     if (trigdesc && trigdesc->trig_update_after_row)
02450     {
02451         HeapTuple   trigtuple = GetTupleForTrigger(estate, NULL, relinfo,
02452                                                    tupleid, LockTupleExclusive,
02453                                                    NULL);
02454 
02455         AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE,
02456                               true, trigtuple, newtuple, recheckIndexes,
02457                               GetModifiedColumns(relinfo, estate));
02458         heap_freetuple(trigtuple);
02459     }
02460 }
02461 
02462 TupleTableSlot *
02463 ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
02464                      HeapTuple trigtuple, TupleTableSlot *slot)
02465 {
02466     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
02467     HeapTuple   slottuple = ExecMaterializeSlot(slot);
02468     HeapTuple   newtuple = slottuple;
02469     TriggerData LocTriggerData;
02470     HeapTuple   oldtuple;
02471     int         i;
02472 
02473     LocTriggerData.type = T_TriggerData;
02474     LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
02475         TRIGGER_EVENT_ROW |
02476         TRIGGER_EVENT_INSTEAD;
02477     LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
02478     for (i = 0; i < trigdesc->numtriggers; i++)
02479     {
02480         Trigger    *trigger = &trigdesc->triggers[i];
02481 
02482         if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
02483                                   TRIGGER_TYPE_ROW,
02484                                   TRIGGER_TYPE_INSTEAD,
02485                                   TRIGGER_TYPE_UPDATE))
02486             continue;
02487         if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
02488                             NULL, trigtuple, newtuple))
02489             continue;
02490 
02491         LocTriggerData.tg_trigtuple = trigtuple;
02492         LocTriggerData.tg_newtuple = oldtuple = newtuple;
02493         LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
02494         LocTriggerData.tg_newtuplebuf = InvalidBuffer;
02495         LocTriggerData.tg_trigger = trigger;
02496         newtuple = ExecCallTriggerFunc(&LocTriggerData,
02497                                        i,
02498                                        relinfo->ri_TrigFunctions,
02499                                        relinfo->ri_TrigInstrument,
02500                                        GetPerTupleMemoryContext(estate));
02501         if (oldtuple != newtuple && oldtuple != slottuple)
02502             heap_freetuple(oldtuple);
02503         if (newtuple == NULL)
02504             return NULL;        /* "do nothing" */
02505     }
02506 
02507     if (newtuple != slottuple)
02508     {
02509         /*
02510          * Return the modified tuple using the es_trig_tuple_slot.  We assume
02511          * the tuple was allocated in per-tuple memory context, and therefore
02512          * will go away by itself. The tuple table slot should not try to
02513          * clear it.
02514          */
02515         TupleTableSlot *newslot = estate->es_trig_tuple_slot;
02516         TupleDesc   tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
02517 
02518         if (newslot->tts_tupleDescriptor != tupdesc)
02519             ExecSetSlotDescriptor(newslot, tupdesc);
02520         ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
02521         slot = newslot;
02522     }
02523     return slot;
02524 }
02525 
02526 void
02527 ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
02528 {
02529     TriggerDesc *trigdesc;
02530     int         i;
02531     TriggerData LocTriggerData;
02532 
02533     trigdesc = relinfo->ri_TrigDesc;
02534 
02535     if (trigdesc == NULL)
02536         return;
02537     if (!trigdesc->trig_truncate_before_statement)
02538         return;
02539 
02540     LocTriggerData.type = T_TriggerData;
02541     LocTriggerData.tg_event = TRIGGER_EVENT_TRUNCATE |
02542         TRIGGER_EVENT_BEFORE;
02543     LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
02544     LocTriggerData.tg_trigtuple = NULL;
02545     LocTriggerData.tg_newtuple = NULL;
02546     LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
02547     LocTriggerData.tg_newtuplebuf = InvalidBuffer;
02548     for (i = 0; i < trigdesc->numtriggers; i++)
02549     {
02550         Trigger    *trigger = &trigdesc->triggers[i];
02551         HeapTuple   newtuple;
02552 
02553         if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
02554                                   TRIGGER_TYPE_STATEMENT,
02555                                   TRIGGER_TYPE_BEFORE,
02556                                   TRIGGER_TYPE_TRUNCATE))
02557             continue;
02558         if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
02559                             NULL, NULL, NULL))
02560             continue;
02561 
02562         LocTriggerData.tg_trigger = trigger;
02563         newtuple = ExecCallTriggerFunc(&LocTriggerData,
02564                                        i,
02565                                        relinfo->ri_TrigFunctions,
02566                                        relinfo->ri_TrigInstrument,
02567                                        GetPerTupleMemoryContext(estate));
02568 
02569         if (newtuple)
02570             ereport(ERROR,
02571                     (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
02572                   errmsg("BEFORE STATEMENT trigger cannot return a value")));
02573     }
02574 }
02575 
02576 void
02577 ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
02578 {
02579     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
02580 
02581     if (trigdesc && trigdesc->trig_truncate_after_statement)
02582         AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_TRUNCATE,
02583                               false, NULL, NULL, NIL, NULL);
02584 }
02585 
02586 
02587 static HeapTuple
02588 GetTupleForTrigger(EState *estate,
02589                    EPQState *epqstate,
02590                    ResultRelInfo *relinfo,
02591                    ItemPointer tid,
02592                    LockTupleMode lockmode,
02593                    TupleTableSlot **newSlot)
02594 {
02595     Relation    relation = relinfo->ri_RelationDesc;
02596     HeapTupleData tuple;
02597     HeapTuple   result;
02598     Buffer      buffer;
02599 
02600     if (newSlot != NULL)
02601     {
02602         HTSU_Result test;
02603         HeapUpdateFailureData hufd;
02604 
02605         *newSlot = NULL;
02606 
02607         /* caller must pass an epqstate if EvalPlanQual is possible */
02608         Assert(epqstate != NULL);
02609 
02610         /*
02611          * lock tuple for update
02612          */
02613 ltrmark:;
02614         tuple.t_self = *tid;
02615         test = heap_lock_tuple(relation, &tuple,
02616                                estate->es_output_cid,
02617                                lockmode, false /* wait */,
02618                                false, &buffer, &hufd);
02619         switch (test)
02620         {
02621             case HeapTupleSelfUpdated:
02622                 /*
02623                  * The target tuple was already updated or deleted by the
02624                  * current command, or by a later command in the current
02625                  * transaction.  We ignore the tuple in the former case, and
02626                  * throw error in the latter case, for the same reasons
02627                  * enumerated in ExecUpdate and ExecDelete in
02628                  * nodeModifyTable.c.
02629                  */
02630                 if (hufd.cmax != estate->es_output_cid)
02631                     ereport(ERROR,
02632                             (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
02633                              errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
02634                              errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
02635 
02636                 /* treat it as deleted; do not process */
02637                 ReleaseBuffer(buffer);
02638                 return NULL;
02639 
02640             case HeapTupleMayBeUpdated:
02641                 break;
02642 
02643             case HeapTupleUpdated:
02644                 ReleaseBuffer(buffer);
02645                 if (IsolationUsesXactSnapshot())
02646                     ereport(ERROR,
02647                             (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
02648                              errmsg("could not serialize access due to concurrent update")));
02649                 if (!ItemPointerEquals(&hufd.ctid, &tuple.t_self))
02650                 {
02651                     /* it was updated, so look at the updated version */
02652                     TupleTableSlot *epqslot;
02653 
02654                     epqslot = EvalPlanQual(estate,
02655                                            epqstate,
02656                                            relation,
02657                                            relinfo->ri_RangeTableIndex,
02658                                            lockmode,
02659                                            &hufd.ctid,
02660                                            hufd.xmax);
02661                     if (!TupIsNull(epqslot))
02662                     {
02663                         *tid = hufd.ctid;
02664                         *newSlot = epqslot;
02665 
02666                         /*
02667                          * EvalPlanQual already locked the tuple, but we
02668                          * re-call heap_lock_tuple anyway as an easy way of
02669                          * re-fetching the correct tuple.  Speed is hardly a
02670                          * criterion in this path anyhow.
02671                          */
02672                         goto ltrmark;
02673                     }
02674                 }
02675 
02676                 /*
02677                  * if tuple was deleted or PlanQual failed for updated tuple -
02678                  * we must not process this tuple!
02679                  */
02680                 return NULL;
02681 
02682             default:
02683                 ReleaseBuffer(buffer);
02684                 elog(ERROR, "unrecognized heap_lock_tuple status: %u", test);
02685                 return NULL;    /* keep compiler quiet */
02686         }
02687     }
02688     else
02689     {
02690         Page        page;
02691         ItemId      lp;
02692 
02693         buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
02694 
02695         /*
02696          * Although we already know this tuple is valid, we must lock the
02697          * buffer to ensure that no one has a buffer cleanup lock; otherwise
02698          * they might move the tuple while we try to copy it.  But we can
02699          * release the lock before actually doing the heap_copytuple call,
02700          * since holding pin is sufficient to prevent anyone from getting a
02701          * cleanup lock they don't already hold.
02702          */
02703         LockBuffer(buffer, BUFFER_LOCK_SHARE);
02704 
02705         page = BufferGetPage(buffer);
02706         lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
02707 
02708         Assert(ItemIdIsNormal(lp));
02709 
02710         tuple.t_data = (HeapTupleHeader) PageGetItem(page, lp);
02711         tuple.t_len = ItemIdGetLength(lp);
02712         tuple.t_self = *tid;
02713         tuple.t_tableOid = RelationGetRelid(relation);
02714 
02715         LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
02716     }
02717 
02718     result = heap_copytuple(&tuple);
02719     ReleaseBuffer(buffer);
02720 
02721     return result;
02722 }
02723 
02724 /*
02725  * Is trigger enabled to fire?
02726  */
02727 static bool
02728 TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
02729                Trigger *trigger, TriggerEvent event,
02730                Bitmapset *modifiedCols,
02731                HeapTuple oldtup, HeapTuple newtup)
02732 {
02733     /* Check replication-role-dependent enable state */
02734     if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
02735     {
02736         if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
02737             trigger->tgenabled == TRIGGER_DISABLED)
02738             return false;
02739     }
02740     else    /* ORIGIN or LOCAL role */
02741     {
02742         if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
02743             trigger->tgenabled == TRIGGER_DISABLED)
02744             return false;
02745     }
02746 
02747     /*
02748      * Check for column-specific trigger (only possible for UPDATE, and in
02749      * fact we *must* ignore tgattr for other event types)
02750      */
02751     if (trigger->tgnattr > 0 && TRIGGER_FIRED_BY_UPDATE(event))
02752     {
02753         int         i;
02754         bool        modified;
02755 
02756         modified = false;
02757         for (i = 0; i < trigger->tgnattr; i++)
02758         {
02759             if (bms_is_member(trigger->tgattr[i] - FirstLowInvalidHeapAttributeNumber,
02760                               modifiedCols))
02761             {
02762                 modified = true;
02763                 break;
02764             }
02765         }
02766         if (!modified)
02767             return false;
02768     }
02769 
02770     /* Check for WHEN clause */
02771     if (trigger->tgqual)
02772     {
02773         TupleDesc   tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
02774         List      **predicate;
02775         ExprContext *econtext;
02776         TupleTableSlot *oldslot = NULL;
02777         TupleTableSlot *newslot = NULL;
02778         MemoryContext oldContext;
02779         int         i;
02780 
02781         Assert(estate != NULL);
02782 
02783         /*
02784          * trigger is an element of relinfo->ri_TrigDesc->triggers[]; find the
02785          * matching element of relinfo->ri_TrigWhenExprs[]
02786          */
02787         i = trigger - relinfo->ri_TrigDesc->triggers;
02788         predicate = &relinfo->ri_TrigWhenExprs[i];
02789 
02790         /*
02791          * If first time through for this WHEN expression, build expression
02792          * nodetrees for it.  Keep them in the per-query memory context so
02793          * they'll survive throughout the query.
02794          */
02795         if (*predicate == NIL)
02796         {
02797             Node       *tgqual;
02798 
02799             oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
02800             tgqual = stringToNode(trigger->tgqual);
02801             /* Change references to OLD and NEW to INNER_VAR and OUTER_VAR */
02802             ChangeVarNodes(tgqual, PRS2_OLD_VARNO, INNER_VAR, 0);
02803             ChangeVarNodes(tgqual, PRS2_NEW_VARNO, OUTER_VAR, 0);
02804             /* ExecQual wants implicit-AND form */
02805             tgqual = (Node *) make_ands_implicit((Expr *) tgqual);
02806             *predicate = (List *) ExecPrepareExpr((Expr *) tgqual, estate);
02807             MemoryContextSwitchTo(oldContext);
02808         }
02809 
02810         /*
02811          * We will use the EState's per-tuple context for evaluating WHEN
02812          * expressions (creating it if it's not already there).
02813          */
02814         econtext = GetPerTupleExprContext(estate);
02815 
02816         /*
02817          * Put OLD and NEW tuples into tupleslots for expression evaluation.
02818          * These slots can be shared across the whole estate, but be careful
02819          * that they have the current resultrel's tupdesc.
02820          */
02821         if (HeapTupleIsValid(oldtup))
02822         {
02823             if (estate->es_trig_oldtup_slot == NULL)
02824             {
02825                 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
02826                 estate->es_trig_oldtup_slot = ExecInitExtraTupleSlot(estate);
02827                 MemoryContextSwitchTo(oldContext);
02828             }
02829             oldslot = estate->es_trig_oldtup_slot;
02830             if (oldslot->tts_tupleDescriptor != tupdesc)
02831                 ExecSetSlotDescriptor(oldslot, tupdesc);
02832             ExecStoreTuple(oldtup, oldslot, InvalidBuffer, false);
02833         }
02834         if (HeapTupleIsValid(newtup))
02835         {
02836             if (estate->es_trig_newtup_slot == NULL)
02837             {
02838                 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
02839                 estate->es_trig_newtup_slot = ExecInitExtraTupleSlot(estate);
02840                 MemoryContextSwitchTo(oldContext);
02841             }
02842             newslot = estate->es_trig_newtup_slot;
02843             if (newslot->tts_tupleDescriptor != tupdesc)
02844                 ExecSetSlotDescriptor(newslot, tupdesc);
02845             ExecStoreTuple(newtup, newslot, InvalidBuffer, false);
02846         }
02847 
02848         /*
02849          * Finally evaluate the expression, making the old and/or new tuples
02850          * available as INNER_VAR/OUTER_VAR respectively.
02851          */
02852         econtext->ecxt_innertuple = oldslot;
02853         econtext->ecxt_outertuple = newslot;
02854         if (!ExecQual(*predicate, econtext, false))
02855             return false;
02856     }
02857 
02858     return true;
02859 }
02860 
02861 
02862 /* ----------
02863  * After-trigger stuff
02864  *
02865  * The AfterTriggersData struct holds data about pending AFTER trigger events
02866  * during the current transaction tree.  (BEFORE triggers are fired
02867  * immediately so we don't need any persistent state about them.)  The struct
02868  * and most of its subsidiary data are kept in TopTransactionContext; however
02869  * the individual event records are kept in a separate sub-context.  This is
02870  * done mainly so that it's easy to tell from a memory context dump how much
02871  * space is being eaten by trigger events.
02872  *
02873  * Because the list of pending events can grow large, we go to some
02874  * considerable effort to minimize per-event memory consumption.  The event
02875  * records are grouped into chunks and common data for similar events in the
02876  * same chunk is only stored once.
02877  *
02878  * XXX We need to be able to save the per-event data in a file if it grows too
02879  * large.
02880  * ----------
02881  */
02882 
02883 /* Per-trigger SET CONSTRAINT status */
02884 typedef struct SetConstraintTriggerData
02885 {
02886     Oid         sct_tgoid;
02887     bool        sct_tgisdeferred;
02888 } SetConstraintTriggerData;
02889 
02890 typedef struct SetConstraintTriggerData *SetConstraintTrigger;
02891 
02892 /*
02893  * SET CONSTRAINT intra-transaction status.
02894  *
02895  * We make this a single palloc'd object so it can be copied and freed easily.
02896  *
02897  * all_isset and all_isdeferred are used to keep track
02898  * of SET CONSTRAINTS ALL {DEFERRED, IMMEDIATE}.
02899  *
02900  * trigstates[] stores per-trigger tgisdeferred settings.
02901  */
02902 typedef struct SetConstraintStateData
02903 {
02904     bool        all_isset;
02905     bool        all_isdeferred;
02906     int         numstates;      /* number of trigstates[] entries in use */
02907     int         numalloc;       /* allocated size of trigstates[] */
02908     SetConstraintTriggerData trigstates[1];     /* VARIABLE LENGTH ARRAY */
02909 } SetConstraintStateData;
02910 
02911 typedef SetConstraintStateData *SetConstraintState;
02912 
02913 
02914 /*
02915  * Per-trigger-event data
02916  *
02917  * The actual per-event data, AfterTriggerEventData, includes DONE/IN_PROGRESS
02918  * status bits and one or two tuple CTIDs.  Each event record also has an
02919  * associated AfterTriggerSharedData that is shared across all instances
02920  * of similar events within a "chunk".
02921  *
02922  * We arrange not to waste storage on ate_ctid2 for non-update events.
02923  * We could go further and not store either ctid for statement-level triggers,
02924  * but that seems unlikely to be worth the trouble.
02925  *
02926  * Note: ats_firing_id is initially zero and is set to something else when
02927  * AFTER_TRIGGER_IN_PROGRESS is set.  It indicates which trigger firing
02928  * cycle the trigger will be fired in (or was fired in, if DONE is set).
02929  * Although this is mutable state, we can keep it in AfterTriggerSharedData
02930  * because all instances of the same type of event in a given event list will
02931  * be fired at the same time, if they were queued between the same firing
02932  * cycles.  So we need only ensure that ats_firing_id is zero when attaching
02933  * a new event to an existing AfterTriggerSharedData record.
02934  */
02935 typedef uint32 TriggerFlags;
02936 
02937 #define AFTER_TRIGGER_OFFSET            0x0FFFFFFF      /* must be low-order
02938                                                          * bits */
02939 #define AFTER_TRIGGER_2CTIDS            0x10000000
02940 #define AFTER_TRIGGER_DONE              0x20000000
02941 #define AFTER_TRIGGER_IN_PROGRESS       0x40000000
02942 
02943 typedef struct AfterTriggerSharedData *AfterTriggerShared;
02944 
02945 typedef struct AfterTriggerSharedData
02946 {
02947     TriggerEvent ats_event;     /* event type indicator, see trigger.h */
02948     Oid         ats_tgoid;      /* the trigger's ID */
02949     Oid         ats_relid;      /* the relation it's on */
02950     CommandId   ats_firing_id;  /* ID for firing cycle */
02951 } AfterTriggerSharedData;
02952 
02953 typedef struct AfterTriggerEventData *AfterTriggerEvent;
02954 
02955 typedef struct AfterTriggerEventData
02956 {
02957     TriggerFlags ate_flags;     /* status bits and offset to shared data */
02958     ItemPointerData ate_ctid1;  /* inserted, deleted, or old updated tuple */
02959     ItemPointerData ate_ctid2;  /* new updated tuple */
02960 } AfterTriggerEventData;
02961 
02962 /* This struct must exactly match the one above except for not having ctid2 */
02963 typedef struct AfterTriggerEventDataOneCtid
02964 {
02965     TriggerFlags ate_flags;     /* status bits and offset to shared data */
02966     ItemPointerData ate_ctid1;  /* inserted, deleted, or old updated tuple */
02967 }   AfterTriggerEventDataOneCtid;
02968 
02969 #define SizeofTriggerEvent(evt) \
02970     (((evt)->ate_flags & AFTER_TRIGGER_2CTIDS) ? \
02971      sizeof(AfterTriggerEventData) : sizeof(AfterTriggerEventDataOneCtid))
02972 
02973 #define GetTriggerSharedData(evt) \
02974     ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
02975 
02976 /*
02977  * To avoid palloc overhead, we keep trigger events in arrays in successively-
02978  * larger chunks (a slightly more sophisticated version of an expansible
02979  * array).  The space between CHUNK_DATA_START and freeptr is occupied by
02980  * AfterTriggerEventData records; the space between endfree and endptr is
02981  * occupied by AfterTriggerSharedData records.
02982  */
02983 typedef struct AfterTriggerEventChunk
02984 {
02985     struct AfterTriggerEventChunk *next;        /* list link */
02986     char       *freeptr;        /* start of free space in chunk */
02987     char       *endfree;        /* end of free space in chunk */
02988     char       *endptr;         /* end of chunk */
02989     /* event data follows here */
02990 } AfterTriggerEventChunk;
02991 
02992 #define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
02993 
02994 /* A list of events */
02995 typedef struct AfterTriggerEventList
02996 {
02997     AfterTriggerEventChunk *head;
02998     AfterTriggerEventChunk *tail;
02999     char       *tailfree;       /* freeptr of tail chunk */
03000 } AfterTriggerEventList;
03001 
03002 /* Macros to help in iterating over a list of events */
03003 #define for_each_chunk(cptr, evtlist) \
03004     for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
03005 #define for_each_event(eptr, cptr) \
03006     for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
03007          (char *) eptr < (cptr)->freeptr; \
03008          eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
03009 /* Use this if no special per-chunk processing is needed */
03010 #define for_each_event_chunk(eptr, cptr, evtlist) \
03011     for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
03012 
03013 
03014 /*
03015  * All per-transaction data for the AFTER TRIGGERS module.
03016  *
03017  * AfterTriggersData has the following fields:
03018  *
03019  * firing_counter is incremented for each call of afterTriggerInvokeEvents.
03020  * We mark firable events with the current firing cycle's ID so that we can
03021  * tell which ones to work on.  This ensures sane behavior if a trigger
03022  * function chooses to do SET CONSTRAINTS: the inner SET CONSTRAINTS will
03023  * only fire those events that weren't already scheduled for firing.
03024  *
03025  * state keeps track of the transaction-local effects of SET CONSTRAINTS.
03026  * This is saved and restored across failed subtransactions.
03027  *
03028  * events is the current list of deferred events.  This is global across
03029  * all subtransactions of the current transaction.  In a subtransaction
03030  * abort, we know that the events added by the subtransaction are at the
03031  * end of the list, so it is relatively easy to discard them.  The event
03032  * list chunks themselves are stored in event_cxt.
03033  *
03034  * query_depth is the current depth of nested AfterTriggerBeginQuery calls
03035  * (-1 when the stack is empty).
03036  *
03037  * query_stack[query_depth] is a list of AFTER trigger events queued by the
03038  * current query (and the query_stack entries below it are lists of trigger
03039  * events queued by calling queries).  None of these are valid until the
03040  * matching AfterTriggerEndQuery call occurs.  At that point we fire
03041  * immediate-mode triggers, and append any deferred events to the main events
03042  * list.
03043  *
03044  * maxquerydepth is just the allocated length of query_stack.
03045  *
03046  * state_stack is a stack of pointers to saved copies of the SET CONSTRAINTS
03047  * state data; each subtransaction level that modifies that state first
03048  * saves a copy, which we use to restore the state if we abort.
03049  *
03050  * events_stack is a stack of copies of the events head/tail pointers,
03051  * which we use to restore those values during subtransaction abort.
03052  *
03053  * depth_stack is a stack of copies of subtransaction-start-time query_depth,
03054  * which we similarly use to clean up at subtransaction abort.
03055  *
03056  * firing_stack is a stack of copies of subtransaction-start-time
03057  * firing_counter.  We use this to recognize which deferred triggers were
03058  * fired (or marked for firing) within an aborted subtransaction.
03059  *
03060  * We use GetCurrentTransactionNestLevel() to determine the correct array
03061  * index in these stacks.  maxtransdepth is the number of allocated entries in
03062  * each stack.  (By not keeping our own stack pointer, we can avoid trouble
03063  * in cases where errors during subxact abort cause multiple invocations
03064  * of AfterTriggerEndSubXact() at the same nesting depth.)
03065  */
03066 typedef struct AfterTriggersData
03067 {
03068     CommandId   firing_counter; /* next firing ID to assign */
03069     SetConstraintState state;   /* the active S C state */
03070     AfterTriggerEventList events;       /* deferred-event list */
03071     int         query_depth;    /* current query list index */
03072     AfterTriggerEventList *query_stack; /* events pending from each query */
03073     int         maxquerydepth;  /* allocated len of above array */
03074     MemoryContext event_cxt;    /* memory context for events, if any */
03075 
03076     /* these fields are just for resetting at subtrans abort: */
03077 
03078     SetConstraintState *state_stack;    /* stacked S C states */
03079     AfterTriggerEventList *events_stack;        /* stacked list pointers */
03080     int        *depth_stack;    /* stacked query_depths */
03081     CommandId  *firing_stack;   /* stacked firing_counters */
03082     int         maxtransdepth;  /* allocated len of above arrays */
03083 } AfterTriggersData;
03084 
03085 typedef AfterTriggersData *AfterTriggers;
03086 
03087 static AfterTriggers afterTriggers;
03088 
03089 
03090 static void AfterTriggerExecute(AfterTriggerEvent event,
03091                     Relation rel, TriggerDesc *trigdesc,
03092                     FmgrInfo *finfo,
03093                     Instrumentation *instr,
03094                     MemoryContext per_tuple_context);
03095 static SetConstraintState SetConstraintStateCreate(int numalloc);
03096 static SetConstraintState SetConstraintStateCopy(SetConstraintState state);
03097 static SetConstraintState SetConstraintStateAddItem(SetConstraintState state,
03098                           Oid tgoid, bool tgisdeferred);
03099 
03100 
03101 /* ----------
03102  * afterTriggerCheckState()
03103  *
03104  *  Returns true if the trigger event is actually in state DEFERRED.
03105  * ----------
03106  */
03107 static bool
03108 afterTriggerCheckState(AfterTriggerShared evtshared)
03109 {
03110     Oid         tgoid = evtshared->ats_tgoid;
03111     SetConstraintState state = afterTriggers->state;
03112     int         i;
03113 
03114     /*
03115      * For not-deferrable triggers (i.e. normal AFTER ROW triggers and
03116      * constraints declared NOT DEFERRABLE), the state is always false.
03117      */
03118     if ((evtshared->ats_event & AFTER_TRIGGER_DEFERRABLE) == 0)
03119         return false;
03120 
03121     /*
03122      * Check if SET CONSTRAINTS has been executed for this specific trigger.
03123      */
03124     for (i = 0; i < state->numstates; i++)
03125     {
03126         if (state->trigstates[i].sct_tgoid == tgoid)
03127             return state->trigstates[i].sct_tgisdeferred;
03128     }
03129 
03130     /*
03131      * Check if SET CONSTRAINTS ALL has been executed; if so use that.
03132      */
03133     if (state->all_isset)
03134         return state->all_isdeferred;
03135 
03136     /*
03137      * Otherwise return the default state for the trigger.
03138      */
03139     return ((evtshared->ats_event & AFTER_TRIGGER_INITDEFERRED) != 0);
03140 }
03141 
03142 
03143 /* ----------
03144  * afterTriggerAddEvent()
03145  *
03146  *  Add a new trigger event to the specified queue.
03147  *  The passed-in event data is copied.
03148  * ----------
03149  */
03150 static void
03151 afterTriggerAddEvent(AfterTriggerEventList *events,
03152                      AfterTriggerEvent event, AfterTriggerShared evtshared)
03153 {
03154     Size        eventsize = SizeofTriggerEvent(event);
03155     Size        needed = eventsize + sizeof(AfterTriggerSharedData);
03156     AfterTriggerEventChunk *chunk;
03157     AfterTriggerShared newshared;
03158     AfterTriggerEvent newevent;
03159 
03160     /*
03161      * If empty list or not enough room in the tail chunk, make a new chunk.
03162      * We assume here that a new shared record will always be needed.
03163      */
03164     chunk = events->tail;
03165     if (chunk == NULL ||
03166         chunk->endfree - chunk->freeptr < needed)
03167     {
03168         Size        chunksize;
03169 
03170         /* Create event context if we didn't already */
03171         if (afterTriggers->event_cxt == NULL)
03172             afterTriggers->event_cxt =
03173                 AllocSetContextCreate(TopTransactionContext,
03174                                       "AfterTriggerEvents",
03175                                       ALLOCSET_DEFAULT_MINSIZE,
03176                                       ALLOCSET_DEFAULT_INITSIZE,
03177                                       ALLOCSET_DEFAULT_MAXSIZE);
03178 
03179         /*
03180          * Chunk size starts at 1KB and is allowed to increase up to 1MB.
03181          * These numbers are fairly arbitrary, though there is a hard limit at
03182          * AFTER_TRIGGER_OFFSET; else we couldn't link event records to their
03183          * shared records using the available space in ate_flags.  Another
03184          * constraint is that if the chunk size gets too huge, the search loop
03185          * below would get slow given a (not too common) usage pattern with
03186          * many distinct event types in a chunk.  Therefore, we double the
03187          * preceding chunk size only if there weren't too many shared records
03188          * in the preceding chunk; otherwise we halve it.  This gives us some
03189          * ability to adapt to the actual usage pattern of the current query
03190          * while still having large chunk sizes in typical usage.  All chunk
03191          * sizes used should be MAXALIGN multiples, to ensure that the shared
03192          * records will be aligned safely.
03193          */
03194 #define MIN_CHUNK_SIZE 1024
03195 #define MAX_CHUNK_SIZE (1024*1024)
03196 
03197 #if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
03198 #error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
03199 #endif
03200 
03201         if (chunk == NULL)
03202             chunksize = MIN_CHUNK_SIZE;
03203         else
03204         {
03205             /* preceding chunk size... */
03206             chunksize = chunk->endptr - (char *) chunk;
03207             /* check number of shared records in preceding chunk */
03208             if ((chunk->endptr - chunk->endfree) <=
03209                 (100 * sizeof(AfterTriggerSharedData)))
03210                 chunksize *= 2; /* okay, double it */
03211             else
03212                 chunksize /= 2; /* too many shared records */
03213             chunksize = Min(chunksize, MAX_CHUNK_SIZE);
03214         }
03215         chunk = MemoryContextAlloc(afterTriggers->event_cxt, chunksize);
03216         chunk->next = NULL;
03217         chunk->freeptr = CHUNK_DATA_START(chunk);
03218         chunk->endptr = chunk->endfree = (char *) chunk + chunksize;
03219         Assert(chunk->endfree - chunk->freeptr >= needed);
03220 
03221         if (events->head == NULL)
03222             events->head = chunk;
03223         else
03224             events->tail->next = chunk;
03225         events->tail = chunk;
03226         /* events->tailfree is now out of sync, but we'll fix it below */
03227     }
03228 
03229     /*
03230      * Try to locate a matching shared-data record already in the chunk. If
03231      * none, make a new one.
03232      */
03233     for (newshared = ((AfterTriggerShared) chunk->endptr) - 1;
03234          (char *) newshared >= chunk->endfree;
03235          newshared--)
03236     {
03237         if (newshared->ats_tgoid == evtshared->ats_tgoid &&
03238             newshared->ats_relid == evtshared->ats_relid &&
03239             newshared->ats_event == evtshared->ats_event &&
03240             newshared->ats_firing_id == 0)
03241             break;
03242     }
03243     if ((char *) newshared < chunk->endfree)
03244     {
03245         *newshared = *evtshared;
03246         newshared->ats_firing_id = 0;   /* just to be sure */
03247         chunk->endfree = (char *) newshared;
03248     }
03249 
03250     /* Insert the data */
03251     newevent = (AfterTriggerEvent) chunk->freeptr;
03252     memcpy(newevent, event, eventsize);
03253     /* ... and link the new event to its shared record */
03254     newevent->ate_flags &= ~AFTER_TRIGGER_OFFSET;
03255     newevent->ate_flags |= (char *) newshared - (char *) newevent;
03256 
03257     chunk->freeptr += eventsize;
03258     events->tailfree = chunk->freeptr;
03259 }
03260 
03261 /* ----------
03262  * afterTriggerFreeEventList()
03263  *
03264  *  Free all the event storage in the given list.
03265  * ----------
03266  */
03267 static void
03268 afterTriggerFreeEventList(AfterTriggerEventList *events)
03269 {
03270     AfterTriggerEventChunk *chunk;
03271     AfterTriggerEventChunk *next_chunk;
03272 
03273     for (chunk = events->head; chunk != NULL; chunk = next_chunk)
03274     {
03275         next_chunk = chunk->next;
03276         pfree(chunk);
03277     }
03278     events->head = NULL;
03279     events->tail = NULL;
03280     events->tailfree = NULL;
03281 }
03282 
03283 /* ----------
03284  * afterTriggerRestoreEventList()
03285  *
03286  *  Restore an event list to its prior length, removing all the events
03287  *  added since it had the value old_events.
03288  * ----------
03289  */
03290 static void
03291 afterTriggerRestoreEventList(AfterTriggerEventList *events,
03292                              const AfterTriggerEventList *old_events)
03293 {
03294     AfterTriggerEventChunk *chunk;
03295     AfterTriggerEventChunk *next_chunk;
03296 
03297     if (old_events->tail == NULL)
03298     {
03299         /* restoring to a completely empty state, so free everything */
03300         afterTriggerFreeEventList(events);
03301     }
03302     else
03303     {
03304         *events = *old_events;
03305         /* free any chunks after the last one we want to keep */
03306         for (chunk = events->tail->next; chunk != NULL; chunk = next_chunk)
03307         {
03308             next_chunk = chunk->next;
03309             pfree(chunk);
03310         }
03311         /* and clean up the tail chunk to be the right length */
03312         events->tail->next = NULL;
03313         events->tail->freeptr = events->tailfree;
03314 
03315         /*
03316          * We don't make any effort to remove now-unused shared data records.
03317          * They might still be useful, anyway.
03318          */
03319     }
03320 }
03321 
03322 
03323 /* ----------
03324  * AfterTriggerExecute()
03325  *
03326  *  Fetch the required tuples back from the heap and fire one
03327  *  single trigger function.
03328  *
03329  *  Frequently, this will be fired many times in a row for triggers of
03330  *  a single relation.  Therefore, we cache the open relation and provide
03331  *  fmgr lookup cache space at the caller level.  (For triggers fired at
03332  *  the end of a query, we can even piggyback on the executor's state.)
03333  *
03334  *  event: event currently being fired.
03335  *  rel: open relation for event.
03336  *  trigdesc: working copy of rel's trigger info.
03337  *  finfo: array of fmgr lookup cache entries (one per trigger in trigdesc).
03338  *  instr: array of EXPLAIN ANALYZE instrumentation nodes (one per trigger),
03339  *      or NULL if no instrumentation is wanted.
03340  *  per_tuple_context: memory context to call trigger function in.
03341  * ----------
03342  */
03343 static void
03344 AfterTriggerExecute(AfterTriggerEvent event,
03345                     Relation rel, TriggerDesc *trigdesc,
03346                     FmgrInfo *finfo, Instrumentation *instr,
03347                     MemoryContext per_tuple_context)
03348 {
03349     AfterTriggerShared evtshared = GetTriggerSharedData(event);
03350     Oid         tgoid = evtshared->ats_tgoid;
03351     TriggerData LocTriggerData;
03352     HeapTupleData tuple1;
03353     HeapTupleData tuple2;
03354     HeapTuple   rettuple;
03355     Buffer      buffer1 = InvalidBuffer;
03356     Buffer      buffer2 = InvalidBuffer;
03357     int         tgindx;
03358 
03359     /*
03360      * Locate trigger in trigdesc.
03361      */
03362     LocTriggerData.tg_trigger = NULL;
03363     for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++)
03364     {
03365         if (trigdesc->triggers[tgindx].tgoid == tgoid)
03366         {
03367             LocTriggerData.tg_trigger = &(trigdesc->triggers[tgindx]);
03368             break;
03369         }
03370     }
03371     if (LocTriggerData.tg_trigger == NULL)
03372         elog(ERROR, "could not find trigger %u", tgoid);
03373 
03374     /*
03375      * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want
03376      * to include time spent re-fetching tuples in the trigger cost.
03377      */
03378     if (instr)
03379         InstrStartNode(instr + tgindx);
03380 
03381     /*
03382      * Fetch the required tuple(s).
03383      */
03384     if (ItemPointerIsValid(&(event->ate_ctid1)))
03385     {
03386         ItemPointerCopy(&(event->ate_ctid1), &(tuple1.t_self));
03387         if (!heap_fetch(rel, SnapshotAny, &tuple1, &buffer1, false, NULL))
03388             elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
03389         LocTriggerData.tg_trigtuple = &tuple1;
03390         LocTriggerData.tg_trigtuplebuf = buffer1;
03391     }
03392     else
03393     {
03394         LocTriggerData.tg_trigtuple = NULL;
03395         LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
03396     }
03397 
03398     /* don't touch ctid2 if not there */
03399     if ((event->ate_flags & AFTER_TRIGGER_2CTIDS) &&
03400         ItemPointerIsValid(&(event->ate_ctid2)))
03401     {
03402         ItemPointerCopy(&(event->ate_ctid2), &(tuple2.t_self));
03403         if (!heap_fetch(rel, SnapshotAny, &tuple2, &buffer2, false, NULL))
03404             elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
03405         LocTriggerData.tg_newtuple = &tuple2;
03406         LocTriggerData.tg_newtuplebuf = buffer2;
03407     }
03408     else
03409     {
03410         LocTriggerData.tg_newtuple = NULL;
03411         LocTriggerData.tg_newtuplebuf = InvalidBuffer;
03412     }
03413 
03414     /*
03415      * Setup the remaining trigger information
03416      */
03417     LocTriggerData.type = T_TriggerData;
03418     LocTriggerData.tg_event =
03419         evtshared->ats_event & (TRIGGER_EVENT_OPMASK | TRIGGER_EVENT_ROW);
03420     LocTriggerData.tg_relation = rel;
03421 
03422     MemoryContextReset(per_tuple_context);
03423 
03424     /*
03425      * Call the trigger and throw away any possibly returned updated tuple.
03426      * (Don't let ExecCallTriggerFunc measure EXPLAIN time.)
03427      */
03428     rettuple = ExecCallTriggerFunc(&LocTriggerData,
03429                                    tgindx,
03430                                    finfo,
03431                                    NULL,
03432                                    per_tuple_context);
03433     if (rettuple != NULL && rettuple != &tuple1 && rettuple != &tuple2)
03434         heap_freetuple(rettuple);
03435 
03436     /*
03437      * Release buffers
03438      */
03439     if (buffer1 != InvalidBuffer)
03440         ReleaseBuffer(buffer1);
03441     if (buffer2 != InvalidBuffer)
03442         ReleaseBuffer(buffer2);
03443 
03444     /*
03445      * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
03446      * one "tuple returned" (really the number of firings).
03447      */
03448     if (instr)
03449         InstrStopNode(instr + tgindx, 1);
03450 }
03451 
03452 
03453 /*
03454  * afterTriggerMarkEvents()
03455  *
03456  *  Scan the given event list for not yet invoked events.  Mark the ones
03457  *  that can be invoked now with the current firing ID.
03458  *
03459  *  If move_list isn't NULL, events that are not to be invoked now are
03460  *  transferred to move_list.
03461  *
03462  *  When immediate_only is TRUE, do not invoke currently-deferred triggers.
03463  *  (This will be FALSE only at main transaction exit.)
03464  *
03465  *  Returns TRUE if any invokable events were found.
03466  */
03467 static bool
03468 afterTriggerMarkEvents(AfterTriggerEventList *events,
03469                        AfterTriggerEventList *move_list,
03470                        bool immediate_only)
03471 {
03472     bool        found = false;
03473     AfterTriggerEvent event;
03474     AfterTriggerEventChunk *chunk;
03475 
03476     for_each_event_chunk(event, chunk, *events)
03477     {
03478         AfterTriggerShared evtshared = GetTriggerSharedData(event);
03479         bool        defer_it = false;
03480 
03481         if (!(event->ate_flags &
03482               (AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS)))
03483         {
03484             /*
03485              * This trigger hasn't been called or scheduled yet. Check if we
03486              * should call it now.
03487              */
03488             if (immediate_only && afterTriggerCheckState(evtshared))
03489             {
03490                 defer_it = true;
03491             }
03492             else
03493             {
03494                 /*
03495                  * Mark it as to be fired in this firing cycle.
03496                  */
03497                 evtshared->ats_firing_id = afterTriggers->firing_counter;
03498                 event->ate_flags |= AFTER_TRIGGER_IN_PROGRESS;
03499                 found = true;
03500             }
03501         }
03502 
03503         /*
03504          * If it's deferred, move it to move_list, if requested.
03505          */
03506         if (defer_it && move_list != NULL)
03507         {
03508             /* add it to move_list */
03509             afterTriggerAddEvent(move_list, event, evtshared);
03510             /* mark original copy "done" so we don't do it again */
03511             event->ate_flags |= AFTER_TRIGGER_DONE;
03512         }
03513     }
03514 
03515     return found;
03516 }
03517 
03518 /*
03519  * afterTriggerInvokeEvents()
03520  *
03521  *  Scan the given event list for events that are marked as to be fired
03522  *  in the current firing cycle, and fire them.
03523  *
03524  *  If estate isn't NULL, we use its result relation info to avoid repeated
03525  *  openings and closing of trigger target relations.  If it is NULL, we
03526  *  make one locally to cache the info in case there are multiple trigger
03527  *  events per rel.
03528  *
03529  *  When delete_ok is TRUE, it's safe to delete fully-processed events.
03530  *  (We are not very tense about that: we simply reset a chunk to be empty
03531  *  if all its events got fired.  The objective here is just to avoid useless
03532  *  rescanning of events when a trigger queues new events during transaction
03533  *  end, so it's not necessary to worry much about the case where only
03534  *  some events are fired.)
03535  *
03536  *  Returns TRUE if no unfired events remain in the list (this allows us
03537  *  to avoid repeating afterTriggerMarkEvents).
03538  */
03539 static bool
03540 afterTriggerInvokeEvents(AfterTriggerEventList *events,
03541                          CommandId firing_id,
03542                          EState *estate,
03543                          bool delete_ok)
03544 {
03545     bool        all_fired = true;
03546     AfterTriggerEventChunk *chunk;
03547     MemoryContext per_tuple_context;
03548     bool        local_estate = false;
03549     Relation    rel = NULL;
03550     TriggerDesc *trigdesc = NULL;
03551     FmgrInfo   *finfo = NULL;
03552     Instrumentation *instr = NULL;
03553 
03554     /* Make a local EState if need be */
03555     if (estate == NULL)
03556     {
03557         estate = CreateExecutorState();
03558         local_estate = true;
03559     }
03560 
03561     /* Make a per-tuple memory context for trigger function calls */
03562     per_tuple_context =
03563         AllocSetContextCreate(CurrentMemoryContext,
03564                               "AfterTriggerTupleContext",
03565                               ALLOCSET_DEFAULT_MINSIZE,
03566                               ALLOCSET_DEFAULT_INITSIZE,
03567                               ALLOCSET_DEFAULT_MAXSIZE);
03568 
03569     for_each_chunk(chunk, *events)
03570     {
03571         AfterTriggerEvent event;
03572         bool        all_fired_in_chunk = true;
03573 
03574         for_each_event(event, chunk)
03575         {
03576             AfterTriggerShared evtshared = GetTriggerSharedData(event);
03577 
03578             /*
03579              * Is it one for me to fire?
03580              */
03581             if ((event->ate_flags & AFTER_TRIGGER_IN_PROGRESS) &&
03582                 evtshared->ats_firing_id == firing_id)
03583             {
03584                 /*
03585                  * So let's fire it... but first, find the correct relation if
03586                  * this is not the same relation as before.
03587                  */
03588                 if (rel == NULL || RelationGetRelid(rel) != evtshared->ats_relid)
03589                 {
03590                     ResultRelInfo *rInfo;
03591 
03592                     rInfo = ExecGetTriggerResultRel(estate, evtshared->ats_relid);
03593                     rel = rInfo->ri_RelationDesc;
03594                     trigdesc = rInfo->ri_TrigDesc;
03595                     finfo = rInfo->ri_TrigFunctions;
03596                     instr = rInfo->ri_TrigInstrument;
03597                     if (trigdesc == NULL)       /* should not happen */
03598                         elog(ERROR, "relation %u has no triggers",
03599                              evtshared->ats_relid);
03600                 }
03601 
03602                 /*
03603                  * Fire it.  Note that the AFTER_TRIGGER_IN_PROGRESS flag is
03604                  * still set, so recursive examinations of the event list
03605                  * won't try to re-fire it.
03606                  */
03607                 AfterTriggerExecute(event, rel, trigdesc, finfo, instr,
03608                                     per_tuple_context);
03609 
03610                 /*
03611                  * Mark the event as done.
03612                  */
03613                 event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
03614                 event->ate_flags |= AFTER_TRIGGER_DONE;
03615             }
03616             else if (!(event->ate_flags & AFTER_TRIGGER_DONE))
03617             {
03618                 /* something remains to be done */
03619                 all_fired = all_fired_in_chunk = false;
03620             }
03621         }
03622 
03623         /* Clear the chunk if delete_ok and nothing left of interest */
03624         if (delete_ok && all_fired_in_chunk)
03625         {
03626             chunk->freeptr = CHUNK_DATA_START(chunk);
03627             chunk->endfree = chunk->endptr;
03628 
03629             /*
03630              * If it's last chunk, must sync event list's tailfree too.  Note
03631              * that delete_ok must NOT be passed as true if there could be
03632              * stacked AfterTriggerEventList values pointing at this event
03633              * list, since we'd fail to fix their copies of tailfree.
03634              */
03635             if (chunk == events->tail)
03636                 events->tailfree = chunk->freeptr;
03637         }
03638     }
03639 
03640     /* Release working resources */
03641     MemoryContextDelete(per_tuple_context);
03642 
03643     if (local_estate)
03644     {
03645         ListCell   *l;
03646 
03647         foreach(l, estate->es_trig_target_relations)
03648         {
03649             ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
03650 
03651             /* Close indices and then the relation itself */
03652             ExecCloseIndices(resultRelInfo);
03653             heap_close(resultRelInfo->ri_RelationDesc, NoLock);
03654         }
03655         FreeExecutorState(estate);
03656     }
03657 
03658     return all_fired;
03659 }
03660 
03661 
03662 /* ----------
03663  * AfterTriggerBeginXact()
03664  *
03665  *  Called at transaction start (either BEGIN or implicit for single
03666  *  statement outside of transaction block).
03667  * ----------
03668  */
03669 void
03670 AfterTriggerBeginXact(void)
03671 {
03672     Assert(afterTriggers == NULL);
03673 
03674     /*
03675      * Build empty after-trigger state structure
03676      */
03677     afterTriggers = (AfterTriggers)
03678         MemoryContextAlloc(TopTransactionContext,
03679                            sizeof(AfterTriggersData));
03680 
03681     afterTriggers->firing_counter = (CommandId) 1;      /* mustn't be 0 */
03682     afterTriggers->state = SetConstraintStateCreate(8);
03683     afterTriggers->events.head = NULL;
03684     afterTriggers->events.tail = NULL;
03685     afterTriggers->events.tailfree = NULL;
03686     afterTriggers->query_depth = -1;
03687 
03688     /* We initialize the query stack to a reasonable size */
03689     afterTriggers->query_stack = (AfterTriggerEventList *)
03690         MemoryContextAlloc(TopTransactionContext,
03691                            8 * sizeof(AfterTriggerEventList));
03692     afterTriggers->maxquerydepth = 8;
03693 
03694     /* Context for events is created only when needed */
03695     afterTriggers->event_cxt = NULL;
03696 
03697     /* Subtransaction stack is empty until/unless needed */
03698     afterTriggers->state_stack = NULL;
03699     afterTriggers->events_stack = NULL;
03700     afterTriggers->depth_stack = NULL;
03701     afterTriggers->firing_stack = NULL;
03702     afterTriggers->maxtransdepth = 0;
03703 }
03704 
03705 
03706 /* ----------
03707  * AfterTriggerBeginQuery()
03708  *
03709  *  Called just before we start processing a single query within a
03710  *  transaction (or subtransaction).  Set up to record AFTER trigger
03711  *  events queued by the query.  Note that it is allowed to have
03712  *  nested queries within a (sub)transaction.
03713  * ----------
03714  */
03715 void
03716 AfterTriggerBeginQuery(void)
03717 {
03718     AfterTriggerEventList *events;
03719 
03720     /* Must be inside a transaction */
03721     Assert(afterTriggers != NULL);
03722 
03723     /* Increase the query stack depth */
03724     afterTriggers->query_depth++;
03725 
03726     /*
03727      * Allocate more space in the query stack if needed.
03728      */
03729     if (afterTriggers->query_depth >= afterTriggers->maxquerydepth)
03730     {
03731         /* repalloc will keep the stack in the same context */
03732         int         new_alloc = afterTriggers->maxquerydepth * 2;
03733 
03734         afterTriggers->query_stack = (AfterTriggerEventList *)
03735             repalloc(afterTriggers->query_stack,
03736                      new_alloc * sizeof(AfterTriggerEventList));
03737         afterTriggers->maxquerydepth = new_alloc;
03738     }
03739 
03740     /* Initialize this query's list to empty */
03741     events = &afterTriggers->query_stack[afterTriggers->query_depth];
03742     events->head = NULL;
03743     events->tail = NULL;
03744     events->tailfree = NULL;
03745 }
03746 
03747 
03748 /* ----------
03749  * AfterTriggerEndQuery()
03750  *
03751  *  Called after one query has been completely processed. At this time
03752  *  we invoke all AFTER IMMEDIATE trigger events queued by the query, and
03753  *  transfer deferred trigger events to the global deferred-trigger list.
03754  *
03755  *  Note that this must be called BEFORE closing down the executor
03756  *  with ExecutorEnd, because we make use of the EState's info about
03757  *  target relations.  Normally it is called from ExecutorFinish.
03758  * ----------
03759  */
03760 void
03761 AfterTriggerEndQuery(EState *estate)
03762 {
03763     AfterTriggerEventList *events;
03764 
03765     /* Must be inside a transaction */
03766     Assert(afterTriggers != NULL);
03767 
03768     /* Must be inside a query, too */
03769     Assert(afterTriggers->query_depth >= 0);
03770 
03771     /*
03772      * Process all immediate-mode triggers queued by the query, and move the
03773      * deferred ones to the main list of deferred events.
03774      *
03775      * Notice that we decide which ones will be fired, and put the deferred
03776      * ones on the main list, before anything is actually fired.  This ensures
03777      * reasonably sane behavior if a trigger function does SET CONSTRAINTS ...
03778      * IMMEDIATE: all events we have decided to defer will be available for it
03779      * to fire.
03780      *
03781      * We loop in case a trigger queues more events at the same query level
03782      * (is that even possible?).  Be careful here: firing a trigger could
03783      * result in query_stack being repalloc'd, so we can't save its address
03784      * across afterTriggerInvokeEvents calls.
03785      *
03786      * If we find no firable events, we don't have to increment
03787      * firing_counter.
03788      */
03789     for (;;)
03790     {
03791         events = &afterTriggers->query_stack[afterTriggers->query_depth];
03792         if (afterTriggerMarkEvents(events, &afterTriggers->events, true))
03793         {
03794             CommandId   firing_id = afterTriggers->firing_counter++;
03795 
03796             /* OK to delete the immediate events after processing them */
03797             if (afterTriggerInvokeEvents(events, firing_id, estate, true))
03798                 break;          /* all fired */
03799         }
03800         else
03801             break;
03802     }
03803 
03804     /* Release query-local storage for events */
03805     afterTriggerFreeEventList(&afterTriggers->query_stack[afterTriggers->query_depth]);
03806 
03807     afterTriggers->query_depth--;
03808 }
03809 
03810 
03811 /* ----------
03812  * AfterTriggerFireDeferred()
03813  *
03814  *  Called just before the current transaction is committed. At this
03815  *  time we invoke all pending DEFERRED triggers.
03816  *
03817  *  It is possible for other modules to queue additional deferred triggers
03818  *  during pre-commit processing; therefore xact.c may have to call this
03819  *  multiple times.
03820  * ----------
03821  */
03822 void
03823 AfterTriggerFireDeferred(void)
03824 {
03825     AfterTriggerEventList *events;
03826     bool        snap_pushed = false;
03827 
03828     /* Must be inside a transaction */
03829     Assert(afterTriggers != NULL);
03830 
03831     /* ... but not inside a query */
03832     Assert(afterTriggers->query_depth == -1);
03833 
03834     /*
03835      * If there are any triggers to fire, make sure we have set a snapshot for
03836      * them to use.  (Since PortalRunUtility doesn't set a snap for COMMIT, we
03837      * can't assume ActiveSnapshot is valid on entry.)
03838      */
03839     events = &afterTriggers->events;
03840     if (events->head != NULL)
03841     {
03842         PushActiveSnapshot(GetTransactionSnapshot());
03843         snap_pushed = true;
03844     }
03845 
03846     /*
03847      * Run all the remaining triggers.  Loop until they are all gone, in case
03848      * some trigger queues more for us to do.
03849      */
03850     while (afterTriggerMarkEvents(events, NULL, false))
03851     {
03852         CommandId   firing_id = afterTriggers->firing_counter++;
03853 
03854         if (afterTriggerInvokeEvents(events, firing_id, NULL, true))
03855             break;              /* all fired */
03856     }
03857 
03858     /*
03859      * We don't bother freeing the event list, since it will go away anyway
03860      * (and more efficiently than via pfree) in AfterTriggerEndXact.
03861      */
03862 
03863     if (snap_pushed)
03864         PopActiveSnapshot();
03865 }
03866 
03867 
03868 /* ----------
03869  * AfterTriggerEndXact()
03870  *
03871  *  The current transaction is finishing.
03872  *
03873  *  Any unfired triggers are canceled so we simply throw
03874  *  away anything we know.
03875  *
03876  *  Note: it is possible for this to be called repeatedly in case of
03877  *  error during transaction abort; therefore, do not complain if
03878  *  already closed down.
03879  * ----------
03880  */
03881 void
03882 AfterTriggerEndXact(bool isCommit)
03883 {
03884     /*
03885      * Forget everything we know about AFTER triggers.
03886      *
03887      * Since all the info is in TopTransactionContext or children thereof, we
03888      * don't really need to do anything to reclaim memory.  However, the
03889      * pending-events list could be large, and so it's useful to discard it as
03890      * soon as possible --- especially if we are aborting because we ran out
03891      * of memory for the list!
03892      */
03893     if (afterTriggers && afterTriggers->event_cxt)
03894         MemoryContextDelete(afterTriggers->event_cxt);
03895 
03896     afterTriggers = NULL;
03897 }
03898 
03899 /*
03900  * AfterTriggerBeginSubXact()
03901  *
03902  *  Start a subtransaction.
03903  */
03904 void
03905 AfterTriggerBeginSubXact(void)
03906 {
03907     int         my_level = GetCurrentTransactionNestLevel();
03908 
03909     /*
03910      * Ignore call if the transaction is in aborted state.  (Probably
03911      * shouldn't happen?)
03912      */
03913     if (afterTriggers == NULL)
03914         return;
03915 
03916     /*
03917      * Allocate more space in the stacks if needed.  (Note: because the
03918      * minimum nest level of a subtransaction is 2, we waste the first couple
03919      * entries of each array; not worth the notational effort to avoid it.)
03920      */
03921     while (my_level >= afterTriggers->maxtransdepth)
03922     {
03923         if (afterTriggers->maxtransdepth == 0)
03924         {
03925             MemoryContext old_cxt;
03926 
03927             old_cxt = MemoryContextSwitchTo(TopTransactionContext);
03928 
03929 #define DEFTRIG_INITALLOC 8
03930             afterTriggers->state_stack = (SetConstraintState *)
03931                 palloc(DEFTRIG_INITALLOC * sizeof(SetConstraintState));
03932             afterTriggers->events_stack = (AfterTriggerEventList *)
03933                 palloc(DEFTRIG_INITALLOC * sizeof(AfterTriggerEventList));
03934             afterTriggers->depth_stack = (int *)
03935                 palloc(DEFTRIG_INITALLOC * sizeof(int));
03936             afterTriggers->firing_stack = (CommandId *)
03937                 palloc(DEFTRIG_INITALLOC * sizeof(CommandId));
03938             afterTriggers->maxtransdepth = DEFTRIG_INITALLOC;
03939 
03940             MemoryContextSwitchTo(old_cxt);
03941         }
03942         else
03943         {
03944             /* repalloc will keep the stacks in the same context */
03945             int         new_alloc = afterTriggers->maxtransdepth * 2;
03946 
03947             afterTriggers->state_stack = (SetConstraintState *)
03948                 repalloc(afterTriggers->state_stack,
03949                          new_alloc * sizeof(SetConstraintState));
03950             afterTriggers->events_stack = (AfterTriggerEventList *)
03951                 repalloc(afterTriggers->events_stack,
03952                          new_alloc * sizeof(AfterTriggerEventList));
03953             afterTriggers->depth_stack = (int *)
03954                 repalloc(afterTriggers->depth_stack,
03955                          new_alloc * sizeof(int));
03956             afterTriggers->firing_stack = (CommandId *)
03957                 repalloc(afterTriggers->firing_stack,
03958                          new_alloc * sizeof(CommandId));
03959             afterTriggers->maxtransdepth = new_alloc;
03960         }
03961     }
03962 
03963     /*
03964      * Push the current information into the stack.  The SET CONSTRAINTS state
03965      * is not saved until/unless changed.  Likewise, we don't make a
03966      * per-subtransaction event context until needed.
03967      */
03968     afterTriggers->state_stack[my_level] = NULL;
03969     afterTriggers->events_stack[my_level] = afterTriggers->events;
03970     afterTriggers->depth_stack[my_level] = afterTriggers->query_depth;
03971     afterTriggers->firing_stack[my_level] = afterTriggers->firing_counter;
03972 }
03973 
03974 /*
03975  * AfterTriggerEndSubXact()
03976  *
03977  *  The current subtransaction is ending.
03978  */
03979 void
03980 AfterTriggerEndSubXact(bool isCommit)
03981 {
03982     int         my_level = GetCurrentTransactionNestLevel();
03983     SetConstraintState state;
03984     AfterTriggerEvent event;
03985     AfterTriggerEventChunk *chunk;
03986     CommandId   subxact_firing_id;
03987 
03988     /*
03989      * Ignore call if the transaction is in aborted state.  (Probably
03990      * unneeded)
03991      */
03992     if (afterTriggers == NULL)
03993         return;
03994 
03995     /*
03996      * Pop the prior state if needed.
03997      */
03998     if (isCommit)
03999     {
04000         Assert(my_level < afterTriggers->maxtransdepth);
04001         /* If we saved a prior state, we don't need it anymore */
04002         state = afterTriggers->state_stack[my_level];
04003         if (state != NULL)
04004             pfree(state);
04005         /* this avoids double pfree if error later: */
04006         afterTriggers->state_stack[my_level] = NULL;
04007         Assert(afterTriggers->query_depth ==
04008                afterTriggers->depth_stack[my_level]);
04009     }
04010     else
04011     {
04012         /*
04013          * Aborting.  It is possible subxact start failed before calling
04014          * AfterTriggerBeginSubXact, in which case we mustn't risk touching
04015          * stack levels that aren't there.
04016          */
04017         if (my_level >= afterTriggers->maxtransdepth)
04018             return;
04019 
04020         /*
04021          * Release any event lists from queries being aborted, and restore
04022          * query_depth to its pre-subxact value.
04023          */
04024         while (afterTriggers->query_depth > afterTriggers->depth_stack[my_level])
04025         {
04026             afterTriggerFreeEventList(&afterTriggers->query_stack[afterTriggers->query_depth]);
04027             afterTriggers->query_depth--;
04028         }
04029         Assert(afterTriggers->query_depth ==
04030                afterTriggers->depth_stack[my_level]);
04031 
04032         /*
04033          * Restore the global deferred-event list to its former length,
04034          * discarding any events queued by the subxact.
04035          */
04036         afterTriggerRestoreEventList(&afterTriggers->events,
04037                                      &afterTriggers->events_stack[my_level]);
04038 
04039         /*
04040          * Restore the trigger state.  If the saved state is NULL, then this
04041          * subxact didn't save it, so it doesn't need restoring.
04042          */
04043         state = afterTriggers->state_stack[my_level];
04044         if (state != NULL)
04045         {
04046             pfree(afterTriggers->state);
04047             afterTriggers->state = state;
04048         }
04049         /* this avoids double pfree if error later: */
04050         afterTriggers->state_stack[my_level] = NULL;
04051 
04052         /*
04053          * Scan for any remaining deferred events that were marked DONE or IN
04054          * PROGRESS by this subxact or a child, and un-mark them. We can
04055          * recognize such events because they have a firing ID greater than or
04056          * equal to the firing_counter value we saved at subtransaction start.
04057          * (This essentially assumes that the current subxact includes all
04058          * subxacts started after it.)
04059          */
04060         subxact_firing_id = afterTriggers->firing_stack[my_level];
04061         for_each_event_chunk(event, chunk, afterTriggers->events)
04062         {
04063             AfterTriggerShared evtshared = GetTriggerSharedData(event);
04064 
04065             if (event->ate_flags &
04066                 (AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS))
04067             {
04068                 if (evtshared->ats_firing_id >= subxact_firing_id)
04069                     event->ate_flags &=
04070                         ~(AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS);
04071             }
04072         }
04073     }
04074 }
04075 
04076 /*
04077  * Create an empty SetConstraintState with room for numalloc trigstates
04078  */
04079 static SetConstraintState
04080 SetConstraintStateCreate(int numalloc)
04081 {
04082     SetConstraintState state;
04083 
04084     /* Behave sanely with numalloc == 0 */
04085     if (numalloc <= 0)
04086         numalloc = 1;
04087 
04088     /*
04089      * We assume that zeroing will correctly initialize the state values.
04090      */
04091     state = (SetConstraintState)
04092         MemoryContextAllocZero(TopTransactionContext,
04093                                sizeof(SetConstraintStateData) +
04094                            (numalloc - 1) *sizeof(SetConstraintTriggerData));
04095 
04096     state->numalloc = numalloc;
04097 
04098     return state;
04099 }
04100 
04101 /*
04102  * Copy a SetConstraintState
04103  */
04104 static SetConstraintState
04105 SetConstraintStateCopy(SetConstraintState origstate)
04106 {
04107     SetConstraintState state;
04108 
04109     state = SetConstraintStateCreate(origstate->numstates);
04110 
04111     state->all_isset = origstate->all_isset;
04112     state->all_isdeferred = origstate->all_isdeferred;
04113     state->numstates = origstate->numstates;
04114     memcpy(state->trigstates, origstate->trigstates,
04115            origstate->numstates * sizeof(SetConstraintTriggerData));
04116 
04117     return state;
04118 }
04119 
04120 /*
04121  * Add a per-trigger item to a SetConstraintState.  Returns possibly-changed
04122  * pointer to the state object (it will change if we have to repalloc).
04123  */
04124 static SetConstraintState
04125 SetConstraintStateAddItem(SetConstraintState state,
04126                           Oid tgoid, bool tgisdeferred)
04127 {
04128     if (state->numstates >= state->numalloc)
04129     {
04130         int         newalloc = state->numalloc * 2;
04131 
04132         newalloc = Max(newalloc, 8);    /* in case original has size 0 */
04133         state = (SetConstraintState)
04134             repalloc(state,
04135                      sizeof(SetConstraintStateData) +
04136                      (newalloc - 1) *sizeof(SetConstraintTriggerData));
04137         state->numalloc = newalloc;
04138         Assert(state->numstates < state->numalloc);
04139     }
04140 
04141     state->trigstates[state->numstates].sct_tgoid = tgoid;
04142     state->trigstates[state->numstates].sct_tgisdeferred = tgisdeferred;
04143     state->numstates++;
04144 
04145     return state;
04146 }
04147 
04148 /* ----------
04149  * AfterTriggerSetState()
04150  *
04151  *  Execute the SET CONSTRAINTS ... utility command.
04152  * ----------
04153  */
04154 void
04155 AfterTriggerSetState(ConstraintsSetStmt *stmt)
04156 {
04157     int         my_level = GetCurrentTransactionNestLevel();
04158 
04159     /*
04160      * Ignore call if we aren't in a transaction.  (Shouldn't happen?)
04161      */
04162     if (afterTriggers == NULL)
04163         return;
04164 
04165     /*
04166      * If in a subtransaction, and we didn't save the current state already,
04167      * save it so it can be restored if the subtransaction aborts.
04168      */
04169     if (my_level > 1 &&
04170         afterTriggers->state_stack[my_level] == NULL)
04171     {
04172         afterTriggers->state_stack[my_level] =
04173             SetConstraintStateCopy(afterTriggers->state);
04174     }
04175 
04176     /*
04177      * Handle SET CONSTRAINTS ALL ...
04178      */
04179     if (stmt->constraints == NIL)
04180     {
04181         /*
04182          * Forget any previous SET CONSTRAINTS commands in this transaction.
04183          */
04184         afterTriggers->state->numstates = 0;
04185 
04186         /*
04187          * Set the per-transaction ALL state to known.
04188          */
04189         afterTriggers->state->all_isset = true;
04190         afterTriggers->state->all_isdeferred = stmt->deferred;
04191     }
04192     else
04193     {
04194         Relation    conrel;
04195         Relation    tgrel;
04196         List       *conoidlist = NIL;
04197         List       *tgoidlist = NIL;
04198         ListCell   *lc;
04199 
04200         /*
04201          * Handle SET CONSTRAINTS constraint-name [, ...]
04202          *
04203          * First, identify all the named constraints and make a list of their
04204          * OIDs.  Since, unlike the SQL spec, we allow multiple constraints of
04205          * the same name within a schema, the specifications are not
04206          * necessarily unique.  Our strategy is to target all matching
04207          * constraints within the first search-path schema that has any
04208          * matches, but disregard matches in schemas beyond the first match.
04209          * (This is a bit odd but it's the historical behavior.)
04210          */
04211         conrel = heap_open(ConstraintRelationId, AccessShareLock);
04212 
04213         foreach(lc, stmt->constraints)
04214         {
04215             RangeVar   *constraint = lfirst(lc);
04216             bool        found;
04217             List       *namespacelist;
04218             ListCell   *nslc;
04219 
04220             if (constraint->catalogname)
04221             {
04222                 if (strcmp(constraint->catalogname, get_database_name(MyDatabaseId)) != 0)
04223                     ereport(ERROR,
04224                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
04225                              errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
04226                              constraint->catalogname, constraint->schemaname,
04227                                     constraint->relname)));
04228             }
04229 
04230             /*
04231              * If we're given the schema name with the constraint, look only
04232              * in that schema.  If given a bare constraint name, use the
04233              * search path to find the first matching constraint.
04234              */
04235             if (constraint->schemaname)
04236             {
04237                 Oid         namespaceId = LookupExplicitNamespace(constraint->schemaname,
04238                                                                   false);
04239 
04240                 namespacelist = list_make1_oid(namespaceId);
04241             }
04242             else
04243             {
04244                 namespacelist = fetch_search_path(true);
04245             }
04246 
04247             found = false;
04248             foreach(nslc, namespacelist)
04249             {
04250                 Oid         namespaceId = lfirst_oid(nslc);
04251                 SysScanDesc conscan;
04252                 ScanKeyData skey[2];
04253                 HeapTuple   tup;
04254 
04255                 ScanKeyInit(&skey[0],
04256                             Anum_pg_constraint_conname,
04257                             BTEqualStrategyNumber, F_NAMEEQ,
04258                             CStringGetDatum(constraint->relname));
04259                 ScanKeyInit(&skey[1],
04260                             Anum_pg_constraint_connamespace,
04261                             BTEqualStrategyNumber, F_OIDEQ,
04262                             ObjectIdGetDatum(namespaceId));
04263 
04264                 conscan = systable_beginscan(conrel, ConstraintNameNspIndexId,
04265                                              true, SnapshotNow, 2, skey);
04266 
04267                 while (HeapTupleIsValid(tup = systable_getnext(conscan)))
04268                 {
04269                     Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup);
04270 
04271                     if (con->condeferrable)
04272                         conoidlist = lappend_oid(conoidlist,
04273                                                  HeapTupleGetOid(tup));
04274                     else if (stmt->deferred)
04275                         ereport(ERROR,
04276                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
04277                                  errmsg("constraint \"%s\" is not deferrable",
04278                                         constraint->relname)));
04279                     found = true;
04280                 }
04281 
04282                 systable_endscan(conscan);
04283 
04284                 /*
04285                  * Once we've found a matching constraint we do not search
04286                  * later parts of the search path.
04287                  */
04288                 if (found)
04289                     break;
04290             }
04291 
04292             list_free(namespacelist);
04293 
04294             /*
04295              * Not found ?
04296              */
04297             if (!found)
04298                 ereport(ERROR,
04299                         (errcode(ERRCODE_UNDEFINED_OBJECT),
04300                          errmsg("constraint \"%s\" does not exist",
04301                                 constraint->relname)));
04302         }
04303 
04304         heap_close(conrel, AccessShareLock);
04305 
04306         /*
04307          * Now, locate the trigger(s) implementing each of these constraints,
04308          * and make a list of their OIDs.
04309          */
04310         tgrel = heap_open(TriggerRelationId, AccessShareLock);
04311 
04312         foreach(lc, conoidlist)
04313         {
04314             Oid         conoid = lfirst_oid(lc);
04315             bool        found;
04316             ScanKeyData skey;
04317             SysScanDesc tgscan;
04318             HeapTuple   htup;
04319 
04320             found = false;
04321 
04322             ScanKeyInit(&skey,
04323                         Anum_pg_trigger_tgconstraint,
04324                         BTEqualStrategyNumber, F_OIDEQ,
04325                         ObjectIdGetDatum(conoid));
04326 
04327             tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
04328                                         SnapshotNow, 1, &skey);
04329 
04330             while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
04331             {
04332                 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
04333 
04334                 /*
04335                  * Silently skip triggers that are marked as non-deferrable in
04336                  * pg_trigger.  This is not an error condition, since a
04337                  * deferrable RI constraint may have some non-deferrable
04338                  * actions.
04339                  */
04340                 if (pg_trigger->tgdeferrable)
04341                     tgoidlist = lappend_oid(tgoidlist,
04342                                             HeapTupleGetOid(htup));
04343 
04344                 found = true;
04345             }
04346 
04347             systable_endscan(tgscan);
04348 
04349             /* Safety check: a deferrable constraint should have triggers */
04350             if (!found)
04351                 elog(ERROR, "no triggers found for constraint with OID %u",
04352                      conoid);
04353         }
04354 
04355         heap_close(tgrel, AccessShareLock);
04356 
04357         /*
04358          * Now we can set the trigger states of individual triggers for this
04359          * xact.
04360          */
04361         foreach(lc, tgoidlist)
04362         {
04363             Oid         tgoid = lfirst_oid(lc);
04364             SetConstraintState state = afterTriggers->state;
04365             bool        found = false;
04366             int         i;
04367 
04368             for (i = 0; i < state->numstates; i++)
04369             {
04370                 if (state->trigstates[i].sct_tgoid == tgoid)
04371                 {
04372                     state->trigstates[i].sct_tgisdeferred = stmt->deferred;
04373                     found = true;
04374                     break;
04375                 }
04376             }
04377             if (!found)
04378             {
04379                 afterTriggers->state =
04380                     SetConstraintStateAddItem(state, tgoid, stmt->deferred);
04381             }
04382         }
04383     }
04384 
04385     /*
04386      * SQL99 requires that when a constraint is set to IMMEDIATE, any deferred
04387      * checks against that constraint must be made when the SET CONSTRAINTS
04388      * command is executed -- i.e. the effects of the SET CONSTRAINTS command
04389      * apply retroactively.  We've updated the constraints state, so scan the
04390      * list of previously deferred events to fire any that have now become
04391      * immediate.
04392      *
04393      * Obviously, if this was SET ... DEFERRED then it can't have converted
04394      * any unfired events to immediate, so we need do nothing in that case.
04395      */
04396     if (!stmt->deferred)
04397     {
04398         AfterTriggerEventList *events = &afterTriggers->events;
04399         bool        snapshot_set = false;
04400 
04401         while (afterTriggerMarkEvents(events, NULL, true))
04402         {
04403             CommandId   firing_id = afterTriggers->firing_counter++;
04404 
04405             /*
04406              * Make sure a snapshot has been established in case trigger
04407              * functions need one.  Note that we avoid setting a snapshot if
04408              * we don't find at least one trigger that has to be fired now.
04409              * This is so that BEGIN; SET CONSTRAINTS ...; SET TRANSACTION
04410              * ISOLATION LEVEL SERIALIZABLE; ... works properly.  (If we are
04411              * at the start of a transaction it's not possible for any trigger
04412              * events to be queued yet.)
04413              */
04414             if (!snapshot_set)
04415             {
04416                 PushActiveSnapshot(GetTransactionSnapshot());
04417                 snapshot_set = true;
04418             }
04419 
04420             /*
04421              * We can delete fired events if we are at top transaction level,
04422              * but we'd better not if inside a subtransaction, since the
04423              * subtransaction could later get rolled back.
04424              */
04425             if (afterTriggerInvokeEvents(events, firing_id, NULL,
04426                                          !IsSubTransaction()))
04427                 break;          /* all fired */
04428         }
04429 
04430         if (snapshot_set)
04431             PopActiveSnapshot();
04432     }
04433 }
04434 
04435 /* ----------
04436  * AfterTriggerPendingOnRel()
04437  *      Test to see if there are any pending after-trigger events for rel.
04438  *
04439  * This is used by TRUNCATE, CLUSTER, ALTER TABLE, etc to detect whether
04440  * it is unsafe to perform major surgery on a relation.  Note that only
04441  * local pending events are examined.  We assume that having exclusive lock
04442  * on a rel guarantees there are no unserviced events in other backends ---
04443  * but having a lock does not prevent there being such events in our own.
04444  *
04445  * In some scenarios it'd be reasonable to remove pending events (more
04446  * specifically, mark them DONE by the current subxact) but without a lot
04447  * of knowledge of the trigger semantics we can't do this in general.
04448  * ----------
04449  */
04450 bool
04451 AfterTriggerPendingOnRel(Oid relid)
04452 {
04453     AfterTriggerEvent event;
04454     AfterTriggerEventChunk *chunk;
04455     int         depth;
04456 
04457     /* No-op if we aren't in a transaction.  (Shouldn't happen?) */
04458     if (afterTriggers == NULL)
04459         return false;
04460 
04461     /* Scan queued events */
04462     for_each_event_chunk(event, chunk, afterTriggers->events)
04463     {
04464         AfterTriggerShared evtshared = GetTriggerSharedData(event);
04465 
04466         /*
04467          * We can ignore completed events.  (Even if a DONE flag is rolled
04468          * back by subxact abort, it's OK because the effects of the TRUNCATE
04469          * or whatever must get rolled back too.)
04470          */
04471         if (event->ate_flags & AFTER_TRIGGER_DONE)
04472             continue;
04473 
04474         if (evtshared->ats_relid == relid)
04475             return true;
04476     }
04477 
04478     /*
04479      * Also scan events queued by incomplete queries.  This could only matter
04480      * if TRUNCATE/etc is executed by a function or trigger within an updating
04481      * query on the same relation, which is pretty perverse, but let's check.
04482      */
04483     for (depth = 0; depth <= afterTriggers->query_depth; depth++)
04484     {
04485         for_each_event_chunk(event, chunk, afterTriggers->query_stack[depth])
04486         {
04487             AfterTriggerShared evtshared = GetTriggerSharedData(event);
04488 
04489             if (event->ate_flags & AFTER_TRIGGER_DONE)
04490                 continue;
04491 
04492             if (evtshared->ats_relid == relid)
04493                 return true;
04494         }
04495     }
04496 
04497     return false;
04498 }
04499 
04500 
04501 /* ----------
04502  * AfterTriggerSaveEvent()
04503  *
04504  *  Called by ExecA[RS]...Triggers() to queue up the triggers that should
04505  *  be fired for an event.
04506  *
04507  *  NOTE: this is called whenever there are any triggers associated with
04508  *  the event (even if they are disabled).  This function decides which
04509  *  triggers actually need to be queued.
04510  * ----------
04511  */
04512 static void
04513 AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
04514                       int event, bool row_trigger,
04515                       HeapTuple oldtup, HeapTuple newtup,
04516                       List *recheckIndexes, Bitmapset *modifiedCols)
04517 {
04518     Relation    rel = relinfo->ri_RelationDesc;
04519     TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
04520     AfterTriggerEventData new_event;
04521     AfterTriggerSharedData new_shared;
04522     int         tgtype_event;
04523     int         tgtype_level;
04524     int         i;
04525 
04526     /*
04527      * Check state.  We use normal tests not Asserts because it is possible to
04528      * reach here in the wrong state given misconfigured RI triggers, in
04529      * particular deferring a cascade action trigger.
04530      */
04531     if (afterTriggers == NULL)
04532         elog(ERROR, "AfterTriggerSaveEvent() called outside of transaction");
04533     if (afterTriggers->query_depth < 0)
04534         elog(ERROR, "AfterTriggerSaveEvent() called outside of query");
04535 
04536     /*
04537      * Validate the event code and collect the associated tuple CTIDs.
04538      *
04539      * The event code will be used both as a bitmask and an array offset, so
04540      * validation is important to make sure we don't walk off the edge of our
04541      * arrays.
04542      */
04543     new_event.ate_flags = 0;
04544     switch (event)
04545     {
04546         case TRIGGER_EVENT_INSERT:
04547             tgtype_event = TRIGGER_TYPE_INSERT;
04548             if (row_trigger)
04549             {
04550                 Assert(oldtup == NULL);
04551                 Assert(newtup != NULL);
04552                 ItemPointerCopy(&(newtup->t_self), &(new_event.ate_ctid1));
04553                 ItemPointerSetInvalid(&(new_event.ate_ctid2));
04554             }
04555             else
04556             {
04557                 Assert(oldtup == NULL);
04558                 Assert(newtup == NULL);
04559                 ItemPointerSetInvalid(&(new_event.ate_ctid1));
04560                 ItemPointerSetInvalid(&(new_event.ate_ctid2));
04561             }
04562             break;
04563         case TRIGGER_EVENT_DELETE:
04564             tgtype_event = TRIGGER_TYPE_DELETE;
04565             if (row_trigger)
04566             {
04567                 Assert(oldtup != NULL);
04568                 Assert(newtup == NULL);
04569                 ItemPointerCopy(&(oldtup->t_self), &(new_event.ate_ctid1));
04570                 ItemPointerSetInvalid(&(new_event.ate_ctid2));
04571             }
04572             else
04573             {
04574                 Assert(oldtup == NULL);
04575                 Assert(newtup == NULL);
04576                 ItemPointerSetInvalid(&(new_event.ate_ctid1));
04577                 ItemPointerSetInvalid(&(new_event.ate_ctid2));
04578             }
04579             break;
04580         case TRIGGER_EVENT_UPDATE:
04581             tgtype_event = TRIGGER_TYPE_UPDATE;
04582             if (row_trigger)
04583             {
04584                 Assert(oldtup != NULL);
04585                 Assert(newtup != NULL);
04586                 ItemPointerCopy(&(oldtup->t_self), &(new_event.ate_ctid1));
04587                 ItemPointerCopy(&(newtup->t_self), &(new_event.ate_ctid2));
04588                 new_event.ate_flags |= AFTER_TRIGGER_2CTIDS;
04589             }
04590             else
04591             {
04592                 Assert(oldtup == NULL);
04593                 Assert(newtup == NULL);
04594                 ItemPointerSetInvalid(&(new_event.ate_ctid1));
04595                 ItemPointerSetInvalid(&(new_event.ate_ctid2));
04596             }
04597             break;
04598         case TRIGGER_EVENT_TRUNCATE:
04599             tgtype_event = TRIGGER_TYPE_TRUNCATE;
04600             Assert(oldtup == NULL);
04601             Assert(newtup == NULL);
04602             ItemPointerSetInvalid(&(new_event.ate_ctid1));
04603             ItemPointerSetInvalid(&(new_event.ate_ctid2));
04604             break;
04605         default:
04606             elog(ERROR, "invalid after-trigger event code: %d", event);
04607             tgtype_event = 0;   /* keep compiler quiet */
04608             break;
04609     }
04610 
04611     tgtype_level = (row_trigger ? TRIGGER_TYPE_ROW : TRIGGER_TYPE_STATEMENT);
04612 
04613     for (i = 0; i < trigdesc->numtriggers; i++)
04614     {
04615         Trigger    *trigger = &trigdesc->triggers[i];
04616 
04617         if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
04618                                   tgtype_level,
04619                                   TRIGGER_TYPE_AFTER,
04620                                   tgtype_event))
04621             continue;
04622         if (!TriggerEnabled(estate, relinfo, trigger, event,
04623                             modifiedCols, oldtup, newtup))
04624             continue;
04625 
04626         /*
04627          * If the trigger is a foreign key enforcement trigger, there are
04628          * certain cases where we can skip queueing the event because we can
04629          * tell by inspection that the FK constraint will still pass.
04630          */
04631         if (TRIGGER_FIRED_BY_UPDATE(event))
04632         {
04633             switch (RI_FKey_trigger_type(trigger->tgfoid))
04634             {
04635                 case RI_TRIGGER_PK:
04636                     /* Update on trigger's PK table */
04637                     if (!RI_FKey_pk_upd_check_required(trigger, rel,
04638                                                        oldtup, newtup))
04639                     {
04640                         /* skip queuing this event */
04641                         continue;
04642                     }
04643                     break;
04644 
04645                 case RI_TRIGGER_FK:
04646                     /* Update on trigger's FK table */
04647                     if (!RI_FKey_fk_upd_check_required(trigger, rel,
04648                                                        oldtup, newtup))
04649                     {
04650                         /* skip queuing this event */
04651                         continue;
04652                     }
04653                     break;
04654 
04655                 case RI_TRIGGER_NONE:
04656                     /* Not an FK trigger */
04657                     break;
04658             }
04659         }
04660 
04661         /*
04662          * If the trigger is a deferred unique constraint check trigger, only
04663          * queue it if the unique constraint was potentially violated, which
04664          * we know from index insertion time.
04665          */
04666         if (trigger->tgfoid == F_UNIQUE_KEY_RECHECK)
04667         {
04668             if (!list_member_oid(recheckIndexes, trigger->tgconstrindid))
04669                 continue;       /* Uniqueness definitely not violated */
04670         }
04671 
04672         /*
04673          * Fill in event structure and add it to the current query's queue.
04674          */
04675         new_shared.ats_event =
04676             (event & TRIGGER_EVENT_OPMASK) |
04677             (row_trigger ? TRIGGER_EVENT_ROW : 0) |
04678             (trigger->tgdeferrable ? AFTER_TRIGGER_DEFERRABLE : 0) |
04679             (trigger->tginitdeferred ? AFTER_TRIGGER_INITDEFERRED : 0);
04680         new_shared.ats_tgoid = trigger->tgoid;
04681         new_shared.ats_relid = RelationGetRelid(rel);
04682         new_shared.ats_firing_id = 0;
04683 
04684         afterTriggerAddEvent(&afterTriggers->query_stack[afterTriggers->query_depth],
04685                              &new_event, &new_shared);
04686     }
04687 }
04688 
04689 Datum
04690 pg_trigger_depth(PG_FUNCTION_ARGS)
04691 {
04692     PG_RETURN_INT32(MyTriggerDepth);
04693 }