From 05d13cad2896a58d56c1372d614fde93c7c12d5a Mon Sep 17 00:00:00 2001
From: Hiroshi Inoue <inoue@tpf.co.jp>
Date: Mon, 11 Oct 1999 06:28:29 +0000
Subject: [PATCH] The 1st step to implement new type of scan,TidScan. Now WHERE
 restriction on ctid is allowed though it is sequentially scanned.

---
 src/backend/access/heap/heapam.c  |  91 ++++++++++++++++++++-
 src/backend/utils/adt/tid.c       | 130 +++++++++++++++++++++++++++++-
 src/include/access/heapam.h       |   3 +-
 src/include/catalog/pg_operator.h |   5 +-
 src/include/catalog/pg_proc.h     |   9 ++-
 src/include/utils/builtins.h      |  10 ++-
 6 files changed, 238 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4c054921949..89956260cee 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.55 1999/09/24 00:23:54 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.56 1999/10/11 06:28:27 inoue Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1086,6 +1086,95 @@ heap_fetch(Relation relation,
 	}
 }
 
+/* ----------------
+ *	heap_get_latest_tid -  get the latest tid of a specified tuple
+ *
+ * ----------------
+ */
+ItemPointer
+heap_get_latest_tid(Relation relation,
+		   Snapshot snapshot,
+		   ItemPointer tid)
+{
+	ItemId		lp;
+	Buffer		buffer;
+	PageHeader	dp;
+	OffsetNumber	offnum;
+	HeapTupleData	tp;
+	HeapTupleHeader	t_data;
+	ItemPointerData	ctid;
+	bool		invalidBlock,linkend;
+
+	/* ----------------
+	 *	get the buffer from the relation descriptor
+	 *	Note that this does a buffer pin.
+	 * ----------------
+	 */
+
+	buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
+
+	if (!BufferIsValid(buffer))
+		elog(ERROR, "heap_get_latest_tid: %s relation: ReadBuffer(%lx) failed",
+			 &relation->rd_rel->relname, (long) tid);
+
+	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+	/* ----------------
+	 *	get the item line pointer corresponding to the requested tid
+	 * ----------------
+	 */
+	dp = (PageHeader) BufferGetPage(buffer);
+	offnum = ItemPointerGetOffsetNumber(tid);
+	invalidBlock = true;
+	if (!PageIsNew(dp))
+	{
+		lp = PageGetItemId(dp, offnum);
+		if (ItemIdIsUsed(lp))
+			invalidBlock = false;
+	}
+	if (invalidBlock)
+	{	
+		LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+		ReleaseBuffer(buffer);
+		return NULL;
+	} 
+
+	/* ----------------
+	 *	more sanity checks
+	 * ----------------
+	 */
+
+	t_data = tp.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
+	tp.t_len = ItemIdGetLength(lp);
+	tp.t_self = *tid;
+	ctid = tp.t_data->t_ctid;
+
+	/* ----------------
+	 *	check time qualification of tid
+	 * ----------------
+	 */
+
+	HeapTupleSatisfies(&tp, relation, buffer, dp,
+					   snapshot, 0, (ScanKey) NULL);
+
+	linkend = true;
+	if ((t_data->t_infomask & HEAP_XMAX_COMMITTED) && 
+		!ItemPointerEquals(tid, &ctid))
+		linkend = false;
+
+	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+	ReleaseBuffer(buffer);
+
+	if (tp.t_data == NULL)
+	{
+		if (linkend)
+			return NULL;
+		return heap_get_latest_tid(relation, snapshot, &ctid); 
+	}
+
+	return tid;
+}
+
 /* ----------------
  *		heap_insert		- insert tuple
  *
diff --git a/src/backend/utils/adt/tid.c b/src/backend/utils/adt/tid.c
index 9e4b81ec095..93fb33f8a95 100644
--- a/src/backend/utils/adt/tid.c
+++ b/src/backend/utils/adt/tid.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.11 1999/07/17 20:18:00 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.12 1999/10/11 06:28:26 inoue Exp $
  *
  * NOTES
  *	  input routine largely stolen from boxin().
@@ -28,9 +28,9 @@
  * ----------------------------------------------------------------
  */
 ItemPointer
-tidin(char *str)
+tidin(const char *str)
 {
-	char	   *p,
+	const	char	   *p,
 			   *coord[NTIDARGS];
 	int			i;
 	ItemPointer result;
@@ -45,8 +45,12 @@ tidin(char *str)
 		if (*p == DELIM || (*p == LDELIM && !i))
 			coord[i++] = p + 1;
 
-	if (i < NTIDARGS - 1)
+	/* if (i < NTIDARGS - 1) */
+	if (i < NTIDARGS)
+	{
+		elog(ERROR, "%s invalid tid format", str);
 		return NULL;
+	}
 
 	blockNumber = (BlockNumber) atoi(coord[0]);
 	offsetNumber = (OffsetNumber) atoi(coord[1]);
@@ -70,6 +74,14 @@ tidout(ItemPointer itemPtr)
 	BlockId		blockId;
 	char		buf[32];
 	char	   *str;
+	static char *invalidTid = "()";
+
+	if (!itemPtr || !ItemPointerIsValid(itemPtr))
+	{
+		str = palloc(strlen(invalidTid));
+		strcpy(str, invalidTid);
+		return str;
+	}
 
 	blockId = &(itemPtr->ip_blkid);
 
@@ -83,3 +95,113 @@ tidout(ItemPointer itemPtr)
 
 	return str;
 }
+
+/*****************************************************************************
+ *	 PUBLIC ROUTINES														 *
+ *****************************************************************************/
+
+bool
+tideq(ItemPointer arg1, ItemPointer arg2)
+{
+	if ((!arg1) || (!arg2))
+	{
+		return false;
+	}
+	
+	return ( BlockIdGetBlockNumber(&(arg1->ip_blkid)) ==
+		 BlockIdGetBlockNumber(&(arg2->ip_blkid)) &&
+		 arg1->ip_posid == arg2->ip_posid );
+}
+
+bool
+tidne(ItemPointer arg1, ItemPointer arg2)
+{
+	if ((!arg1) || (!arg2))
+	{
+		return false;
+	}
+	return ( BlockIdGetBlockNumber(&(arg1->ip_blkid)) !=
+		 BlockIdGetBlockNumber(&(arg2->ip_blkid)) ||
+		 arg1->ip_posid != arg2->ip_posid );
+}
+
+text *
+tid_text(ItemPointer tid)
+{
+	char	   *str;
+
+	if (!tid)	return (text *)NULL;
+	str = tidout(tid);
+
+	return textin(str);
+}	/* tid_text() */
+
+ItemPointer
+text_tid(const text *string)
+{
+	ItemPointer	result;
+	char		*str;
+
+	if (!string)	return (ItemPointer)0;
+
+	str = textout(string);
+	result = tidin(str);
+	pfree(str);
+
+	return result;
+}	/* text_tid() */
+
+
+/*
+ *	Functions to get latest tid of a specified tuple.
+ *	Maybe these implementations is moved
+ *	to another place
+*/
+#include <utils/relcache.h>
+ItemPointer
+currtid_byreloid(Oid reloid, ItemPointer tid)
+{
+	ItemPointer	result = NULL, ret;
+	Relation	rel;
+
+	result = (ItemPointer) palloc(sizeof(ItemPointerData));
+	ItemPointerSetInvalid(result);
+	if (rel = heap_open(reloid, AccessShareLock), rel)
+	{
+		ret = heap_get_latest_tid(rel, SnapshotNow, tid);
+		if (ret)
+			ItemPointerCopy(ret, result);
+		heap_close(rel, AccessShareLock);
+	}
+	else
+		elog(ERROR, "Relation %u not found", reloid);
+
+	return result;
+}	/* currtid_byreloid() */
+
+ItemPointer
+currtid_byrelname(const text *relname, ItemPointer tid)
+{
+	ItemPointer	result = NULL, ret;
+	char		*str;
+	Relation	rel;
+
+	if (!relname)	return result;
+
+	str = textout(relname);
+
+	result = (ItemPointer) palloc(sizeof(ItemPointerData));
+	ItemPointerSetInvalid(result);
+	if (rel = heap_openr(str, AccessShareLock), rel)
+	{
+		ret = heap_get_latest_tid(rel, SnapshotNow, tid);
+		if (ret)
+			ItemPointerCopy(ret, result);
+		heap_close(rel, AccessShareLock);
+	}
+	else
+		elog(ERROR, "Relation %s not found", relname);
+	pfree(str);
+
+	return result;
+}	/* currtid_byrelname() */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index b6dccc33fa8..b672b58053e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heapam.h,v 1.46 1999/09/18 19:08:13 tgl Exp $
+ * $Id: heapam.h,v 1.47 1999/10/11 06:28:29 inoue Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -256,6 +256,7 @@ extern void heap_rescan(HeapScanDesc scan, bool scanFromEnd, ScanKey key);
 extern void heap_endscan(HeapScanDesc scan);
 extern HeapTuple heap_getnext(HeapScanDesc scandesc, int backw);
 extern void heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tup, Buffer *userbuf);
+extern ItemPointer heap_get_latest_tid(Relation relation, Snapshot snapshot, ItemPointer tid);
 extern Oid	heap_insert(Relation relation, HeapTuple tup);
 extern int	heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid);
 extern int heap_replace(Relation relation, ItemPointer otid, HeapTuple tup,
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index 5667b870e68..c23f67a4c66 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_operator.h,v 1.59 1999/09/06 21:16:18 tgl Exp $
+ * $Id: pg_operator.h,v 1.60 1999/10/11 06:28:29 inoue Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -136,6 +136,9 @@ DATA(insert OID = 399 (  "="	   PGUID 0 b t f  1026	1026  16  399 0  0	0 array_e
 DATA(insert OID = 400 (  "="	   PGUID 0 b t f  1027	1027  16  400 0  0	0 array_eq eqsel eqjoinsel ));
 DATA(insert OID = 401 (  "="	   PGUID 0 b t f  1034	1034  16  401 0  0	0 array_eq eqsel eqjoinsel ));
 
+DATA(insert OID = 387 ( "="	   PGUID 0 b t t  27  27  16 387  0  0  0 tideq eqsel eqjoinsel ));
+#define TIDEqualOperator   387
+
 DATA(insert OID = 410 ( "="		   PGUID 0 b t t  20  20  16 410 411 412 412 int8eq eqsel eqjoinsel ));
 DATA(insert OID = 411 ( "<>"	   PGUID 0 b t f  20  20  16 411 410 0 0 int8ne neqsel neqjoinsel ));
 DATA(insert OID = 412 ( "<"		   PGUID 0 b t f  20  20  16 413 415 0 0 int8lt intltsel intltjoinsel ));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 24e74f0e624..89ff91c8e84 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.104 1999/09/30 14:54:23 wieck Exp $
+ * $Id: pg_proc.h,v 1.105 1999/10/11 06:28:28 inoue Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -1560,6 +1560,13 @@ DESCR("truncate _char()");
 DATA(insert OID = 1291 (  _varchar		   PGUID 11 f t t 2 f 1015 "1015 23" 100 0 0 100  _varchar - ));
 DESCR("truncate _varchar()");
 
+DATA(insert OID = 1292 ( tideq			   PGUID 11 f t f 2 f 16 "27 27" 100 0 0 100  tideq - ));
+DESCR("equal");
+DATA(insert OID = 1293 ( currtid		   PGUID 11 f t f 2 f 27 "26 27" 100 0 0 100  currtid_byreloid - ));
+DESCR("latest tid of a tuple");
+DATA(insert OID = 1294 ( currtid2		   PGUID 11 f t f 2 f 27 "25 27" 100 0 0 100  currtid_byrelname - ));
+DESCR("latest tid of a tuple");
+
 DATA(insert OID = 1297 (  timestamp_in	   PGUID 11 f t f 1 f 1296 "0" 100 0 0 100	timestamp_in - ));
 DESCR("(internal)");
 DATA(insert OID = 1298 (  timestamp_out    PGUID 11 f t f 1 f	23 "0" 100 0 0 100	timestamp_out - ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index da09be65243..fe6fd117187 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: builtins.h,v 1.88 1999/10/03 23:55:37 tgl Exp $
+ * $Id: builtins.h,v 1.89 1999/10/11 06:28:28 inoue Exp $
  *
  * NOTES
  *	  This should normally only be included by fmgr.h.
@@ -399,8 +399,14 @@ extern float64 gistsel(Oid operatorObjectId, Oid indrelid, AttrNumber attributeN
 extern float64 gistnpage(Oid operatorObjectId, Oid indrelid, AttrNumber attributeNumber, char *constValue, int32 constFlag, int32 nIndexKeys, Oid indexrelid);
 
 /* tid.c */
-extern ItemPointer tidin(char *str);
+extern ItemPointer tidin(const char *str);
 extern char *tidout(ItemPointer itemPtr);
+extern bool tideq(ItemPointer,ItemPointer);
+extern bool tidne(ItemPointer,ItemPointer);
+extern text *tid_text(ItemPointer);
+extern ItemPointer text_tid(const text *); 
+extern ItemPointer currtid_byreloid(Oid relOid, ItemPointer); 
+extern ItemPointer currtid_byrelname(const text* relName, ItemPointer); 
 
 /* timestamp.c */
 extern time_t timestamp_in(const char *timestamp_str);
-- 
GitLab