From 3152996ffb8e9954927268b12f11814902e90166 Mon Sep 17 00:00:00 2001
From: "Vadim B. Mikheev" <vadim4o@yahoo.com>
Date: Fri, 29 Aug 1997 09:05:25 +0000
Subject: [PATCH] Fix very old bug which made tuples changed/inserted by a
 commnd visible to command itself (so we had multiple update of updated
 tuples, etc).

---
 src/backend/access/transam/xact.c | 42 ++++++++++++++++++++++++++++++-
 src/backend/utils/time/tqual.c    | 24 ++++++++++++------
 src/include/access/xact.h         |  8 ++++--
 3 files changed, 63 insertions(+), 11 deletions(-)

diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 903cca41130..5ac4a42c7c7 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.12 1997/08/19 21:30:19 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.13 1997/08/29 09:02:11 vadim Exp $
  *	
  * NOTES
  *	Transaction aborts can now occur two ways:
@@ -377,6 +377,22 @@ GetCurrentCommandId()
     return s->commandId;
 }
 
+CommandId
+GetScanCommandId()
+{
+    TransactionState s = CurrentTransactionState;
+    
+    /* ----------------
+     *	if the transaction system is disabled, we return
+     *  the special "disabled" command id.
+     * ----------------
+     */
+    if (s->state == TRANS_DISABLED)
+	return (CommandId) DisabledCommandId;
+    
+    return s->scanCommandId;
+}
+
 
 /* --------------------------------
  *	GetCurrentTransactionStartTime
@@ -432,6 +448,18 @@ CommandIdIsCurrentCommandId(CommandId cid)
 	(cid == s->commandId) ? true : false;
 }
 
+bool
+CommandIdGEScanCommandId(CommandId cid)
+{
+    TransactionState s = CurrentTransactionState;
+    
+    if (AMI_OVERRIDE)
+	return false;
+    
+    return 	
+	(cid >= s->scanCommandId) ? true : false;
+}
+
 
 /* --------------------------------
  *	ClearCommandIdCounterOverflowFlag
@@ -458,11 +486,22 @@ CommandCounterIncrement()
 	elog(WARN, "You may only have 65535 commands per transaction");
     }
     
+    CurrentTransactionStateData.scanCommandId = 
+    		CurrentTransactionStateData.commandId;
+    
     /* make cache changes visible to me */
     AtCommit_Cache();
     AtStart_Cache();
 }
 
+void 
+SetScanCommandId (CommandId savedId)
+{
+
+    CurrentTransactionStateData.scanCommandId = savedId;
+    
+}
+
 /* ----------------------------------------------------------------
  *		        initialization stuff
  * ----------------------------------------------------------------
@@ -757,6 +796,7 @@ StartTransaction()
      * ----------------
      */
     s->commandId = 		FirstCommandId;
+    s->scanCommandId = 		FirstCommandId;
     s->startTime = 		GetCurrentAbsoluteTime();
     
     /* ----------------
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index a5843004733..1fcf3679fe4 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.3 1997/08/19 21:36:12 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.4 1997/08/29 09:04:54 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -580,6 +580,13 @@ HeapTupleSatisfiesItself(HeapTuple tuple)
  *	    (Xmax is not committed &&           the row was deleted by another transaction
  *           Xmax != my-transaction))))         that has not been committed
  *
+ * XXX
+ *	CommandId stuff didn't work properly if one used SQL-functions in 
+ *	UPDATE/INSERT(fromSELECT)/DELETE scans: SQL-funcs call 
+ *	CommandCounterIncrement and made tuples changed/inserted by
+ *	current command visible to command itself (so we had multiple
+ *	update of updated tuples, etc).		- vadim 08/29/97
+ *	
  *	mao says 17 march 1993:  the tests in this routine are correct;
  *	if you think they're not, you're wrong, and you should think
  *	about it again.  i know, it happened to me.  we don't need to
@@ -615,13 +622,13 @@ HeapTupleSatisfiesNow(HeapTuple tuple)
     if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) {
 	
 	if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin)
-	    && CommandIdIsCurrentCommandId(tuple->t_cmin)) {
+	    && CommandIdGEScanCommandId(tuple->t_cmin)) {
 	    
 	    return (false);
 	}
 	
 	if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin)
-	    && !CommandIdIsCurrentCommandId(tuple->t_cmin)) {
+	    && !CommandIdGEScanCommandId(tuple->t_cmin)) {
 	    
 	    if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
 		return (true);
@@ -629,7 +636,7 @@ HeapTupleSatisfiesNow(HeapTuple tuple)
 	    
 	    Assert(TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax));
 	    
-	    if (CommandIdIsCurrentCommandId(tuple->t_cmax)) {
+	    if (CommandIdGEScanCommandId(tuple->t_cmax)) {
 		return (true);
 	    }
 	}
@@ -813,13 +820,13 @@ HeapTupleSatisfiesUpperUnboundedInternalTimeQual(HeapTuple tuple,
     if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) {
 	
 	if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) &&
-	    CommandIdIsCurrentCommandId(tuple->t_cmin)) {
+	    CommandIdGEScanCommandId(tuple->t_cmin)) {
 	    
 	    return (false);
 	}
 	
 	if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) &&
-	    !CommandIdIsCurrentCommandId(tuple->t_cmin)) {
+	    !CommandIdGEScanCommandId(tuple->t_cmin)) {
 	    
 	    if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
 		return (true);
@@ -827,7 +834,7 @@ HeapTupleSatisfiesUpperUnboundedInternalTimeQual(HeapTuple tuple,
 	    
 	    Assert(TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax));
 	    
-	    return ((bool) !CommandIdIsCurrentCommandId(tuple->t_cmax));
+	    return ((bool) !CommandIdGEScanCommandId(tuple->t_cmax));
 	}
 	
 	if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
@@ -849,7 +856,8 @@ HeapTupleSatisfiesUpperUnboundedInternalTimeQual(HeapTuple tuple,
 	}
 	
 	if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)) {
-	    return (CommandIdIsCurrentCommandId(tuple->t_cmin));
+	    return (CommandIdGEScanCommandId(tuple->t_cmin));
+	    /* it looks like error		      ^^^^ */
 	}
 	
 	if (!TransactionIdDidCommit((TransactionId)tuple->t_xmax)) {
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index ef148c6b9b6..0aec4bccb82 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: xact.h,v 1.5 1997/08/19 21:37:40 momjian Exp $
+ * $Id: xact.h,v 1.6 1997/08/29 09:05:25 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,7 +22,8 @@
 typedef struct TransactionStateData {
     TransactionId	transactionIdData;
     CommandId		commandId;
-    AbsoluteTime		startTime;
+    CommandId		scanCommandId;
+    AbsoluteTime	startTime;
     int			state;
     int			blockState;
 } TransactionStateData;
@@ -63,9 +64,12 @@ extern bool IsAbortedTransactionBlockState(void);
 extern void OverrideTransactionSystem(bool flag);
 extern TransactionId GetCurrentTransactionId(void);
 extern CommandId GetCurrentCommandId(void);
+extern CommandId GetScanCommandId(void);
+extern void SetScanCommandId(CommandId);
 extern AbsoluteTime GetCurrentTransactionStartTime(void);
 extern bool TransactionIdIsCurrentTransactionId(TransactionId xid);
 extern bool CommandIdIsCurrentCommandId(CommandId cid);
+extern bool CommandIdGEScanCommandId(CommandId cid);
 extern void CommandCounterIncrement(void);
 extern void InitializeTransactionSystem(void);
 extern bool CurrentXactInProgress(void);
-- 
GitLab