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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy