summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/heap/heapam.c8
-rw-r--r--src/backend/access/heap/tuptoaster.c4
-rw-r--r--src/backend/access/transam/xact.c67
-rw-r--r--src/backend/commands/async.c5
-rw-r--r--src/backend/commands/copy.c6
-rw-r--r--src/backend/commands/explain.c4
-rw-r--r--src/backend/commands/trigger.c29
-rw-r--r--src/backend/executor/execMain.c65
-rw-r--r--src/backend/executor/execUtils.c4
-rw-r--r--src/backend/executor/spi.c4
-rw-r--r--src/backend/storage/ipc/procarray.c4
-rw-r--r--src/backend/utils/cache/inval.c15
-rw-r--r--src/backend/utils/time/tqual.c8
13 files changed, 143 insertions, 80 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 20027592b5..1a4fc92f1c 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.245 2007/11/15 21:14:32 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.246 2007/11/30 21:22:53 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -1891,7 +1891,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
Oid
simple_heap_insert(Relation relation, HeapTuple tup)
{
- return heap_insert(relation, tup, GetCurrentCommandId(), true, true);
+ return heap_insert(relation, tup, GetCurrentCommandId(true), true, true);
}
/*
@@ -2174,7 +2174,7 @@ simple_heap_delete(Relation relation, ItemPointer tid)
result = heap_delete(relation, tid,
&update_ctid, &update_xmax,
- GetCurrentCommandId(), InvalidSnapshot,
+ GetCurrentCommandId(true), InvalidSnapshot,
true /* wait for commit */ );
switch (result)
{
@@ -2817,7 +2817,7 @@ simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
result = heap_update(relation, otid, tup,
&update_ctid, &update_xmax,
- GetCurrentCommandId(), InvalidSnapshot,
+ GetCurrentCommandId(true), InvalidSnapshot,
true /* wait for commit */ );
switch (result)
{
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 0a8873f994..f26fa9f4a6 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.79 2007/11/15 21:14:32 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.80 2007/11/30 21:22:53 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -1086,7 +1086,7 @@ toast_save_datum(Relation rel, Datum value,
TupleDesc toasttupDesc;
Datum t_values[3];
bool t_isnull[3];
- CommandId mycid = GetCurrentCommandId();
+ CommandId mycid = GetCurrentCommandId(true);
struct varlena *result;
struct varatt_external toast_pointer;
struct
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 04804c3871..ce0dd81281 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.253 2007/11/15 21:14:32 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.254 2007/11/30 21:22:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -161,6 +161,7 @@ static TransactionState CurrentTransactionState = &TopTransactionStateData;
*/
static SubTransactionId currentSubTransactionId;
static CommandId currentCommandId;
+static bool currentCommandIdUsed;
/*
* xactStartTimestamp is the value of transaction_timestamp().
@@ -435,11 +436,18 @@ GetCurrentSubTransactionId(void)
/*
* GetCurrentCommandId
+ *
+ * "used" must be TRUE if the caller intends to use the command ID to mark
+ * inserted/updated/deleted tuples. FALSE means the ID is being fetched
+ * for read-only purposes (ie, as a snapshot validity cutoff). See
+ * CommandCounterIncrement() for discussion.
*/
CommandId
-GetCurrentCommandId(void)
+GetCurrentCommandId(bool used)
{
/* this is global to a transaction, not subtransaction-local */
+ if (used)
+ currentCommandIdUsed = true;
return currentCommandId;
}
@@ -566,25 +574,50 @@ TransactionIdIsCurrentTransactionId(TransactionId xid)
void
CommandCounterIncrement(void)
{
- currentCommandId += 1;
- if (currentCommandId == FirstCommandId) /* check for overflow */
+ /*
+ * If the current value of the command counter hasn't been "used" to
+ * mark tuples, we need not increment it, since there's no need to
+ * distinguish a read-only command from others. This helps postpone
+ * command counter overflow, and keeps no-op CommandCounterIncrement
+ * operations cheap.
+ */
+ if (currentCommandIdUsed)
{
- currentCommandId -= 1;
- ereport(ERROR,
- (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ currentCommandId += 1;
+ if (currentCommandId == FirstCommandId) /* check for overflow */
+ {
+ currentCommandId -= 1;
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("cannot have more than 2^32-1 commands in a transaction")));
- }
+ }
+ currentCommandIdUsed = false;
- /* Propagate new command ID into static snapshots, if set */
- if (SerializableSnapshot)
- SerializableSnapshot->curcid = currentCommandId;
- if (LatestSnapshot)
- LatestSnapshot->curcid = currentCommandId;
+ /* Propagate new command ID into static snapshots, if set */
+ if (SerializableSnapshot)
+ SerializableSnapshot->curcid = currentCommandId;
+ if (LatestSnapshot)
+ LatestSnapshot->curcid = currentCommandId;
+
+ /*
+ * Make any catalog changes done by the just-completed command
+ * visible in the local syscache. We obviously don't need to do
+ * this after a read-only command. (But see hacks in inval.c
+ * to make real sure we don't think a command that queued inval
+ * messages was read-only.)
+ */
+ AtCommit_LocalCache();
+ }
/*
- * make cache changes visible to me.
+ * Make any other backends' catalog changes visible to me.
+ *
+ * XXX this is probably in the wrong place: CommandCounterIncrement
+ * should be purely a local operation, most likely. However fooling
+ * with this will affect asynchronous cross-backend interactions,
+ * which doesn't seem like a wise thing to do in late beta, so save
+ * improving this for another day - tgl 2007-11-30
*/
- AtCommit_LocalCache();
AtStart_Cache();
}
@@ -1416,6 +1449,7 @@ StartTransaction(void)
s->subTransactionId = TopSubTransactionId;
currentSubTransactionId = TopSubTransactionId;
currentCommandId = FirstCommandId;
+ currentCommandIdUsed = false;
/*
* must initialize resource-management stuff first
@@ -4007,13 +4041,14 @@ ShowTransactionStateRec(TransactionState s)
/* use ereport to suppress computation if msg will not be printed */
ereport(DEBUG3,
- (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s",
+ (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u%s, nestlvl: %d, children: %s",
PointerIsValid(s->name) ? s->name : "unnamed",
BlockStateAsString(s->blockState),
TransStateAsString(s->state),
(unsigned int) s->transactionId,
(unsigned int) s->subTransactionId,
(unsigned int) currentCommandId,
+ currentCommandIdUsed ? " (used)" : "",
s->nestingLevel,
nodeToString(s->childXids))));
}
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 55b99f8c92..c32dd2b19f 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.136 2007/04/12 06:53:46 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.137 2007/11/30 21:22:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -562,7 +562,8 @@ AtCommit_Notify(void)
*/
result = heap_update(lRel, &lTuple->t_self, rTuple,
&update_ctid, &update_xmax,
- GetCurrentCommandId(), InvalidSnapshot,
+ GetCurrentCommandId(true),
+ InvalidSnapshot,
false /* no wait for commit */ );
switch (result)
{
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index ef7e04ca28..c68d828fea 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.288 2007/11/15 21:14:33 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.289 2007/11/30 21:22:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1033,7 +1033,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
* which COPY can be invoked, I think it's OK, because the active
* snapshot shouldn't be shared with anything else anyway.)
*/
- ActiveSnapshot->curcid = GetCurrentCommandId();
+ ActiveSnapshot->curcid = GetCurrentCommandId(false);
/* Create dest receiver for COPY OUT */
dest = CreateDestReceiver(DestCopyOut, NULL);
@@ -1637,7 +1637,7 @@ CopyFrom(CopyState cstate)
ExprContext *econtext; /* used for ExecEvalExpr for default atts */
MemoryContext oldcontext = CurrentMemoryContext;
ErrorContextCallback errcontext;
- CommandId mycid = GetCurrentCommandId();
+ CommandId mycid = GetCurrentCommandId(true);
bool use_wal = true; /* by default, use WAL logging */
bool use_fsm = true; /* by default, use FSM for free space */
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index a9aa2cb3e1..f77f8cdc5e 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.167 2007/11/15 22:25:15 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.168 2007/11/30 21:22:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -233,7 +233,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params,
* EXPLAIN can be invoked, I think it's OK, because the active snapshot
* shouldn't be shared with anything else anyway.)
*/
- ActiveSnapshot->curcid = GetCurrentCommandId();
+ ActiveSnapshot->curcid = GetCurrentCommandId(false);
/* Create a QueryDesc requesting no output */
queryDesc = CreateQueryDesc(plannedstmt,
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 7dc1950534..1b66bd22ba 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.224 2007/11/16 01:51:22 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.225 2007/11/30 21:22:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -51,7 +51,6 @@ static void InsertTrigger(TriggerDesc *trigdesc, Trigger *trigger, int indx);
static HeapTuple GetTupleForTrigger(EState *estate,
ResultRelInfo *relinfo,
ItemPointer tid,
- CommandId cid,
TupleTableSlot **newSlot);
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
int tgindx,
@@ -1801,8 +1800,7 @@ ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
bool
ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
- ItemPointer tupleid,
- CommandId cid)
+ ItemPointer tupleid)
{
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
@@ -1814,7 +1812,7 @@ ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
TupleTableSlot *newSlot;
int i;
- trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, cid, &newSlot);
+ trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
if (trigtuple == NULL)
return false;
@@ -1871,9 +1869,7 @@ ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
{
HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
- tupleid,
- (CommandId) 0,
- NULL);
+ tupleid, NULL);
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE,
true, trigtuple, NULL);
@@ -1952,8 +1948,7 @@ ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
HeapTuple
ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
- ItemPointer tupleid, HeapTuple newtuple,
- CommandId cid)
+ ItemPointer tupleid, HeapTuple newtuple)
{
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
@@ -1965,7 +1960,7 @@ ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
TupleTableSlot *newSlot;
int i;
- trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, cid, &newSlot);
+ trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
if (trigtuple == NULL)
return NULL;
@@ -2025,9 +2020,7 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
{
HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
- tupleid,
- (CommandId) 0,
- NULL);
+ tupleid, NULL);
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
true, trigtuple, newtuple);
@@ -2038,7 +2031,7 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
static HeapTuple
GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
- ItemPointer tid, CommandId cid,
+ ItemPointer tid,
TupleTableSlot **newSlot)
{
Relation relation = relinfo->ri_RelationDesc;
@@ -2060,7 +2053,8 @@ GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
ltrmark:;
tuple.t_self = *tid;
test = heap_lock_tuple(relation, &tuple, &buffer,
- &update_ctid, &update_xmax, cid,
+ &update_ctid, &update_xmax,
+ estate->es_output_cid,
LockTupleExclusive, false);
switch (test)
{
@@ -2086,8 +2080,7 @@ ltrmark:;
epqslot = EvalPlanQual(estate,
relinfo->ri_RangeTableIndex,
&update_ctid,
- update_xmax,
- cid);
+ update_xmax);
if (!TupIsNull(epqslot))
{
*tid = update_ctid;
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 4b6ad47adb..5886234a1e 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.300 2007/11/15 22:25:15 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.301 2007/11/30 21:22:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -161,6 +161,30 @@ ExecutorStart(QueryDesc *queryDesc, int eflags)
palloc0(queryDesc->plannedstmt->nParamExec * sizeof(ParamExecData));
/*
+ * If non-read-only query, set the command ID to mark output tuples with
+ */
+ switch (queryDesc->operation)
+ {
+ case CMD_SELECT:
+ /* SELECT INTO and SELECT FOR UPDATE/SHARE need to mark tuples */
+ if (queryDesc->plannedstmt->intoClause != NULL ||
+ queryDesc->plannedstmt->rowMarks != NIL)
+ estate->es_output_cid = GetCurrentCommandId(true);
+ break;
+
+ case CMD_INSERT:
+ case CMD_DELETE:
+ case CMD_UPDATE:
+ estate->es_output_cid = GetCurrentCommandId(true);
+ break;
+
+ default:
+ elog(ERROR, "unrecognized operation code: %d",
+ (int) queryDesc->operation);
+ break;
+ }
+
+ /*
* Copy other important information into the EState
*/
estate->es_snapshot = queryDesc->snapshot;
@@ -1285,7 +1309,7 @@ lnext: ;
test = heap_lock_tuple(erm->relation, &tuple, &buffer,
&update_ctid, &update_xmax,
- estate->es_snapshot->curcid,
+ estate->es_output_cid,
lockmode, erm->noWait);
ReleaseBuffer(buffer);
switch (test)
@@ -1309,8 +1333,7 @@ lnext: ;
newSlot = EvalPlanQual(estate,
erm->rti,
&update_ctid,
- update_xmax,
- estate->es_snapshot->curcid);
+ update_xmax);
if (!TupIsNull(newSlot))
{
slot = planSlot = newSlot;
@@ -1503,7 +1526,7 @@ ExecInsert(TupleTableSlot *slot,
* t_self field.
*/
newId = heap_insert(resultRelationDesc, tuple,
- estate->es_snapshot->curcid,
+ estate->es_output_cid,
true, true);
IncrAppended();
@@ -1557,8 +1580,7 @@ ExecDelete(ItemPointer tupleid,
{
bool dodelete;
- dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid,
- estate->es_snapshot->curcid);
+ dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid);
if (!dodelete) /* "do nothing" */
return;
@@ -1575,7 +1597,7 @@ ExecDelete(ItemPointer tupleid,
ldelete:;
result = heap_delete(resultRelationDesc, tupleid,
&update_ctid, &update_xmax,
- estate->es_snapshot->curcid,
+ estate->es_output_cid,
estate->es_crosscheck_snapshot,
true /* wait for commit */ );
switch (result)
@@ -1599,8 +1621,7 @@ ldelete:;
epqslot = EvalPlanQual(estate,
resultRelInfo->ri_RangeTableIndex,
&update_ctid,
- update_xmax,
- estate->es_snapshot->curcid);
+ update_xmax);
if (!TupIsNull(epqslot))
{
*tupleid = update_ctid;
@@ -1708,8 +1729,7 @@ ExecUpdate(TupleTableSlot *slot,
HeapTuple newtuple;
newtuple = ExecBRUpdateTriggers(estate, resultRelInfo,
- tupleid, tuple,
- estate->es_snapshot->curcid);
+ tupleid, tuple);
if (newtuple == NULL) /* "do nothing" */
return;
@@ -1755,7 +1775,7 @@ lreplace:;
*/
result = heap_update(resultRelationDesc, tupleid, tuple,
&update_ctid, &update_xmax,
- estate->es_snapshot->curcid,
+ estate->es_output_cid,
estate->es_crosscheck_snapshot,
true /* wait for commit */ );
switch (result)
@@ -1779,8 +1799,7 @@ lreplace:;
epqslot = EvalPlanQual(estate,
resultRelInfo->ri_RangeTableIndex,
&update_ctid,
- update_xmax,
- estate->es_snapshot->curcid);
+ update_xmax);
if (!TupIsNull(epqslot))
{
*tupleid = update_ctid;
@@ -1973,7 +1992,6 @@ ExecProcessReturning(ProjectionInfo *projectReturning,
* rti - rangetable index of table containing tuple
* *tid - t_ctid from the outdated tuple (ie, next updated version)
* priorXmax - t_xmax from the outdated tuple
- * curCid - command ID of current command of my transaction
*
* *tid is also an output parameter: it's modified to hold the TID of the
* latest version of the tuple (note this may be changed even on failure)
@@ -1983,7 +2001,7 @@ ExecProcessReturning(ProjectionInfo *projectReturning,
*/
TupleTableSlot *
EvalPlanQual(EState *estate, Index rti,
- ItemPointer tid, TransactionId priorXmax, CommandId curCid)
+ ItemPointer tid, TransactionId priorXmax)
{
evalPlanQual *epq;
EState *epqstate;
@@ -2063,17 +2081,17 @@ EvalPlanQual(EState *estate, Index rti,
/*
* If tuple was inserted by our own transaction, we have to check
- * cmin against curCid: cmin >= curCid means our command cannot
- * see the tuple, so we should ignore it. Without this we are
- * open to the "Halloween problem" of indefinitely re-updating the
- * same tuple. (We need not check cmax because
+ * cmin against es_output_cid: cmin >= current CID means our
+ * command cannot see the tuple, so we should ignore it. Without
+ * this we are open to the "Halloween problem" of indefinitely
+ * re-updating the same tuple. (We need not check cmax because
* HeapTupleSatisfiesDirty will consider a tuple deleted by our
* transaction dead, regardless of cmax.) We just checked that
* priorXmax == xmin, so we can test that variable instead of
* doing HeapTupleHeaderGetXmin again.
*/
if (TransactionIdIsCurrentTransactionId(priorXmax) &&
- HeapTupleHeaderGetCmin(tuple.t_data) >= curCid)
+ HeapTupleHeaderGetCmin(tuple.t_data) >= estate->es_output_cid)
{
ReleaseBuffer(buffer);
return NULL;
@@ -2360,6 +2378,7 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
epqstate->es_snapshot = estate->es_snapshot;
epqstate->es_crosscheck_snapshot = estate->es_crosscheck_snapshot;
epqstate->es_range_table = estate->es_range_table;
+ epqstate->es_output_cid = estate->es_output_cid;
epqstate->es_result_relations = estate->es_result_relations;
epqstate->es_num_result_relations = estate->es_num_result_relations;
epqstate->es_result_relation_info = estate->es_result_relation_info;
@@ -2718,7 +2737,7 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
heap_insert(estate->es_into_relation_descriptor,
tuple,
- estate->es_snapshot->curcid,
+ estate->es_output_cid,
estate->es_into_relation_use_wal,
false); /* never any point in using FSM */
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 230d5c919f..12ddc910f4 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.152 2007/11/15 21:14:34 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.153 2007/11/30 21:22:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -178,6 +178,8 @@ CreateExecutorState(void)
estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
estate->es_range_table = NIL;
+ estate->es_output_cid = (CommandId) 0;
+
estate->es_result_relations = NULL;
estate->es_num_result_relations = 0;
estate->es_result_relation_info = NULL;
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index a5601ecdfc..e08e91cb0a 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.185 2007/11/30 18:38:34 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.186 2007/11/30 21:22:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1593,7 +1593,7 @@ _SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
*/
ActiveSnapshot = CopySnapshot(snapshot);
if (!read_only)
- ActiveSnapshot->curcid = GetCurrentCommandId();
+ ActiveSnapshot->curcid = GetCurrentCommandId(false);
}
if (IsA(stmt, PlannedStmt) &&
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index d7c8d706fd..156f947604 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -23,7 +23,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.37 2007/11/15 21:14:38 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.38 2007/11/30 21:22:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -814,7 +814,7 @@ GetSnapshotData(Snapshot snapshot, bool serializable)
snapshot->xcnt = count;
snapshot->subxcnt = subcount;
- snapshot->curcid = GetCurrentCommandId();
+ snapshot->curcid = GetCurrentCommandId(false);
return snapshot;
}
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 844dbc2be0..803727f084 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -80,7 +80,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.81 2007/11/15 21:14:39 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.82 2007/11/30 21:22:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -403,6 +403,14 @@ RegisterRelcacheInvalidation(Oid dbId, Oid relId)
dbId, relId);
/*
+ * Most of the time, relcache invalidation is associated with system
+ * catalog updates, but there are a few cases where it isn't. Quick
+ * hack to ensure that the next CommandCounterIncrement() will think
+ * that we need to do CommandEndInvalidationMessages().
+ */
+ (void) GetCurrentCommandId(true);
+
+ /*
* If the relation being invalidated is one of those cached in the
* relcache init file, mark that we need to zap that file at commit.
*/
@@ -420,6 +428,11 @@ RegisterSmgrInvalidation(RelFileNode rnode)
{
AddSmgrInvalidationMessage(&transInvalInfo->CurrentCmdInvalidMsgs,
rnode);
+
+ /*
+ * As above, just in case there is not an associated catalog change.
+ */
+ (void) GetCurrentCommandId(true);
}
/*
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index 4c128e4446..dad379573c 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -31,7 +31,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.107 2007/11/15 21:14:41 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.108 2007/11/30 21:22:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -382,7 +382,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
}
else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
{
- if (HeapTupleHeaderGetCmin(tuple) >= GetCurrentCommandId())
+ if (HeapTupleHeaderGetCmin(tuple) >= GetCurrentCommandId(false))
return false; /* inserted after scan started */
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
@@ -401,7 +401,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
return true;
}
- if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId())
+ if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId(false))
return true; /* deleted after scan started */
else
return false; /* deleted before scan started */
@@ -443,7 +443,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
{
if (tuple->t_infomask & HEAP_IS_LOCKED)
return true;
- if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId())
+ if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId(false))
return true; /* deleted after scan started */
else
return false; /* deleted before scan started */