*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.134 2002/05/20 23:51:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.135 2002/05/21 22:05:53 tgl Exp $
*
*
* INTERFACE ROUTINES
return tid;
}
-/* ----------------
- * heap_insert - insert tuple into a heap
+/*
+ * heap_insert - insert tuple into a heap
*
- * The assignment of t_min (and thus the others) should be
- * removed eventually.
- * ----------------
+ * The new tuple is stamped with current transaction ID and the specified
+ * command ID.
*/
Oid
-heap_insert(Relation relation, HeapTuple tup)
+heap_insert(Relation relation, HeapTuple tup, CommandId cid)
{
Buffer buffer;
}
TransactionIdStore(GetCurrentTransactionId(), &(tup->t_data->t_xmin));
- tup->t_data->t_cmin = GetCurrentCommandId();
+ tup->t_data->t_cmin = cid;
StoreInvalidTransactionId(&(tup->t_data->t_xmax));
+ tup->t_data->t_cmax = FirstCommandId;
tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
tup->t_tableOid = relation->rd_id;
return tup->t_data->t_oid;
}
+/*
+ * simple_heap_insert - insert a tuple
+ *
+ * Currently, this routine differs from heap_insert only in supplying
+ * a default command ID. But it should be used rather than using
+ * heap_insert directly in most places where we are modifying system catalogs.
+ */
+Oid
+simple_heap_insert(Relation relation, HeapTuple tup)
+{
+ return heap_insert(relation, tup, GetCurrentCommandId());
+}
+
/*
* heap_delete - delete a tuple
*
* concurrent-update conditions. Use simple_heap_delete instead.
*/
int
-heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid)
+heap_delete(Relation relation, ItemPointer tid,
+ ItemPointer ctid, CommandId cid)
{
ItemId lp;
HeapTupleData tp;
tp.t_tableOid = relation->rd_id;
l1:
- result = HeapTupleSatisfiesUpdate(&tp);
+ result = HeapTupleSatisfiesUpdate(&tp, cid);
if (result == HeapTupleInvisible)
{
START_CRIT_SECTION();
/* store transaction information of xact deleting the tuple */
TransactionIdStore(GetCurrentTransactionId(), &(tp.t_data->t_xmax));
- tp.t_data->t_cmax = GetCurrentCommandId();
+ tp.t_data->t_cmax = cid;
tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
/* XLOG stuff */
ItemPointerData ctid;
int result;
- result = heap_delete(relation, tid, &ctid);
+ result = heap_delete(relation, tid, &ctid, GetCurrentCommandId());
switch (result)
{
case HeapTupleSelfUpdated:
elog(ERROR, "Unknown status %u from heap_delete", result);
break;
}
-
}
/*
*/
int
heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
- ItemPointer ctid)
+ ItemPointer ctid, CommandId cid)
{
ItemId lp;
HeapTupleData oldtup;
*/
l2:
- result = HeapTupleSatisfiesUpdate(&oldtup);
+ result = HeapTupleSatisfiesUpdate(&oldtup, cid);
if (result == HeapTupleInvisible)
{
/* Fill in OID and transaction status data for newtup */
newtup->t_data->t_oid = oldtup.t_data->t_oid;
TransactionIdStore(GetCurrentTransactionId(), &(newtup->t_data->t_xmin));
- newtup->t_data->t_cmin = GetCurrentCommandId();
+ newtup->t_data->t_cmin = cid;
StoreInvalidTransactionId(&(newtup->t_data->t_xmax));
newtup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
newtup->t_data->t_infomask |= (HEAP_XMAX_INVALID | HEAP_UPDATED);
TransactionIdStore(GetCurrentTransactionId(),
&(oldtup.t_data->t_xmax));
- oldtup.t_data->t_cmax = GetCurrentCommandId();
+ oldtup.t_data->t_cmax = cid;
oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
HEAP_XMAX_INVALID |
HEAP_MARKED_FOR_UPDATE);
{
TransactionIdStore(GetCurrentTransactionId(),
&(oldtup.t_data->t_xmax));
- oldtup.t_data->t_cmax = GetCurrentCommandId();
+ oldtup.t_data->t_cmax = cid;
oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
HEAP_XMAX_INVALID |
HEAP_MARKED_FOR_UPDATE);
ItemPointerData ctid;
int result;
- result = heap_update(relation, otid, tup, &ctid);
+ result = heap_update(relation, otid, tup, &ctid, GetCurrentCommandId());
switch (result)
{
case HeapTupleSelfUpdated:
* heap_mark4update - mark a tuple for update
*/
int
-heap_mark4update(Relation relation, HeapTuple tuple, Buffer *buffer)
+heap_mark4update(Relation relation, HeapTuple tuple, Buffer *buffer,
+ CommandId cid)
{
ItemPointer tid = &(tuple->t_self);
ItemId lp;
tuple->t_len = ItemIdGetLength(lp);
l3:
- result = HeapTupleSatisfiesUpdate(tuple);
+ result = HeapTupleSatisfiesUpdate(tuple, cid);
if (result == HeapTupleInvisible)
{
/* store transaction information of xact marking the tuple */
TransactionIdStore(GetCurrentTransactionId(), &(tuple->t_data->t_xmax));
- tuple->t_data->t_cmax = GetCurrentCommandId();
+ tuple->t_data->t_cmax = cid;
tuple->t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID);
tuple->t_data->t_infomask |= HEAP_MARKED_FOR_UPDATE;
htup = (HeapTupleHeader) PageGetItem(page, lp);
- if (!TransactionIdEquals(htup->t_xmax, GetCurrentTransactionId()) ||
- htup->t_cmax != GetCurrentCommandId())
- elog(PANIC, "_heap_unlock_tuple: invalid xmax/cmax in rollback");
+ if (!TransactionIdEquals(htup->t_xmax, GetCurrentTransactionId()))
+ elog(PANIC, "_heap_unlock_tuple: invalid xmax in rollback");
htup->t_infomask &= ~HEAP_XMAX_UNLOGGED;
htup->t_infomask |= HEAP_XMAX_INVALID;
UnlockAndWriteBuffer(buffer);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.29 2002/05/20 23:51:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.30 2002/05/21 22:05:53 tgl Exp $
*
*
* INTERFACE ROUTINES
if (!HeapTupleIsValid(toasttup))
elog(ERROR, "Failed to build TOAST tuple");
- heap_insert(toastrel, toasttup);
+ simple_heap_insert(toastrel, toasttup);
/*
* Create the index entry. We cheat a little here by not using
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.122 2002/05/17 20:53:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.123 2002/05/21 22:05:53 tgl Exp $
*
* NOTES
* Transaction aborts can now occur two ways:
return s->commandId;
}
-CommandId
-GetScanCommandId(void)
-{
- TransactionState s = CurrentTransactionState;
-
- return s->scanCommandId;
-}
-
/* --------------------------------
* GetCurrentTransactionStartTime
return (cid == s->commandId) ? true : false;
}
-bool
-CommandIdGEScanCommandId(CommandId cid)
-{
- TransactionState s = CurrentTransactionState;
-
- if (AMI_OVERRIDE)
- return false;
-
- return (cid >= s->scanCommandId) ? true : false;
-}
-
/* --------------------------------
* CommandCounterIncrement
void
CommandCounterIncrement(void)
{
- CurrentTransactionStateData.commandId += 1;
- if (CurrentTransactionStateData.commandId == FirstCommandId)
+ TransactionState s = CurrentTransactionState;
+
+ s->commandId += 1;
+ if (s->commandId == FirstCommandId) /* check for overflow */
elog(ERROR, "You may only have 2^32-1 commands per transaction");
- CurrentTransactionStateData.scanCommandId = CurrentTransactionStateData.commandId;
+ /* Propagate new command ID into query snapshots, if set */
+ if (QuerySnapshot)
+ QuerySnapshot->curcid = s->commandId;
+ if (SerializableSnapshot)
+ SerializableSnapshot->curcid = s->commandId;
/*
* make cache changes visible to me. AtCommit_LocalCache() instead of
AtStart_Cache();
}
-void
-SetScanCommandId(CommandId savedId)
-{
- CurrentTransactionStateData.scanCommandId = savedId;
-}
/* ----------------------------------------------------------------
* StartTransaction stuff
* initialize current transaction state fields
*/
s->commandId = FirstCommandId;
- s->scanCommandId = FirstCommandId;
-#if NOT_USED
- s->startTime = GetCurrentAbsoluteTime();
-#endif
s->startTime = GetCurrentAbsoluteTimeUsec(&(s->startTimeUsec));
/*
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.130 2002/05/20 23:51:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.131 2002/05/21 22:05:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
if (objectid != (Oid) 0)
tuple->t_data->t_oid = objectid;
- heap_insert(boot_reldesc, tuple);
+ simple_heap_insert(boot_reldesc, tuple);
heap_freetuple(tuple);
elog(DEBUG3, "row inserted");
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.200 2002/05/20 23:51:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.201 2002/05/21 22:05:53 tgl Exp $
*
*
* INTERFACE ROUTINES
ATTRIBUTE_TUPLE_SIZE,
(void *) *dpp);
- heap_insert(rel, tup);
+ simple_heap_insert(rel, tup);
if (hasindex)
CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
/* attStruct->attstattarget = 0; */
/* attStruct->attcacheoff = -1; */
- heap_insert(rel, tup);
+ simple_heap_insert(rel, tup);
if (hasindex)
CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
/*
* finally insert the new tuple and free it.
*/
- heap_insert(pg_class_desc, tup);
+ simple_heap_insert(pg_class_desc, tup);
if (!IsIgnoringSystemIndexes())
{
CStringGetDatum(adsrc));
adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
tuple = heap_formtuple(adrel->rd_att, values, nulls);
- heap_insert(adrel, tuple);
+ simple_heap_insert(adrel, tuple);
CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices,
idescs);
CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
CStringGetDatum(ccsrc));
rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
tuple = heap_formtuple(rcrel->rd_att, values, nulls);
- heap_insert(rcrel, tuple);
+ simple_heap_insert(rcrel, tuple);
CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices,
idescs);
CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.178 2002/05/20 23:51:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.179 2002/05/21 22:05:53 tgl Exp $
*
*
* INTERFACE ROUTINES
* sure would be embarrassing to do this sort of thing in polite company.
*/
tuple->t_data->t_oid = RelationGetRelid(indexRelation);
- heap_insert(pg_class, tuple);
+ simple_heap_insert(pg_class, tuple);
/*
* During normal processing, we need to make sure that the system
ATTRIBUTE_TUPLE_SIZE,
(void *) indexTupDesc->attrs[i]);
- heap_insert(pg_attribute, new_tuple);
+ simple_heap_insert(pg_attribute, new_tuple);
if (hasind)
CatalogIndexInsert(idescs, Num_pg_attr_indices, pg_attribute, new_tuple);
/*
* insert the tuple into the pg_index
*/
- heap_insert(pg_index, tuple);
+ simple_heap_insert(pg_index, tuple);
/*
* add index tuples for it
ItemPointerData tidsave;
ItemPointerCopy(&(rtup->t_self), &tidsave);
- test = heap_mark4update(relationRelation, rtup, buffer);
+ test = heap_mark4update(relationRelation, rtup, buffer,
+ GetCurrentCommandId());
switch (test)
{
case HeapTupleSelfUpdated:
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.46 2002/05/18 13:47:59 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.47 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
tupDesc = aggdesc->rd_att;
tup = heap_formtuple(tupDesc, values, nulls);
- heap_insert(aggdesc, tup);
+ simple_heap_insert(aggdesc, tup);
if (RelationGetForm(aggdesc)->relhasindex)
{
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.11 2002/05/20 23:51:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.12 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* Insert it
*/
- heap_insert(pg_largeobject, ntup);
+ simple_heap_insert(pg_largeobject, ntup);
/*
* Update indices
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_namespace.c,v 1.2 2002/03/31 06:26:30 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_namespace.c,v 1.3 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
nspdesc = heap_openr(NamespaceRelationName, RowExclusiveLock);
tupDesc = nspdesc->rd_att;
- if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc,
- values,
- nulls)))
- elog(ERROR, "NamespaceCreate: heap_formtuple failed");
- nspoid = heap_insert(nspdesc, tup);
- if (!OidIsValid(nspoid))
- elog(ERROR, "NamespaceCreate: heap_insert failed");
+
+ tup = heap_formtuple(tupDesc, values, nulls);
+ nspoid = simple_heap_insert(nspdesc, tup);
+ Assert(OidIsValid(nspoid));
if (RelationGetForm(nspdesc)->relhasindex)
{
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.68 2002/04/27 03:45:00 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.69 2002/05/21 22:05:54 tgl Exp $
*
* NOTES
* these routines moved here from commands/define.c and somewhat cleaned up.
/*
* insert our "shell" operator tuple
*/
- heap_insert(pg_operator_desc, tup);
- operatorObjectId = tup->t_data->t_oid;
+ operatorObjectId = simple_heap_insert(pg_operator_desc, tup);
if (RelationGetForm(pg_operator_desc)->relhasindex)
{
* get the t_self from the modified tuple and call RelationReplaceHeapTuple
* else if a new operator is being created
* create a tuple using heap_formtuple
- * call heap_insert
+ * call simple_heap_insert
*/
void
OperatorCreate(const char *operatorName,
tupDesc = pg_operator_desc->rd_att;
tup = heap_formtuple(tupDesc, values, nulls);
- heap_insert(pg_operator_desc, tup);
- operatorObjectId = tup->t_data->t_oid;
+ operatorObjectId = simple_heap_insert(pg_operator_desc, tup);
}
/* Must update the indexes in either case */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.72 2002/05/18 13:47:59 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.73 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
nulls[Anum_pg_proc_proacl-1] = 'n';
tup = heap_formtuple(tupDesc, values, nulls);
- heap_insert(rel, tup);
+ simple_heap_insert(rel, tup);
}
/* Need to update indices for either the insert or update case */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.70 2002/03/29 19:06:02 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.71 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* insert the tuple in the relation and get the tuple's oid.
*/
- heap_insert(pg_type_desc, tup);
- typoid = tup->t_data->t_oid;
+ typoid = simple_heap_insert(pg_type_desc, tup);
if (RelationGetForm(pg_type_desc)->relhasindex)
{
/* preassign tuple Oid, if one was given */
tup->t_data->t_oid = assignedTypeOid;
- heap_insert(pg_type_desc, tup);
-
- typeObjectId = tup->t_data->t_oid;
+ typeObjectId = simple_heap_insert(pg_type_desc, tup);
}
/* Update indices (not necessary if bootstrapping) */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.33 2002/05/20 23:51:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.34 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
/* No, insert new tuple */
stup = heap_formtuple(sd->rd_att, values, nulls);
- heap_insert(sd, stup);
+ simple_heap_insert(sd, stup);
}
/* update indices too */
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.85 2002/05/20 23:51:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.86 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
values[i++] = (Datum) 0; /* no notifies pending */
tuple = heap_formtuple(RelationGetDescr(lRel), values, nulls);
- heap_insert(lRel, tuple);
+ simple_heap_insert(lRel, tuple);
#ifdef NOT_USED /* currently there are no indexes */
if (RelationGetForm(lRel)->relhasindex)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.80 2002/05/20 23:51:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.81 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
HeapTuple copiedTuple = heap_copytuple(LocalHeapTuple);
- heap_insert(LocalNewHeap, copiedTuple);
+ simple_heap_insert(LocalNewHeap, copiedTuple);
heap_freetuple(copiedTuple);
CHECK_FOR_INTERRUPTS();
* Copyright (c) 1999-2001, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.47 2002/05/20 23:51:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.48 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
newtuple = heap_formtuple(RelationGetDescr(description),
values, nulls);
- heap_insert(description, newtuple);
+ simple_heap_insert(description, newtuple);
}
/* Update indexes, if necessary */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.154 2002/05/20 23:51:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.155 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* OK, store the tuple and create index entries for it
*/
- heap_insert(rel, tuple);
+ simple_heap_insert(rel, tuple);
if (resultRelInfo->ri_NumIndices > 0)
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.90 2002/05/20 23:51:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.91 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
tuple->t_data->t_oid = dboid; /* override heap_insert's OID
* selection */
- heap_insert(pg_database_rel, tuple);
+ simple_heap_insert(pg_database_rel, tuple);
/*
* Update indexes
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.2 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
EState *estate;
MemoryContext oldcontext;
ScanDirection direction;
- CommandId savedId;
bool temp_desc = false;
/* initialize completion status in case of early exit */
temp_desc = true;
}
- /*
- * Restore the scanCommandId that was current when the cursor was
- * opened. This ensures that we see the same tuples throughout the
- * execution of the cursor.
- */
- savedId = GetScanCommandId();
- SetScanCommandId(PortalGetCommandId(portal));
-
/*
* Determine which direction to go in, and check to see if we're
* already at the end of the available tuples in that direction. If
(dest == None) ? "MOVE" : "FETCH",
estate->es_processed);
- /*
- * Restore outer command ID.
- */
- SetScanCommandId(savedId);
-
/*
* Clean up and switch back to old context.
*/
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.31 2002/04/15 05:22:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.32 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
tupDesc = rel->rd_att;
tup = heap_formtuple(tupDesc, values, nulls);
- heap_insert(rel, tup);
+ simple_heap_insert(rel, tup);
if (RelationGetForm(rel)->relhasindex)
{
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.77 2002/04/15 05:22:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.78 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* Now form & insert sequence tuple */
tuple = heap_formtuple(tupDesc, value, null);
- heap_insert(rel, tuple);
+ simple_heap_insert(rel, tuple);
Assert(ItemPointerGetOffsetNumber(&(tuple->t_self)) == FirstOffsetNumber);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.15 2002/05/20 23:51:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.16 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
tuple = heap_formtuple(desc, datum, nullarr);
- heap_insert(relation, tuple);
+ simple_heap_insert(relation, tuple);
if (RelationGetForm(relation)->relhasindex)
{
ReleaseSysCache(typeTuple);
- heap_insert(attrdesc, attributeTuple);
+ simple_heap_insert(attrdesc, attributeTuple);
/* Update indexes on pg_attribute */
if (RelationGetForm(attrdesc)->relhasindex)
classtuple.t_self = reltup->t_self;
ReleaseSysCache(reltup);
- switch (heap_mark4update(class_rel, &classtuple, &buffer))
+ switch (heap_mark4update(class_rel, &classtuple, &buffer,
+ GetCurrentCommandId()))
{
case HeapTupleSelfUpdated:
case HeapTupleMayBeUpdated:
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.117 2002/04/30 01:24:57 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.118 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* Insert tuple into pg_trigger.
*/
- heap_insert(tgrel, tuple);
+ simple_heap_insert(tgrel, tuple);
CatalogOpenIndices(Num_pg_trigger_indices, Name_pg_trigger_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
CatalogCloseIndices(Num_pg_trigger_indices, idescs);
*newSlot = NULL;
tuple.t_self = *tid;
ltrmark:;
- test = heap_mark4update(relation, &tuple, &buffer);
+ test = heap_mark4update(relation, &tuple, &buffer,
+ GetCurrentCommandId());
switch (test)
{
case HeapTupleSelfUpdated:
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.102 2002/05/20 23:51:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.103 2002/05/21 22:05:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* Insert new record in the pg_shadow table
*/
- heap_insert(pg_shadow_rel, tuple);
+ simple_heap_insert(pg_shadow_rel, tuple);
/*
* Update indexes
tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls);
/*
- * Insert a new record in the pg_group_table
+ * Insert a new record in the pg_group table
*/
- heap_insert(pg_group_rel, tuple);
+ simple_heap_insert(pg_group_rel, tuple);
/*
* Update indexes
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.161 2002/05/12 20:10:02 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.162 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
ExecutorStart(QueryDesc *queryDesc, EState *estate)
{
TupleDesc result;
+ Snapshot es_snapshot;
/* sanity checks */
Assert(queryDesc != NULL);
}
/*
- * Make our own private copy of the current queries snapshot data
+ * Make our own private copy of the current query snapshot data.
+ *
+ * This "freezes" our idea of which tuples are good and which are not
+ * for the life of this query, even if it outlives the current command
+ * and current snapshot.
*/
- if (QuerySnapshot == NULL)
- estate->es_snapshot = NULL;
- else
+ if (QuerySnapshot == NULL) /* should be set already, but... */
+ SetQuerySnapshot();
+
+ es_snapshot = (Snapshot) palloc(sizeof(SnapshotData));
+ memcpy(es_snapshot, QuerySnapshot, sizeof(SnapshotData));
+ if (es_snapshot->xcnt > 0)
{
- estate->es_snapshot = (Snapshot) palloc(sizeof(SnapshotData));
- memcpy(estate->es_snapshot, QuerySnapshot, sizeof(SnapshotData));
- if (estate->es_snapshot->xcnt > 0)
- {
- estate->es_snapshot->xip = (TransactionId *)
- palloc(estate->es_snapshot->xcnt * sizeof(TransactionId));
- memcpy(estate->es_snapshot->xip, QuerySnapshot->xip,
- estate->es_snapshot->xcnt * sizeof(TransactionId));
- }
+ es_snapshot->xip = (TransactionId *)
+ palloc(es_snapshot->xcnt * sizeof(TransactionId));
+ memcpy(es_snapshot->xip, QuerySnapshot->xip,
+ es_snapshot->xcnt * sizeof(TransactionId));
}
+ else
+ es_snapshot->xip = NULL;
+
+ estate->es_snapshot = es_snapshot;
/*
* Initialize the plan
erm->resname);
tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
- test = heap_mark4update(erm->relation, &tuple, &buffer);
+ test = heap_mark4update(erm->relation, &tuple, &buffer,
+ estate->es_snapshot->curcid);
ReleaseBuffer(buffer);
switch (test)
{
*/
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);
IncrAppended();
}
/*
* insert the tuple
*/
- newId = heap_insert(resultRelationDesc, tuple);
+ newId = heap_insert(resultRelationDesc, tuple,
+ estate->es_snapshot->curcid);
IncrAppended();
(estate->es_processed)++;
* delete the tuple
*/
ldelete:;
- result = heap_delete(resultRelationDesc, tupleid, &ctid);
+ result = heap_delete(resultRelationDesc, tupleid,
+ &ctid,
+ estate->es_snapshot->curcid);
switch (result)
{
case HeapTupleSelfUpdated:
/*
* replace the heap tuple
*/
- result = heap_update(resultRelationDesc, tupleid, tuple, &ctid);
+ result = heap_update(resultRelationDesc, tupleid, tuple,
+ &ctid,
+ estate->es_snapshot->curcid);
switch (result)
{
case HeapTupleSelfUpdated:
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.50 2002/05/12 20:10:02 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.51 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
SQLFunctionCachePtr fcache;
execution_state *es;
Datum result = 0;
- CommandId savedId;
/*
* Switch to context in which the fcache lives. This ensures that
*/
oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
- /*
- * Before we start do anything we must save CurrentScanCommandId to
- * restore it before return to upper Executor. Also, we have to set
- * CurrentScanCommandId equal to CurrentCommandId. - vadim 08/29/97
- */
- savedId = GetScanCommandId();
- SetScanCommandId(GetCurrentCommandId());
-
/*
* Initialize fcache and execution state if first time through.
*/
es = es->next;
}
- /*
- * Restore outer command ID.
- */
- SetScanCommandId(savedId);
-
/*
* If we've gone through every command in this function, we are done.
*/
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.69 2002/04/15 05:22:04 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.70 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* ... and switch to procedure's context */
_SPI_current->savedcxt = MemoryContextSwitchTo(_SPI_current->procCxt);
- _SPI_current->savedId = GetScanCommandId();
- SetScanCommandId(GetCurrentCommandId());
-
return SPI_OK_CONNECT;
-
}
int
MemoryContextDelete(_SPI_current->execCxt);
MemoryContextDelete(_SPI_current->procCxt);
- SetScanCommandId(_SPI_current->savedId);
-
/*
* After _SPI_begin_call _SPI_connected == _SPI_curid. Now we are
* closing connection to SPI and returning to upper Executor and so
EState *estate;
MemoryContext oldcontext;
ScanDirection direction;
- CommandId savedId;
CommandDest olddest;
/* Check that the portal is valid */
olddest = querydesc->dest;
querydesc->dest = dest;
- /*
- * Restore the scanCommandId that was current when the cursor was
- * opened. This ensures that we see the same tuples throughout the
- * execution of the cursor.
- */
- savedId = GetScanCommandId();
- SetScanCommandId(PortalGetCommandId(portal));
-
/* Run the executor like PerformPortalFetch and remember states */
if (forward)
{
_SPI_current->processed = estate->es_processed;
- /*
- * Restore outer command ID.
- */
- SetScanCommandId(savedId);
-
/* Restore the old command destination and switch back to callers */
/* memory context */
querydesc->dest = olddest;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.71 2002/05/20 23:51:43 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.72 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
values,
nulls);
- heap_insert(pg_rewrite_desc, tup);
-
- rewriteObjectId = tup->t_data->t_oid;
+ rewriteObjectId = simple_heap_insert(pg_rewrite_desc, tup);
if (RelationGetForm(pg_rewrite_desc)->relhasindex)
{
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.45 2002/03/02 23:35:57 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.46 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Assert(TransactionIdIsValid(MyProc->xmin));
snapshot->xcnt = count;
+
+ snapshot->curcid = GetCurrentCommandId();
+
return snapshot;
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.91 2002/05/20 23:51:43 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.92 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno);
values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
newtup = heap_formtuple(obj_desc->heap_r->rd_att, values, nulls);
- heap_insert(obj_desc->heap_r, newtup);
+ simple_heap_insert(obj_desc->heap_r, newtup);
if (write_indices)
CatalogIndexInsert(idescs, Num_pg_largeobject_indices,
obj_desc->heap_r, newtup);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.47 2002/03/06 06:10:29 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.48 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
portal->queryDesc = queryDesc;
portal->attinfo = attinfo;
- portal->commandId = GetScanCommandId();
portal->state = state;
portal->atStart = true; /* Allow fetch forward only */
portal->atEnd = false;
/* initialize portal query */
portal->queryDesc = NULL;
portal->attinfo = NULL;
- portal->commandId = 0;
portal->state = NULL;
portal->atStart = true; /* disallow fetches until query is set */
portal->atEnd = true;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.50 2002/05/06 02:39:01 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.51 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
}
else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
{
- if (CommandIdGEScanCommandId(tuple->t_cmin))
+ if (tuple->t_cmin >= GetCurrentCommandId())
return false; /* inserted after scan started */
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
return true;
- if (CommandIdGEScanCommandId(tuple->t_cmax))
+ if (tuple->t_cmax >= GetCurrentCommandId())
return true; /* deleted after scan started */
else
return false; /* deleted before scan started */
{
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
return true;
- if (CommandIdGEScanCommandId(tuple->t_cmax))
+ if (tuple->t_cmax >= GetCurrentCommandId())
return true; /* deleted after scan started */
else
return false; /* deleted before scan started */
* HeapTupleSatisfiesUpdate
*
* Same logic as HeapTupleSatisfiesNow, but returns a more detailed result
- * code, since UPDATE needs to know more than "is it visible?".
+ * code, since UPDATE needs to know more than "is it visible?". Also,
+ * tuples of my own xact are tested against the passed CommandId not
+ * CurrentCommandId.
*/
int
-HeapTupleSatisfiesUpdate(HeapTuple htuple)
+HeapTupleSatisfiesUpdate(HeapTuple htuple, CommandId curcid)
{
HeapTupleHeader tuple = htuple->t_data;
}
else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
{
- if (CommandIdGEScanCommandId(tuple->t_cmin))
+ if (tuple->t_cmin >= curcid)
return HeapTupleInvisible; /* inserted after scan
* started */
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
return HeapTupleMayBeUpdated;
- if (CommandIdGEScanCommandId(tuple->t_cmax))
+ if (tuple->t_cmax >= curcid)
return HeapTupleSelfUpdated; /* updated after scan
* started */
else
{
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
return HeapTupleMayBeUpdated;
- if (CommandIdGEScanCommandId(tuple->t_cmax))
+ if (tuple->t_cmax >= curcid)
return HeapTupleSelfUpdated; /* updated after scan
* started */
else
}
else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
{
- if (CommandIdGEScanCommandId(tuple->t_cmin))
+ if (tuple->t_cmin >= snapshot->curcid)
return false; /* inserted after scan started */
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
return true;
- if (CommandIdGEScanCommandId(tuple->t_cmax))
+ if (tuple->t_cmax >= snapshot->curcid)
return true; /* deleted after scan started */
else
return false; /* deleted before scan started */
{
if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
{
- if (CommandIdGEScanCommandId(tuple->t_cmax))
+ if (tuple->t_cmax >= snapshot->curcid)
return true; /* deleted after scan started */
else
return false; /* deleted before scan started */
{
free(QuerySnapshot->xip);
free(QuerySnapshot);
+ QuerySnapshot = NULL;
}
if (XactIsoLevel == XACT_SERIALIZABLE)
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: heapam.h,v 1.74 2002/05/20 23:51:43 tgl Exp $
+ * $Id: heapam.h,v 1.75 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
HeapTuple tuple, Buffer *userbuf,
PgStat_Info *pgstat_info);
-extern ItemPointer heap_get_latest_tid(Relation relation, Snapshot snapshot, ItemPointer tid);
+extern ItemPointer heap_get_latest_tid(Relation relation, Snapshot snapshot,
+ ItemPointer tid);
extern void setLastTid(const ItemPointer tid);
-extern Oid heap_insert(Relation relation, HeapTuple tup);
-extern int heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid);
+
+extern Oid heap_insert(Relation relation, HeapTuple tup, CommandId cid);
+extern int heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid,
+ CommandId cid);
extern int heap_update(Relation relation, ItemPointer otid, HeapTuple tup,
- ItemPointer ctid);
-extern int heap_mark4update(Relation relation, HeapTuple tup, Buffer *userbuf);
+ ItemPointer ctid, CommandId cid);
+extern int heap_mark4update(Relation relation, HeapTuple tup,
+ Buffer *userbuf, CommandId cid);
+
+extern Oid simple_heap_insert(Relation relation, HeapTuple tup);
extern void simple_heap_delete(Relation relation, ItemPointer tid);
extern void simple_heap_update(Relation relation, ItemPointer otid,
HeapTuple tup);
+
extern void heap_markpos(HeapScanDesc scan);
extern void heap_restrpos(HeapScanDesc scan);
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: xact.h,v 1.42 2002/04/01 03:34:27 tgl Exp $
+ * $Id: xact.h,v 1.43 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
TransactionId transactionIdData;
CommandId commandId;
- CommandId scanCommandId;
AbsoluteTime startTime;
int startTimeUsec;
int state;
extern bool IsAbortedTransactionBlockState(void);
extern TransactionId GetCurrentTransactionId(void);
extern CommandId GetCurrentCommandId(void);
-extern CommandId GetScanCommandId(void);
-extern void SetScanCommandId(CommandId);
extern AbsoluteTime GetCurrentTransactionStartTime(void);
extern AbsoluteTime GetCurrentTransactionStartTimeUsec(int *usec);
extern bool TransactionIdIsCurrentTransactionId(TransactionId xid);
extern bool CommandIdIsCurrentCommandId(CommandId cid);
-extern bool CommandIdGEScanCommandId(CommandId cid);
extern void CommandCounterIncrement(void);
extern void StartTransactionCommand(void);
extern void CommitTransactionCommand(void);
* spi.c
* Server Programming Interface private declarations
*
- * $Header: /cvsroot/pgsql/src/include/executor/spi_priv.h,v 1.11 2001/11/05 17:46:33 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/include/executor/spi_priv.h,v 1.12 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
MemoryContext procCxt; /* procedure context */
MemoryContext execCxt; /* executor context */
MemoryContext savedcxt;
- CommandId savedId;
} _SPI_connection;
typedef struct
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: portal.h,v 1.32 2002/02/14 15:24:10 tgl Exp $
+ * $Id: portal.h,v 1.33 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
MemoryContext heap; /* subsidiary memory */
QueryDesc *queryDesc; /* Info about query associated with portal */
TupleDesc attinfo;
- CommandId commandId; /* Command counter value for query */
EState *state; /* Execution state of query */
bool atStart; /* T => fetch backwards is not allowed */
bool atEnd; /* T => fetch forwards is not allowed */
*/
#define PortalGetQueryDesc(portal) ((portal)->queryDesc)
#define PortalGetTupleDesc(portal) ((portal)->attinfo)
-#define PortalGetCommandId(portal) ((portal)->commandId)
#define PortalGetState(portal) ((portal)->state)
#define PortalGetHeapMemory(portal) ((portal)->heap)
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: tqual.h,v 1.38 2002/01/16 20:29:02 tgl Exp $
+ * $Id: tqual.h,v 1.39 2002/05/21 22:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
uint32 xcnt; /* # of xact ids in xip[] */
TransactionId *xip; /* array of xact IDs in progress */
/* note: all ids in xip[] satisfy xmin <= xip[i] < xmax */
+ CommandId curcid; /* in my xact, CID < curcid are visible */
ItemPointerData tid; /* required for Dirty snapshot -:( */
} SnapshotData;
extern bool HeapTupleSatisfiesToast(HeapTupleHeader tuple);
extern bool HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple,
Snapshot snapshot);
-extern int HeapTupleSatisfiesUpdate(HeapTuple tuple);
+extern int HeapTupleSatisfiesUpdate(HeapTuple tuple,
+ CommandId curcid);
extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple,
TransactionId OldestXmin);