mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
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.
This commit is contained in:
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.115 2003/08/11 20:46:46 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.116 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -207,7 +207,7 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
|
|||||||
gettimeofday(&starttime, NULL);
|
gettimeofday(&starttime, NULL);
|
||||||
|
|
||||||
/* call ExecutorStart to prepare the plan for execution */
|
/* call ExecutorStart to prepare the plan for execution */
|
||||||
ExecutorStart(queryDesc, !stmt->analyze);
|
ExecutorStart(queryDesc, false, !stmt->analyze);
|
||||||
|
|
||||||
/* Execute the plan for statistics if asked for */
|
/* Execute the plan for statistics if asked for */
|
||||||
if (stmt->analyze)
|
if (stmt->analyze)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.157 2003/09/25 06:57:58 petere Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.158 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1862,12 +1862,6 @@ DeferredTriggerExecute(DeferredTriggerEvent event, int itemno,
|
|||||||
if (rettuple != NULL && rettuple != &oldtuple && rettuple != &newtuple)
|
if (rettuple != NULL && rettuple != &oldtuple && rettuple != &newtuple)
|
||||||
heap_freetuple(rettuple);
|
heap_freetuple(rettuple);
|
||||||
|
|
||||||
/*
|
|
||||||
* Might have been a referential integrity constraint trigger. Reset
|
|
||||||
* the snapshot overriding flag.
|
|
||||||
*/
|
|
||||||
ReferentialIntegritySnapshotOverride = false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release buffers
|
* Release buffers
|
||||||
*/
|
*/
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.218 2003/09/25 06:57:59 petere Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.219 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -104,6 +104,9 @@ static void EvalPlanQualStop(evalPlanQual *epq);
|
|||||||
* field of the QueryDesc is filled in to describe the tuples that will be
|
* field of the QueryDesc is filled in to describe the tuples that will be
|
||||||
* returned, and the internal fields (estate and planstate) are set up.
|
* returned, and the internal fields (estate and planstate) are set up.
|
||||||
*
|
*
|
||||||
|
* If useSnapshotNow is true, run the query with SnapshotNow time qual rules
|
||||||
|
* instead of the normal use of QuerySnapshot.
|
||||||
|
*
|
||||||
* If explainOnly is true, we are not actually intending to run the plan,
|
* If explainOnly is true, we are not actually intending to run the plan,
|
||||||
* only to set up for EXPLAIN; so skip unwanted side-effects.
|
* only to set up for EXPLAIN; so skip unwanted side-effects.
|
||||||
*
|
*
|
||||||
@ -112,7 +115,7 @@ static void EvalPlanQualStop(evalPlanQual *epq);
|
|||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ExecutorStart(QueryDesc *queryDesc, bool explainOnly)
|
ExecutorStart(QueryDesc *queryDesc, bool useSnapshotNow, bool explainOnly)
|
||||||
{
|
{
|
||||||
EState *estate;
|
EState *estate;
|
||||||
MemoryContext oldcontext;
|
MemoryContext oldcontext;
|
||||||
@ -154,7 +157,16 @@ ExecutorStart(QueryDesc *queryDesc, bool explainOnly)
|
|||||||
* the life of this query, even if it outlives the current command and
|
* the life of this query, even if it outlives the current command and
|
||||||
* current snapshot.
|
* current snapshot.
|
||||||
*/
|
*/
|
||||||
|
if (useSnapshotNow)
|
||||||
|
{
|
||||||
|
estate->es_snapshot = SnapshotNow;
|
||||||
|
estate->es_snapshot_cid = GetCurrentCommandId();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
estate->es_snapshot = CopyQuerySnapshot();
|
estate->es_snapshot = CopyQuerySnapshot();
|
||||||
|
estate->es_snapshot_cid = estate->es_snapshot->curcid;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the plan state tree
|
* Initialize the plan state tree
|
||||||
@ -1106,7 +1118,7 @@ lnext: ;
|
|||||||
|
|
||||||
tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
|
tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
|
||||||
test = heap_mark4update(erm->relation, &tuple, &buffer,
|
test = heap_mark4update(erm->relation, &tuple, &buffer,
|
||||||
estate->es_snapshot->curcid);
|
estate->es_snapshot_cid);
|
||||||
ReleaseBuffer(buffer);
|
ReleaseBuffer(buffer);
|
||||||
switch (test)
|
switch (test)
|
||||||
{
|
{
|
||||||
@ -1266,7 +1278,7 @@ ExecSelect(TupleTableSlot *slot,
|
|||||||
if (estate->es_into_relation_descriptor != NULL)
|
if (estate->es_into_relation_descriptor != NULL)
|
||||||
{
|
{
|
||||||
heap_insert(estate->es_into_relation_descriptor, tuple,
|
heap_insert(estate->es_into_relation_descriptor, tuple,
|
||||||
estate->es_snapshot->curcid);
|
estate->es_snapshot_cid);
|
||||||
IncrAppended();
|
IncrAppended();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1342,7 +1354,7 @@ ExecInsert(TupleTableSlot *slot,
|
|||||||
* insert the tuple
|
* insert the tuple
|
||||||
*/
|
*/
|
||||||
newId = heap_insert(resultRelationDesc, tuple,
|
newId = heap_insert(resultRelationDesc, tuple,
|
||||||
estate->es_snapshot->curcid);
|
estate->es_snapshot_cid);
|
||||||
|
|
||||||
IncrAppended();
|
IncrAppended();
|
||||||
(estate->es_processed)++;
|
(estate->es_processed)++;
|
||||||
@ -1394,7 +1406,7 @@ ExecDelete(TupleTableSlot *slot,
|
|||||||
bool dodelete;
|
bool dodelete;
|
||||||
|
|
||||||
dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid,
|
dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid,
|
||||||
estate->es_snapshot->curcid);
|
estate->es_snapshot_cid);
|
||||||
|
|
||||||
if (!dodelete) /* "do nothing" */
|
if (!dodelete) /* "do nothing" */
|
||||||
return;
|
return;
|
||||||
@ -1406,7 +1418,7 @@ ExecDelete(TupleTableSlot *slot,
|
|||||||
ldelete:;
|
ldelete:;
|
||||||
result = heap_delete(resultRelationDesc, tupleid,
|
result = heap_delete(resultRelationDesc, tupleid,
|
||||||
&ctid,
|
&ctid,
|
||||||
estate->es_snapshot->curcid,
|
estate->es_snapshot_cid,
|
||||||
true /* wait for commit */);
|
true /* wait for commit */);
|
||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
@ -1505,7 +1517,7 @@ ExecUpdate(TupleTableSlot *slot,
|
|||||||
|
|
||||||
newtuple = ExecBRUpdateTriggers(estate, resultRelInfo,
|
newtuple = ExecBRUpdateTriggers(estate, resultRelInfo,
|
||||||
tupleid, tuple,
|
tupleid, tuple,
|
||||||
estate->es_snapshot->curcid);
|
estate->es_snapshot_cid);
|
||||||
|
|
||||||
if (newtuple == NULL) /* "do nothing" */
|
if (newtuple == NULL) /* "do nothing" */
|
||||||
return;
|
return;
|
||||||
@ -1541,7 +1553,7 @@ lreplace:;
|
|||||||
*/
|
*/
|
||||||
result = heap_update(resultRelationDesc, tupleid, tuple,
|
result = heap_update(resultRelationDesc, tupleid, tuple,
|
||||||
&ctid,
|
&ctid,
|
||||||
estate->es_snapshot->curcid,
|
estate->es_snapshot_cid,
|
||||||
true /* wait for commit */);
|
true /* wait for commit */);
|
||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
@ -2027,6 +2039,7 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
|
|||||||
*/
|
*/
|
||||||
epqstate->es_direction = ForwardScanDirection;
|
epqstate->es_direction = ForwardScanDirection;
|
||||||
epqstate->es_snapshot = estate->es_snapshot;
|
epqstate->es_snapshot = estate->es_snapshot;
|
||||||
|
epqstate->es_snapshot_cid = estate->es_snapshot_cid;
|
||||||
epqstate->es_range_table = estate->es_range_table;
|
epqstate->es_range_table = estate->es_range_table;
|
||||||
epqstate->es_result_relations = estate->es_result_relations;
|
epqstate->es_result_relations = estate->es_result_relations;
|
||||||
epqstate->es_num_result_relations = estate->es_num_result_relations;
|
epqstate->es_num_result_relations = estate->es_num_result_relations;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.104 2003/09/24 18:54:01 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.105 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -178,6 +178,7 @@ CreateExecutorState(void)
|
|||||||
*/
|
*/
|
||||||
estate->es_direction = ForwardScanDirection;
|
estate->es_direction = ForwardScanDirection;
|
||||||
estate->es_snapshot = SnapshotNow;
|
estate->es_snapshot = SnapshotNow;
|
||||||
|
estate->es_snapshot_cid = FirstCommandId;
|
||||||
estate->es_range_table = NIL;
|
estate->es_range_table = NIL;
|
||||||
|
|
||||||
estate->es_result_relations = NULL;
|
estate->es_result_relations = NULL;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.74 2003/09/25 06:57:59 petere Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.75 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -291,7 +291,7 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
|
|||||||
|
|
||||||
/* Utility commands don't need Executor. */
|
/* Utility commands don't need Executor. */
|
||||||
if (es->qd->operation != CMD_UTILITY)
|
if (es->qd->operation != CMD_UTILITY)
|
||||||
ExecutorStart(es->qd, false);
|
ExecutorStart(es->qd, false, false);
|
||||||
|
|
||||||
es->status = F_EXEC_RUN;
|
es->status = F_EXEC_RUN;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.56 2003/09/25 06:57:59 petere Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.57 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -709,6 +709,7 @@ ExecInitSubPlan(SubPlanState *node, EState *estate)
|
|||||||
sp_estate->es_tupleTable =
|
sp_estate->es_tupleTable =
|
||||||
ExecCreateTupleTable(ExecCountSlotsNode(subplan->plan) + 10);
|
ExecCreateTupleTable(ExecCountSlotsNode(subplan->plan) + 10);
|
||||||
sp_estate->es_snapshot = estate->es_snapshot;
|
sp_estate->es_snapshot = estate->es_snapshot;
|
||||||
|
sp_estate->es_snapshot_cid = estate->es_snapshot_cid;
|
||||||
sp_estate->es_instrument = estate->es_instrument;
|
sp_estate->es_instrument = estate->es_instrument;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.20 2003/08/04 02:39:59 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.21 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -177,6 +177,7 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate)
|
|||||||
sp_estate->es_tupleTable =
|
sp_estate->es_tupleTable =
|
||||||
ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10);
|
ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10);
|
||||||
sp_estate->es_snapshot = estate->es_snapshot;
|
sp_estate->es_snapshot = estate->es_snapshot;
|
||||||
|
sp_estate->es_snapshot_cid = estate->es_snapshot_cid;
|
||||||
sp_estate->es_instrument = estate->es_instrument;
|
sp_estate->es_instrument = estate->es_instrument;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.105 2003/09/23 15:11:33 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.106 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -32,10 +32,12 @@ static int _SPI_connected = -1;
|
|||||||
static int _SPI_curid = -1;
|
static int _SPI_curid = -1;
|
||||||
|
|
||||||
static int _SPI_execute(const char *src, int tcount, _SPI_plan *plan);
|
static int _SPI_execute(const char *src, int tcount, _SPI_plan *plan);
|
||||||
static int _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount);
|
static int _SPI_pquery(QueryDesc *queryDesc, bool runit,
|
||||||
|
bool useSnapshotNow, int tcount);
|
||||||
|
|
||||||
static int _SPI_execute_plan(_SPI_plan *plan,
|
static int _SPI_execute_plan(_SPI_plan *plan,
|
||||||
Datum *Values, const char *Nulls, int tcount);
|
Datum *Values, const char *Nulls,
|
||||||
|
bool useSnapshotNow, int tcount);
|
||||||
|
|
||||||
static void _SPI_cursor_operation(Portal portal, bool forward, int count,
|
static void _SPI_cursor_operation(Portal portal, bool forward, int count,
|
||||||
DestReceiver *dest);
|
DestReceiver *dest);
|
||||||
@ -236,7 +238,33 @@ SPI_execp(void *plan, Datum *Values, const char *Nulls, int tcount)
|
|||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
res = _SPI_execute_plan((_SPI_plan *) plan, Values, Nulls, tcount);
|
res = _SPI_execute_plan((_SPI_plan *) plan, Values, Nulls, false, tcount);
|
||||||
|
|
||||||
|
_SPI_end_call(true);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SPI_execp_now -- identical to SPI_execp, except that we use SnapshotNow
|
||||||
|
* instead of the normal QuerySnapshot. This is currently not documented
|
||||||
|
* in spi.sgml because it is only intended for use by RI triggers.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
SPI_execp_now(void *plan, Datum *Values, const char *Nulls, int tcount)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (plan == NULL || tcount < 0)
|
||||||
|
return SPI_ERROR_ARGUMENT;
|
||||||
|
|
||||||
|
if (((_SPI_plan *) plan)->nargs > 0 && Values == NULL)
|
||||||
|
return SPI_ERROR_PARAM;
|
||||||
|
|
||||||
|
res = _SPI_begin_call(true);
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
res = _SPI_execute_plan((_SPI_plan *) plan, Values, Nulls, true, tcount);
|
||||||
|
|
||||||
_SPI_end_call(true);
|
_SPI_end_call(true);
|
||||||
return res;
|
return res;
|
||||||
@ -1068,7 +1096,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
|
|||||||
{
|
{
|
||||||
qdesc = CreateQueryDesc(queryTree, planTree, dest,
|
qdesc = CreateQueryDesc(queryTree, planTree, dest,
|
||||||
NULL, false);
|
NULL, false);
|
||||||
res = _SPI_pquery(qdesc, true,
|
res = _SPI_pquery(qdesc, true, false,
|
||||||
queryTree->canSetTag ? tcount : 0);
|
queryTree->canSetTag ? tcount : 0);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
@ -1078,7 +1106,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
|
|||||||
{
|
{
|
||||||
qdesc = CreateQueryDesc(queryTree, planTree, dest,
|
qdesc = CreateQueryDesc(queryTree, planTree, dest,
|
||||||
NULL, false);
|
NULL, false);
|
||||||
res = _SPI_pquery(qdesc, false, 0);
|
res = _SPI_pquery(qdesc, false, false, 0);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -1096,7 +1124,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
_SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
|
_SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
|
||||||
int tcount)
|
bool useSnapshotNow, int tcount)
|
||||||
{
|
{
|
||||||
List *query_list_list = plan->qtlist;
|
List *query_list_list = plan->qtlist;
|
||||||
List *plan_list = plan->ptlist;
|
List *plan_list = plan->ptlist;
|
||||||
@ -1167,7 +1195,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
|
|||||||
{
|
{
|
||||||
qdesc = CreateQueryDesc(queryTree, planTree, dest,
|
qdesc = CreateQueryDesc(queryTree, planTree, dest,
|
||||||
paramLI, false);
|
paramLI, false);
|
||||||
res = _SPI_pquery(qdesc, true,
|
res = _SPI_pquery(qdesc, true, useSnapshotNow,
|
||||||
queryTree->canSetTag ? tcount : 0);
|
queryTree->canSetTag ? tcount : 0);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
@ -1180,7 +1208,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
|
_SPI_pquery(QueryDesc *queryDesc, bool runit, bool useSnapshotNow, int tcount)
|
||||||
{
|
{
|
||||||
int operation = queryDesc->operation;
|
int operation = queryDesc->operation;
|
||||||
int res;
|
int res;
|
||||||
@ -1217,7 +1245,7 @@ _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
|
|||||||
ResetUsage();
|
ResetUsage();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ExecutorStart(queryDesc, false);
|
ExecutorStart(queryDesc, useSnapshotNow, false);
|
||||||
|
|
||||||
ExecutorRun(queryDesc, ForwardScanDirection, (long) tcount);
|
ExecutorRun(queryDesc, ForwardScanDirection, (long) tcount);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.72 2003/08/12 18:23:21 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.73 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -131,7 +131,7 @@ ProcessQuery(Query *parsetree,
|
|||||||
/*
|
/*
|
||||||
* Call ExecStart to prepare the plan for execution
|
* Call ExecStart to prepare the plan for execution
|
||||||
*/
|
*/
|
||||||
ExecutorStart(queryDesc, false);
|
ExecutorStart(queryDesc, false, false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Run the plan to completion.
|
* Run the plan to completion.
|
||||||
@ -269,7 +269,7 @@ PortalStart(Portal portal, ParamListInfo params)
|
|||||||
/*
|
/*
|
||||||
* Call ExecStart to prepare the plan for execution
|
* Call ExecStart to prepare the plan for execution
|
||||||
*/
|
*/
|
||||||
ExecutorStart(queryDesc, false);
|
ExecutorStart(queryDesc, false, false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This tells PortalCleanup to shut down the executor
|
* This tells PortalCleanup to shut down the executor
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.57 2003/09/25 06:58:04 petere Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.58 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
@ -187,8 +187,6 @@ RI_FKey_check(PG_FUNCTION_ARGS)
|
|||||||
int i;
|
int i;
|
||||||
int match_type;
|
int match_type;
|
||||||
|
|
||||||
ReferentialIntegritySnapshotOverride = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that this is a valid trigger call on the right time and
|
* Check that this is a valid trigger call on the right time and
|
||||||
* event.
|
* event.
|
||||||
@ -627,8 +625,6 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS)
|
|||||||
int i;
|
int i;
|
||||||
int match_type;
|
int match_type;
|
||||||
|
|
||||||
ReferentialIntegritySnapshotOverride = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that this is a valid trigger call on the right time and
|
* Check that this is a valid trigger call on the right time and
|
||||||
* event.
|
* event.
|
||||||
@ -807,8 +803,6 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
|
|||||||
int i;
|
int i;
|
||||||
int match_type;
|
int match_type;
|
||||||
|
|
||||||
ReferentialIntegritySnapshotOverride = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that this is a valid trigger call on the right time and
|
* Check that this is a valid trigger call on the right time and
|
||||||
* event.
|
* event.
|
||||||
@ -995,8 +989,6 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
|
|||||||
void *qplan;
|
void *qplan;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ReferentialIntegritySnapshotOverride = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that this is a valid trigger call on the right time and
|
* Check that this is a valid trigger call on the right time and
|
||||||
* event.
|
* event.
|
||||||
@ -1159,8 +1151,6 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
|
|||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
ReferentialIntegritySnapshotOverride = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that this is a valid trigger call on the right time and
|
* Check that this is a valid trigger call on the right time and
|
||||||
* event.
|
* event.
|
||||||
@ -1349,8 +1339,6 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS)
|
|||||||
void *qplan;
|
void *qplan;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ReferentialIntegritySnapshotOverride = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that this is a valid trigger call on the right time and
|
* Check that this is a valid trigger call on the right time and
|
||||||
* event.
|
* event.
|
||||||
@ -1520,8 +1508,6 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
|
|||||||
void *qplan;
|
void *qplan;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ReferentialIntegritySnapshotOverride = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that this is a valid trigger call on the right time and
|
* Check that this is a valid trigger call on the right time and
|
||||||
* event.
|
* event.
|
||||||
@ -1694,8 +1680,6 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS)
|
|||||||
void *qplan;
|
void *qplan;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ReferentialIntegritySnapshotOverride = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that this is a valid trigger call on the right time and
|
* Check that this is a valid trigger call on the right time and
|
||||||
* event.
|
* event.
|
||||||
@ -1868,8 +1852,6 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
|
|||||||
int match_type;
|
int match_type;
|
||||||
bool use_cached_query;
|
bool use_cached_query;
|
||||||
|
|
||||||
ReferentialIntegritySnapshotOverride = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that this is a valid trigger call on the right time and
|
* Check that this is a valid trigger call on the right time and
|
||||||
* event.
|
* event.
|
||||||
@ -2083,8 +2065,6 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
|
|||||||
RI_QueryKey qkey;
|
RI_QueryKey qkey;
|
||||||
void *qplan;
|
void *qplan;
|
||||||
|
|
||||||
ReferentialIntegritySnapshotOverride = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that this is a valid trigger call on the right time and
|
* Check that this is a valid trigger call on the right time and
|
||||||
* event.
|
* event.
|
||||||
@ -2296,8 +2276,6 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
|
|||||||
void *qplan;
|
void *qplan;
|
||||||
int match_type;
|
int match_type;
|
||||||
|
|
||||||
ReferentialIntegritySnapshotOverride = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that this is a valid trigger call on the right time and
|
* Check that this is a valid trigger call on the right time and
|
||||||
* event.
|
* event.
|
||||||
@ -2936,15 +2914,19 @@ ri_PerformCheck(RI_QueryKey *qkey, void *qplan,
|
|||||||
*/
|
*/
|
||||||
limit = (expect_OK == SPI_OK_SELECT) ? 1 : 0;
|
limit = (expect_OK == SPI_OK_SELECT) ? 1 : 0;
|
||||||
|
|
||||||
/* Run the plan */
|
/*
|
||||||
spi_result = SPI_execp(qplan, vals, nulls, limit);
|
* Run the plan, using SnapshotNow time qual rules so that we can see
|
||||||
|
* all committed tuples, even those committed after our own transaction
|
||||||
|
* or query started.
|
||||||
|
*/
|
||||||
|
spi_result = SPI_execp_now(qplan, vals, nulls, limit);
|
||||||
|
|
||||||
/* Restore UID */
|
/* Restore UID */
|
||||||
SetUserId(save_uid);
|
SetUserId(save_uid);
|
||||||
|
|
||||||
/* Check result */
|
/* Check result */
|
||||||
if (spi_result < 0)
|
if (spi_result < 0)
|
||||||
elog(ERROR, "SPI_execp failed");
|
elog(ERROR, "SPI_execp_now returned %d", spi_result);
|
||||||
|
|
||||||
if (expect_OK >= 0 && spi_result != expect_OK)
|
if (expect_OK >= 0 && spi_result != expect_OK)
|
||||||
ri_ReportViolation(qkey, constrname ? constrname : "",
|
ri_ReportViolation(qkey, constrname ? constrname : "",
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.68 2003/09/22 00:47:23 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.69 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -39,8 +39,6 @@ Snapshot SerializableSnapshot = NULL;
|
|||||||
TransactionId RecentXmin = InvalidTransactionId;
|
TransactionId RecentXmin = InvalidTransactionId;
|
||||||
TransactionId RecentGlobalXmin = InvalidTransactionId;
|
TransactionId RecentGlobalXmin = InvalidTransactionId;
|
||||||
|
|
||||||
bool ReferentialIntegritySnapshotOverride = false;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* HeapTupleSatisfiesItself
|
* HeapTupleSatisfiesItself
|
||||||
@ -665,10 +663,6 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
|
|||||||
bool
|
bool
|
||||||
HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
|
HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
|
||||||
{
|
{
|
||||||
/* XXX this is horribly ugly: */
|
|
||||||
if (ReferentialIntegritySnapshotOverride)
|
|
||||||
return HeapTupleSatisfiesNow(tuple);
|
|
||||||
|
|
||||||
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
||||||
{
|
{
|
||||||
if (tuple->t_infomask & HEAP_XMIN_INVALID)
|
if (tuple->t_infomask & HEAP_XMIN_INVALID)
|
||||||
@ -978,9 +972,6 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
|
|||||||
void
|
void
|
||||||
SetQuerySnapshot(void)
|
SetQuerySnapshot(void)
|
||||||
{
|
{
|
||||||
/* Initialize snapshot overriding to false */
|
|
||||||
ReferentialIntegritySnapshotOverride = false;
|
|
||||||
|
|
||||||
/* 1st call in xaction? */
|
/* 1st call in xaction? */
|
||||||
if (SerializableSnapshot == NULL)
|
if (SerializableSnapshot == NULL)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: valid.h,v 1.30 2003/08/04 02:40:10 momjian Exp $
|
* $Id: valid.h,v 1.31 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -93,7 +93,7 @@ do \
|
|||||||
relation, \
|
relation, \
|
||||||
buffer, \
|
buffer, \
|
||||||
disk_page, \
|
disk_page, \
|
||||||
seeself, \
|
snapshot, \
|
||||||
nKeys, \
|
nKeys, \
|
||||||
key, \
|
key, \
|
||||||
res) \
|
res) \
|
||||||
@ -112,7 +112,7 @@ do \
|
|||||||
{ \
|
{ \
|
||||||
uint16 _infomask = (tuple)->t_data->t_infomask; \
|
uint16 _infomask = (tuple)->t_data->t_infomask; \
|
||||||
\
|
\
|
||||||
(res) = HeapTupleSatisfiesVisibility((tuple), (seeself)); \
|
(res) = HeapTupleSatisfiesVisibility((tuple), (snapshot)); \
|
||||||
if ((tuple)->t_data->t_infomask != _infomask) \
|
if ((tuple)->t_data->t_infomask != _infomask) \
|
||||||
SetBufferCommitInfoNeedsSave(buffer); \
|
SetBufferCommitInfoNeedsSave(buffer); \
|
||||||
} \
|
} \
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: executor.h,v 1.100 2003/08/19 01:13:41 tgl Exp $
|
* $Id: executor.h,v 1.101 2003/09/25 18:58:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -85,7 +85,8 @@ extern HeapTuple ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot);
|
|||||||
/*
|
/*
|
||||||
* prototypes from functions in execMain.c
|
* prototypes from functions in execMain.c
|
||||||
*/
|
*/
|
||||||
extern void ExecutorStart(QueryDesc *queryDesc, bool explainOnly);
|
extern void ExecutorStart(QueryDesc *queryDesc, bool useSnapshotNow,
|
||||||
|
bool explainOnly);
|
||||||
extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc,
|
extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc,
|
||||||
ScanDirection direction, long count);
|
ScanDirection direction, long count);
|
||||||
extern void ExecutorEnd(QueryDesc *queryDesc);
|
extern void ExecutorEnd(QueryDesc *queryDesc);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* spi.h
|
* spi.h
|
||||||
*
|
*
|
||||||
* $Id: spi.h,v 1.37 2003/08/04 00:43:31 momjian Exp $
|
* $Id: spi.h,v 1.38 2003/09/25 18:58:36 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -84,6 +84,8 @@ extern void SPI_pop(void);
|
|||||||
extern int SPI_exec(const char *src, int tcount);
|
extern int SPI_exec(const char *src, int tcount);
|
||||||
extern int SPI_execp(void *plan, Datum *values, const char *Nulls,
|
extern int SPI_execp(void *plan, Datum *values, const char *Nulls,
|
||||||
int tcount);
|
int tcount);
|
||||||
|
extern int SPI_execp_now(void *plan, Datum *values, const char *Nulls,
|
||||||
|
int tcount);
|
||||||
extern void *SPI_prepare(const char *src, int nargs, Oid *argtypes);
|
extern void *SPI_prepare(const char *src, int nargs, Oid *argtypes);
|
||||||
extern void *SPI_saveplan(void *plan);
|
extern void *SPI_saveplan(void *plan);
|
||||||
extern int SPI_freeplan(void *plan);
|
extern int SPI_freeplan(void *plan);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: execnodes.h,v 1.105 2003/08/22 20:26:43 tgl Exp $
|
* $Id: execnodes.h,v 1.106 2003/09/25 18:58:36 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -286,6 +286,7 @@ typedef struct EState
|
|||||||
/* Basic state for all query types: */
|
/* Basic state for all query types: */
|
||||||
ScanDirection es_direction; /* current scan direction */
|
ScanDirection es_direction; /* current scan direction */
|
||||||
Snapshot es_snapshot; /* time qual to use */
|
Snapshot es_snapshot; /* time qual to use */
|
||||||
|
CommandId es_snapshot_cid; /* CommandId component of time qual */
|
||||||
List *es_range_table; /* List of RangeTableEntrys */
|
List *es_range_table; /* List of RangeTableEntrys */
|
||||||
|
|
||||||
/* Info about target table for insert/update/delete queries: */
|
/* Info about target table for insert/update/delete queries: */
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: tqual.h,v 1.46 2003/08/04 02:40:15 momjian Exp $
|
* $Id: tqual.h,v 1.47 2003/09/25 18:58:36 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -44,14 +44,6 @@ extern DLLIMPORT Snapshot SerializableSnapshot;
|
|||||||
extern TransactionId RecentXmin;
|
extern TransactionId RecentXmin;
|
||||||
extern TransactionId RecentGlobalXmin;
|
extern TransactionId RecentGlobalXmin;
|
||||||
|
|
||||||
extern bool ReferentialIntegritySnapshotOverride;
|
|
||||||
|
|
||||||
#define IsSnapshotNow(snapshot) ((Snapshot) (snapshot) == SnapshotNow)
|
|
||||||
#define IsSnapshotSelf(snapshot) ((Snapshot) (snapshot) == SnapshotSelf)
|
|
||||||
#define IsSnapshotAny(snapshot) ((Snapshot) (snapshot) == SnapshotAny)
|
|
||||||
#define IsSnapshotToast(snapshot) ((Snapshot) (snapshot) == SnapshotToast)
|
|
||||||
#define IsSnapshotDirty(snapshot) ((Snapshot) (snapshot) == SnapshotDirty)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* HeapTupleSatisfiesVisibility
|
* HeapTupleSatisfiesVisibility
|
||||||
@ -62,19 +54,19 @@ extern bool ReferentialIntegritySnapshotOverride;
|
|||||||
* Beware of multiple evaluations of snapshot argument.
|
* Beware of multiple evaluations of snapshot argument.
|
||||||
*/
|
*/
|
||||||
#define HeapTupleSatisfiesVisibility(tuple, snapshot) \
|
#define HeapTupleSatisfiesVisibility(tuple, snapshot) \
|
||||||
(IsSnapshotNow(snapshot) ? \
|
((snapshot) == SnapshotNow ? \
|
||||||
HeapTupleSatisfiesNow((tuple)->t_data) \
|
HeapTupleSatisfiesNow((tuple)->t_data) \
|
||||||
: \
|
: \
|
||||||
(IsSnapshotSelf(snapshot) ? \
|
((snapshot) == SnapshotSelf ? \
|
||||||
HeapTupleSatisfiesItself((tuple)->t_data) \
|
HeapTupleSatisfiesItself((tuple)->t_data) \
|
||||||
: \
|
: \
|
||||||
(IsSnapshotAny(snapshot) ? \
|
((snapshot) == SnapshotAny ? \
|
||||||
true \
|
true \
|
||||||
: \
|
: \
|
||||||
(IsSnapshotToast(snapshot) ? \
|
((snapshot) == SnapshotToast ? \
|
||||||
HeapTupleSatisfiesToast((tuple)->t_data) \
|
HeapTupleSatisfiesToast((tuple)->t_data) \
|
||||||
: \
|
: \
|
||||||
(IsSnapshotDirty(snapshot) ? \
|
((snapshot) == SnapshotDirty ? \
|
||||||
HeapTupleSatisfiesDirty((tuple)->t_data) \
|
HeapTupleSatisfiesDirty((tuple)->t_data) \
|
||||||
: \
|
: \
|
||||||
HeapTupleSatisfiesSnapshot((tuple)->t_data, snapshot) \
|
HeapTupleSatisfiesSnapshot((tuple)->t_data, snapshot) \
|
||||||
|
Reference in New Issue
Block a user