From b0f5086e4133d1d8ec092799952dda65ebd717c8 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Sat, 20 Jul 2002 05:16:59 +0000
Subject: [PATCH] oid is needed, it is added at the end of the struct (after
 the null bitmap, if present).

Per Tom Lane's suggestion the information whether a tuple has an oid
or not is carried in the tuple descriptor.  For debugging reasons
tdhasoid is of type char, not bool.  There are predefined values for
WITHOID, WITHOUTOID and UNDEFOID.

This patch has been generated against a cvs snapshot from last week
and I don't expect it to apply cleanly to current sources.  While I
post it here for public review, I'm working on a new version against a
current snapshot.  (There's been heavy activity recently; hope to
catch up some day ...)

This is a long patch;  if it is too hard to swallow, I can provide it
in smaller pieces:

Part 1:  Accessor macros
Part 2:  tdhasoid in TupDesc
Part 3:  Regression test
Part 4:  Parameter withoid to heap_addheader
Part 5:  Eliminate t_oid from HeapTupleHeader

Part 2 is the most hairy part because of changes in the executor and
even in the parser;  the other parts are straightforward.

Up to part 4 the patched postmaster stays binary compatible to
databases created with an unpatched version.  Part 5 is small (100
lines) and finally breaks compatibility.

Manfred Koizar
---
 contrib/dbsize/dbsize.c                 |  2 +-
 contrib/fulltextindex/fti.c             |  2 +-
 contrib/rserv/rserv.c                   |  4 +-
 src/backend/access/common/heaptuple.c   | 27 ++++++--
 src/backend/access/common/tupdesc.c     | 16 +++--
 src/backend/access/heap/heapam.c        | 88 +++++++++++++++++--------
 src/backend/access/heap/tuptoaster.c    |  4 +-
 src/backend/bootstrap/bootparse.y       |  4 +-
 src/backend/bootstrap/bootstrap.c       | 16 +++--
 src/backend/catalog/aclchk.c            |  5 +-
 src/backend/catalog/heap.c              | 25 ++++---
 src/backend/catalog/index.c             | 15 +++--
 src/backend/catalog/namespace.c         | 17 ++---
 src/backend/catalog/pg_operator.c       |  6 +-
 src/backend/catalog/pg_proc.c           |  6 +-
 src/backend/catalog/pg_type.c           |  8 ++-
 src/backend/commands/comment.c          | 19 ++++--
 src/backend/commands/copy.c             | 13 ++--
 src/backend/commands/dbcommands.c       | 10 ++-
 src/backend/commands/explain.c          |  4 +-
 src/backend/commands/functioncmds.c     |  4 +-
 src/backend/commands/indexcmds.c        |  8 +--
 src/backend/commands/proclang.c         |  6 +-
 src/backend/commands/tablecmds.c        | 10 ++-
 src/backend/commands/trigger.c          | 11 ++--
 src/backend/commands/typecmds.c         |  4 +-
 src/backend/commands/vacuum.c           |  9 +--
 src/backend/commands/vacuumlazy.c       |  6 +-
 src/backend/executor/execJunk.c         |  8 +--
 src/backend/executor/execMain.c         |  6 +-
 src/backend/executor/execQual.c         |  5 +-
 src/backend/executor/execTuples.c       |  7 +-
 src/backend/executor/execUtils.c        | 18 ++++-
 src/backend/executor/nodeFunctionscan.c |  4 +-
 src/backend/executor/spi.c              | 12 ++--
 src/backend/optimizer/util/clauses.c    |  4 +-
 src/backend/parser/parse_oper.c         |  4 +-
 src/backend/parser/parse_type.c         |  4 +-
 src/backend/postmaster/pgstat.c         |  5 +-
 src/backend/rewrite/rewriteRemove.c     |  4 +-
 src/backend/utils/adt/regproc.c         | 18 +++--
 src/backend/utils/adt/sets.c            |  5 +-
 src/backend/utils/cache/catcache.c      | 21 +++---
 src/backend/utils/cache/inval.c         |  7 +-
 src/backend/utils/cache/relcache.c      | 17 +++--
 src/backend/utils/cache/syscache.c      |  4 +-
 src/backend/utils/init/postinit.c       |  5 +-
 src/backend/utils/misc/database.c       |  4 +-
 src/include/access/heapam.h             |  4 +-
 src/include/access/htup.h               | 44 +++++++++++--
 src/include/access/tupdesc.h            | 27 +++++++-
 src/include/executor/executor.h         |  4 +-
 src/include/pg_config.h.in              |  8 ++-
 src/pl/plpython/plpython.c              |  4 +-
 src/pl/tcl/pltcl.c                      |  4 +-
 src/test/regress/parallel_schedule      |  3 +
 src/test/regress/serial_schedule        |  3 +-
 57 files changed, 414 insertions(+), 198 deletions(-)

diff --git a/contrib/dbsize/dbsize.c b/contrib/dbsize/dbsize.c
index b072a86912f..44699aa6936 100644
--- a/contrib/dbsize/dbsize.c
+++ b/contrib/dbsize/dbsize.c
@@ -65,7 +65,7 @@ database_size(PG_FUNCTION_ARGS)
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "database %s does not exist", NameStr(*dbname));
 
-	dbid = tuple->t_data->t_oid;
+	dbid = HeapTupleGetOid(tuple);
 	if (dbid == InvalidOid)
 		elog(ERROR, "invalid database id");
 
diff --git a/contrib/fulltextindex/fti.c b/contrib/fulltextindex/fti.c
index aabb2caf9f9..8050f2a9d72 100644
--- a/contrib/fulltextindex/fti.c
+++ b/contrib/fulltextindex/fti.c
@@ -190,7 +190,7 @@ fti(PG_FUNCTION_ARGS)
 	tupdesc = rel->rd_att;		/* what the tuple looks like (?) */
 
 	/* get oid of current tuple, needed by all, so place here */
-	oid = rettuple->t_data->t_oid;
+	oid = rel->rd_rel->relhasoids ? HeapTupleGetOid(rettuple) : InvalidOid;
 	if (!OidIsValid(oid))
 		elog(ERROR, "Full Text Indexing: Oid of current tuple is invalid");
 
diff --git a/contrib/rserv/rserv.c b/contrib/rserv/rserv.c
index 401cc5fd9cc..54da14a6961 100644
--- a/contrib/rserv/rserv.c
+++ b/contrib/rserv/rserv.c
@@ -102,7 +102,9 @@ _rserv_log_()
 
 	if (keynum == ObjectIdAttributeNumber)
 	{
-		sprintf(oidbuf, "%u", tuple->t_data->t_oid);
+		sprintf(oidbuf, "%u", rel->rd_rel->relhasoids
+		                      ? HeapTupleGetOid(tuple)
+		                      : InvalidOid);
 		key = oidbuf;
 	}
 	else
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index adad245c643..19e02dee67e 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.77 2002/06/20 20:29:24 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.78 2002/07/20 05:16:56 momjian Exp $
  *
  * NOTES
  *	  The old interface functions have been converted to macros
@@ -436,7 +436,7 @@ heap_getsysattr(HeapTuple tup, int attnum, bool *isnull)
 			result = PointerGetDatum(&(tup->t_self));
 			break;
 		case ObjectIdAttributeNumber:
-			result = ObjectIdGetDatum(tup->t_data->t_oid);
+			result = ObjectIdGetDatum(HeapTupleGetOid(tup));
 			break;
 		case MinTransactionIdAttributeNumber:
 			result = TransactionIdGetDatum(HeapTupleHeaderGetXmin(tup->t_data));
@@ -581,6 +581,8 @@ heap_formtuple(TupleDesc tupleDescriptor,
 		elog(ERROR, "heap_formtuple: numberOfAttributes %d exceeds limit %d",
 			 numberOfAttributes, MaxTupleAttributeNumber);
 
+	AssertTupleDescHasOidIsValid(tupleDescriptor);
+
 	for (i = 0; i < numberOfAttributes; i++)
 	{
 		if (nulls[i] != ' ')
@@ -595,6 +597,9 @@ heap_formtuple(TupleDesc tupleDescriptor,
 	if (hasnull)
 		len += BITMAPLEN(numberOfAttributes);
 
+	if (tupleDescriptor->tdhasoid == WITHOID)
+		len += sizeof(Oid);
+
 	hoff = len = MAXALIGN(len); /* align user data safely */
 
 	len += ComputeDataSize(tupleDescriptor, value, nulls);
@@ -698,14 +703,18 @@ heap_modifytuple(HeapTuple tuple,
 	 * t_infomask
 	 */
 	infomask = newTuple->t_data->t_infomask;
-	memmove((char *) &newTuple->t_data->t_oid,	/* XXX */
-			(char *) &tuple->t_data->t_oid,
-			((char *) &tuple->t_data->t_hoff -
-			 (char *) &tuple->t_data->t_oid));	/* XXX */
+	/*
+	 * copy t_xmin, t_cid, t_xmax, t_ctid, t_natts, t_infomask
+	 */
+	memmove((char *) newTuple->t_data,	/* XXX */
+			(char *) tuple->t_data,
+			offsetof(HeapTupleHeaderData, t_hoff));	/* XXX */
 	newTuple->t_data->t_infomask = infomask;
 	newTuple->t_data->t_natts = numberOfAttributes;
 	newTuple->t_self = tuple->t_self;
 	newTuple->t_tableOid = tuple->t_tableOid;
+	if (relation->rd_rel->relhasoids)
+		HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
 
 	return newTuple;
 }
@@ -738,6 +747,7 @@ heap_freetuple(HeapTuple htup)
  */
 HeapTuple
 heap_addheader(int natts,		/* max domain index */
+			   bool withoid,	/* reserve space for oid */
 			   Size structlen,	/* its length */
 			   void *structure) /* pointer to the struct */
 {
@@ -749,7 +759,10 @@ heap_addheader(int natts,		/* max domain index */
 	AssertArg(natts > 0);
 
 	/* header needs no null bitmap */
-	hoff = MAXALIGN(offsetof(HeapTupleHeaderData, t_bits));
+	hoff = offsetof(HeapTupleHeaderData, t_bits);
+	if (withoid)
+		hoff += sizeof(Oid);
+	hoff = MAXALIGN(hoff);
 	len = hoff + structlen;
 
 	tuple = (HeapTuple) palloc(HEAPTUPLESIZE + len);
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index af73941369e..24f33fac4be 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.80 2002/06/20 20:29:24 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.81 2002/07/20 05:16:56 momjian Exp $
  *
  * NOTES
  *	  some of the executor utility code such as "ExecTypeFromTL" should be
@@ -36,7 +36,7 @@
  * ----------------------------------------------------------------
  */
 TupleDesc
-CreateTemplateTupleDesc(int natts)
+CreateTemplateTupleDesc(int natts, hasoid_t withoid)
 {
 	uint32		size;
 	TupleDesc	desc;
@@ -58,6 +58,7 @@ CreateTemplateTupleDesc(int natts)
 	MemSet(desc->attrs, 0, size);
 
 	desc->natts = natts;
+	desc->tdhasoid = withoid;
 
 	return desc;
 }
@@ -82,6 +83,7 @@ CreateTupleDesc(int natts, Form_pg_attribute *attrs)
 	desc->attrs = attrs;
 	desc->natts = natts;
 	desc->constr = NULL;
+	desc->tdhasoid = UNDEFOID;
 
 	return desc;
 }
@@ -116,6 +118,7 @@ CreateTupleDescCopy(TupleDesc tupdesc)
 		desc->attrs[i]->atthasdef = false;
 	}
 	desc->constr = NULL;
+	desc->tdhasoid = tupdesc->tdhasoid;
 
 	return desc;
 }
@@ -182,6 +185,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
 	else
 		desc->constr = NULL;
 
+	desc->tdhasoid = tupdesc->tdhasoid;
 	return desc;
 }
 
@@ -235,6 +239,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
 
 	if (tupdesc1->natts != tupdesc2->natts)
 		return false;
+	if (tupdesc1->tdhasoid != tupdesc2->tdhasoid)
+		return false;
 	for (i = 0; i < tupdesc1->natts; i++)
 	{
 		Form_pg_attribute attr1 = tupdesc1->attrs[i];
@@ -392,7 +398,7 @@ TupleDescInitEntry(TupleDesc desc,
 	 */
 	typeForm = (Form_pg_type) GETSTRUCT(tuple);
 
-	att->atttypid = tuple->t_data->t_oid;
+	att->atttypid = HeapTupleGetOid(tuple);
 
 	/*
 	 * There are a couple of cases where we must override the information
@@ -479,7 +485,7 @@ BuildDescForRelation(List *schema)
 	 * allocate a new tuple descriptor
 	 */
 	natts = length(schema);
-	desc = CreateTemplateTupleDesc(natts);
+	desc = CreateTemplateTupleDesc(natts, UNDEFOID);
 	constr->has_not_null = false;
 
 	attnum = 0;
@@ -646,7 +652,7 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases)
 		/* OK, get the column alias */
 		attname = strVal(lfirst(colaliases));
 
-		tupdesc = CreateTemplateTupleDesc(1);
+		tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID);
 		TupleDescInitEntry(tupdesc,
 						   (AttrNumber) 1,
 						   attname,
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 9a6a0b07400..35249188135 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.141 2002/07/02 05:48:44 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.142 2002/07/20 05:16:56 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1116,10 +1116,11 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid)
 		 * to support a persistent object store (objects need to contain
 		 * pointers to one another).
 		 */
-		if (!OidIsValid(tup->t_data->t_oid))
-			tup->t_data->t_oid = newoid();
+		AssertTupleDescHasOid(relation->rd_att);
+		if (!OidIsValid(HeapTupleGetOid(tup)))
+			HeapTupleSetOid(tup, newoid());
 		else
-			CheckMaxObjectId(tup->t_data->t_oid);
+			CheckMaxObjectId(HeapTupleGetOid(tup));
 	}
 
 	HeapTupleHeaderSetXmin(tup->t_data, GetCurrentTransactionId());
@@ -1166,7 +1167,13 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid)
 		rdata[0].len = SizeOfHeapInsert;
 		rdata[0].next = &(rdata[1]);
 
-		xlhdr.t_oid = tup->t_data->t_oid;
+		if (relation->rd_rel->relhasoids)
+		{
+			AssertTupleDescHasOid(relation->rd_att);
+			xlhdr.t_oid = HeapTupleGetOid(tup);
+		}
+		else
+			xlhdr.t_oid = InvalidOid;
 		xlhdr.t_natts = tup->t_data->t_natts;
 		xlhdr.t_hoff = tup->t_data->t_hoff;
 		xlhdr.mask = tup->t_data->t_infomask;
@@ -1176,6 +1183,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid)
 		rdata[1].next = &(rdata[2]);
 
 		rdata[2].buffer = buffer;
+		/* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */
 		rdata[2].data = (char *) tup->t_data + offsetof(HeapTupleHeaderData, t_bits);
 		rdata[2].len = tup->t_len - offsetof(HeapTupleHeaderData, t_bits);
 		rdata[2].next = NULL;
@@ -1206,7 +1214,11 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid)
 	 */
 	CacheInvalidateHeapTuple(relation, tup);
 
-	return tup->t_data->t_oid;
+	if (!relation->rd_rel->relhasoids)
+		return InvalidOid;
+		
+	AssertTupleDescHasOid(relation->rd_att);
+	return HeapTupleGetOid(tup);
 }
 
 /*
@@ -1499,7 +1511,11 @@ l2:
 	}
 
 	/* Fill in OID and transaction status data for newtup */
-	newtup->t_data->t_oid = oldtup.t_data->t_oid;
+	if (relation->rd_rel->relhasoids)
+	{
+		AssertTupleDescHasOid(relation->rd_att);
+		HeapTupleSetOid(newtup, HeapTupleGetOid(&oldtup));
+	}
 	newtup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
 	newtup->t_data->t_infomask |= (HEAP_XMAX_INVALID | HEAP_UPDATED);
 	HeapTupleHeaderSetXmin(newtup->t_data, GetCurrentTransactionId());
@@ -1972,24 +1988,28 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
 	rdata[1].len = 0;
 	rdata[1].next = &(rdata[2]);
 
-	xlhdr.hdr.t_oid = newtup->t_data->t_oid;
+	if (reln->rd_rel->relhasoids)
+	{
+		AssertTupleDescHasOid(reln->rd_att);
+		xlhdr.hdr.t_oid = HeapTupleGetOid(newtup);
+	}
+	else
+		xlhdr.hdr.t_oid = InvalidOid;
 	xlhdr.hdr.t_natts = newtup->t_data->t_natts;
 	xlhdr.hdr.t_hoff = newtup->t_data->t_hoff;
 	xlhdr.hdr.mask = newtup->t_data->t_infomask;
 	if (move)					/* remember xmin & xmax */
 	{
-		TransactionId xmax;
-		TransactionId xmin;
+		TransactionId xid[2];   /* xmax, xmin */
 
-		if (newtup->t_data->t_infomask & HEAP_XMAX_INVALID ||
-			newtup->t_data->t_infomask & HEAP_MARKED_FOR_UPDATE)
-			xmax = InvalidTransactionId;
+		if (newtup->t_data->t_infomask & (HEAP_XMAX_INVALID |
+		                                  HEAP_MARKED_FOR_UPDATE))
+			xid[0] = InvalidTransactionId;
 		else
-			xmax = HeapTupleHeaderGetXmax(newtup->t_data);
-		xmin = HeapTupleHeaderGetXmin(newtup->t_data);
-		memcpy((char *) &xlhdr + hsize, &xmax, sizeof(TransactionId));
-		memcpy((char *) &xlhdr + hsize + sizeof(TransactionId),
-			   &xmin, sizeof(TransactionId));
+			xid[0] = HeapTupleHeaderGetXmax(newtup->t_data);
+		xid[1] = HeapTupleHeaderGetXmin(newtup->t_data);
+		memcpy((char *) &xlhdr + hsize,
+		       (char *) xid,            2 * sizeof(TransactionId));
 		hsize += 2 * sizeof(TransactionId);
 	}
 	rdata[2].buffer = newbuf;
@@ -1998,6 +2018,7 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
 	rdata[2].next = &(rdata[3]);
 
 	rdata[3].buffer = newbuf;
+	/* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */
 	rdata[3].data = (char *) newtup->t_data + offsetof(HeapTupleHeaderData, t_bits);
 	rdata[3].len = newtup->t_len - offsetof(HeapTupleHeaderData, t_bits);
 	rdata[3].next = NULL;
@@ -2193,12 +2214,13 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
 		memcpy((char *) &xlhdr,
 			   (char *) xlrec + SizeOfHeapInsert,
 			   SizeOfHeapHeader);
+		htup = &tbuf.hdr;
+		MemSet((char *) htup, 0, sizeof(HeapTupleHeaderData));
+		/* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */
 		memcpy((char *) &tbuf + offsetof(HeapTupleHeaderData, t_bits),
 			   (char *) xlrec + SizeOfHeapInsert + SizeOfHeapHeader,
 			   newlen);
 		newlen += offsetof(HeapTupleHeaderData, t_bits);
-		htup = &tbuf.hdr;
-		htup->t_oid = xlhdr.t_oid;
 		htup->t_natts = xlhdr.t_natts;
 		htup->t_hoff = xlhdr.t_hoff;
 		htup->t_infomask = HEAP_XMAX_INVALID | xlhdr.mask;
@@ -2206,6 +2228,11 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
 		HeapTupleHeaderSetCmin(htup, FirstCommandId);
 		HeapTupleHeaderSetXmaxInvalid(htup);
 		HeapTupleHeaderSetCmax(htup, FirstCommandId);
+		if (reln->rd_rel->relhasoids)
+		{
+			AssertTupleDescHasOid(reln->rd_att);
+			HeapTupleHeaderSetOid(htup, xlhdr.t_oid);
+		}
 
 		offnum = PageAddItem(page, (Item) htup, newlen, offnum,
 							 LP_USED | OverwritePageMode);
@@ -2362,28 +2389,33 @@ newsame:;
 		memcpy((char *) &xlhdr,
 			   (char *) xlrec + SizeOfHeapUpdate,
 			   SizeOfHeapHeader);
+		htup = &tbuf.hdr;
+		MemSet((char *) htup, 0, sizeof(HeapTupleHeaderData));
+		/* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */
 		memcpy((char *) &tbuf + offsetof(HeapTupleHeaderData, t_bits),
 			   (char *) xlrec + hsize,
 			   newlen);
 		newlen += offsetof(HeapTupleHeaderData, t_bits);
-		htup = &tbuf.hdr;
-		htup->t_oid = xlhdr.t_oid;
 		htup->t_natts = xlhdr.t_natts;
 		htup->t_hoff = xlhdr.t_hoff;
+		if (reln->rd_rel->relhasoids)
+		{
+			AssertTupleDescHasOid(reln->rd_att);
+			HeapTupleHeaderSetOid(htup, xlhdr.t_oid);
+		}
 		if (move)
 		{
-			TransactionId xmax;
-			TransactionId xmin;
+			TransactionId xid[2];   /* xmax, xmin */
 			
 			hsize = SizeOfHeapUpdate + SizeOfHeapHeader;
-			memcpy(&xmax, (char *) xlrec + hsize, sizeof(TransactionId));
-			memcpy(&xmin, (char *) xlrec + hsize + sizeof(TransactionId), sizeof(TransactionId));
+			memcpy((char *) xid,
+			       (char *) xlrec + hsize, 2 * sizeof(TransactionId));
 			htup->t_infomask = xlhdr.mask;
 			htup->t_infomask &= ~(HEAP_XMIN_COMMITTED |
 								  HEAP_XMIN_INVALID | HEAP_MOVED_OFF);
 			htup->t_infomask |= HEAP_MOVED_IN;
-			HeapTupleHeaderSetXmin(htup, xmin);
-			HeapTupleHeaderSetXmax(htup, xmax);
+			HeapTupleHeaderSetXmin(htup, xid[1]);
+			HeapTupleHeaderSetXmax(htup, xid[0]);
 			HeapTupleHeaderSetXvac(htup, record->xl_xid);
 		}
 		else
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 3c66aed1db1..2945cf3458c 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.32 2002/05/27 19:53:33 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.33 2002/07/20 05:16:56 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -726,6 +726,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
 		new_len = offsetof(HeapTupleHeaderData, t_bits);
 		if (has_nulls)
 			new_len += BITMAPLEN(numAttrs);
+		if (rel->rd_rel->relhasoids)
+			new_len += sizeof(Oid);
 		new_len = MAXALIGN(new_len);
 		Assert(new_len == olddata->t_hoff);
 		new_len += ComputeDataSize(tupleDesc, toast_values, toast_nulls);
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index 705a2b1fe80..f2d31356d9c 100644
--- a/src/backend/bootstrap/bootparse.y
+++ b/src/backend/bootstrap/bootparse.y
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.49 2002/07/12 18:43:13 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.50 2002/07/20 05:16:56 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -179,13 +179,13 @@ Boot_CreateStmt:
 						}
 
 						tupdesc = CreateTupleDesc(numattr, attrtypes);
+						tupdesc->tdhasoid = BoolToHasOid(! ($4));
 						boot_reldesc = heap_create(LexIDStr($5),
 												   PG_CATALOG_NAMESPACE,
 												   tupdesc,
 												   $3,
 												   true,
 												   true);
-						boot_reldesc->rd_rel->relhasoids = ! ($4);
 						elog(DEBUG3, "bootstrap relation created");
 					}
 					else
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index bd2f823f1a6..4300c0211da 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.132 2002/06/20 20:29:26 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.133 2002/07/20 05:16:56 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -495,7 +495,8 @@ boot_openrel(char *relname)
 		app = Typ;
 		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		{
-			(*app)->am_oid = tup->t_data->t_oid;
+			AssertTupleDescHasOid(rel->rd_att);
+			(*app)->am_oid = HeapTupleGetOid(tup);
 			memcpy((char *) &(*app)->am_typ,
 				   (char *) GETSTRUCT(tup),
 				   sizeof((*app)->am_typ));
@@ -675,11 +676,15 @@ InsertOneTuple(Oid objectid)
 	elog(DEBUG3, "inserting row oid %u, %d columns", objectid, numattr);
 
 	tupDesc = CreateTupleDesc(numattr, attrtypes);
+	tupDesc->tdhasoid = BoolToHasOid(RelationGetForm(boot_reldesc)->relhasoids);
 	tuple = heap_formtuple(tupDesc, values, Blanks);
-	pfree(tupDesc);				/* just free's tupDesc, not the attrtypes */
 
 	if (objectid != (Oid) 0)
-		tuple->t_data->t_oid = objectid;
+	{
+		AssertTupleDescHasOid(tupDesc);
+		HeapTupleSetOid(tuple, objectid);
+	}
+	pfree(tupDesc);				/* just free's tupDesc, not the attrtypes */
 	simple_heap_insert(boot_reldesc, tuple);
 	heap_freetuple(tuple);
 	elog(DEBUG3, "row inserted");
@@ -871,7 +876,8 @@ gettype(char *type)
 		app = Typ;
 		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		{
-			(*app)->am_oid = tup->t_data->t_oid;
+			AssertTupleDescHasOid(rel->rd_att);
+			(*app)->am_oid = HeapTupleGetOid(tup);
 			memmove((char *) &(*app++)->am_typ,
 					(char *) GETSTRUCT(tup),
 					sizeof((*app)->am_typ));
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 2a0495b8e6f..5827915d8a5 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.70 2002/07/18 04:50:10 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.71 2002/07/20 05:16:56 momjian Exp $
  *
  * NOTES
  *	  See acl.h.
@@ -592,7 +592,8 @@ ExecuteGrantStmt_Namespace(GrantStmt *stmt)
 			elog(ERROR, "namespace \"%s\" not found", nspname);
 		pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
 
-		if (!pg_namespace_ownercheck(tuple->t_data->t_oid, GetUserId()))
+		AssertTupleDescHasOid(relation->rd_att);
+		if (!pg_namespace_ownercheck(HeapTupleGetOid(tuple), GetUserId()))
 			aclcheck_error(ACLCHECK_NOT_OWNER, nspname);
 
 		/*
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 930abe00f85..86651c6053e 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.211 2002/07/19 22:21:17 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.212 2002/07/20 05:16:56 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -65,7 +65,7 @@
 static void AddNewRelationTuple(Relation pg_class_desc,
 					Relation new_rel_desc,
 					Oid new_rel_oid, Oid new_type_oid,
-					char relkind, bool relhasoids);
+					char relkind);
 static void AddNewRelationType(const char *typeName,
 							   Oid typeNamespace,
 							   Oid new_rel_oid,
@@ -445,6 +445,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
 		(*dpp)->attcacheoff = -1;
 
 		tup = heap_addheader(Natts_pg_attribute,
+		                     false,
 							 ATTRIBUTE_TUPLE_SIZE,
 							 (void *) *dpp);
 
@@ -481,6 +482,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
 				Form_pg_attribute attStruct;
 
 				tup = heap_addheader(Natts_pg_attribute,
+				                     false,
 									 ATTRIBUTE_TUPLE_SIZE,
 									 (void *) *dpp);
 
@@ -527,8 +529,7 @@ AddNewRelationTuple(Relation pg_class_desc,
 					Relation new_rel_desc,
 					Oid new_rel_oid,
 					Oid new_type_oid,
-					char relkind,
-					bool relhasoids)
+					char relkind)
 {
 	Form_pg_class new_rel_reltup;
 	HeapTuple	tup;
@@ -579,7 +580,6 @@ AddNewRelationTuple(Relation pg_class_desc,
 	new_rel_reltup->relowner = GetUserId();
 	new_rel_reltup->reltype = new_type_oid;
 	new_rel_reltup->relkind = relkind;
-	new_rel_reltup->relhasoids = relhasoids;
 
 	/* ----------------
 	 *	now form a tuple to add to pg_class
@@ -587,11 +587,13 @@ AddNewRelationTuple(Relation pg_class_desc,
 	 * ----------------
 	 */
 	tup = heap_addheader(Natts_pg_class_fixed,
+	                     true,
 						 CLASS_TUPLE_SIZE,
 						 (void *) new_rel_reltup);
 
 	/* force tuple to have the desired OID */
-	tup->t_data->t_oid = new_rel_oid;
+	AssertTupleDescHasOid(pg_class_desc->rd_att);
+	HeapTupleSetOid(tup, new_rel_oid);
 
 	/*
 	 * finally insert the new tuple and free it.
@@ -691,6 +693,8 @@ heap_create_with_catalog(const char *relname,
 	if (get_relname_relid(relname, relnamespace))
 		elog(ERROR, "Relation '%s' already exists", relname);
 
+	tupdesc->tdhasoid = BoolToHasOid(relhasoids);
+	
 	/*
 	 * Tell heap_create not to create a physical file; we'll do that below
 	 * after all our catalog updates are done.	(This isn't really
@@ -723,8 +727,7 @@ heap_create_with_catalog(const char *relname,
 						new_rel_desc,
 						new_rel_oid,
 						new_type_oid,
-						relkind,
-						relhasoids);
+						relkind);
 
 	/*
 	 * since defining a relation also defines a complex type, we add a new
@@ -920,13 +923,14 @@ RemoveAttrDefault(Oid relid, AttrNumber attnum,
 	scan = systable_beginscan(attrdef_rel, AttrDefaultIndex, true,
 							  SnapshotNow, 2, scankeys);
 
+	AssertTupleDescHasOid(attrdef_rel->rd_att);
 	/* There should be at most one matching tuple, but we loop anyway */
 	while (HeapTupleIsValid(tuple = systable_getnext(scan)))
 	{
 		ObjectAddress	object;
 
 		object.classId = RelationGetRelid(attrdef_rel);
-		object.objectId = tuple->t_data->t_oid;
+		object.objectId = HeapTupleGetOid(tuple);
 		object.objectSubId = 0;
 
 		performDeletion(&object, behavior);
@@ -1711,6 +1715,7 @@ RemoveRelConstraints(Relation rel, const char *constrName,
 	conscan = systable_beginscan(conrel, ConstraintRelidIndex, true,
 								 SnapshotNow, 1, key);
 
+	AssertTupleDescHasOid(conrel->rd_att);
 	/*
 	 * Scan over the result set, removing any matching entries.
 	 */
@@ -1723,7 +1728,7 @@ RemoveRelConstraints(Relation rel, const char *constrName,
 			ObjectAddress	conobj;
 
 			conobj.classId = RelationGetRelid(conrel);
-			conobj.objectId = contup->t_data->t_oid;
+			conobj.objectId = HeapTupleGetOid(contup);
 			conobj.objectSubId = 0;
 
 			performDeletion(&conobj, behavior);
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 92d4d361a5b..0937367957c 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.185 2002/07/18 16:47:23 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.186 2002/07/20 05:16:56 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -111,7 +111,7 @@ BuildFuncTupleDesc(Oid funcOid,
 	/*
 	 * Allocate and zero a tuple descriptor for a one-column tuple.
 	 */
-	funcTupDesc = CreateTemplateTupleDesc(1);
+	funcTupDesc = CreateTemplateTupleDesc(1, UNDEFOID);
 	funcTupDesc->attrs[0] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
 	MemSet(funcTupDesc->attrs[0], 0, ATTRIBUTE_TUPLE_SIZE);
 
@@ -199,7 +199,7 @@ ConstructTupleDescriptor(Relation heapRelation,
 	 * allocate the new tuple descriptor
 	 */
 
-	indexTupDesc = CreateTemplateTupleDesc(numatts);
+	indexTupDesc = CreateTemplateTupleDesc(numatts, WITHOUTOID);
 
 	/* ----------------
 	 *	  for each attribute we are indexing, obtain its attribute
@@ -320,6 +320,7 @@ UpdateRelationRelation(Relation indexRelation)
 
 	/* XXX Natts_pg_class_fixed is a hack - see pg_class.h */
 	tuple = heap_addheader(Natts_pg_class_fixed,
+	                       true,
 						   CLASS_TUPLE_SIZE,
 						   (void *) indexRelation->rd_rel);
 
@@ -327,7 +328,8 @@ UpdateRelationRelation(Relation indexRelation)
 	 * the new tuple must have the oid already chosen for the index.
 	 * sure would be embarrassing to do this sort of thing in polite company.
 	 */
-	tuple->t_data->t_oid = RelationGetRelid(indexRelation);
+	AssertTupleDescHasOid(pg_class->rd_att);
+	HeapTupleSetOid(tuple, RelationGetRelid(indexRelation));
 	simple_heap_insert(pg_class, tuple);
 
 	/*
@@ -406,6 +408,7 @@ AppendAttributeTuples(Relation indexRelation, int numatts)
 		Assert(indexTupDesc->attrs[i]->attcacheoff == -1);
 
 		new_tuple = heap_addheader(Natts_pg_attribute,
+		                           false,
 								   ATTRIBUTE_TUPLE_SIZE,
 								   (void *) indexTupDesc->attrs[i]);
 
@@ -495,6 +498,7 @@ UpdateIndexRelation(Oid indexoid,
 	 * form a tuple to insert into pg_index
 	 */
 	tuple = heap_addheader(Natts_pg_index,
+	                       false,
 						   itupLen,
 						   (void *) indexForm);
 
@@ -599,6 +603,7 @@ index_create(Oid heapRelationId,
 											indexInfo->ii_KeyAttrNumbers,
 												classObjectId);
 
+	indexTupDesc->tdhasoid = WITHOUTOID;
 	/*
 	 * create the index relation (but don't create storage yet)
 	 */
@@ -626,7 +631,7 @@ index_create(Oid heapRelationId,
 	indexRelation->rd_rel->relowner = GetUserId();
 	indexRelation->rd_rel->relam = accessMethodObjectId;
 	indexRelation->rd_rel->relkind = RELKIND_INDEX;
-	indexRelation->rd_rel->relhasoids = false;
+	indexRelation->rd_rel->relhasoids = false;  /* WITHOUTOID! */
 
 	/*
 	 * store index's pg_class entry
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index e78bde1d7bb..f02789fa807 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.25 2002/07/16 06:58:14 ishii Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.26 2002/07/20 05:16:56 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -571,7 +571,7 @@ FuncnameGetCandidates(List *names, int nargs)
 						continue; /* keep previous result */
 					/* replace previous result */
 					prevResult->pathpos = pathpos;
-					prevResult->oid = proctup->t_data->t_oid;
+					prevResult->oid = HeapTupleGetOid(proctup);
 					continue;	/* args are same, of course */
 				}
 			}
@@ -584,7 +584,7 @@ FuncnameGetCandidates(List *names, int nargs)
 			palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
 				   + nargs * sizeof(Oid));
 		newResult->pathpos = pathpos;
-		newResult->oid = proctup->t_data->t_oid;
+		newResult->oid = HeapTupleGetOid(proctup);
 		newResult->nargs = nargs;
 		memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
 
@@ -818,7 +818,7 @@ OpernameGetCandidates(List *names, char oprkind)
 						continue; /* keep previous result */
 					/* replace previous result */
 					prevResult->pathpos = pathpos;
-					prevResult->oid = opertup->t_data->t_oid;
+					prevResult->oid = HeapTupleGetOid(opertup);
 					continue;	/* args are same, of course */
 				}
 			}
@@ -830,7 +830,7 @@ OpernameGetCandidates(List *names, char oprkind)
 		newResult = (FuncCandidateList)
 			palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid));
 		newResult->pathpos = pathpos;
-		newResult->oid = opertup->t_data->t_oid;
+		newResult->oid = HeapTupleGetOid(opertup);
 		newResult->nargs = 2;
 		newResult->args[0] = operform->oprleft;
 		newResult->args[1] = operform->oprright;
@@ -994,7 +994,7 @@ OpclassGetCandidates(Oid amid)
 				/* replace previous result */
 				prevResult->opcname_tmp = NameStr(opcform->opcname);
 				prevResult->pathpos = pathpos;
-				prevResult->oid = opctup->t_data->t_oid;
+				prevResult->oid = HeapTupleGetOid(opctup);
 				prevResult->opcintype = opcform->opcintype;
 				prevResult->opcdefault = opcform->opcdefault;
 				prevResult->opckeytype = opcform->opckeytype;
@@ -1009,7 +1009,7 @@ OpclassGetCandidates(Oid amid)
 			palloc(sizeof(struct _OpclassCandidateList));
 		newResult->opcname_tmp = NameStr(opcform->opcname);
 		newResult->pathpos = pathpos;
-		newResult->oid = opctup->t_data->t_oid;
+		newResult->oid = HeapTupleGetOid(opctup);
 		newResult->opcintype = opcform->opcintype;
 		newResult->opcdefault = opcform->opcdefault;
 		newResult->opckeytype = opcform->opckeytype;
@@ -1572,8 +1572,9 @@ RemoveTempRelations(Oid tempNamespaceId)
 			case RELKIND_RELATION:
 			case RELKIND_SEQUENCE:
 			case RELKIND_VIEW:
+				AssertTupleDescHasOid(pgclass->rd_att);
 				object.classId = RelOid_pg_class;
-				object.objectId = tuple->t_data->t_oid;
+				object.objectId = HeapTupleGetOid(tuple);
 				object.objectSubId = 0;
 				performDeletion(&object, DROP_CASCADE);
 				break;
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index a2a591f1e62..768c0237f9b 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.72 2002/07/18 16:47:23 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.73 2002/07/20 05:16:56 momjian Exp $
  *
  * NOTES
  *	  these routines moved here from commands/define.c and somewhat cleaned up.
@@ -144,7 +144,7 @@ OperatorGet(const char *operatorName,
 	{
 		RegProcedure oprcode = ((Form_pg_operator) GETSTRUCT(tup))->oprcode;
 
-		operatorObjectId = tup->t_data->t_oid;
+		operatorObjectId = HeapTupleGetOid(tup);
 		*defined = RegProcedureIsValid(oprcode);
 		ReleaseSysCache(tup);
 	}
@@ -918,7 +918,7 @@ makeOperatorDependencies(HeapTuple tuple, Oid pg_operator_relid)
 					referenced;
 
 	myself.classId = pg_operator_relid;
-	myself.objectId = tuple->t_data->t_oid;
+	myself.objectId = HeapTupleGetOid(tuple);
 	myself.objectSubId = 0;
 
 	/* In case we are updating a shell, delete any existing entries */
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 29cfbb9b46e..d0f19968a1c 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.79 2002/07/18 23:11:27 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.80 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -239,6 +239,7 @@ ProcedureCreate(const char *procedureName,
 		/* start out with empty permissions */
 		nulls[Anum_pg_proc_proacl-1] = 'n';
 
+		AssertTupleDescHasOid(tupDesc);
 		tup = heap_formtuple(tupDesc, values, nulls);
 		simple_heap_insert(rel, tup);
 		is_update = false;
@@ -254,7 +255,8 @@ ProcedureCreate(const char *procedureName,
 		CatalogCloseIndices(Num_pg_proc_indices, idescs);
 	}
 
-	retval = tup->t_data->t_oid;
+	AssertTupleDescHasOid(tupDesc);
+	retval = HeapTupleGetOid(tup);
 
 	/*
 	 * Create dependencies for the new function.  If we are updating an
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 5cd5d291d7e..b911ecacc5d 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.74 2002/07/18 16:47:23 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.75 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -274,7 +274,8 @@ TypeCreate(const char *typeName,
 
 		simple_heap_update(pg_type_desc, &tup->t_self, tup);
 
-		typeObjectId = tup->t_data->t_oid;
+		AssertTupleDescHasOid(pg_type_desc->rd_att);
+		typeObjectId = HeapTupleGetOid(tup);
 	}
 	else
 	{
@@ -285,7 +286,8 @@ TypeCreate(const char *typeName,
 							 nulls);
 
 		/* preassign tuple Oid, if one was given */
-		tup->t_data->t_oid = assignedTypeOid;
+		AssertTupleDescHasOid(tupDesc);
+		HeapTupleSetOid(tup, assignedTypeOid);
 
 		typeObjectId = simple_heap_insert(pg_type_desc, tup);
 	}
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index aede51e0c98..83b8af7e6bf 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -7,7 +7,7 @@
  * Copyright (c) 1996-2001, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.51 2002/07/14 23:38:13 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.52 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -435,7 +435,8 @@ CommentDatabase(List *qualname, char *comment)
 
 	if (!HeapTupleIsValid(dbtuple))
 		elog(ERROR, "database \"%s\" does not exist", database);
-	oid = dbtuple->t_data->t_oid;
+	AssertTupleDescHasOid(pg_database->rd_att);
+	oid = HeapTupleGetOid(dbtuple);
 
 	/* Allow if the user matches the database dba or is a superuser */
 
@@ -481,7 +482,8 @@ CommentNamespace(List *qualname, char *comment)
 		elog(ERROR, "CommentSchema: Schema \"%s\" could not be found",
 			 namespace);
 
-	oid = tp->t_data->t_oid;
+	/* no TupleDesc here to Assert(...->tdhasoid); */
+	oid = HeapTupleGetOid(tp);
 
 	/* Check object security */
 	if (!pg_namespace_ownercheck(oid, GetUserId()))
@@ -552,7 +554,8 @@ CommentRule(List *qualname, char *comment)
 		if (HeapTupleIsValid(tuple))
 		{
 			reloid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
-			ruleoid = tuple->t_data->t_oid;
+			AssertTupleDescHasOid(RewriteRelation->rd_att);
+			ruleoid = HeapTupleGetOid(tuple);
 		}
 		else
 		{
@@ -592,7 +595,8 @@ CommentRule(List *qualname, char *comment)
 		if (!HeapTupleIsValid(tuple))
 			elog(ERROR, "rule \"%s\" does not exist", rulename);
 		Assert(reloid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class);
-		ruleoid = tuple->t_data->t_oid;
+		AssertTupleDescHasOid(relation->rd_att);
+		ruleoid = HeapTupleGetOid(tuple);
 		ReleaseSysCache(tuple);
 	}
 
@@ -805,7 +809,8 @@ CommentTrigger(List *qualname, char *comment)
 		elog(ERROR, "trigger \"%s\" for relation \"%s\" does not exist",
 			 trigname, RelationGetRelationName(relation));
 
-	oid = triggertuple->t_data->t_oid;
+	AssertTupleDescHasOid(pg_trigger->rd_att);
+	oid = HeapTupleGetOid(triggertuple);
 
 	systable_endscan(scan);
 
@@ -880,7 +885,7 @@ CommentConstraint(List *qualname, char *comment)
 			if (OidIsValid(conOid))
 				elog(ERROR, "Relation \"%s\" has multiple constraints named \"%s\"",
 					 RelationGetRelationName(relation), conName);
-			conOid = tuple->t_data->t_oid;
+			conOid = HeapTupleGetOid(tuple);
 		}
 	}
 
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 438126a3e18..272e45d384e 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.159 2002/07/18 04:43:50 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.160 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -614,9 +614,13 @@ CopyTo(Relation rel, List *attlist, bool binary, bool oids,
 			/* Send OID if wanted --- note fld_count doesn't include it */
 			if (oids)
 			{
+				Oid oid;
+				
+				AssertTupleDescHasOid(tupDesc);
+				oid = HeapTupleGetOid(tuple);
 				fld_size = sizeof(Oid);
 				CopySendData(&fld_size, sizeof(int16), fp);
-				CopySendData(&tuple->t_data->t_oid, sizeof(Oid), fp);
+				CopySendData(&oid, sizeof(Oid), fp);
 			}
 		}
 		else
@@ -624,8 +628,9 @@ CopyTo(Relation rel, List *attlist, bool binary, bool oids,
 			/* Text format has no per-tuple header, but send OID if wanted */
 			if (oids)
 			{
+				AssertTupleDescHasOid(tupDesc);
 				string = DatumGetCString(DirectFunctionCall1(oidout,
-								ObjectIdGetDatum(tuple->t_data->t_oid)));
+								ObjectIdGetDatum(HeapTupleGetOid(tuple))));
 				CopySendString(string, fp);
 				pfree(string);
 				need_delim = true;
@@ -1069,7 +1074,7 @@ CopyFrom(Relation rel, List *attlist, bool binary, bool oids,
 		tuple = heap_formtuple(tupDesc, values, nulls);
   	
 		if (oids && file_has_oids)
-			tuple->t_data->t_oid = loaded_oid;
+			HeapTupleSetOid(tuple, loaded_oid);
 
 		skip_tuple = false;
 
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index c6bbb371860..2c401a6dbdc 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.96 2002/07/12 18:43:15 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.97 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -341,7 +341,8 @@ createdb(const CreatedbStmt *stmt)
 
 	tuple = heap_formtuple(pg_database_dsc, new_record, new_record_nulls);
 
-	tuple->t_data->t_oid = dboid;		/* override heap_insert's OID
+	AssertTupleDescHasOid(pg_database_dsc);
+	HeapTupleSetOid(tuple, dboid);		/* override heap_insert's OID
 										 * selection */
 
 	simple_heap_insert(pg_database_rel, tuple);
@@ -616,7 +617,10 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
 
 		/* oid of the database */
 		if (dbIdP)
-			*dbIdP = tuple->t_data->t_oid;
+		{
+			AssertTupleDescHasOid(relation->rd_att);
+			*dbIdP = HeapTupleGetOid(tuple);
+		}
 		/* sysid of the owner */
 		if (ownerIdP)
 			*ownerIdP = dbform->datdba;
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index b14ae4274f6..2c90df205af 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -5,7 +5,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.80 2002/06/20 20:29:27 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.81 2002/07/20 05:16:57 momjian Exp $
  *
  */
 
@@ -855,7 +855,7 @@ begin_text_output(CommandDest dest, char *title)
 	tstate = (TextOutputState *) palloc(sizeof(TextOutputState));
 
 	/* need a tuple descriptor representing a single TEXT column */
-	tupdesc = CreateTemplateTupleDesc(1);
+	tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, title,
 					   TEXTOID, -1, 0, false);
 
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 2ed9581b665..e4e89a8d755 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.9 2002/07/18 23:11:27 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.10 2002/07/20 05:16:57 momjian Exp $
  *
  * DESCRIPTION
  *	  These routines take the parse tree and pick out the
@@ -425,7 +425,7 @@ CreateFunction(CreateFunctionStmt *stmt)
 	if (!HeapTupleIsValid(languageTuple))
 		elog(ERROR, "language \"%s\" does not exist", languageName);
 
-	languageOid = languageTuple->t_data->t_oid;
+	languageOid = HeapTupleGetOid(languageTuple);
 	languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
 
 	if (languageStruct->lanpltrusted)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 5cf03bd11aa..f36bad8ada1 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.77 2002/07/12 18:43:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.78 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -141,7 +141,7 @@ DefineIndex(RangeVar *heapRelation,
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "DefineIndex: access method \"%s\" not found",
 			 accessMethodName);
-	accessMethodId = tuple->t_data->t_oid;
+	accessMethodId = HeapTupleGetOid(tuple);
 	accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
 
 	if (unique && !accessMethodForm->amcanunique)
@@ -496,7 +496,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
 	 * Verify that the index operator class accepts this
 	 * datatype.  Note we will accept binary compatibility.
 	 */
-	opClassId = tuple->t_data->t_oid;
+	opClassId = HeapTupleGetOid(tuple);
 	opInputType = ((Form_pg_opclass) GETSTRUCT(tuple))->opcintype;
 
 	if (!IsBinaryCompatible(attrType, opInputType))
@@ -761,7 +761,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
 				relids = repalloc(relids, sizeof(Oid) * relalc);
 			}
 			MemoryContextSwitchTo(old);
-			relids[relcnt] = tuple->t_data->t_oid;
+			relids[relcnt] = HeapTupleGetOid(tuple);
 			relcnt++;
 		}
 	}
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 98b61324262..5dd70e9e55f 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.36 2002/07/16 22:12:19 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.37 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -134,7 +134,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 	 * Create dependencies for language
 	 */
 	myself.classId = RelationGetRelid(rel);
-	myself.objectId = tup->t_data->t_oid;
+	myself.objectId = HeapTupleGetOid(tup);
 	myself.objectSubId = 0;
 
 	/* dependency on the PL handler function */
@@ -191,7 +191,7 @@ DropProceduralLanguage(DropPLangStmt *stmt)
 			 languageName);
 
 	object.classId = get_system_catalog_relid(LanguageRelationName);
-	object.objectId = langTup->t_data->t_oid;
+	object.objectId = HeapTupleGetOid(langTup);
 	object.objectSubId = 0;
 
 	ReleaseSysCache(langTup);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 391adb04225..6b943723bb8 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.23 2002/07/16 22:12:19 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.24 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -149,6 +149,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
 	 * have to copy inherited constraints here.)
 	 */
 	descriptor = BuildDescForRelation(schema);
+	descriptor->tdhasoid = BoolToHasOid(stmt->hasoids || parentHasOids);
 
 	if (old_constraints != NIL)
 	{
@@ -1658,6 +1659,7 @@ AlterTableAddColumn(Oid myrelid,
 	tform = (Form_pg_type) GETSTRUCT(typeTuple);
 
 	attributeTuple = heap_addheader(Natts_pg_attribute,
+	                                false,
 									ATTRIBUTE_TUPLE_SIZE,
 									(void *) &attributeD);
 
@@ -1665,7 +1667,7 @@ AlterTableAddColumn(Oid myrelid,
 
 	attribute->attrelid = myrelid;
 	namestrcpy(&(attribute->attname), colDef->colname);
-	attribute->atttypid = typeTuple->t_data->t_oid;
+	attribute->atttypid = HeapTupleGetOid(typeTuple);
 	attribute->attstattarget = DEFAULT_ATTSTATTARGET;
 	attribute->attlen = tform->typlen;
 	attribute->attcacheoff = -1;
@@ -1682,6 +1684,7 @@ AlterTableAddColumn(Oid myrelid,
 
 	ReleaseSysCache(typeTuple);
 
+	AssertTupleDescHasNoOid(attrdesc->rd_att);
 	simple_heap_insert(attrdesc, attributeTuple);
 
 	/* Update indexes on pg_attribute */
@@ -1702,6 +1705,7 @@ AlterTableAddColumn(Oid myrelid,
 	newreltup = heap_copytuple(reltup);
 
 	((Form_pg_class) GETSTRUCT(newreltup))->relnatts = maxatts;
+	AssertTupleDescHasOid(pgclass->rd_att);
 	simple_heap_update(pgclass, &newreltup->t_self, newreltup);
 
 	/* keep catalog indices current */
@@ -3299,7 +3303,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
 	sprintf(toast_idxname, "pg_toast_%u_index", relOid);
 
 	/* this is pretty painful...  need a tuple descriptor */
-	tupdesc = CreateTemplateTupleDesc(3);
+	tupdesc = CreateTemplateTupleDesc(3, WITHOUTOID);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1,
 					   "chunk_id",
 					   OIDOID,
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index b27dd0f4380..4c2ee626fe0 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
- *	  $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.121 2002/07/12 18:43:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.122 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -400,8 +400,9 @@ DropTrigger(Oid relid, const char *trigname, DropBehavior behavior)
 	if (!pg_class_ownercheck(relid, GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, get_rel_name(relid));
 
+	AssertTupleDescHasOid(tgrel->rd_att);
 	object.classId = RelationGetRelid(tgrel);
-	object.objectId = tup->t_data->t_oid;
+	object.objectId = HeapTupleGetOid(tup);
 	object.objectSubId = 0;
 
 	systable_endscan(tgscan);
@@ -671,7 +672,8 @@ RelationBuildTriggers(Relation relation)
 				 RelationGetRelationName(relation));
 		build = &(triggers[found]);
 
-		build->tgoid = htup->t_data->t_oid;
+		AssertTupleDescHasOid(tgrel->rd_att);
+		build->tgoid = HeapTupleGetOid(htup);
 		build->tgname = MemoryContextStrdup(CacheMemoryContext,
 							 DatumGetCString(DirectFunctionCall1(nameout,
 									NameGetDatum(&pg_trigger->tgname))));
@@ -1932,7 +1934,8 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 				elog(ERROR, "Constraint '%s' is not deferrable",
 					 cname);
 
-			constr_oid = htup->t_data->t_oid;
+			AssertTupleDescHasOid(tgrel->rd_att);
+			constr_oid = HeapTupleGetOid(htup);
 			loid = lappendi(loid, constr_oid);
 			found = true;
 		}
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index c94b67883be..d387e17d5bb 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.6 2002/07/16 22:12:19 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.7 2002/07/20 05:16:57 momjian Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -396,7 +396,7 @@ DefineDomain(CreateDomainStmt *stmt)
 	typeTup = typenameType(stmt->typename);
 
 	baseType = (Form_pg_type) GETSTRUCT(typeTup);
-	basetypeoid = typeTup->t_data->t_oid;
+	basetypeoid = HeapTupleGetOid(typeTup);
 
 	/*
 	 * What we really don't want is domains of domains.  This could cause all sorts
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 1809981486f..c893ea86a09 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.231 2002/07/20 04:57:13 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.232 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -392,7 +392,8 @@ getrels(const RangeVar *vacrel, const char *stmttype)
 		{
 			/* Make a relation list entry for this guy */
 			oldcontext = MemoryContextSwitchTo(vac_context);
-			vrl = lappendi(vrl, tuple->t_data->t_oid);
+			AssertTupleDescHasOid(pgclass->rd_att);
+			vrl = lappendi(vrl, HeapTupleGetOid(tuple));
 			MemoryContextSwitchTo(oldcontext);
 		}
 
@@ -1172,8 +1173,8 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
 			/*
 			 * Other checks...
 			 */
-			if (!OidIsValid(tuple.t_data->t_oid) &&
-				onerel->rd_rel->relhasoids)
+			if (onerel->rd_rel->relhasoids &&
+				!OidIsValid(HeapTupleGetOid(&tuple)))
 				elog(WARNING, "Rel %s: TID %u/%u: OID IS INVALID. TUPGONE %d.",
 					 relname, blkno, offnum, (int) tupgone);
 
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index 7e3b82fdd74..bbf9e39ae80 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -31,7 +31,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.16 2002/06/20 20:29:27 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.17 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -368,8 +368,8 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
 			/*
 			 * Other checks...
 			 */
-			if (!OidIsValid(tuple.t_data->t_oid) &&
-				onerel->rd_rel->relhasoids)
+			if (onerel->rd_rel->relhasoids &&
+				!OidIsValid(HeapTupleGetOid(&tuple)))
 				elog(WARNING, "Rel %s: TID %u/%u: OID IS INVALID. TUPGONE %d.",
 					 relname, blkno, offnum, (int) tupgone);
 
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c
index 94c375012e1..d808b85337a 100644
--- a/src/backend/executor/execJunk.c
+++ b/src/backend/executor/execJunk.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.30 2002/06/20 20:29:27 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.31 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -170,7 +170,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType,
 	 * Now calculate the tuple type for the cleaned tuple (we were already
 	 * given the type for the original targetlist).
 	 */
-	cleanTupType = ExecTypeFromTL(cleanTargetList);
+	cleanTupType = ExecTypeFromTL(cleanTargetList, tupType->tdhasoid);
 
 	len = ExecTargetListLength(targetList);
 	cleanLength = ExecTargetListLength(cleanTargetList);
@@ -383,8 +383,8 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
 	 * information for the new "clean" tuple.
 	 *
 	 * Note: we use memory on the stack to optimize things when we are
-	 * dealing with a small number of tuples. for large tuples we just use
-	 * palloc.
+	 * dealing with a small number of attributes. for large tuples we
+	 * just use palloc.
 	 */
 	if (cleanLength > 64)
 	{
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index df7f3b42ae0..ce6d6794d26 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -27,7 +27,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.170 2002/07/11 21:36:20 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.171 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -716,6 +716,10 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
 									   get_namespace_name(namespaceId));
 				}
 
+				/*
+				 * new "INTO" table is created WITH OIDS
+				 */
+				tupType->tdhasoid = WITHOID;
 				/*
 				 * have to copy tupType to get rid of constraints
 				 */
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 63e5bab6ee9..f74f8f1b41b 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.99 2002/07/18 17:14:19 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.100 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1770,7 +1770,10 @@ ExecTargetList(List *targetlist,
 	 * natts = 0 to deal with it.
 	 */
 	if (targettype == NULL)
+	{
 		targettype = &NullTupleDesc;
+		targettype->tdhasoid = WITHOUTOID;
+	}
 
 	/*
 	 * allocate an array of char's to hold the "null" information only if
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 4f234f62b94..5124bd023fb 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.54 2002/07/18 04:40:30 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.55 2002/07/20 05:16:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -540,6 +540,7 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
 
 	ExecSetSlotDescriptor(slot, tupType, false);
 
+	NullTupleDesc.tdhasoid = WITHOUTOID;
 	nullTuple = heap_formtuple(&NullTupleDesc, values, nulls);
 
 	return ExecStoreTuple(nullTuple, slot, InvalidBuffer, true);
@@ -557,7 +558,7 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
  * ----------------------------------------------------------------
  */
 TupleDesc
-ExecTypeFromTL(List *targetList)
+ExecTypeFromTL(List *targetList, hasoid_t withoid)
 {
 	List	   *tlitem;
 	TupleDesc	typeInfo;
@@ -576,7 +577,7 @@ ExecTypeFromTL(List *targetList)
 	/*
 	 * allocate a new typeInfo
 	 */
-	typeInfo = CreateTemplateTupleDesc(len);
+	typeInfo = CreateTemplateTupleDesc(len, withoid);
 
 	/*
 	 * scan list, generate type info for each entry
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 7799ed4d935..c2bd2de48ab 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.86 2002/06/26 21:58:56 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.87 2002/07/20 05:16:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -290,9 +290,23 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate)
 void
 ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
 {
+	ResultRelInfo *ri;
+	Relation	rel;
+	hasoid_t	withoid;
 	TupleDesc	tupDesc;
 
-	tupDesc = ExecTypeFromTL(node->targetlist);
+	ri = node->state->es_result_relation_info;
+	if (ri != NULL)
+		rel = ri->ri_RelationDesc;
+	else
+		rel = node->state->es_into_relation_descriptor;
+
+	if (rel != NULL)
+		withoid = BoolToHasOid(rel->rd_rel->relhasoids);
+	else
+		withoid = WITHOUTOID;
+		
+	tupDesc = ExecTypeFromTL(node->targetlist, withoid);
 	ExecAssignResultType(commonstate, tupDesc, true);
 }
 
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 3645a188334..d87f8e6fe88 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.2 2002/06/20 20:29:28 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.3 2002/07/20 05:16:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -234,7 +234,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
 		 */
 		char	   *attname = strVal(lfirst(rte->eref->colnames));
 
-		tupdesc = CreateTemplateTupleDesc(1);
+		tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID);
 		TupleDescInitEntry(tupdesc,
 						   (AttrNumber) 1,
 						   attname,
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 60b39768d53..8535d875328 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.71 2002/06/20 20:29:28 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.72 2002/07/20 05:16:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -435,11 +435,15 @@ SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum,
 	{
 		mtuple = heap_formtuple(rel->rd_att, v, n);
 		infomask = mtuple->t_data->t_infomask;
-		memmove(&(mtuple->t_data->t_oid), &(tuple->t_data->t_oid),
-				((char *) &(tuple->t_data->t_hoff) -
-				 (char *) &(tuple->t_data->t_oid)));
+		/*
+		 * copy t_xmin, t_cid, t_xmax, t_ctid, t_natts, t_infomask
+		 */
+		memmove((char *)mtuple->t_data, (char *)tuple->t_data,
+				offsetof(HeapTupleHeaderData, t_hoff));
 		mtuple->t_data->t_infomask = infomask;
 		mtuple->t_data->t_natts = numberOfAttributes;
+		if (rel->rd_rel->relhasoids)
+			HeapTupleSetOid(mtuple, HeapTupleGetOid(tuple));
 	}
 	else
 	{
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index f7dfb9e9298..9e8372139ef 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.105 2002/07/18 17:14:19 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.106 2002/07/20 05:16:58 momjian Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -1071,7 +1071,7 @@ CommuteClause(Expr *clause)
 
 	commuTup = (Form_pg_operator) GETSTRUCT(optup);
 
-	commu = makeOper(optup->t_data->t_oid,
+	commu = makeOper(HeapTupleGetOid(optup),
 					 commuTup->oprcode,
 					 commuTup->oprresult,
 					 ((Oper *) clause->oper)->opretset);
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index 663e83831b3..78128b4f698 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.57 2002/06/20 20:29:33 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.58 2002/07/20 05:16:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -150,7 +150,7 @@ any_ordering_op(Oid argtype)
 Oid
 oprid(Operator op)
 {
-	return op->t_data->t_oid;
+	return HeapTupleGetOid(op);
 }
 
 /* given operator tuple, return the underlying function's OID */
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 14510a69b1b..7eafe3e7c84 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.44 2002/07/06 20:16:36 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.45 2002/07/20 05:16:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -283,7 +283,7 @@ typeTypeId(Type tp)
 {
 	if (tp == NULL)
 		elog(ERROR, "typeTypeId() called with NULL type struct");
-	return tp->t_data->t_oid;
+	return HeapTupleGetOid(tp);
 }
 
 /* given type (as type struct), return the length of type */
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index b578305b4c5..58bd1ef69b9 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -16,7 +16,7 @@
  *
  *	Copyright (c) 2001, PostgreSQL Global Development Group
  *
- *	$Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.21 2002/05/20 23:51:43 tgl Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.22 2002/07/20 05:16:58 momjian Exp $
  * ----------
  */
 #include "postgres.h"
@@ -628,7 +628,8 @@ pgstat_vacuum_tabstat(void)
 			dbidlist = (Oid *) repalloc((char *) dbidlist,
 										sizeof(Oid) * dbidalloc);
 		}
-		dbidlist[dbidused++] = dbtup->t_data->t_oid;
+		AssertTupleDescHasOid(dbrel->rd_att);
+		dbidlist[dbidused++] = HeapTupleGetOid(dbtup);
 	}
 	heap_endscan(dbscan);
 	heap_close(dbrel, AccessShareLock);
diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c
index 4ce9f3f2b90..1fd5f36ce55 100644
--- a/src/backend/rewrite/rewriteRemove.c
+++ b/src/backend/rewrite/rewriteRemove.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.51 2002/07/12 18:43:17 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.52 2002/07/20 05:16:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -69,7 +69,7 @@ RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior)
 	 * Do the deletion
 	 */
 	object.classId = get_system_catalog_relid(RewriteRelationName);
-	object.objectId = tuple->t_data->t_oid;
+	object.objectId = HeapTupleGetOid(tuple);
 	object.objectSubId = 0;
 
 	ReleaseSysCache(tuple);
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 18569e5479b..7dfd26d2db1 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.70 2002/06/20 20:29:38 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.71 2002/07/20 05:16:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -110,7 +110,8 @@ regprocin(PG_FUNCTION_ARGS)
 
 		while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
 		{
-			result = (RegProcedure) tuple->t_data->t_oid;
+			AssertTupleDescHasOid(hdesc->rd_att);
+			result = (RegProcedure) HeapTupleGetOid(tuple);
 			if (++matches > 1)
 				break;
 		}
@@ -414,7 +415,8 @@ regoperin(PG_FUNCTION_ARGS)
 
 		while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
 		{
-			result = tuple->t_data->t_oid;
+			AssertTupleDescHasOid(hdesc->rd_att);
+			result = HeapTupleGetOid(tuple);
 			if (++matches > 1)
 				break;
 		}
@@ -731,7 +733,10 @@ regclassin(PG_FUNCTION_ARGS)
 									 SnapshotNow, 1, skey);
 
 		if (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
-			result = tuple->t_data->t_oid;
+		{
+			AssertTupleDescHasOid(hdesc->rd_att);
+			result = HeapTupleGetOid(tuple);
+		}
 		else
 			elog(ERROR, "No class with name %s", class_name_or_oid);
 
@@ -884,7 +889,10 @@ regtypein(PG_FUNCTION_ARGS)
 									 SnapshotNow, 1, skey);
 
 		if (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
-			result = tuple->t_data->t_oid;
+		{
+			AssertTupleDescHasOid(hdesc->rd_att);
+			result = HeapTupleGetOid(tuple);
+		}
 		else
 			elog(ERROR, "No type with name %s", typ_name_or_oid);
 
diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c
index d03fd88e4df..0a378c47288 100644
--- a/src/backend/utils/adt/sets.c
+++ b/src/backend/utils/adt/sets.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.47 2002/07/18 23:11:29 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.48 2002/07/20 05:16:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -119,7 +119,8 @@ SetDefine(char *querystr, Oid elemType)
 
 		simple_heap_update(procrel, &newtup->t_self, newtup);
 
-		setoid = newtup->t_data->t_oid;
+		AssertTupleDescHasOid(procrel->rd_att);
+		setoid = HeapTupleGetOid(newtup);
 
 		if (RelationGetForm(procrel)->relhasindex)
 		{
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index a4f05a7d117..21f1e01dabb 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.96 2002/06/20 20:29:39 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.97 2002/07/20 05:16:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -218,7 +218,7 @@ CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple)
 		case 4:
 			cur_skey[3].sk_argument =
 				(cache->cc_key[3] == ObjectIdAttributeNumber)
-				? ObjectIdGetDatum(tuple->t_data->t_oid)
+				? ObjectIdGetDatum(HeapTupleGetOid(tuple))
 				: fastgetattr(tuple,
 							  cache->cc_key[3],
 							  cache->cc_tupdesc,
@@ -228,7 +228,7 @@ CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple)
 		case 3:
 			cur_skey[2].sk_argument =
 				(cache->cc_key[2] == ObjectIdAttributeNumber)
-				? ObjectIdGetDatum(tuple->t_data->t_oid)
+				? ObjectIdGetDatum(HeapTupleGetOid(tuple))
 				: fastgetattr(tuple,
 							  cache->cc_key[2],
 							  cache->cc_tupdesc,
@@ -238,7 +238,7 @@ CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple)
 		case 2:
 			cur_skey[1].sk_argument =
 				(cache->cc_key[1] == ObjectIdAttributeNumber)
-				? ObjectIdGetDatum(tuple->t_data->t_oid)
+				? ObjectIdGetDatum(HeapTupleGetOid(tuple))
 				: fastgetattr(tuple,
 							  cache->cc_key[1],
 							  cache->cc_tupdesc,
@@ -248,7 +248,7 @@ CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple)
 		case 1:
 			cur_skey[0].sk_argument =
 				(cache->cc_key[0] == ObjectIdAttributeNumber)
-				? ObjectIdGetDatum(tuple->t_data->t_oid)
+				? ObjectIdGetDatum(HeapTupleGetOid(tuple))
 				: fastgetattr(tuple,
 							  cache->cc_key[0],
 							  cache->cc_tupdesc,
@@ -572,7 +572,7 @@ AtEOXact_CatCache(bool isCommit)
 			if (isCommit)
 				elog(WARNING, "Cache reference leak: cache %s (%d), tuple %u has count %d",
 					 ct->my_cache->cc_relname, ct->my_cache->id,
-					 ct->tuple.t_data->t_oid,
+					 HeapTupleGetOid(&ct->tuple),
 					 ct->refcount);
 			ct->refcount = 0;
 		}
@@ -717,7 +717,7 @@ CatalogCacheFlushRelation(Oid relId)
 					continue;
 
 				if (cache->cc_reloidattr == ObjectIdAttributeNumber)
-					tupRelid = ct->tuple.t_data->t_oid;
+					tupRelid = HeapTupleGetOid(&ct->tuple);
 				else
 				{
 					bool		isNull;
@@ -907,6 +907,7 @@ CatalogCacheInitializeCache(CatCache *cache)
 	 * copy the relcache's tuple descriptor to permanent cache storage
 	 */
 	tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
+	AssertTupleDescHasOidIsValid(tupdesc);
 
 	/*
 	 * get the relation's OID and relisshared flag, too
@@ -1685,7 +1686,11 @@ build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys)
 	}
 
 	ntp = heap_formtuple(tupDesc, values, nulls);
-	ntp->t_data->t_oid = tupOid;
+	if (tupOid != InvalidOid)
+	{
+		AssertTupleDescHasOid(tupDesc);
+		HeapTupleSetOid(ntp, tupOid);
+	}
 
 	pfree(values);
 	pfree(nulls);
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 02a6d8f8ddc..c2929262381 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -74,7 +74,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.52 2002/06/20 20:29:39 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.53 2002/07/20 05:16:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -525,7 +525,10 @@ PrepareForTupleInvalidation(Relation relation, HeapTuple tuple,
 	tupleRelId = RelationGetRelid(relation);
 
 	if (tupleRelId == RelOid_pg_class)
-		relationId = tuple->t_data->t_oid;
+	{
+		AssertTupleDescHasOid(relation->rd_att);
+		relationId = HeapTupleGetOid(tuple);
+	}
 	else if (tupleRelId == RelOid_pg_attribute)
 		relationId = ((Form_pg_attribute) GETSTRUCT(tuple))->attrelid;
 	else
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 532c68f7b3a..d7fd83775b1 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.167 2002/07/15 01:57:51 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.168 2002/07/20 05:16:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -440,7 +440,7 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp)
 	relation->rd_rel = relationForm;
 
 	/* and allocate attribute tuple form storage */
-	relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts);
+	relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts, BoolToHasOid(relationForm->relhasoids));
 
 	MemoryContextSwitchTo(oldcxt);
 
@@ -701,7 +701,8 @@ RelationBuildRuleLock(Relation relation)
 		rule = (RewriteRule *) MemoryContextAlloc(rulescxt,
 												  sizeof(RewriteRule));
 
-		rule->ruleId = rewrite_tuple->t_data->t_oid;
+		AssertTupleDescHasOid(rewrite_tupdesc);
+		rule->ruleId = HeapTupleGetOid(rewrite_tuple);
 
 		rule->event = rewrite_form->ev_type - '0';
 		rule->attrno = rewrite_form->ev_attr;
@@ -839,7 +840,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
 	/*
 	 * get information from the pg_class_tuple
 	 */
-	relid = pg_class_tuple->t_data->t_oid;
+	relid = HeapTupleGetOid(pg_class_tuple);
 	relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
 
 	/*
@@ -872,6 +873,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
 	 * initialize the tuple descriptor (relation->rd_att).
 	 */
 	RelationBuildTupleDesc(buildinfo, relation);
+	RelationGetDescr(relation)->tdhasoid = BoolToHasOid(RelationGetForm(relation)->relhasoids);
 
 	/*
 	 * Fetch rules and triggers that affect this relation
@@ -1395,7 +1397,7 @@ formrdesc(const char *relationName,
 	 * right because it will never be replaced.  The input values must be
 	 * correctly defined by macros in src/include/catalog/ headers.
 	 */
-	relation->rd_att = CreateTemplateTupleDesc(natts);
+	relation->rd_att = CreateTemplateTupleDesc(natts, BoolToHasOid(relation->rd_rel->relhasoids));
 
 	/*
 	 * initialize tuple desc info
@@ -2067,7 +2069,7 @@ RelationBuildLocalRelation(const char *relname,
 	rel->rd_rel->relnamespace = relnamespace;
 
 	rel->rd_rel->relkind = RELKIND_UNCATALOGED;
-	rel->rd_rel->relhasoids = true;
+	rel->rd_rel->relhasoids = (rel->rd_att->tdhasoid == WITHOID);
 	rel->rd_rel->relnatts = natts;
 	rel->rd_rel->reltype = InvalidOid;
 
@@ -2313,6 +2315,7 @@ RelationCacheInitializePhase2(void)
 			 */
 			Assert(relation->rd_rel != NULL);
 			memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
+			relation->rd_att->tdhasoid = BoolToHasOid(relp->relhasoids);
 
 			ReleaseSysCache(htup);
 		}
@@ -2774,7 +2777,7 @@ load_relcache_init_file(void)
 		rel->rd_rel = relform;
 
 		/* initialize attribute tuple forms */
-		rel->rd_att = CreateTemplateTupleDesc(relform->relnatts);
+		rel->rd_att = CreateTemplateTupleDesc(relform->relnatts, BoolToHasOid(relform->relhasoids));
 
 		/* next read all the attribute tuple form data entries */
 		for (i = 0; i < relform->relnatts; i++)
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 5f0be16b75a..9966a8d881f 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.82 2002/07/18 23:11:29 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.83 2002/07/20 05:16:58 momjian Exp $
  *
  * NOTES
  *	  These routines allow the parser/planner/executor to perform
@@ -597,7 +597,7 @@ GetSysCacheOid(int cacheId,
 	tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
 	if (!HeapTupleIsValid(tuple))
 		return InvalidOid;
-	result = tuple->t_data->t_oid;
+	result = HeapTupleGetOid(tuple);
 	ReleaseSysCache(tuple);
 	return result;
 }
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 04e33b9b198..433b9a5ed05 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.108 2002/06/20 20:29:40 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.109 2002/07/20 05:16:59 momjian Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -98,8 +98,9 @@ ReverifyMyDatabase(const char *name)
 	pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key);
 
 	tup = heap_getnext(pgdbscan, ForwardScanDirection);
+	AssertTupleDescHasOid(pgdbrel->rd_att);
 	if (!HeapTupleIsValid(tup) ||
-		tup->t_data->t_oid != MyDatabaseId)
+		HeapTupleGetOid(tup) != MyDatabaseId)
 	{
 		/* OOPS */
 		heap_close(pgdbrel, AccessShareLock);
diff --git a/src/backend/utils/misc/database.c b/src/backend/utils/misc/database.c
index 9b2cb49022f..fd80b23bb89 100644
--- a/src/backend/utils/misc/database.c
+++ b/src/backend/utils/misc/database.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/misc/Attic/database.c,v 1.51 2002/06/20 20:29:40 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/misc/Attic/database.c,v 1.52 2002/07/20 05:16:59 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -220,7 +220,7 @@ GetRawDatabaseInfo(const char *name, Oid *db_id, char *path)
 			if (strcmp(name, NameStr(tup_db->datname)) == 0)
 			{
 				/* Found it; extract the OID and the database path. */
-				*db_id = tup.t_data->t_oid;
+				*db_id = HeapTupleGetOid(&tup);
 				pathlen = VARSIZE(&(tup_db->datpath)) - VARHDRSZ;
 				if (pathlen < 0)
 					pathlen = 0;				/* pure paranoia */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index eafa3224572..b0e32214adf 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heapam.h,v 1.77 2002/06/20 20:29:43 momjian Exp $
+ * $Id: heapam.h,v 1.78 2002/07/20 05:16:59 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -200,6 +200,6 @@ extern HeapTuple heap_formtuple(TupleDesc tupleDescriptor,
 extern HeapTuple heap_modifytuple(HeapTuple tuple,
 		Relation relation, Datum *replValue, char *replNull, char *repl);
 extern void heap_freetuple(HeapTuple tuple);
-extern HeapTuple heap_addheader(int natts, Size structlen, void *structure);
+extern HeapTuple heap_addheader(int natts, bool withoid, Size structlen, void *structure);
 
 #endif   /* HEAPAM_H */
diff --git a/src/include/access/htup.h b/src/include/access/htup.h
index 87f1727f9e4..5da1c3608ed 100644
--- a/src/include/access/htup.h
+++ b/src/include/access/htup.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: htup.h,v 1.56 2002/07/08 01:52:23 momjian Exp $
+ * $Id: htup.h,v 1.57 2002/07/20 05:16:59 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -70,8 +70,6 @@
 */
 typedef struct HeapTupleHeaderData
 {
-	Oid			t_oid;			/* OID of this tuple -- 4 bytes */
-
 	TransactionId t_xmin;		/* Xmin -- 4 bytes each */
 	TransactionId t_cid;		/* Cmin, Cmax, Xvac */
 	TransactionId t_xmax;		/* Xmax, Cmax */
@@ -84,7 +82,7 @@ typedef struct HeapTupleHeaderData
 
 	uint8		t_hoff;			/* sizeof header incl. bitmap, padding */
 
-	/* ^ - 27 bytes - ^ */
+	/* ^ - 23 bytes - ^ */
 
 	bits8		t_bits[1];		/* bitmap of NULLs -- VARIABLE LENGTH */
 
@@ -123,10 +121,42 @@ typedef HeapTupleHeaderData *HeapTupleHeader;
 
 #define HEAP_XACT_MASK			0xFFF0	/* visibility-related bits */
 
+/* paranoid checking */
+
+#ifdef DEBUG_TUPLE_ACCESS
+
+#define HeapTupleHeaderExpectedLen(tup, withoid) \
+	MAXALIGN(offsetof(HeapTupleHeaderData, t_bits) + \
+	         (((tup)->t_infomask & HEAP_HASNULL) \
+	          ? BITMAPLEN((tup)->t_natts) : 0) + \
+		     ((withoid) ? sizeof(Oid) : 0) \
+	        ) 
+
+#define AssertHeapTupleHeaderHoffIsValid(tup, withoid) \
+	AssertMacro((tup)->t_hoff == HeapTupleHeaderExpectedLen(tup, withoid))
+
+#else
+
+#define AssertHeapTupleHeaderHoffIsValid(tup, withoid) ((void)true)
+
+#endif  /* DEBUG_TUPLE_ACCESS */
 
 
 /* HeapTupleHeader accessor macros */
 
+#define HeapTupleHeaderGetOid(tup) \
+( \
+	AssertHeapTupleHeaderHoffIsValid(tup, true), \
+	*((Oid *)((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) \
+)
+
+#define HeapTupleHeaderSetOid(tup, oid) \
+( \
+	AssertHeapTupleHeaderHoffIsValid(tup, true), \
+	*((Oid *)((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) = (oid) \
+)
+		
+
 #define HeapTupleHeaderGetXmin(tup) \
 ( \
 	(tup)->t_xmin \
@@ -406,4 +436,10 @@ typedef HeapTupleData *HeapTuple;
 #define HeapTupleHasExtended(tuple) \
 		((((HeapTuple)(tuple))->t_data->t_infomask & HEAP_HASEXTENDED) != 0)
 
+#define HeapTupleGetOid(tuple) \
+		HeapTupleHeaderGetOid(((HeapTuple)(tuple))->t_data)
+
+#define HeapTupleSetOid(tuple, oid) \
+		HeapTupleHeaderSetOid(((HeapTuple)(tuple))->t_data, (oid))
+
 #endif   /* HTUP_H */
diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h
index 0f277d1c9e8..c8c9839985e 100644
--- a/src/include/access/tupdesc.h
+++ b/src/include/access/tupdesc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tupdesc.h,v 1.36 2002/07/12 18:43:19 tgl Exp $
+ * $Id: tupdesc.h,v 1.37 2002/07/20 05:16:59 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -41,6 +41,11 @@ typedef struct tupleConstr
 	bool		has_not_null;
 } TupleConstr;
 
+typedef char hasoid_t;
+#define WITHOID 'C'
+#define WITHOUTOID 'S'
+#define UNDEFOID '?'
+#define BoolToHasOid(b) ((b) ? WITHOID : WITHOUTOID)
 /*
  * This structure contains all information (i.e. from Classes
  * pg_attribute, pg_attrdef, pg_constraint) for a tuple.
@@ -51,9 +56,27 @@ typedef struct tupleDesc
 	Form_pg_attribute *attrs;
 	/* attrs[N] is a pointer to the description of Attribute Number N+1.  */
 	TupleConstr *constr;
+	hasoid_t	tdhasoid;		/* Tuple has an oid attribute in its header */
 }	*TupleDesc;
 
-extern TupleDesc CreateTemplateTupleDesc(int natts);
+#ifdef DEBUG_TUPLE_ACCESS
+
+#define AssertTupleDescHasOidIsValid(td) \
+	Assert(((td)->tdhasoid == WITHOID) || ((td)->tdhasoid == WITHOUTOID))
+#define AssertTupleDescHasOid(td) \
+	Assert((td)->tdhasoid == WITHOID)
+#define AssertTupleDescHasNoOid(td) \
+	Assert((td)->tdhasoid == WITHOUTOID)
+
+#else
+
+#define AssertTupleDescHasOidIsValid(td)
+#define AssertTupleDescHasOid(td)
+#define AssertTupleDescHasNoOid(td)
+
+#endif
+
+extern TupleDesc CreateTemplateTupleDesc(int natts, hasoid_t withoid);
 
 extern TupleDesc CreateTupleDesc(int natts, Form_pg_attribute *attrs);
 
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index ee399f9b3a8..427c146a574 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: executor.h,v 1.69 2002/06/26 21:58:56 momjian Exp $
+ * $Id: executor.h,v 1.70 2002/07/20 05:16:59 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -118,7 +118,7 @@ extern void ExecInitScanTupleSlot(EState *estate,
 extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate);
 extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate,
 					  TupleDesc tupType);
-extern TupleDesc ExecTypeFromTL(List *targetList);
+extern TupleDesc ExecTypeFromTL(List *targetList, hasoid_t withoid);
 extern void SetChangedParamList(Plan *node, List *newchg);
 
 /*
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index b3a5b8d6e1b..7a616440cf4 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -8,7 +8,7 @@
  * or in pg_config.h afterwards.  Of course, if you edit pg_config.h, then your
  * changes will be overwritten the next time you run configure.
  *
- * $Id: pg_config.h.in,v 1.24 2002/05/05 00:03:29 tgl Exp $
+ * $Id: pg_config.h.in,v 1.25 2002/07/20 05:16:59 momjian Exp $
  */
 
 #ifndef PG_CONFIG_H
@@ -311,6 +311,12 @@
 /* #define ACLDEBUG */
 /* #define RTDEBUG */
 /* #define GISTDEBUG */
+/*
+ * DEBUG_TUPLE_ACCESS enables paranoid assertions during
+ * elimination of oids from the fixed sized part of HeapTupleHeader.
+ * This is expected to be undef'd after v7.3 release at the latest.
+ */
+#define DEBUG_TUPLE_ACCESS
 
 /*
  * defining unsafe floats will make float4 and float8 ops faster
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index 4c88d931535..6d26cc75ddb 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -29,7 +29,7 @@
  * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * IDENTIFICATION
- *	$Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.18 2002/06/15 19:54:24 momjian Exp $
+ *	$Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.19 2002/07/20 05:16:59 momjian Exp $
  *
  *********************************************************************
  */
@@ -2091,7 +2091,7 @@ PLy_spi_prepare(PyObject * self, PyObject * args)
 				Py_DECREF(optr);
 				optr = NULL;	/* this is important */
 
-				plan->types[i] = typeTup->t_data->t_oid;
+				plan->types[i] = HeapTupleGetOid(typeTup);
 				typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
 				if (typeStruct->typrelid == InvalidOid)
 					PLy_output_datum_func(&plan->args[i], typeStruct);
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 2888f4d9aaa..6f2080b1a43 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -31,7 +31,7 @@
  *	  ENHANCEMENTS, OR MODIFICATIONS.
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.58 2002/07/18 05:07:30 ishii Exp $
+ *	  $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.59 2002/07/20 05:16:59 momjian Exp $
  *
  **********************************************************************/
 
@@ -1743,7 +1743,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
 	{
 		/* XXX should extend this to allow qualified type names */
 		typeTup = typenameType(makeTypeName(args[i]));
-		qdesc->argtypes[i] = typeTup->t_data->t_oid;
+		qdesc->argtypes[i] = HeapTupleGetOid(typeTup);
 		perm_fmgr_info(((Form_pg_type) GETSTRUCT(typeTup))->typinput,
 					   &(qdesc->arginfuncs[i]));
 		qdesc->argtypelems[i] = ((Form_pg_type) GETSTRUCT(typeTup))->typelem;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 218a5bd14d9..fd9ae6c89a1 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -75,3 +75,6 @@ test: select_views alter_table portals_p2 rules foreign_key
 # ----------
 # "plpgsql" cannot run concurrently with "rules"
 test: limit plpgsql temp domain rangefuncs copy2
+
+test: without_oid
+
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 3e79a9c3073..566b3962299 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -1,4 +1,4 @@
-# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.12 2002/07/20 04:57:13 momjian Exp $
+# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.13 2002/07/20 05:16:59 momjian Exp $
 # This should probably be in an order similar to parallel_schedule.
 test: boolean
 test: char
@@ -85,3 +85,4 @@ test: copy2
 test: temp
 test: domain
 test: rangefuncs
+test: without_oid
-- 
GitLab