summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/include')
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_trigger.h31
-rw-r--r--src/include/commands/trigger.h58
-rw-r--r--src/include/nodes/parsenodes.h5
-rw-r--r--src/include/utils/rel.h41
5 files changed, 92 insertions, 45 deletions
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index c9212ab584b..910474cdcfc 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201009281
+#define CATALOG_VERSION_NO 201010101
#endif
diff --git a/src/include/catalog/pg_trigger.h b/src/include/catalog/pg_trigger.h
index 46285ac3038..4eb72f20916 100644
--- a/src/include/catalog/pg_trigger.h
+++ b/src/include/catalog/pg_trigger.h
@@ -38,7 +38,7 @@ CATALOG(pg_trigger,2620)
Oid tgrelid; /* relation trigger is attached to */
NameData tgname; /* trigger's name */
Oid tgfoid; /* OID of function to be called */
- int2 tgtype; /* BEFORE/AFTER UPDATE/DELETE/INSERT
+ int2 tgtype; /* BEFORE/AFTER/INSTEAD, UPDATE/DELETE/INSERT,
* ROW/STATEMENT; see below */
char tgenabled; /* trigger's firing configuration WRT
* session_replication_role */
@@ -91,22 +91,49 @@ typedef FormData_pg_trigger *Form_pg_trigger;
#define TRIGGER_TYPE_DELETE (1 << 3)
#define TRIGGER_TYPE_UPDATE (1 << 4)
#define TRIGGER_TYPE_TRUNCATE (1 << 5)
+#define TRIGGER_TYPE_INSTEAD (1 << 6)
+
+#define TRIGGER_TYPE_LEVEL_MASK (TRIGGER_TYPE_ROW)
+#define TRIGGER_TYPE_STATEMENT 0
+
+/* Note bits within TRIGGER_TYPE_TIMING_MASK aren't adjacent */
+#define TRIGGER_TYPE_TIMING_MASK \
+ (TRIGGER_TYPE_BEFORE | TRIGGER_TYPE_INSTEAD)
+#define TRIGGER_TYPE_AFTER 0
+
+#define TRIGGER_TYPE_EVENT_MASK \
+ (TRIGGER_TYPE_INSERT | TRIGGER_TYPE_DELETE | TRIGGER_TYPE_UPDATE | TRIGGER_TYPE_TRUNCATE)
/* Macros for manipulating tgtype */
#define TRIGGER_CLEAR_TYPE(type) ((type) = 0)
#define TRIGGER_SETT_ROW(type) ((type) |= TRIGGER_TYPE_ROW)
+#define TRIGGER_SETT_STATEMENT(type) ((type) |= TRIGGER_TYPE_STATEMENT)
#define TRIGGER_SETT_BEFORE(type) ((type) |= TRIGGER_TYPE_BEFORE)
+#define TRIGGER_SETT_AFTER(type) ((type) |= TRIGGER_TYPE_AFTER)
+#define TRIGGER_SETT_INSTEAD(type) ((type) |= TRIGGER_TYPE_INSTEAD)
#define TRIGGER_SETT_INSERT(type) ((type) |= TRIGGER_TYPE_INSERT)
#define TRIGGER_SETT_DELETE(type) ((type) |= TRIGGER_TYPE_DELETE)
#define TRIGGER_SETT_UPDATE(type) ((type) |= TRIGGER_TYPE_UPDATE)
#define TRIGGER_SETT_TRUNCATE(type) ((type) |= TRIGGER_TYPE_TRUNCATE)
#define TRIGGER_FOR_ROW(type) ((type) & TRIGGER_TYPE_ROW)
-#define TRIGGER_FOR_BEFORE(type) ((type) & TRIGGER_TYPE_BEFORE)
+#define TRIGGER_FOR_BEFORE(type) (((type) & TRIGGER_TYPE_TIMING_MASK) == TRIGGER_TYPE_BEFORE)
+#define TRIGGER_FOR_AFTER(type) (((type) & TRIGGER_TYPE_TIMING_MASK) == TRIGGER_TYPE_AFTER)
+#define TRIGGER_FOR_INSTEAD(type) (((type) & TRIGGER_TYPE_TIMING_MASK) == TRIGGER_TYPE_INSTEAD)
#define TRIGGER_FOR_INSERT(type) ((type) & TRIGGER_TYPE_INSERT)
#define TRIGGER_FOR_DELETE(type) ((type) & TRIGGER_TYPE_DELETE)
#define TRIGGER_FOR_UPDATE(type) ((type) & TRIGGER_TYPE_UPDATE)
#define TRIGGER_FOR_TRUNCATE(type) ((type) & TRIGGER_TYPE_TRUNCATE)
+/*
+ * Efficient macro for checking if tgtype matches a particular level
+ * (TRIGGER_TYPE_ROW or TRIGGER_TYPE_STATEMENT), timing (TRIGGER_TYPE_BEFORE,
+ * TRIGGER_TYPE_AFTER or TRIGGER_TYPE_INSTEAD), and event (TRIGGER_TYPE_INSERT,
+ * TRIGGER_TYPE_DELETE, TRIGGER_TYPE_UPDATE, or TRIGGER_TYPE_TRUNCATE). Note
+ * that a tgtype can match more than one event, but only one level or timing.
+ */
+#define TRIGGER_TYPE_MATCHES(type, level, timing, event) \
+ (((type) & (TRIGGER_TYPE_LEVEL_MASK | TRIGGER_TYPE_TIMING_MASK | (event))) == ((level) | (timing) | (event)))
+
#endif /* PG_TRIGGER_H */
diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h
index 08bb22a3681..30dc314c00d 100644
--- a/src/include/commands/trigger.h
+++ b/src/include/commands/trigger.h
@@ -51,44 +51,48 @@ typedef struct TriggerData
#define TRIGGER_EVENT_UPDATE 0x00000002
#define TRIGGER_EVENT_TRUNCATE 0x00000003
#define TRIGGER_EVENT_OPMASK 0x00000003
+
#define TRIGGER_EVENT_ROW 0x00000004
+
#define TRIGGER_EVENT_BEFORE 0x00000008
+#define TRIGGER_EVENT_AFTER 0x00000000
+#define TRIGGER_EVENT_INSTEAD 0x00000010
+#define TRIGGER_EVENT_TIMINGMASK 0x00000018
/* More TriggerEvent flags, used only within trigger.c */
-#define AFTER_TRIGGER_DEFERRABLE 0x00000010
-#define AFTER_TRIGGER_INITDEFERRED 0x00000020
+#define AFTER_TRIGGER_DEFERRABLE 0x00000020
+#define AFTER_TRIGGER_INITDEFERRED 0x00000040
-#define TRIGGER_FIRED_BY_INSERT(event) \
- (((TriggerEvent) (event) & TRIGGER_EVENT_OPMASK) == \
- TRIGGER_EVENT_INSERT)
+#define TRIGGER_FIRED_BY_INSERT(event) \
+ (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_INSERT)
-#define TRIGGER_FIRED_BY_DELETE(event) \
- (((TriggerEvent) (event) & TRIGGER_EVENT_OPMASK) == \
- TRIGGER_EVENT_DELETE)
+#define TRIGGER_FIRED_BY_DELETE(event) \
+ (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_DELETE)
-#define TRIGGER_FIRED_BY_UPDATE(event) \
- (((TriggerEvent) (event) & TRIGGER_EVENT_OPMASK) == \
- TRIGGER_EVENT_UPDATE)
+#define TRIGGER_FIRED_BY_UPDATE(event) \
+ (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_UPDATE)
#define TRIGGER_FIRED_BY_TRUNCATE(event) \
- (((TriggerEvent) (event) & TRIGGER_EVENT_OPMASK) == \
- TRIGGER_EVENT_TRUNCATE)
+ (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_TRUNCATE)
+
+#define TRIGGER_FIRED_FOR_ROW(event) \
+ ((event) & TRIGGER_EVENT_ROW)
-#define TRIGGER_FIRED_FOR_ROW(event) \
- ((TriggerEvent) (event) & TRIGGER_EVENT_ROW)
+#define TRIGGER_FIRED_FOR_STATEMENT(event) \
+ (!TRIGGER_FIRED_FOR_ROW(event))
-#define TRIGGER_FIRED_FOR_STATEMENT(event) \
- (!TRIGGER_FIRED_FOR_ROW (event))
+#define TRIGGER_FIRED_BEFORE(event) \
+ (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_BEFORE)
-#define TRIGGER_FIRED_BEFORE(event) \
- ((TriggerEvent) (event) & TRIGGER_EVENT_BEFORE)
+#define TRIGGER_FIRED_AFTER(event) \
+ (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_AFTER)
-#define TRIGGER_FIRED_AFTER(event) \
- (!TRIGGER_FIRED_BEFORE (event))
+#define TRIGGER_FIRED_INSTEAD(event) \
+ (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_INSTEAD)
/*
- * Definitions for the replication role based firing.
+ * Definitions for replication role based firing.
*/
#define SESSION_REPLICATION_ROLE_ORIGIN 0
#define SESSION_REPLICATION_ROLE_REPLICA 1
@@ -135,6 +139,9 @@ extern void ExecARInsertTriggers(EState *estate,
ResultRelInfo *relinfo,
HeapTuple trigtuple,
List *recheckIndexes);
+extern HeapTuple ExecIRInsertTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ HeapTuple trigtuple);
extern void ExecBSDeleteTriggers(EState *estate,
ResultRelInfo *relinfo);
extern void ExecASDeleteTriggers(EState *estate,
@@ -146,6 +153,9 @@ extern bool ExecBRDeleteTriggers(EState *estate,
extern void ExecARDeleteTriggers(EState *estate,
ResultRelInfo *relinfo,
ItemPointer tupleid);
+extern bool ExecIRDeleteTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ HeapTuple trigtuple);
extern void ExecBSUpdateTriggers(EState *estate,
ResultRelInfo *relinfo);
extern void ExecASUpdateTriggers(EState *estate,
@@ -160,6 +170,10 @@ extern void ExecARUpdateTriggers(EState *estate,
ItemPointer tupleid,
HeapTuple newtuple,
List *recheckIndexes);
+extern HeapTuple ExecIRUpdateTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ HeapTuple oldtuple,
+ HeapTuple newtuple);
extern void ExecBSTruncateTriggers(EState *estate,
ResultRelInfo *relinfo);
extern void ExecASTruncateTriggers(EState *estate,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index b2f0fef5139..ca225d06ec1 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1608,10 +1608,11 @@ typedef struct CreateTrigStmt
RangeVar *relation; /* relation trigger is on */
List *funcname; /* qual. name of function to call */
List *args; /* list of (T_String) Values or NIL */
- bool before; /* BEFORE/AFTER */
bool row; /* ROW/STATEMENT */
+ /* timing uses the TRIGGER_TYPE bits defined in catalog/pg_trigger.h */
+ int16 timing; /* BEFORE, AFTER, or INSTEAD */
/* events uses the TRIGGER_TYPE bits defined in catalog/pg_trigger.h */
- int16 events; /* INSERT/UPDATE/DELETE/TRUNCATE */
+ int16 events; /* "OR" of INSERT/UPDATE/DELETE/TRUNCATE */
List *columns; /* column names, or NIL for all columns */
Node *whenClause; /* qual expression, or NULL if none */
bool isconstraint; /* This is a constraint trigger */
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 17ad88820d8..9ad92c299e8 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -71,26 +71,31 @@ typedef struct Trigger
typedef struct TriggerDesc
{
+ Trigger *triggers; /* array of Trigger structs */
+ int numtriggers; /* number of array entries */
+
/*
- * Index data to identify which triggers are which. Since each trigger
- * can appear in more than one class, for each class we provide a list of
- * integer indexes into the triggers array. The class codes are defined
- * by TRIGGER_EVENT_xxx macros in commands/trigger.h.
+ * These flags indicate whether the array contains at least one of each
+ * type of trigger. We use these to skip searching the array if not.
*/
-#define TRIGGER_NUM_EVENT_CLASSES 4
-
- uint16 n_before_statement[TRIGGER_NUM_EVENT_CLASSES];
- uint16 n_before_row[TRIGGER_NUM_EVENT_CLASSES];
- uint16 n_after_row[TRIGGER_NUM_EVENT_CLASSES];
- uint16 n_after_statement[TRIGGER_NUM_EVENT_CLASSES];
- int *tg_before_statement[TRIGGER_NUM_EVENT_CLASSES];
- int *tg_before_row[TRIGGER_NUM_EVENT_CLASSES];
- int *tg_after_row[TRIGGER_NUM_EVENT_CLASSES];
- int *tg_after_statement[TRIGGER_NUM_EVENT_CLASSES];
-
- /* The actual array of triggers is here */
- Trigger *triggers;
- int numtriggers;
+ bool trig_insert_before_row;
+ bool trig_insert_after_row;
+ bool trig_insert_instead_row;
+ bool trig_insert_before_statement;
+ bool trig_insert_after_statement;
+ bool trig_update_before_row;
+ bool trig_update_after_row;
+ bool trig_update_instead_row;
+ bool trig_update_before_statement;
+ bool trig_update_after_statement;
+ bool trig_delete_before_row;
+ bool trig_delete_after_row;
+ bool trig_delete_instead_row;
+ bool trig_delete_before_statement;
+ bool trig_delete_after_statement;
+ /* there are no row-level truncate triggers */
+ bool trig_truncate_before_statement;
+ bool trig_truncate_after_statement;
} TriggerDesc;