Skip to content

Commit c63a545

Browse files
committed
Get rid of ReferentialIntegritySnapshotOverride by extending Executor API
to allow es_snapshot to be set to SnapshotNow rather than a query snapshot. This solves a bug reported by Wade Klaver, wherein triggers fired as a result of RI cascade updates could misbehave.
1 parent 7ab5c5b commit c63a545

File tree

16 files changed

+101
-94
lines changed

16 files changed

+101
-94
lines changed

src/backend/commands/explain.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994-5, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.115 2003/08/11 20:46:46 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.116 2003/09/25 18:58:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -207,7 +207,7 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
207207
gettimeofday(&starttime, NULL);
208208

209209
/* call ExecutorStart to prepare the plan for execution */
210-
ExecutorStart(queryDesc, !stmt->analyze);
210+
ExecutorStart(queryDesc, false, !stmt->analyze);
211211

212212
/* Execute the plan for statistics if asked for */
213213
if (stmt->analyze)

src/backend/commands/trigger.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.157 2003/09/25 06:57:58 petere Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.158 2003/09/25 18:58:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -1862,12 +1862,6 @@ DeferredTriggerExecute(DeferredTriggerEvent event, int itemno,
18621862
if (rettuple != NULL && rettuple != &oldtuple && rettuple != &newtuple)
18631863
heap_freetuple(rettuple);
18641864

1865-
/*
1866-
* Might have been a referential integrity constraint trigger. Reset
1867-
* the snapshot overriding flag.
1868-
*/
1869-
ReferentialIntegritySnapshotOverride = false;
1870-
18711865
/*
18721866
* Release buffers
18731867
*/

src/backend/executor/execMain.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.218 2003/09/25 06:57:59 petere Exp $
29+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.219 2003/09/25 18:58:35 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -104,6 +104,9 @@ static void EvalPlanQualStop(evalPlanQual *epq);
104104
* field of the QueryDesc is filled in to describe the tuples that will be
105105
* returned, and the internal fields (estate and planstate) are set up.
106106
*
107+
* If useSnapshotNow is true, run the query with SnapshotNow time qual rules
108+
* instead of the normal use of QuerySnapshot.
109+
*
107110
* If explainOnly is true, we are not actually intending to run the plan,
108111
* only to set up for EXPLAIN; so skip unwanted side-effects.
109112
*
@@ -112,7 +115,7 @@ static void EvalPlanQualStop(evalPlanQual *epq);
112115
* ----------------------------------------------------------------
113116
*/
114117
void
115-
ExecutorStart(QueryDesc *queryDesc, bool explainOnly)
118+
ExecutorStart(QueryDesc *queryDesc, bool useSnapshotNow, bool explainOnly)
116119
{
117120
EState *estate;
118121
MemoryContext oldcontext;
@@ -154,7 +157,16 @@ ExecutorStart(QueryDesc *queryDesc, bool explainOnly)
154157
* the life of this query, even if it outlives the current command and
155158
* current snapshot.
156159
*/
157-
estate->es_snapshot = CopyQuerySnapshot();
160+
if (useSnapshotNow)
161+
{
162+
estate->es_snapshot = SnapshotNow;
163+
estate->es_snapshot_cid = GetCurrentCommandId();
164+
}
165+
else
166+
{
167+
estate->es_snapshot = CopyQuerySnapshot();
168+
estate->es_snapshot_cid = estate->es_snapshot->curcid;
169+
}
158170

159171
/*
160172
* Initialize the plan state tree
@@ -1106,7 +1118,7 @@ lnext: ;
11061118

11071119
tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
11081120
test = heap_mark4update(erm->relation, &tuple, &buffer,
1109-
estate->es_snapshot->curcid);
1121+
estate->es_snapshot_cid);
11101122
ReleaseBuffer(buffer);
11111123
switch (test)
11121124
{
@@ -1266,7 +1278,7 @@ ExecSelect(TupleTableSlot *slot,
12661278
if (estate->es_into_relation_descriptor != NULL)
12671279
{
12681280
heap_insert(estate->es_into_relation_descriptor, tuple,
1269-
estate->es_snapshot->curcid);
1281+
estate->es_snapshot_cid);
12701282
IncrAppended();
12711283
}
12721284

@@ -1342,7 +1354,7 @@ ExecInsert(TupleTableSlot *slot,
13421354
* insert the tuple
13431355
*/
13441356
newId = heap_insert(resultRelationDesc, tuple,
1345-
estate->es_snapshot->curcid);
1357+
estate->es_snapshot_cid);
13461358

13471359
IncrAppended();
13481360
(estate->es_processed)++;
@@ -1394,7 +1406,7 @@ ExecDelete(TupleTableSlot *slot,
13941406
bool dodelete;
13951407

13961408
dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid,
1397-
estate->es_snapshot->curcid);
1409+
estate->es_snapshot_cid);
13981410

13991411
if (!dodelete) /* "do nothing" */
14001412
return;
@@ -1406,7 +1418,7 @@ ExecDelete(TupleTableSlot *slot,
14061418
ldelete:;
14071419
result = heap_delete(resultRelationDesc, tupleid,
14081420
&ctid,
1409-
estate->es_snapshot->curcid,
1421+
estate->es_snapshot_cid,
14101422
true /* wait for commit */);
14111423
switch (result)
14121424
{
@@ -1505,7 +1517,7 @@ ExecUpdate(TupleTableSlot *slot,
15051517

15061518
newtuple = ExecBRUpdateTriggers(estate, resultRelInfo,
15071519
tupleid, tuple,
1508-
estate->es_snapshot->curcid);
1520+
estate->es_snapshot_cid);
15091521

15101522
if (newtuple == NULL) /* "do nothing" */
15111523
return;
@@ -1541,7 +1553,7 @@ lreplace:;
15411553
*/
15421554
result = heap_update(resultRelationDesc, tupleid, tuple,
15431555
&ctid,
1544-
estate->es_snapshot->curcid,
1556+
estate->es_snapshot_cid,
15451557
true /* wait for commit */);
15461558
switch (result)
15471559
{
@@ -2027,6 +2039,7 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
20272039
*/
20282040
epqstate->es_direction = ForwardScanDirection;
20292041
epqstate->es_snapshot = estate->es_snapshot;
2042+
epqstate->es_snapshot_cid = estate->es_snapshot_cid;
20302043
epqstate->es_range_table = estate->es_range_table;
20312044
epqstate->es_result_relations = estate->es_result_relations;
20322045
epqstate->es_num_result_relations = estate->es_num_result_relations;

src/backend/executor/execUtils.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.104 2003/09/24 18:54:01 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.105 2003/09/25 18:58:35 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -178,6 +178,7 @@ CreateExecutorState(void)
178178
*/
179179
estate->es_direction = ForwardScanDirection;
180180
estate->es_snapshot = SnapshotNow;
181+
estate->es_snapshot_cid = FirstCommandId;
181182
estate->es_range_table = NIL;
182183

183184
estate->es_result_relations = NULL;

src/backend/executor/functions.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.74 2003/09/25 06:57:59 petere Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.75 2003/09/25 18:58:35 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -291,7 +291,7 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
291291

292292
/* Utility commands don't need Executor. */
293293
if (es->qd->operation != CMD_UTILITY)
294-
ExecutorStart(es->qd, false);
294+
ExecutorStart(es->qd, false, false);
295295

296296
es->status = F_EXEC_RUN;
297297
}

src/backend/executor/nodeSubplan.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.56 2003/09/25 06:57:59 petere Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.57 2003/09/25 18:58:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -709,6 +709,7 @@ ExecInitSubPlan(SubPlanState *node, EState *estate)
709709
sp_estate->es_tupleTable =
710710
ExecCreateTupleTable(ExecCountSlotsNode(subplan->plan) + 10);
711711
sp_estate->es_snapshot = estate->es_snapshot;
712+
sp_estate->es_snapshot_cid = estate->es_snapshot_cid;
712713
sp_estate->es_instrument = estate->es_instrument;
713714

714715
/*

src/backend/executor/nodeSubqueryscan.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*
1313
*
1414
* IDENTIFICATION
15-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.20 2003/08/04 02:39:59 momjian Exp $
15+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.21 2003/09/25 18:58:35 tgl Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -177,6 +177,7 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate)
177177
sp_estate->es_tupleTable =
178178
ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10);
179179
sp_estate->es_snapshot = estate->es_snapshot;
180+
sp_estate->es_snapshot_cid = estate->es_snapshot_cid;
180181
sp_estate->es_instrument = estate->es_instrument;
181182

182183
/*

src/backend/executor/spi.c

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.105 2003/09/23 15:11:33 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.106 2003/09/25 18:58:35 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -32,10 +32,12 @@ static int _SPI_connected = -1;
3232
static int _SPI_curid = -1;
3333

3434
static int _SPI_execute(const char *src, int tcount, _SPI_plan *plan);
35-
static int _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount);
35+
static int _SPI_pquery(QueryDesc *queryDesc, bool runit,
36+
bool useSnapshotNow, int tcount);
3637

3738
static int _SPI_execute_plan(_SPI_plan *plan,
38-
Datum *Values, const char *Nulls, int tcount);
39+
Datum *Values, const char *Nulls,
40+
bool useSnapshotNow, int tcount);
3941

4042
static void _SPI_cursor_operation(Portal portal, bool forward, int count,
4143
DestReceiver *dest);
@@ -236,7 +238,33 @@ SPI_execp(void *plan, Datum *Values, const char *Nulls, int tcount)
236238
if (res < 0)
237239
return res;
238240

239-
res = _SPI_execute_plan((_SPI_plan *) plan, Values, Nulls, tcount);
241+
res = _SPI_execute_plan((_SPI_plan *) plan, Values, Nulls, false, tcount);
242+
243+
_SPI_end_call(true);
244+
return res;
245+
}
246+
247+
/*
248+
* SPI_execp_now -- identical to SPI_execp, except that we use SnapshotNow
249+
* instead of the normal QuerySnapshot. This is currently not documented
250+
* in spi.sgml because it is only intended for use by RI triggers.
251+
*/
252+
int
253+
SPI_execp_now(void *plan, Datum *Values, const char *Nulls, int tcount)
254+
{
255+
int res;
256+
257+
if (plan == NULL || tcount < 0)
258+
return SPI_ERROR_ARGUMENT;
259+
260+
if (((_SPI_plan *) plan)->nargs > 0 && Values == NULL)
261+
return SPI_ERROR_PARAM;
262+
263+
res = _SPI_begin_call(true);
264+
if (res < 0)
265+
return res;
266+
267+
res = _SPI_execute_plan((_SPI_plan *) plan, Values, Nulls, true, tcount);
240268

241269
_SPI_end_call(true);
242270
return res;
@@ -1068,7 +1096,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
10681096
{
10691097
qdesc = CreateQueryDesc(queryTree, planTree, dest,
10701098
NULL, false);
1071-
res = _SPI_pquery(qdesc, true,
1099+
res = _SPI_pquery(qdesc, true, false,
10721100
queryTree->canSetTag ? tcount : 0);
10731101
if (res < 0)
10741102
return res;
@@ -1078,7 +1106,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
10781106
{
10791107
qdesc = CreateQueryDesc(queryTree, planTree, dest,
10801108
NULL, false);
1081-
res = _SPI_pquery(qdesc, false, 0);
1109+
res = _SPI_pquery(qdesc, false, false, 0);
10821110
if (res < 0)
10831111
return res;
10841112
}
@@ -1096,7 +1124,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
10961124

10971125
static int
10981126
_SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
1099-
int tcount)
1127+
bool useSnapshotNow, int tcount)
11001128
{
11011129
List *query_list_list = plan->qtlist;
11021130
List *plan_list = plan->ptlist;
@@ -1167,7 +1195,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
11671195
{
11681196
qdesc = CreateQueryDesc(queryTree, planTree, dest,
11691197
paramLI, false);
1170-
res = _SPI_pquery(qdesc, true,
1198+
res = _SPI_pquery(qdesc, true, useSnapshotNow,
11711199
queryTree->canSetTag ? tcount : 0);
11721200
if (res < 0)
11731201
return res;
@@ -1180,7 +1208,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
11801208
}
11811209

11821210
static int
1183-
_SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
1211+
_SPI_pquery(QueryDesc *queryDesc, bool runit, bool useSnapshotNow, int tcount)
11841212
{
11851213
int operation = queryDesc->operation;
11861214
int res;
@@ -1217,7 +1245,7 @@ _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
12171245
ResetUsage();
12181246
#endif
12191247

1220-
ExecutorStart(queryDesc, false);
1248+
ExecutorStart(queryDesc, useSnapshotNow, false);
12211249

12221250
ExecutorRun(queryDesc, ForwardScanDirection, (long) tcount);
12231251

src/backend/tcop/pquery.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.72 2003/08/12 18:23:21 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.73 2003/09/25 18:58:35 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -131,7 +131,7 @@ ProcessQuery(Query *parsetree,
131131
/*
132132
* Call ExecStart to prepare the plan for execution
133133
*/
134-
ExecutorStart(queryDesc, false);
134+
ExecutorStart(queryDesc, false, false);
135135

136136
/*
137137
* Run the plan to completion.
@@ -269,7 +269,7 @@ PortalStart(Portal portal, ParamListInfo params)
269269
/*
270270
* Call ExecStart to prepare the plan for execution
271271
*/
272-
ExecutorStart(queryDesc, false);
272+
ExecutorStart(queryDesc, false, false);
273273

274274
/*
275275
* This tells PortalCleanup to shut down the executor

0 commit comments

Comments
 (0)