Index: src/backend/access/index/indexam.c =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/src/backend/access/index/indexam.c,v retrieving revision 1.66 diff -c -r1.66 indexam.c *** src/backend/access/index/indexam.c 24 Mar 2003 21:42:33 -0000 1.66 --- src/backend/access/index/indexam.c 28 Apr 2003 01:38:27 -0000 *************** *** 528,534 **** LockBuffer(scan->xs_cbuf, BUFFER_LOCK_SHARE); sv_infomask = heapTuple->t_data->t_infomask; ! if (HeapTupleSatisfiesVacuum(heapTuple->t_data, RecentGlobalXmin) == HEAPTUPLE_DEAD) scan->kill_prior_tuple = true; --- 528,534 ---- LockBuffer(scan->xs_cbuf, BUFFER_LOCK_SHARE); sv_infomask = heapTuple->t_data->t_infomask; ! if (HeapTupleSatisfiesVacuum(heapTuple->t_data, GetRecentGlobalXmin()) == HEAPTUPLE_DEAD) scan->kill_prior_tuple = true; Index: src/backend/access/nbtree/nbtinsert.c =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/src/backend/access/nbtree/nbtinsert.c,v retrieving revision 1.99 diff -c -r1.99 nbtinsert.c *** src/backend/access/nbtree/nbtinsert.c 23 Feb 2003 06:17:13 -0000 1.99 --- src/backend/access/nbtree/nbtinsert.c 28 Apr 2003 01:33:15 -0000 *************** *** 212,224 **** { cbti = (BTItem) PageGetItem(page, curitemid); htup.t_self = cbti->bti_itup.t_tid; ! if (heap_fetch(heapRel, SnapshotDirty, &htup, &hbuffer, true, NULL)) { /* it is a duplicate */ TransactionId xwait = ! (TransactionIdIsValid(SnapshotDirty->xmin)) ? ! SnapshotDirty->xmin : SnapshotDirty->xmax; ReleaseBuffer(hbuffer); --- 212,224 ---- { cbti = (BTItem) PageGetItem(page, curitemid); htup.t_self = cbti->bti_itup.t_tid; ! if (heap_fetch(heapRel, GetSnapshotDirty(), &htup, &hbuffer, true, NULL)) { /* it is a duplicate */ TransactionId xwait = ! (TransactionIdIsValid(GetXminSnapshotDirty())) ? ! GetXminSnapshotDirty() : GetXmaxSnapshotDirty(); ReleaseBuffer(hbuffer); *************** *** 252,258 **** LockBuffer(hbuffer, BUFFER_LOCK_SHARE); sv_infomask = htup.t_data->t_infomask; if (HeapTupleSatisfiesVacuum(htup.t_data, ! RecentGlobalXmin) == HEAPTUPLE_DEAD) { curitemid->lp_flags |= LP_DELETE; --- 252,258 ---- LockBuffer(hbuffer, BUFFER_LOCK_SHARE); sv_infomask = htup.t_data->t_infomask; if (HeapTupleSatisfiesVacuum(htup.t_data, ! GetRecentGlobalXmin()) == HEAPTUPLE_DEAD) { curitemid->lp_flags |= LP_DELETE; Index: src/backend/access/nbtree/nbtpage.c =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/src/backend/access/nbtree/nbtpage.c,v retrieving revision 1.64 diff -c -r1.64 nbtpage.c *** src/backend/access/nbtree/nbtpage.c 4 Mar 2003 21:51:20 -0000 1.64 --- src/backend/access/nbtree/nbtpage.c 28 Apr 2003 01:33:40 -0000 *************** *** 539,545 **** */ opaque = (BTPageOpaque) PageGetSpecialPointer(page); if (P_ISDELETED(opaque) && ! TransactionIdPrecedesOrEquals(opaque->btpo.xact, RecentXmin)) return true; return false; } --- 539,545 ---- */ opaque = (BTPageOpaque) PageGetSpecialPointer(page); if (P_ISDELETED(opaque) && ! TransactionIdPrecedesOrEquals(opaque->btpo.xact, GetRecentXmin())) return true; return false; } Index: src/backend/access/transam/xact.c =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/src/backend/access/transam/xact.c,v retrieving revision 1.146 diff -c -r1.146 xact.c *** src/backend/access/transam/xact.c 26 Apr 2003 20:22:59 -0000 1.146 --- src/backend/access/transam/xact.c 28 Apr 2003 01:18:10 -0000 *************** *** 407,416 **** elog(ERROR, "You may only have 2^32-1 commands per transaction"); /* 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 --- 407,416 ---- elog(ERROR, "You may only have 2^32-1 commands per transaction"); /* Propagate new command ID into query snapshots, if set */ ! if (IsValidQuerySnapshot()) ! SetQuerySnapshotCurCid(s->commandId); ! if (IsValidSerializableSnapshot()) ! SetSerializableSnapshotCurCid(s->commandId); /* * make cache changes visible to me. AtCommit_LocalCache() instead of *************** *** 829,835 **** { TransactionState s = CurrentTransactionState; - FreeXactSnapshot(); XactIsoLevel = DefaultXactIsoLevel; XactReadOnly = DefaultXactReadOnly; --- 829,834 ---- *************** *** 869,874 **** --- 868,874 ---- * initialize the various transaction subsystems */ AtStart_Memory(); + AtStart_Snapshot(); AtStart_Cache(); AtStart_Locks(); *************** *** 993,998 **** --- 993,999 ---- AtEOXact_CatCache(true); AtEOXact_Files(); pgstat_count_xact_commit(); + AtEOXact_Snapshot(); AtCommit_Memory(); /* *************** *** 1101,1106 **** --- 1102,1108 ---- AtEOXact_Namespace(false); AtEOXact_CatCache(false); AtEOXact_Files(); + AtEOXact_Snapshot(); pgstat_count_xact_rollback(); /* Index: src/backend/bootstrap/bootparse.y =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/src/backend/bootstrap/bootparse.y,v retrieving revision 1.55 diff -c -r1.55 bootparse.y *** src/backend/bootstrap/bootparse.y 11 Nov 2002 22:19:21 -0000 1.55 --- src/backend/bootstrap/bootparse.y 28 Apr 2003 03:21:44 -0000 *************** *** 259,265 **** ; Boot_BuildIndsStmt: ! XBUILD INDICES { build_indices(); } ; --- 259,270 ---- ; Boot_BuildIndsStmt: ! XBUILD INDICES ! { ! do_start(); ! build_indices(); ! do_end(); ! } ; Index: src/backend/commands/trigger.c =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/src/backend/commands/trigger.c,v retrieving revision 1.148 diff -c -r1.148 trigger.c *** src/backend/commands/trigger.c 20 Apr 2003 17:03:25 -0000 1.148 --- src/backend/commands/trigger.c 28 Apr 2003 01:11:32 -0000 *************** *** 1828,1834 **** * Might have been a referential integrity constraint trigger. Reset * the snapshot overriding flag. */ ! ReferentialIntegritySnapshotOverride = false; /* * Release buffers --- 1828,1834 ---- * Might have been a referential integrity constraint trigger. Reset * the snapshot overriding flag. */ ! SetReferentialIntegritySnapshotOverride(false); /* * Release buffers Index: src/backend/commands/variable.c =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/src/backend/commands/variable.c,v retrieving revision 1.74 diff -c -r1.74 variable.c *** src/backend/commands/variable.c 25 Apr 2003 19:45:08 -0000 1.74 --- src/backend/commands/variable.c 28 Apr 2003 01:35:03 -0000 *************** *** 416,422 **** const char * assign_XactIsoLevel(const char *value, bool doit, bool interactive) { ! if (doit && interactive && SerializableSnapshot != NULL) elog(ERROR, "SET TRANSACTION ISOLATION LEVEL must be called before any query"); if (strcmp(value, "serializable") == 0) --- 416,422 ---- const char * assign_XactIsoLevel(const char *value, bool doit, bool interactive) { ! if (doit && interactive && IsValidSerializableSnapshot()) elog(ERROR, "SET TRANSACTION ISOLATION LEVEL must be called before any query"); if (strcmp(value, "serializable") == 0) Index: src/backend/executor/execMain.c =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/src/backend/executor/execMain.c,v retrieving revision 1.205 diff -c -r1.205 execMain.c *** src/backend/executor/execMain.c 27 Mar 2003 16:51:27 -0000 1.205 --- src/backend/executor/execMain.c 28 Apr 2003 01:35:33 -0000 *************** *** 1732,1742 **** { Buffer buffer; ! if (heap_fetch(relation, SnapshotDirty, &tuple, &buffer, false, NULL)) { ! TransactionId xwait = SnapshotDirty->xmax; ! if (TransactionIdIsValid(SnapshotDirty->xmin)) elog(ERROR, "EvalPlanQual: t_xmin is uncommitted ?!"); /* --- 1732,1742 ---- { Buffer buffer; ! if (heap_fetch(relation, GetSnapshotDirty(), &tuple, &buffer, false, NULL)) { ! TransactionId xwait = GetXmaxSnapshotDirty(); ! if (TransactionIdIsValid(GetXminSnapshotDirty())) elog(ERROR, "EvalPlanQual: t_xmin is uncommitted ?!"); /* *************** *** 1763,1773 **** * Note that it's possible to get invalid SnapshotDirty->tid if * tuple updated by this transaction. Have we to check this ? */ ! if (ItemPointerIsValid(&(SnapshotDirty->tid)) && ! !(ItemPointerEquals(&(tuple.t_self), &(SnapshotDirty->tid)))) { /* updated, so look at the updated copy */ ! tuple.t_self = SnapshotDirty->tid; continue; } --- 1763,1774 ---- * Note that it's possible to get invalid SnapshotDirty->tid if * tuple updated by this transaction. Have we to check this ? */ ! if (ItemPointerIsValid(GetTidSnapshotDirty()) && ! !(ItemPointerEquals(&(tuple.t_self), GetTidSnapshotDirty()))) { /* updated, so look at the updated copy */ ! ItemPointer tid = GetTidSnapshotDirty(); ! tuple.t_self = *tid; continue; } Index: src/backend/storage/ipc/sinval.c =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/src/backend/storage/ipc/sinval.c,v retrieving revision 1.54 diff -c -r1.54 sinval.c *** src/backend/storage/ipc/sinval.c 23 Feb 2003 23:20:52 -0000 1.54 --- src/backend/storage/ipc/sinval.c 28 Apr 2003 03:11:24 -0000 *************** *** 19,24 **** --- 19,25 ---- #include "storage/sinval.h" #include "storage/sinvaladt.h" #include "utils/tqual.h" + #include "utils/memutils.h" #include "miscadmin.h" *************** *** 307,313 **** Snapshot GetSnapshotData(bool serializable) { ! Snapshot snapshot = (Snapshot) malloc(sizeof(SnapshotData)); SISeg *segP = shmInvalBuffer; ProcState *stateP = segP->procState; TransactionId xmin; --- 308,314 ---- Snapshot GetSnapshotData(bool serializable) { ! Snapshot snapshot; SISeg *segP = shmInvalBuffer; ProcState *stateP = segP->procState; TransactionId xmin; *************** *** 315,333 **** TransactionId globalxmin; int index; int count = 0; ! ! if (snapshot == NULL) ! elog(ERROR, "Memory exhausted in GetSnapshotData"); /* * Allocating space for MaxBackends xids is usually overkill; * lastBackend would be sufficient. But it seems better to do the ! * malloc while not holding the lock, so we can't look at lastBackend. */ snapshot->xip = (TransactionId *) ! malloc(MaxBackends * sizeof(TransactionId)); ! if (snapshot->xip == NULL) ! elog(ERROR, "Memory exhausted in GetSnapshotData"); globalxmin = xmin = GetCurrentTransactionId(); --- 316,334 ---- TransactionId globalxmin; int index; int count = 0; ! MemoryContext old_cxt = MemoryContextSwitchTo(TopTransactionContext); ! ! snapshot = (Snapshot) palloc(sizeof(SnapshotData)); /* * Allocating space for MaxBackends xids is usually overkill; * lastBackend would be sufficient. But it seems better to do the ! * palloc while not holding the lock, so we can't look at lastBackend. */ snapshot->xip = (TransactionId *) ! palloc(MaxBackends * sizeof(TransactionId)); ! ! MemoryContextSwitchTo(old_cxt); globalxmin = xmin = GetCurrentTransactionId(); *************** *** 421,428 **** globalxmin = xmin; /* Update globals for use by VACUUM */ ! RecentGlobalXmin = globalxmin; ! RecentXmin = xmin; snapshot->xmin = xmin; snapshot->xmax = xmax; --- 422,429 ---- globalxmin = xmin; /* Update globals for use by VACUUM */ ! SetRecentGlobalXmin(globalxmin); ! SetRecentXmin(xmin); snapshot->xmin = xmin; snapshot->xmax = xmax; Index: src/backend/utils/adt/ri_triggers.c =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/src/backend/utils/adt/ri_triggers.c,v retrieving revision 1.50 diff -c -r1.50 ri_triggers.c *** src/backend/utils/adt/ri_triggers.c 26 Apr 2003 22:21:47 -0000 1.50 --- src/backend/utils/adt/ri_triggers.c 28 Apr 2003 01:37:26 -0000 *************** *** 196,202 **** int i; int match_type; ! ReferentialIntegritySnapshotOverride = true; /* * Check that this is a valid trigger call on the right time and --- 196,202 ---- int i; int match_type; ! SetReferentialIntegritySnapshotOverride(true); /* * Check that this is a valid trigger call on the right time and *************** *** 648,654 **** int i; int match_type; ! ReferentialIntegritySnapshotOverride = true; /* * Check that this is a valid trigger call on the right time and --- 648,654 ---- int i; int match_type; ! SetReferentialIntegritySnapshotOverride(true); /* * Check that this is a valid trigger call on the right time and *************** *** 839,845 **** int i; int match_type; ! ReferentialIntegritySnapshotOverride = true; /* * Check that this is a valid trigger call on the right time and --- 839,845 ---- int i; int match_type; ! SetReferentialIntegritySnapshotOverride(true); /* * Check that this is a valid trigger call on the right time and *************** *** 1037,1043 **** void *qplan; int i; ! ReferentialIntegritySnapshotOverride = true; /* * Check that this is a valid trigger call on the right time and --- 1037,1043 ---- void *qplan; int i; ! SetReferentialIntegritySnapshotOverride(true); /* * Check that this is a valid trigger call on the right time and *************** *** 1213,1219 **** int i; int j; ! ReferentialIntegritySnapshotOverride = true; /* * Check that this is a valid trigger call on the right time and --- 1213,1219 ---- int i; int j; ! SetReferentialIntegritySnapshotOverride(true); /* * Check that this is a valid trigger call on the right time and *************** *** 1414,1420 **** void *qplan; int i; ! ReferentialIntegritySnapshotOverride = true; /* * Check that this is a valid trigger call on the right time and --- 1414,1420 ---- void *qplan; int i; ! SetReferentialIntegritySnapshotOverride(true); /* * Check that this is a valid trigger call on the right time and *************** *** 1596,1602 **** void *qplan; int i; ! ReferentialIntegritySnapshotOverride = true; /* * Check that this is a valid trigger call on the right time and --- 1596,1602 ---- void *qplan; int i; ! SetReferentialIntegritySnapshotOverride(true); /* * Check that this is a valid trigger call on the right time and *************** *** 1781,1787 **** void *qplan; int i; ! ReferentialIntegritySnapshotOverride = true; /* * Check that this is a valid trigger call on the right time and --- 1781,1787 ---- void *qplan; int i; ! SetReferentialIntegritySnapshotOverride(true); /* * Check that this is a valid trigger call on the right time and *************** *** 1966,1972 **** int match_type; bool use_cached_query; ! ReferentialIntegritySnapshotOverride = true; /* * Check that this is a valid trigger call on the right time and --- 1966,1972 ---- int match_type; bool use_cached_query; ! SetReferentialIntegritySnapshotOverride(true); /* * Check that this is a valid trigger call on the right time and *************** *** 2192,2198 **** RI_QueryKey qkey; void *qplan; ! ReferentialIntegritySnapshotOverride = true; /* * Check that this is a valid trigger call on the right time and --- 2192,2198 ---- RI_QueryKey qkey; void *qplan; ! SetReferentialIntegritySnapshotOverride(true); /* * Check that this is a valid trigger call on the right time and *************** *** 2416,2422 **** void *qplan; int match_type; ! ReferentialIntegritySnapshotOverride = true; /* * Check that this is a valid trigger call on the right time and --- 2416,2422 ---- void *qplan; int match_type; ! SetReferentialIntegritySnapshotOverride(true); /* * Check that this is a valid trigger call on the right time and Index: src/backend/utils/time/tqual.c =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/src/backend/utils/time/tqual.c,v retrieving revision 1.62 diff -c -r1.62 tqual.c *** src/backend/utils/time/tqual.c 23 Feb 2003 23:20:52 -0000 1.62 --- src/backend/utils/time/tqual.c 28 Apr 2003 01:45:17 -0000 *************** *** 24,44 **** #include "postgres.h" #include "storage/sinval.h" #include "utils/tqual.h" ! static SnapshotData SnapshotDirtyData; ! Snapshot SnapshotDirty = &SnapshotDirtyData; ! ! Snapshot QuerySnapshot = NULL; ! Snapshot SerializableSnapshot = NULL; ! ! /* These are updated by GetSnapshotData: */ ! TransactionId RecentXmin = InvalidTransactionId; ! TransactionId RecentGlobalXmin = InvalidTransactionId; ! ! bool ReferentialIntegritySnapshotOverride = false; /* * HeapTupleSatisfiesItself --- 24,45 ---- #include "postgres.h" #include "storage/sinval.h" + #include "utils/memutils.h" #include "utils/tqual.h" + typedef struct SnapshotStackData { + SnapshotData SnapshotDirtyData; + Snapshot QuerySnapshot; + Snapshot SerializableSnapshot; + TransactionId RecentXmin; + TransactionId RecentGlobalXmin; + bool ReferentialIntegritySnapshotOverride; + struct SnapshotStackData *parent; + } SnapshotStackData; ! typedef SnapshotStackData *SnapshotStack; + static SnapshotStack snapshotStack = NULL; /* * HeapTupleSatisfiesItself *************** *** 501,508 **** bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple) { ! SnapshotDirty->xmin = SnapshotDirty->xmax = InvalidTransactionId; ! ItemPointerSetInvalid(&(SnapshotDirty->tid)); if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { --- 502,510 ---- bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple) { ! snapshotStack->SnapshotDirtyData.xmin = ! snapshotStack->SnapshotDirtyData.xmax = InvalidTransactionId; ! ItemPointerSetInvalid(&(snapshotStack->SnapshotDirtyData.tid)); if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { *************** *** 557,563 **** tuple->t_infomask |= HEAP_XMIN_INVALID; return false; } ! SnapshotDirty->xmin = HeapTupleHeaderGetXmin(tuple); /* XXX shouldn't we fall through to look at xmax? */ return true; /* in insertion by other */ } --- 559,565 ---- tuple->t_infomask |= HEAP_XMIN_INVALID; return false; } ! snapshotStack->SnapshotDirtyData.xmin = HeapTupleHeaderGetXmin(tuple); /* XXX shouldn't we fall through to look at xmax? */ return true; /* in insertion by other */ } *************** *** 574,580 **** { if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE) return true; ! SnapshotDirty->tid = tuple->t_ctid; return false; /* updated by other */ } --- 576,582 ---- { if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE) return true; ! snapshotStack->SnapshotDirtyData.tid = tuple->t_ctid; return false; /* updated by other */ } *************** *** 593,599 **** return true; } /* running xact */ ! SnapshotDirty->xmax = HeapTupleHeaderGetXmax(tuple); return true; /* in updation by other */ } --- 595,601 ---- return true; } /* running xact */ ! snapshotStack->SnapshotDirtyData.xmax = HeapTupleHeaderGetXmax(tuple); return true; /* in updation by other */ } *************** *** 603,609 **** if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE) return true; ! SnapshotDirty->tid = tuple->t_ctid; return false; /* updated by other */ } --- 605,611 ---- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE) return true; ! snapshotStack->SnapshotDirtyData.tid = tuple->t_ctid; return false; /* updated by other */ } *************** *** 632,638 **** HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot) { /* XXX this is horribly ugly: */ ! if (ReferentialIntegritySnapshotOverride) return HeapTupleSatisfiesNow(tuple); if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) --- 634,640 ---- HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot) { /* XXX this is horribly ugly: */ ! if (snapshotStack->ReferentialIntegritySnapshotOverride) return HeapTupleSatisfiesNow(tuple); if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) *************** *** 936,965 **** SetQuerySnapshot(void) { /* Initialize snapshot overriding to false */ ! ReferentialIntegritySnapshotOverride = false; /* 1st call in xaction? */ ! if (SerializableSnapshot == NULL) { ! SerializableSnapshot = GetSnapshotData(true); ! QuerySnapshot = SerializableSnapshot; ! Assert(QuerySnapshot != NULL); return; } ! if (QuerySnapshot != SerializableSnapshot) { ! free(QuerySnapshot->xip); ! free(QuerySnapshot); ! QuerySnapshot = NULL; } if (XactIsoLevel == XACT_SERIALIZABLE) ! QuerySnapshot = SerializableSnapshot; else ! QuerySnapshot = GetSnapshotData(false); ! Assert(QuerySnapshot != NULL); } /* --- 938,967 ---- SetQuerySnapshot(void) { /* Initialize snapshot overriding to false */ ! snapshotStack->ReferentialIntegritySnapshotOverride = false; /* 1st call in xaction? */ ! if (snapshotStack->SerializableSnapshot == NULL) { ! snapshotStack->SerializableSnapshot = GetSnapshotData(true); ! snapshotStack->QuerySnapshot = snapshotStack->SerializableSnapshot; ! Assert(snapshotStack->QuerySnapshot != NULL); return; } ! if (snapshotStack->QuerySnapshot != snapshotStack->SerializableSnapshot) { ! pfree(snapshotStack->QuerySnapshot->xip); ! pfree(snapshotStack->QuerySnapshot); ! snapshotStack->QuerySnapshot = NULL; } if (XactIsoLevel == XACT_SERIALIZABLE) ! snapshotStack->QuerySnapshot = snapshotStack->SerializableSnapshot; else ! snapshotStack->QuerySnapshot = GetSnapshotData(false); ! Assert(snapshotStack->QuerySnapshot != NULL); } /* *************** *** 978,993 **** { Snapshot snapshot; ! if (QuerySnapshot == NULL) /* should be set beforehand */ elog(ERROR, "CopyQuerySnapshot: no snapshot has been set"); snapshot = (Snapshot) palloc(sizeof(SnapshotData)); ! memcpy(snapshot, QuerySnapshot, sizeof(SnapshotData)); if (snapshot->xcnt > 0) { snapshot->xip = (TransactionId *) palloc(snapshot->xcnt * sizeof(TransactionId)); ! memcpy(snapshot->xip, QuerySnapshot->xip, snapshot->xcnt * sizeof(TransactionId)); } else --- 980,995 ---- { Snapshot snapshot; ! if (snapshotStack->QuerySnapshot == NULL) /* should be set beforehand */ elog(ERROR, "CopyQuerySnapshot: no snapshot has been set"); snapshot = (Snapshot) palloc(sizeof(SnapshotData)); ! memcpy(snapshot, snapshotStack->QuerySnapshot, sizeof(SnapshotData)); if (snapshot->xcnt > 0) { snapshot->xip = (TransactionId *) palloc(snapshot->xcnt * sizeof(TransactionId)); ! memcpy(snapshot->xip, snapshotStack->QuerySnapshot->xip, snapshot->xcnt * sizeof(TransactionId)); } else *************** *** 997,1021 **** } /* ! * FreeXactSnapshot ! * Free snapshot(s) at end of transaction. */ void ! FreeXactSnapshot(void) { ! if (QuerySnapshot != NULL && QuerySnapshot != SerializableSnapshot) ! { ! free(QuerySnapshot->xip); ! free(QuerySnapshot); ! } ! QuerySnapshot = NULL; ! if (SerializableSnapshot != NULL) ! { ! free(SerializableSnapshot->xip); ! free(SerializableSnapshot); ! } ! SerializableSnapshot = NULL; } --- 999,1129 ---- } /* ! * Add a SnapshotStack item */ void ! AtStart_Snapshot(void) { ! SnapshotStack ssitem; ! MemoryContext old_cxt; ! old_cxt = MemoryContextSwitchTo(TopTransactionContext); ! ssitem = (SnapshotStack) palloc(sizeof(SnapshotStackData)); ! ssitem->parent = snapshotStack; ! ssitem->SerializableSnapshot = NULL; ! ssitem->QuerySnapshot = NULL; ! ssitem->RecentXmin = InvalidTransactionId; ! ssitem->RecentGlobalXmin = InvalidTransactionId; ! snapshotStack = ssitem; ! MemoryContextSwitchTo(old_cxt); ! } ! /* ! * Pops the SnapshotStack item ! */ ! void ! AtEOXact_Snapshot(void) ! { ! Assert(snapshotStack != NULL); ! snapshotStack = snapshotStack->parent; ! ! /* ! * The leftover stack item will be deleted when the transaction ! * memory context is reset or deleted. ! */ ! ! } ! ! TransactionId ! GetRecentXmin(void) ! { ! return snapshotStack->RecentXmin; ! } ! ! void ! SetRecentXmin(TransactionId recentXmin) ! { ! snapshotStack->RecentXmin = recentXmin; ! } ! ! TransactionId ! GetRecentGlobalXmin(void) ! { ! return snapshotStack->RecentGlobalXmin; ! } ! ! void ! SetRecentGlobalXmin(TransactionId recentGlobalXmin) ! { ! snapshotStack->RecentGlobalXmin = recentGlobalXmin; ! } ! ! void ! SetReferentialIntegritySnapshotOverride(bool override) ! { ! Assert(snapshotStack != NULL); ! snapshotStack->ReferentialIntegritySnapshotOverride = override; ! } ! Snapshot ! GetSnapshotDirty(void) ! { ! Assert(snapshotStack != NULL); ! return &(snapshotStack->SnapshotDirtyData); ! } ! ! void ! SetQuerySnapshotCurCid(CommandId curcid) ! { ! Assert(IsValidQuerySnapshot()); ! snapshotStack->QuerySnapshot->curcid = curcid; ! } ! ! bool ! IsValidQuerySnapshot(void) ! { ! Assert (snapshotStack != NULL); ! return (snapshotStack->QuerySnapshot != NULL); ! } ! ! void ! SetSerializableSnapshotCurCid(CommandId curcid) ! { ! Assert(IsValidSerializableSnapshot()); ! snapshotStack->SerializableSnapshot->curcid = curcid; ! } ! ! bool ! IsValidSerializableSnapshot(void) ! { ! Assert(snapshotStack != NULL); ! return (snapshotStack->SerializableSnapshot != NULL); ! } ! ! bool ! IsSnapshotDirty(Snapshot snapshot) ! { ! Assert(snapshotStack != NULL); ! return (snapshot == &(snapshotStack->SnapshotDirtyData)); ! } ! ! TransactionId ! GetXminSnapshotDirty(void) ! { ! Assert(snapshotStack != NULL); ! return snapshotStack->SnapshotDirtyData.xmin; ! } ! ! TransactionId ! GetXmaxSnapshotDirty(void) ! { ! Assert(snapshotStack != NULL); ! return snapshotStack->SnapshotDirtyData.xmax; ! } ! ! ItemPointer ! GetTidSnapshotDirty(void) ! { ! Assert(snapshotStack != NULL); ! return &(snapshotStack->SnapshotDirtyData.tid); } Index: src/include/utils/tqual.h =================================================================== RCS file: /home/alvherre/cvs/pgsql-server/src/include/utils/tqual.h,v retrieving revision 1.44 diff -c -r1.44 tqual.h *** src/include/utils/tqual.h 23 Feb 2003 23:20:52 -0000 1.44 --- src/include/utils/tqual.h 28 Apr 2003 01:00:40 -0000 *************** *** 37,56 **** #define SnapshotAny ((Snapshot) 0x2) #define SnapshotToast ((Snapshot) 0x3) - extern DLLIMPORT Snapshot SnapshotDirty; - extern DLLIMPORT Snapshot QuerySnapshot; - extern DLLIMPORT Snapshot SerializableSnapshot; - - extern TransactionId RecentXmin; - 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) /* --- 37,46 ---- *************** *** 117,121 **** --- 107,129 ---- extern void SetQuerySnapshot(void); extern Snapshot CopyQuerySnapshot(void); extern void FreeXactSnapshot(void); + + extern void AtStart_Snapshot(void); + extern void AtEOXact_Snapshot(void); + + extern TransactionId GetRecentXmin(void); + extern void SetRecentXmin(TransactionId recentXmin); + extern TransactionId GetRecentGlobalXmin(void); + extern void SetRecentGlobalXmin(TransactionId recentGlobalXmin); + extern void SetReferentialIntegritySnapshotOverride(bool override); + extern Snapshot GetSnapshotDirty(void); + extern void SetQuerySnapshotCurCid(CommandId curcid); + extern bool IsValidQuerySnapshot(void); + extern void SetSerializableSnapshotCurCid(CommandId curcid); + extern bool IsValidSerializableSnapshot(void); + extern bool IsSnapshotDirty(Snapshot snapshot); + extern TransactionId GetXminSnapshotDirty(void); + extern TransactionId GetXmaxSnapshotDirty(void); + extern ItemPointer GetTidSnapshotDirty(void); #endif /* TQUAL_H */