aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/trigger.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-12-13 02:00:20 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-12-13 02:00:20 +0000
commitc98a923786fdd5c297e3cd0165e39102094277d8 (patch)
tree278fae9d3cd52d742cb4c93b52200e6a52ea5e6b /src/backend/commands/trigger.c
parent0f864a63ea532a475490d4259608385ad717280c (diff)
downloadpostgresql-c98a923786fdd5c297e3cd0165e39102094277d8.tar.gz
postgresql-c98a923786fdd5c297e3cd0165e39102094277d8.zip
Fix failure to ensure that a snapshot is available to datatype input functions
when they are invoked by the parser. We had been setting up a snapshot at plan time but really it needs to be done earlier, before parse analysis. Per report from Dmitry Koterov. Also fix two related problems discovered while poking at this one: exec_bind_message called datatype input functions without establishing a snapshot, and SET CONSTRAINTS IMMEDIATE could call trigger functions without establishing a snapshot. Backpatch to 8.2. The underlying problem goes much further back, but it is masked in 8.1 and before because we didn't attempt to invoke domain check constraints within datatype input. It would only be exposed if a C-language datatype input function used the snapshot; which evidently none do, or we'd have heard complaints sooner. Since this code has changed a lot over time, a back-patch is hardly risk-free, and so I'm disinclined to patch further than absolutely necessary.
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r--src/backend/commands/trigger.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 7a08ffca5e9..d5d90d57044 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.241 2008/11/21 20:14:27 mha Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.242 2008/12/13 02:00:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -3716,12 +3716,28 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
if (!stmt->deferred)
{
AfterTriggerEventList *events = &afterTriggers->events;
+ bool snapshot_set = false;
while (afterTriggerMarkEvents(events, NULL, true))
{
CommandId firing_id = afterTriggers->firing_counter++;
/*
+ * Make sure a snapshot has been established in case trigger
+ * functions need one. Note that we avoid setting a snapshot if
+ * we don't find at least one trigger that has to be fired now.
+ * This is so that BEGIN; SET CONSTRAINTS ...; SET TRANSACTION
+ * ISOLATION LEVEL SERIALIZABLE; ... works properly. (If we are
+ * at the start of a transaction it's not possible for any trigger
+ * events to be queued yet.)
+ */
+ if (!snapshot_set)
+ {
+ PushActiveSnapshot(GetTransactionSnapshot());
+ snapshot_set = true;
+ }
+
+ /*
* We can delete fired events if we are at top transaction level,
* but we'd better not if inside a subtransaction, since the
* subtransaction could later get rolled back.
@@ -3730,6 +3746,9 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
!IsSubTransaction()))
break; /* all fired */
}
+
+ if (snapshot_set)
+ PopActiveSnapshot();
}
}