diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml
index bda539c3857d8447ff797b29957da525027601bb..d6b830604854b5f992c7839a5fe46310f4a2acf7 100644
--- a/doc/src/sgml/indexam.sgml
+++ b/doc/src/sgml/indexam.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.1 2005/02/13 03:04:15 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.2 2005/03/21 01:23:55 tgl Exp $
 -->
 
 <chapter id="indexam">
@@ -151,16 +151,16 @@ ambuild (Relation heapRelation,
 
   <para>
 <programlisting>
-InsertIndexResult
+bool
 aminsert (Relation indexRelation,
-          Datum *datums,
-          char *nulls,
+          Datum *values,
+          bool *isnull,
           ItemPointer heap_tid,
           Relation heapRelation,
           bool check_uniqueness);
 </programlisting>
-   Insert a new tuple into an existing index.  The <literal>datums</> and
-   <literal>nulls</> arrays give the key values to be indexed, and
+   Insert a new tuple into an existing index.  The <literal>values</> and
+   <literal>isnull</> arrays give the key values to be indexed, and
    <literal>heap_tid</> is the TID to be indexed.
    If the access method supports unique indexes (its
    <structname>pg_am</>.<structfield>amcanunique</> flag is true) then
@@ -168,8 +168,9 @@ aminsert (Relation indexRelation,
    must verify that there is no conflicting row; this is the only situation in
    which the access method normally needs the <literal>heapRelation</>
    parameter.  See <xref linkend="index-unique-checks"> for details.
-   The result is a struct that must be pfree'd by the caller.  (The result
-   struct is really quite useless and should be removed...)
+   The result is TRUE if an index entry was inserted, FALSE if not. (A FALSE
+   result does not denote an error condition, but is used for cases such
+   as an index AM refusing to index a NULL.)
   </para>
 
   <para>
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 88df2231795e6e1a730b1342e97341688c4eb050..8b9714184c269b843158b33ee691b00c8d2bba3d 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -16,7 +16,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.98 2005/03/16 21:38:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.99 2005/03/21 01:23:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -68,7 +68,7 @@ heap_compute_data_size(TupleDesc tupleDesc,
  * OLD API with char 'n'/' ' convention for indicating nulls
  * ----------------
  */
-Size
+static Size
 ComputeDataSize(TupleDesc tupleDesc,
 				Datum *values,
 				char *nulls)
@@ -193,7 +193,7 @@ heap_fill_tuple(TupleDesc tupleDesc,
  * OLD API with char 'n'/' ' convention for indicating nulls
  * ----------------
  */
-void
+static void
 DataFill(char *data,
 		 TupleDesc tupleDesc,
 		 Datum *values,
diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c
index bd3b6c23654adbc456bc87dc6a0d1e6cab81f0fc..e52f61a2ad40c5bb85590d1d2ba5d29e0ead9578 100644
--- a/src/backend/access/common/indextuple.c
+++ b/src/backend/access/common/indextuple.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/common/indextuple.c,v 1.72 2004/12/31 21:59:07 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/common/indextuple.c,v 1.73 2005/03/21 01:23:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,13 +28,13 @@
  */
 
 /* ----------------
- *		index_formtuple
+ *		index_form_tuple
  * ----------------
  */
 IndexTuple
-index_formtuple(TupleDesc tupleDescriptor,
-				Datum *value,
-				char *null)
+index_form_tuple(TupleDesc tupleDescriptor,
+				 Datum *values,
+				 bool *isnull)
 {
 	char	   *tp;				/* tuple pointer */
 	IndexTuple	tuple;			/* return tuple */
@@ -47,7 +47,7 @@ index_formtuple(TupleDesc tupleDescriptor,
 	int			numberOfAttributes = tupleDescriptor->natts;
 
 #ifdef TOAST_INDEX_HACK
-	Datum		untoasted_value[INDEX_MAX_KEYS];
+	Datum		untoasted_values[INDEX_MAX_KEYS];
 	bool		untoasted_free[INDEX_MAX_KEYS];
 #endif
 
@@ -62,22 +62,22 @@ index_formtuple(TupleDesc tupleDescriptor,
 	{
 		Form_pg_attribute att = tupleDescriptor->attrs[i];
 
-		untoasted_value[i] = value[i];
+		untoasted_values[i] = values[i];
 		untoasted_free[i] = false;
 
 		/* Do nothing if value is NULL or not of varlena type */
-		if (null[i] != ' ' || att->attlen != -1)
+		if (isnull[i] || att->attlen != -1)
 			continue;
 
 		/*
 		 * If value is stored EXTERNAL, must fetch it so we are not
 		 * depending on outside storage.  This should be improved someday.
 		 */
-		if (VARATT_IS_EXTERNAL(value[i]))
+		if (VARATT_IS_EXTERNAL(values[i]))
 		{
-			untoasted_value[i] = PointerGetDatum(
+			untoasted_values[i] = PointerGetDatum(
 												 heap_tuple_fetch_attr(
-							   (varattrib *) DatumGetPointer(value[i])));
+							   (varattrib *) DatumGetPointer(values[i])));
 			untoasted_free[i] = true;
 		}
 
@@ -85,18 +85,18 @@ index_formtuple(TupleDesc tupleDescriptor,
 		 * If value is above size target, and is of a compressible
 		 * datatype, try to compress it in-line.
 		 */
-		if (VARATT_SIZE(untoasted_value[i]) > TOAST_INDEX_TARGET &&
-			!VARATT_IS_EXTENDED(untoasted_value[i]) &&
+		if (VARATT_SIZE(untoasted_values[i]) > TOAST_INDEX_TARGET &&
+			!VARATT_IS_EXTENDED(untoasted_values[i]) &&
 			(att->attstorage == 'x' || att->attstorage == 'm'))
 		{
-			Datum		cvalue = toast_compress_datum(untoasted_value[i]);
+			Datum		cvalue = toast_compress_datum(untoasted_values[i]);
 
 			if (DatumGetPointer(cvalue) != NULL)
 			{
 				/* successful compression */
 				if (untoasted_free[i])
-					pfree(DatumGetPointer(untoasted_value[i]));
-				untoasted_value[i] = cvalue;
+					pfree(DatumGetPointer(untoasted_values[i]));
+				untoasted_values[i] = cvalue;
 				untoasted_free[i] = true;
 			}
 		}
@@ -105,7 +105,7 @@ index_formtuple(TupleDesc tupleDescriptor,
 
 	for (i = 0; i < numberOfAttributes; i++)
 	{
-		if (null[i] != ' ')
+		if (isnull[i])
 		{
 			hasnull = true;
 			break;
@@ -117,41 +117,42 @@ index_formtuple(TupleDesc tupleDescriptor,
 
 	hoff = IndexInfoFindDataOffset(infomask);
 #ifdef TOAST_INDEX_HACK
-	size = hoff + ComputeDataSize(tupleDescriptor, untoasted_value, null);
+	size = hoff + heap_compute_data_size(tupleDescriptor,
+										 untoasted_values, isnull);
 #else
-	size = hoff + ComputeDataSize(tupleDescriptor, value, null);
+	size = hoff + heap_compute_data_size(tupleDescriptor,
+										 values, isnull);
 #endif
 	size = MAXALIGN(size);		/* be conservative */
 
 	tp = (char *) palloc0(size);
 	tuple = (IndexTuple) tp;
 
-	DataFill((char *) tp + hoff,
-			 tupleDescriptor,
+	heap_fill_tuple(tupleDescriptor,
 #ifdef TOAST_INDEX_HACK
-			 untoasted_value,
+					untoasted_values,
 #else
-			 value,
+					values,
 #endif
-			 null,
-			 &tupmask,
-			 (hasnull ? (bits8 *) tp + sizeof(*tuple) : NULL));
+					isnull,
+					(char *) tp + hoff,
+					&tupmask,
+					(hasnull ? (bits8 *) tp + sizeof(*tuple) : NULL));
 
 #ifdef TOAST_INDEX_HACK
 	for (i = 0; i < numberOfAttributes; i++)
 	{
 		if (untoasted_free[i])
-			pfree(DatumGetPointer(untoasted_value[i]));
+			pfree(DatumGetPointer(untoasted_values[i]));
 	}
 #endif
 
 	/*
-	 * We do this because DataFill wants to initialize a "tupmask" which
-	 * is used for HeapTuples, but we want an indextuple infomask.	The
-	 * only relevant info is the "has variable attributes" field. We have
-	 * already set the hasnull bit above.
+	 * We do this because heap_fill_tuple wants to initialize a "tupmask"
+	 * which is used for HeapTuples, but we want an indextuple infomask.
+	 * The only relevant info is the "has variable attributes" field.
+	 * We have already set the hasnull bit above.
 	 */
-
 	if (tupmask & HEAP_HASVARWIDTH)
 		infomask |= INDEX_VAR_MASK;
 
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 4ff257338f972b1136f4b42bee6583241ba994c5..c1e3dfae36701a992cb9cf46b6a69788ae5cca76 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.112 2004/12/31 21:59:10 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.113 2005/03/21 01:23:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -71,18 +71,16 @@ typedef struct
 /* non-export function prototypes */
 static void gistbuildCallback(Relation index,
 				  HeapTuple htup,
-				  Datum *attdata,
-				  char *nulls,
+				  Datum *values,
+				  bool *isnull,
 				  bool tupleIsAlive,
 				  void *state);
 static void gistdoinsert(Relation r,
 			 IndexTuple itup,
-			 InsertIndexResult *res,
 			 GISTSTATE *GISTstate);
 static int gistlayerinsert(Relation r, BlockNumber blkno,
 				IndexTuple **itup,
 				int *len,
-				InsertIndexResult *res,
 				GISTSTATE *giststate);
 static OffsetNumber gistwritebuffer(Relation r,
 				Page page,
@@ -114,8 +112,7 @@ static IndexTuple *gistSplit(Relation r,
 		  Buffer buffer,
 		  IndexTuple *itup,
 		  int *len,
-		  GISTSTATE *giststate,
-		  InsertIndexResult *res);
+		  GISTSTATE *giststate);
 static void gistnewroot(Relation r,
 			IndexTuple *itup, int len);
 static void GISTInitBuffer(Buffer b, uint32 f);
@@ -223,8 +220,8 @@ gistbuild(PG_FUNCTION_ARGS)
 static void
 gistbuildCallback(Relation index,
 				  HeapTuple htup,
-				  Datum *attdata,
-				  char *nulls,
+				  Datum *values,
+				  bool *isnull,
 				  bool tupleIsAlive,
 				  void *state)
 {
@@ -235,33 +232,33 @@ gistbuildCallback(Relation index,
 	int			i;
 
 	/* GiST cannot index tuples with leading NULLs */
-	if (nulls[0] == 'n')
+	if (isnull[0])
 		return;
 
 	/* immediately compress keys to normalize */
 	for (i = 0; i < buildstate->numindexattrs; i++)
 	{
-		if (nulls[i] == 'n')
+		if (isnull[i])
 		{
-			attdata[i] = (Datum) 0;
+			values[i] = (Datum) 0;
 			compvec[i] = FALSE;
 		}
 		else
 		{
-			gistcentryinit(&buildstate->giststate, i, &tmpcentry, attdata[i],
+			gistcentryinit(&buildstate->giststate, i, &tmpcentry, values[i],
 						   NULL, NULL, (OffsetNumber) 0,
 						 -1 /* size is currently bogus */ , TRUE, FALSE);
-			if (attdata[i] != tmpcentry.key &&
+			if (values[i] != tmpcentry.key &&
 				!(isAttByVal(&buildstate->giststate, i)))
 				compvec[i] = TRUE;
 			else
 				compvec[i] = FALSE;
-			attdata[i] = tmpcentry.key;
+			values[i] = tmpcentry.key;
 		}
 	}
 
 	/* form an index tuple and point it at the heap tuple */
-	itup = index_formtuple(buildstate->giststate.tupdesc, attdata, nulls);
+	itup = index_form_tuple(buildstate->giststate.tupdesc, values, isnull);
 	itup->t_tid = htup->t_self;
 
 	/*
@@ -271,13 +268,13 @@ gistbuildCallback(Relation index,
 	 * thing to do if you're inserting single tups, but not when you're
 	 * initializing the whole index at once.
 	 */
-	gistdoinsert(index, itup, NULL, &buildstate->giststate);
+	gistdoinsert(index, itup, &buildstate->giststate);
 
 	buildstate->indtuples += 1;
 
 	for (i = 0; i < buildstate->numindexattrs; i++)
 		if (compvec[i])
-			pfree(DatumGetPointer(attdata[i]));
+			pfree(DatumGetPointer(values[i]));
 
 	pfree(itup);
 }
@@ -292,15 +289,14 @@ Datum
 gistinsert(PG_FUNCTION_ARGS)
 {
 	Relation	r = (Relation) PG_GETARG_POINTER(0);
-	Datum	   *datum = (Datum *) PG_GETARG_POINTER(1);
-	char	   *nulls = (char *) PG_GETARG_POINTER(2);
+	Datum	   *values = (Datum *) PG_GETARG_POINTER(1);
+	bool	   *isnull = (bool *) PG_GETARG_POINTER(2);
 	ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
 
 #ifdef NOT_USED
 	Relation	heapRel = (Relation) PG_GETARG_POINTER(4);
 	bool		checkUnique = PG_GETARG_BOOL(5);
 #endif
-	InsertIndexResult res;
 	IndexTuple	itup;
 	GISTSTATE	giststate;
 	GISTENTRY	tmpentry;
@@ -314,47 +310,43 @@ gistinsert(PG_FUNCTION_ARGS)
 	 */
 
 	/* GiST cannot index tuples with leading NULLs */
-	if (nulls[0] == 'n')
-	{
-		res = NULL;
-		PG_RETURN_POINTER(res);
-	}
+	if (isnull[0])
+		PG_RETURN_BOOL(false);
 
 	initGISTstate(&giststate, r);
 
 	/* immediately compress keys to normalize */
 	for (i = 0; i < r->rd_att->natts; i++)
 	{
-		if (nulls[i] == 'n')
+		if (isnull[i])
 		{
-			datum[i] = (Datum) 0;
+			values[i] = (Datum) 0;
 			compvec[i] = FALSE;
 		}
 		else
 		{
-			gistcentryinit(&giststate, i, &tmpentry, datum[i],
+			gistcentryinit(&giststate, i, &tmpentry, values[i],
 						   NULL, NULL, (OffsetNumber) 0,
 						 -1 /* size is currently bogus */ , TRUE, FALSE);
-			if (datum[i] != tmpentry.key && !(isAttByVal(&giststate, i)))
+			if (values[i] != tmpentry.key && !(isAttByVal(&giststate, i)))
 				compvec[i] = TRUE;
 			else
 				compvec[i] = FALSE;
-			datum[i] = tmpentry.key;
+			values[i] = tmpentry.key;
 		}
 	}
-	itup = index_formtuple(giststate.tupdesc, datum, nulls);
+	itup = index_form_tuple(giststate.tupdesc, values, isnull);
 	itup->t_tid = *ht_ctid;
 
-	res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
-	gistdoinsert(r, itup, &res, &giststate);
+	gistdoinsert(r, itup, &giststate);
 
 	for (i = 0; i < r->rd_att->natts; i++)
 		if (compvec[i] == TRUE)
-			pfree(DatumGetPointer(datum[i]));
+			pfree(DatumGetPointer(values[i]));
 	pfree(itup);
 	freeGISTstate(&giststate);
 
-	PG_RETURN_POINTER(res);
+	PG_RETURN_BOOL(true);
 }
 
 #ifdef GIST_PAGEADDITEM
@@ -411,7 +403,6 @@ gistPageAddItem(GISTSTATE *giststate,
 static void
 gistdoinsert(Relation r,
 			 IndexTuple itup,
-			 InsertIndexResult *res,
 			 GISTSTATE *giststate)
 {
 	IndexTuple *instup;
@@ -423,7 +414,7 @@ gistdoinsert(Relation r,
 	instup[0] = (IndexTuple) palloc(IndexTupleSize(itup));
 	memcpy(instup[0], itup, IndexTupleSize(itup));
 
-	ret = gistlayerinsert(r, GISTP_ROOT, &instup, &len, res, giststate);
+	ret = gistlayerinsert(r, GISTP_ROOT, &instup, &len, giststate);
 	if (ret & SPLITED)
 		gistnewroot(r, instup, len);
 
@@ -436,7 +427,6 @@ static int
 gistlayerinsert(Relation r, BlockNumber blkno,
 				IndexTuple **itup,		/* in - out, has compressed entry */
 				int *len,		/* in - out */
-				InsertIndexResult *res, /* out */
 				GISTSTATE *giststate)
 {
 	Buffer		buffer;
@@ -468,7 +458,7 @@ gistlayerinsert(Relation r, BlockNumber blkno,
 		 * contains keys for each page 2. if  child page wasn't splited,
 		 * then itup contains additional for adjustment of current key
 		 */
-		ret = gistlayerinsert(r, nblkno, itup, len, res, giststate);
+		ret = gistlayerinsert(r, nblkno, itup, len, giststate);
 
 		/* nothing inserted in child */
 		if (!(ret & INSERTED))
@@ -520,9 +510,7 @@ gistlayerinsert(Relation r, BlockNumber blkno,
 		itvec = gistreadbuffer(buffer, &tlen);
 		itvec = gistjoinvector(itvec, &tlen, (*itup), *len);
 		oldlen = *len;
-		newitup = gistSplit(r, buffer, itvec, &tlen, giststate,
-							(opaque->flags & F_LEAF) ? res : NULL);		/* res only for
-																		 * inserting in leaf */
+		newitup = gistSplit(r, buffer, itvec, &tlen, giststate);
 		ReleaseBuffer(buffer);
 		do
 			pfree((*itup)[oldlen - 1]);
@@ -545,12 +533,6 @@ gistlayerinsert(Relation r, BlockNumber blkno,
 		l = gistwritebuffer(r, page, (*itup), *len, off);
 		WriteBuffer(buffer);
 
-		/*
-		 * set res if insert into leaf page, in this case, len = 1 always
-		 */
-		if (res && (opaque->flags & F_LEAF))
-			ItemPointerSet(&((*res)->pointerData), blkno, l);
-
 		if (*len > 1)
 		{						/* previous insert ret & SPLITED != 0 */
 			int			i;
@@ -666,7 +648,7 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
 {
 	Datum		attr[INDEX_MAX_KEYS];
 	bool		whatfree[INDEX_MAX_KEYS];
-	char		isnull[INDEX_MAX_KEYS];
+	bool		isnull[INDEX_MAX_KEYS];
 	GistEntryVector *evec;
 	Datum		datum;
 	int			datumsize,
@@ -706,7 +688,7 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
 		if (reallen == 0)
 		{
 			attr[j] = (Datum) 0;
-			isnull[j] = 'n';
+			isnull[j] = TRUE;
 			whatfree[j] = FALSE;
 		}
 		else
@@ -732,7 +714,7 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
 			gistcentryinit(giststate, j, &centry[j], datum,
 						   NULL, NULL, (OffsetNumber) 0,
 						   datumsize, FALSE, FALSE);
-			isnull[j] = ' ';
+			isnull[j] = FALSE;
 			attr[j] = centry[j].key;
 			if (!isAttByVal(giststate, j))
 			{
@@ -748,7 +730,7 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
 	pfree(evec);
 	pfree(needfree);
 
-	newtup = (IndexTuple) index_formtuple(giststate->tupdesc, attr, isnull);
+	newtup = index_form_tuple(giststate->tupdesc, attr, isnull);
 	for (j = 0; j < r->rd_att->natts; j++)
 		if (whatfree[j])
 			pfree(DatumGetPointer(attr[j]));
@@ -768,7 +750,7 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
 	int			datumsize;
 	bool		result,
 				neednew = false;
-	char		isnull[INDEX_MAX_KEYS],
+	bool		isnull[INDEX_MAX_KEYS],
 				whatfree[INDEX_MAX_KEYS];
 	Datum		attr[INDEX_MAX_KEYS];
 	GISTENTRY	centry[INDEX_MAX_KEYS],
@@ -799,8 +781,8 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
 	{
 		if (oldisnull[j] && addisnull[j])
 		{
-			isnull[j] = 'n';
 			attr[j] = (Datum) 0;
+			isnull[j] = TRUE;
 			whatfree[j] = FALSE;
 		}
 		else
@@ -839,8 +821,8 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
 						   NULL, NULL, (OffsetNumber) 0,
 						   datumsize, FALSE, FALSE);
 
-			isnull[j] = ' ';
 			attr[j] = centry[j].key;
+			isnull[j] = FALSE;
 			if ((!isAttByVal(giststate, j)))
 			{
 				whatfree[j] = TRUE;
@@ -856,7 +838,7 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
 	if (neednew)
 	{
 		/* need to update key */
-		newtup = (IndexTuple) index_formtuple(giststate->tupdesc, attr, isnull);
+		newtup = index_form_tuple(giststate->tupdesc, attr, isnull);
 		newtup->t_tid = oldtup->t_tid;
 	}
 
@@ -1010,7 +992,7 @@ gistfindgroup(GISTSTATE *giststate, GISTENTRY *valvec, GIST_SPLITVEC *spl)
 		/* find all other equal value in left part */
 		if (len)
 		{
-			/* add current val to list of equial values */
+			/* add current val to list of equal values */
 			spl->spl_idgrp[spl->spl_left[i]] = curid;
 			/* searching .. */
 			for (j = i + 1; j < spl->spl_nleft; j++)
@@ -1207,8 +1189,7 @@ gistSplit(Relation r,
 		  Buffer buffer,
 		  IndexTuple *itup,		/* contains compressed entry */
 		  int *len,
-		  GISTSTATE *giststate,
-		  InsertIndexResult *res)
+		  GISTSTATE *giststate)
 {
 	Page		p;
 	Buffer		leftbuf,
@@ -1344,8 +1325,7 @@ gistSplit(Relation r,
 	if (gistnospace(right, rvectup, v.spl_nright))
 	{
 		nlen = v.spl_nright;
-		newtup = gistSplit(r, rightbuf, rvectup, &nlen, giststate,
-			  (res && rvectup[nlen - 1] == itup[*len - 1]) ? res : NULL);
+		newtup = gistSplit(r, rightbuf, rvectup, &nlen, giststate);
 		ReleaseBuffer(rightbuf);
 		for (j = 1; j < r->rd_att->natts; j++)
 			if ((!isAttByVal(giststate, j)) && !v.spl_risnull[j])
@@ -1358,9 +1338,6 @@ gistSplit(Relation r,
 		l = gistwritebuffer(r, right, rvectup, v.spl_nright, FirstOffsetNumber);
 		WriteBuffer(rightbuf);
 
-		if (res)
-			ItemPointerSet(&((*res)->pointerData), rbknum, l);
-
 		nlen = 1;
 		newtup = (IndexTuple *) palloc(sizeof(IndexTuple) * 1);
 		newtup[0] = gistFormTuple(giststate, r, v.spl_rattr, v.spl_rattrsize, v.spl_risnull);
@@ -1373,8 +1350,7 @@ gistSplit(Relation r,
 		int			llen = v.spl_nleft;
 		IndexTuple *lntup;
 
-		lntup = gistSplit(r, leftbuf, lvectup, &llen, giststate,
-			  (res && lvectup[llen - 1] == itup[*len - 1]) ? res : NULL);
+		lntup = gistSplit(r, leftbuf, lvectup, &llen, giststate);
 		ReleaseBuffer(leftbuf);
 
 		for (j = 1; j < r->rd_att->natts; j++)
@@ -1394,9 +1370,6 @@ gistSplit(Relation r,
 
 		WriteBuffer(leftbuf);
 
-		if (res)
-			ItemPointerSet(&((*res)->pointerData), lbknum, l);
-
 		nlen += 1;
 		newtup = (IndexTuple *) repalloc((void *) newtup, sizeof(IndexTuple) * nlen);
 		newtup[nlen - 1] = gistFormTuple(giststate, r, v.spl_lattr, v.spl_lattrsize, v.spl_lisnull);
@@ -1704,7 +1677,7 @@ gist_tuple_replacekey(Relation r, GISTENTRY entry, IndexTuple t)
 	/*
 	 * If new entry fits in index tuple, copy it in.  To avoid worrying
 	 * about null-value bitmask, pass it off to the general
-	 * index_formtuple routine if either the previous or new value is
+	 * index_form_tuple routine if either the previous or new value is
 	 * NULL.
 	 */
 	if (!IsNull && DatumGetPointer(entry.key) != NULL &&
@@ -1725,12 +1698,10 @@ gist_tuple_replacekey(Relation r, GISTENTRY entry, IndexTuple t)
 		/* generate a new index tuple for the compressed entry */
 		TupleDesc	tupDesc = r->rd_att;
 		IndexTuple	newtup;
-		char		isnull;
+		bool		isnull;
 
-		isnull = DatumGetPointer(entry.key) != NULL ? ' ' : 'n';
-		newtup = (IndexTuple) index_formtuple(tupDesc,
-											  &(entry.key),
-											  &isnull);
+		isnull = (DatumGetPointer(entry.key) == NULL);
+		newtup = index_form_tuple(tupDesc, &(entry.key), &isnull);
 		newtup->t_tid = t->t_tid;
 		return newtup;
 	}
@@ -1799,7 +1770,6 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
 			  Datum attdata[], int datumsize[], bool isnull[])
 {
 	IndexTuple	tup;
-	char		isnullchar[INDEX_MAX_KEYS];
 	bool		whatfree[INDEX_MAX_KEYS];
 	GISTENTRY	centry[INDEX_MAX_KEYS];
 	Datum		compatt[INDEX_MAX_KEYS];
@@ -1809,7 +1779,6 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
 	{
 		if (isnull[j])
 		{
-			isnullchar[j] = 'n';
 			compatt[j] = (Datum) 0;
 			whatfree[j] = FALSE;
 		}
@@ -1818,7 +1787,6 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
 			gistcentryinit(giststate, j, &centry[j], attdata[j],
 						   NULL, NULL, (OffsetNumber) 0,
 						   datumsize[j], FALSE, FALSE);
-			isnullchar[j] = ' ';
 			compatt[j] = centry[j].key;
 			if (!isAttByVal(giststate, j))
 			{
@@ -1831,7 +1799,7 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
 		}
 	}
 
-	tup = (IndexTuple) index_formtuple(giststate->tupdesc, compatt, isnullchar);
+	tup = index_form_tuple(giststate->tupdesc, compatt, isnull);
 	for (j = 0; j < r->rd_att->natts; j++)
 		if (whatfree[j])
 			pfree(DatumGetPointer(compatt[j]));
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index a97d780c06e794bcf989ee9597c8e0ffe1219bc8..1fd901e96a33a73333fb0f3ecbb9aa68740165fc 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.76 2004/12/31 21:59:13 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.77 2005/03/21 01:23:57 tgl Exp $
  *
  * NOTES
  *	  This file contains only the public interface routines.
@@ -36,8 +36,8 @@ typedef struct
 
 static void hashbuildCallback(Relation index,
 				  HeapTuple htup,
-				  Datum *attdata,
-				  char *nulls,
+				  Datum *values,
+				  bool *isnull,
 				  bool tupleIsAlive,
 				  void *state);
 
@@ -103,18 +103,17 @@ hashbuild(PG_FUNCTION_ARGS)
 static void
 hashbuildCallback(Relation index,
 				  HeapTuple htup,
-				  Datum *attdata,
-				  char *nulls,
+				  Datum *values,
+				  bool *isnull,
 				  bool tupleIsAlive,
 				  void *state)
 {
 	HashBuildState *buildstate = (HashBuildState *) state;
 	IndexTuple	itup;
 	HashItem	hitem;
-	InsertIndexResult res;
 
 	/* form an index tuple and point it at the heap tuple */
-	itup = index_formtuple(RelationGetDescr(index), attdata, nulls);
+	itup = index_form_tuple(RelationGetDescr(index), values, isnull);
 	itup->t_tid = htup->t_self;
 
 	/* Hash indexes don't index nulls, see notes in hashinsert */
@@ -126,10 +125,7 @@ hashbuildCallback(Relation index,
 
 	hitem = _hash_formitem(itup);
 
-	res = _hash_doinsert(index, hitem);
-
-	if (res)
-		pfree(res);
+	_hash_doinsert(index, hitem);
 
 	buildstate->indtuples += 1;
 
@@ -141,27 +137,25 @@ hashbuildCallback(Relation index,
  *	hashinsert() -- insert an index tuple into a hash table.
  *
  *	Hash on the index tuple's key, find the appropriate location
- *	for the new tuple, put it there, and return an InsertIndexResult
- *	to the caller.
+ *	for the new tuple, and put it there.
  */
 Datum
 hashinsert(PG_FUNCTION_ARGS)
 {
 	Relation	rel = (Relation) PG_GETARG_POINTER(0);
-	Datum	   *datum = (Datum *) PG_GETARG_POINTER(1);
-	char	   *nulls = (char *) PG_GETARG_POINTER(2);
+	Datum	   *values = (Datum *) PG_GETARG_POINTER(1);
+	bool	   *isnull = (bool *) PG_GETARG_POINTER(2);
 	ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
 
 #ifdef NOT_USED
 	Relation	heapRel = (Relation) PG_GETARG_POINTER(4);
 	bool		checkUnique = PG_GETARG_BOOL(5);
 #endif
-	InsertIndexResult res;
 	HashItem	hitem;
 	IndexTuple	itup;
 
 	/* generate an index tuple */
-	itup = index_formtuple(RelationGetDescr(rel), datum, nulls);
+	itup = index_form_tuple(RelationGetDescr(rel), values, isnull);
 	itup->t_tid = *ht_ctid;
 
 	/*
@@ -176,17 +170,17 @@ hashinsert(PG_FUNCTION_ARGS)
 	if (IndexTupleHasNulls(itup))
 	{
 		pfree(itup);
-		PG_RETURN_POINTER(NULL);
+		PG_RETURN_BOOL(false);
 	}
 
 	hitem = _hash_formitem(itup);
 
-	res = _hash_doinsert(rel, hitem);
+	_hash_doinsert(rel, hitem);
 
 	pfree(hitem);
 	pfree(itup);
 
-	PG_RETURN_POINTER(res);
+	PG_RETURN_BOOL(true);
 }
 
 
diff --git a/src/backend/access/hash/hashinsert.c b/src/backend/access/hash/hashinsert.c
index 22ad1a09108ae683dfcc66784a6fd0eefebddafd..a09b8b4bc151041381ad9f8348254fe9d6cf269f 100644
--- a/src/backend/access/hash/hashinsert.c
+++ b/src/backend/access/hash/hashinsert.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.35 2004/12/31 21:59:13 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.36 2005/03/21 01:23:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,7 +30,7 @@ static OffsetNumber _hash_pgaddtup(Relation rel, Buffer buf,
  *		and hashinsert.  By here, hashitem is completely filled in.
  *		The datum to be used as a "key" is in the hashitem.
  */
-InsertIndexResult
+void
 _hash_doinsert(Relation rel, HashItem hitem)
 {
 	Buffer		buf;
@@ -39,7 +39,6 @@ _hash_doinsert(Relation rel, HashItem hitem)
 	IndexTuple	itup;
 	BlockNumber itup_blkno;
 	OffsetNumber itup_off;
-	InsertIndexResult res;
 	BlockNumber blkno;
 	Page		page;
 	HashPageOpaque pageopaque;
@@ -190,13 +189,6 @@ _hash_doinsert(Relation rel, HashItem hitem)
 
 	/* Finally drop our pin on the metapage */
 	_hash_dropbuf(rel, metabuf);
-
-	/* Create the return data structure */
-	res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
-
-	ItemPointerSet(&(res->pointerData), itup_blkno, itup_off);
-
-	return res;
 }
 
 /*
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 44ed126fca2df884e7631786c7465603391a2545..3a3e2d301b6313ffaa96dabb702d0d1470d4b809 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.48 2005/03/14 04:41:12 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.49 2005/03/21 01:23:58 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -283,7 +283,7 @@ toast_delete(Relation rel, HeapTuple oldtup)
 	int			numAttrs;
 	int			i;
 	Datum		toast_values[MaxHeapAttributeNumber];
-	char		toast_nulls[MaxHeapAttributeNumber];
+	bool		toast_isnull[MaxHeapAttributeNumber];
 
 	/*
 	 * Get the tuple descriptor and break down the tuple into fields.
@@ -301,7 +301,7 @@ toast_delete(Relation rel, HeapTuple oldtup)
 	numAttrs = tupleDesc->natts;
 
 	Assert(numAttrs <= MaxHeapAttributeNumber);
-	heap_deformtuple(oldtup, tupleDesc, toast_values, toast_nulls);
+	heap_deform_tuple(oldtup, tupleDesc, toast_values, toast_isnull);
 
 	/*
 	 * Check for external stored attributes and delete them from the
@@ -313,7 +313,7 @@ toast_delete(Relation rel, HeapTuple oldtup)
 		{
 			Datum		value = toast_values[i];
 
-			if (toast_nulls[i] != 'n' && VARATT_IS_EXTERNAL(value))
+			if (!toast_isnull[i] && VARATT_IS_EXTERNAL(value))
 				toast_delete_datum(rel, value);
 		}
 	}
@@ -343,8 +343,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
 	Size		maxDataLen;
 
 	char		toast_action[MaxHeapAttributeNumber];
-	char		toast_nulls[MaxHeapAttributeNumber];
-	char		toast_oldnulls[MaxHeapAttributeNumber];
+	bool		toast_isnull[MaxHeapAttributeNumber];
+	bool		toast_oldisnull[MaxHeapAttributeNumber];
 	Datum		toast_values[MaxHeapAttributeNumber];
 	Datum		toast_oldvalues[MaxHeapAttributeNumber];
 	int32		toast_sizes[MaxHeapAttributeNumber];
@@ -359,9 +359,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
 	numAttrs = tupleDesc->natts;
 
 	Assert(numAttrs <= MaxHeapAttributeNumber);
-	heap_deformtuple(newtup, tupleDesc, toast_values, toast_nulls);
+	heap_deform_tuple(newtup, tupleDesc, toast_values, toast_isnull);
 	if (oldtup != NULL)
-		heap_deformtuple(oldtup, tupleDesc, toast_oldvalues, toast_oldnulls);
+		heap_deform_tuple(oldtup, tupleDesc, toast_oldvalues, toast_oldisnull);
 
 	/* ----------
 	 * Then collect information about the values given
@@ -396,10 +396,10 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
 			 * If the old value is an external stored one, check if it has
 			 * changed so we have to delete it later.
 			 */
-			if (att[i]->attlen == -1 && toast_oldnulls[i] != 'n' &&
+			if (att[i]->attlen == -1 && !toast_oldisnull[i] &&
 				VARATT_IS_EXTERNAL(old_value))
 			{
-				if (toast_nulls[i] == 'n' || !VARATT_IS_EXTERNAL(new_value) ||
+				if (toast_isnull[i] || !VARATT_IS_EXTERNAL(new_value) ||
 					old_value->va_content.va_external.va_valueid !=
 					new_value->va_content.va_external.va_valueid ||
 					old_value->va_content.va_external.va_toastrelid !=
@@ -436,7 +436,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
 		/*
 		 * Handle NULL attributes
 		 */
-		if (toast_nulls[i] == 'n')
+		if (toast_isnull[i])
 		{
 			toast_action[i] = 'p';
 			has_nulls = true;
@@ -499,7 +499,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
 	/*
 	 * Look for attributes with attstorage 'x' to compress
 	 */
-	while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) >
+	while (MAXALIGN(heap_compute_data_size(tupleDesc,
+										   toast_values, toast_isnull)) >
 		   maxDataLen)
 	{
 		int			biggest_attno = -1;
@@ -560,7 +561,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
 	 * Second we look for attributes of attstorage 'x' or 'e' that are
 	 * still inline.
 	 */
-	while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) >
+	while (MAXALIGN(heap_compute_data_size(tupleDesc,
+										   toast_values, toast_isnull)) >
 		   maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid)
 	{
 		int			biggest_attno = -1;
@@ -611,7 +613,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
 	 * Round 3 - this time we take attributes with storage 'm' into
 	 * compression
 	 */
-	while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) >
+	while (MAXALIGN(heap_compute_data_size(tupleDesc,
+										   toast_values, toast_isnull)) >
 		   maxDataLen)
 	{
 		int			biggest_attno = -1;
@@ -671,7 +674,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
 	/*
 	 * Finally we store attributes of type 'm' external
 	 */
-	while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) >
+	while (MAXALIGN(heap_compute_data_size(tupleDesc,
+										   toast_values, toast_isnull)) >
 		   maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid)
 	{
 		int			biggest_attno = -1;
@@ -739,7 +743,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
 			new_len += sizeof(Oid);
 		new_len = MAXALIGN(new_len);
 		Assert(new_len == olddata->t_hoff);
-		new_len += ComputeDataSize(tupleDesc, toast_values, toast_nulls);
+		new_len += heap_compute_data_size(tupleDesc,
+										  toast_values, toast_isnull);
 
 		/*
 		 * Allocate new tuple in same context as old one.
@@ -753,12 +758,12 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
 		 */
 		memcpy(new_data, olddata, olddata->t_hoff);
 
-		DataFill((char *) new_data + olddata->t_hoff,
-				 tupleDesc,
-				 toast_values,
-				 toast_nulls,
-				 &(newtup->t_data->t_infomask),
-				 has_nulls ? newtup->t_data->t_bits : NULL);
+		heap_fill_tuple(tupleDesc,
+						toast_values,
+						toast_isnull,
+						(char *) new_data + olddata->t_hoff,
+						&(newtup->t_data->t_infomask),
+						has_nulls ? newtup->t_data->t_bits : NULL);
 
 		/*
 		 * In the case we modified a previously modified tuple again, free
@@ -810,7 +815,7 @@ toast_flatten_tuple_attribute(Datum value,
 	bool		need_change = false;
 	bool		has_nulls = false;
 	Datum		toast_values[MaxTupleAttributeNumber];
-	char		toast_nulls[MaxTupleAttributeNumber];
+	bool		toast_isnull[MaxTupleAttributeNumber];
 	bool		toast_free[MaxTupleAttributeNumber];
 
 	/*
@@ -836,7 +841,7 @@ toast_flatten_tuple_attribute(Datum value,
 	tmptup.t_data = olddata;
 
 	Assert(numAttrs <= MaxTupleAttributeNumber);
-	heap_deformtuple(&tmptup, tupleDesc, toast_values, toast_nulls);
+	heap_deform_tuple(&tmptup, tupleDesc, toast_values, toast_isnull);
 
 	memset(toast_free, 0, numAttrs * sizeof(bool));
 
@@ -845,7 +850,7 @@ toast_flatten_tuple_attribute(Datum value,
 		/*
 		 * Look at non-null varlena attributes
 		 */
-		if (toast_nulls[i] == 'n')
+		if (toast_isnull[i])
 			has_nulls = true;
 		else if (att[i]->attlen == -1)
 		{
@@ -879,7 +884,7 @@ toast_flatten_tuple_attribute(Datum value,
 		new_len += sizeof(Oid);
 	new_len = MAXALIGN(new_len);
 	Assert(new_len == olddata->t_hoff);
-	new_len += ComputeDataSize(tupleDesc, toast_values, toast_nulls);
+	new_len += heap_compute_data_size(tupleDesc, toast_values, toast_isnull);
 
 	new_data = (HeapTupleHeader) palloc0(new_len);
 
@@ -890,12 +895,12 @@ toast_flatten_tuple_attribute(Datum value,
 
 	HeapTupleHeaderSetDatumLength(new_data, new_len);
 
-	DataFill((char *) new_data + olddata->t_hoff,
-			 tupleDesc,
-			 toast_values,
-			 toast_nulls,
-			 &(new_data->t_infomask),
-			 has_nulls ? new_data->t_bits : NULL);
+	heap_fill_tuple(tupleDesc,
+					toast_values,
+					toast_isnull,
+					(char *) new_data + olddata->t_hoff,
+					&(new_data->t_infomask),
+					has_nulls ? new_data->t_bits : NULL);
 
 	/*
 	 * Free allocated temp values
@@ -955,10 +960,9 @@ toast_save_datum(Relation rel, Datum value)
 	Relation	toastrel;
 	Relation	toastidx;
 	HeapTuple	toasttup;
-	InsertIndexResult idxres;
 	TupleDesc	toasttupDesc;
 	Datum		t_values[3];
-	char		t_nulls[3];
+	bool		t_isnull[3];
 	varattrib  *result;
 	struct
 	{
@@ -996,9 +1000,9 @@ toast_save_datum(Relation rel, Datum value)
 	 */
 	t_values[0] = ObjectIdGetDatum(result->va_content.va_external.va_valueid);
 	t_values[2] = PointerGetDatum(&chunk_data);
-	t_nulls[0] = ' ';
-	t_nulls[1] = ' ';
-	t_nulls[2] = ' ';
+	t_isnull[0] = false;
+	t_isnull[1] = false;
+	t_isnull[2] = false;
 
 	/*
 	 * Get the data to process
@@ -1031,7 +1035,7 @@ toast_save_datum(Relation rel, Datum value)
 		t_values[1] = Int32GetDatum(chunk_seq++);
 		VARATT_SIZEP(&chunk_data) = chunk_size + VARHDRSZ;
 		memcpy(VARATT_DATA(&chunk_data), data_p, chunk_size);
-		toasttup = heap_formtuple(toasttupDesc, t_values, t_nulls);
+		toasttup = heap_form_tuple(toasttupDesc, t_values, t_isnull);
 		if (!HeapTupleIsValid(toasttup))
 			elog(ERROR, "failed to build TOAST tuple");
 
@@ -1045,16 +1049,13 @@ toast_save_datum(Relation rel, Datum value)
 		 * Note also that there had better not be any user-created index on
 		 * the TOAST table, since we don't bother to update anything else.
 		 */
-		idxres = index_insert(toastidx, t_values, t_nulls,
-							  &(toasttup->t_self),
-							  toastrel, toastidx->rd_index->indisunique);
-		if (idxres == NULL)
-			elog(ERROR, "failed to insert index entry for TOAST tuple");
+		index_insert(toastidx, t_values, t_isnull,
+					 &(toasttup->t_self),
+					 toastrel, toastidx->rd_index->indisunique);
 
 		/*
 		 * Free memory
 		 */
-		pfree(idxres);
 		heap_freetuple(toasttup);
 
 		/*
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 38f0443194e441305642bd579216d8639a768706..6d7a874aac80be88f272ca371a6718bd8d53926a 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.77 2004/12/31 21:59:19 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.78 2005/03/21 01:23:58 tgl Exp $
  *
  * INTERFACE ROUTINES
  *		index_open		- open an index relation by relation OID
@@ -211,16 +211,15 @@ index_close(Relation relation)
  *		index_insert - insert an index tuple into a relation
  * ----------------
  */
-InsertIndexResult
+bool
 index_insert(Relation indexRelation,
-			 Datum *datums,
-			 char *nulls,
+			 Datum *values,
+			 bool *isnull,
 			 ItemPointer heap_t_ctid,
 			 Relation heapRelation,
 			 bool check_uniqueness)
 {
 	RegProcedure procedure;
-	InsertIndexResult specificResult;
 
 	RELATION_CHECKS;
 	GET_REL_PROCEDURE(insert, aminsert);
@@ -228,17 +227,13 @@ index_insert(Relation indexRelation,
 	/*
 	 * have the am's insert proc do all the work.
 	 */
-	specificResult = (InsertIndexResult)
-		DatumGetPointer(OidFunctionCall6(procedure,
+	return DatumGetBool(OidFunctionCall6(procedure,
 										 PointerGetDatum(indexRelation),
-										 PointerGetDatum(datums),
-										 PointerGetDatum(nulls),
+										 PointerGetDatum(values),
+										 PointerGetDatum(isnull),
 										 PointerGetDatum(heap_t_ctid),
 										 PointerGetDatum(heapRelation),
 										 BoolGetDatum(check_uniqueness)));
-
-	/* must be pfree'ed */
-	return specificResult;
 }
 
 /* ----------------
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index 3a1a4712897c535a51eb6a55f69049165d68f6c7..868a91ab3a5efa16c1294d7389693f7c31b26916 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.119 2004/12/31 21:59:22 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.120 2005/03/21 01:23:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -41,7 +41,7 @@ static Buffer _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf);
 static TransactionId _bt_check_unique(Relation rel, BTItem btitem,
 				 Relation heapRel, Buffer buf,
 				 ScanKey itup_scankey);
-static InsertIndexResult _bt_insertonpg(Relation rel, Buffer buf,
+static void _bt_insertonpg(Relation rel, Buffer buf,
 			   BTStack stack,
 			   int keysz, ScanKey scankey,
 			   BTItem btitem,
@@ -71,7 +71,7 @@ static bool _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum,
  *		This routine is called by the public interface routines, btbuild
  *		and btinsert.  By here, btitem is filled in, including the TID.
  */
-InsertIndexResult
+void
 _bt_doinsert(Relation rel, BTItem btitem,
 			 bool index_is_unique, Relation heapRel)
 {
@@ -80,7 +80,6 @@ _bt_doinsert(Relation rel, BTItem btitem,
 	ScanKey		itup_scankey;
 	BTStack		stack;
 	Buffer		buf;
-	InsertIndexResult res;
 
 	/* we need a scan key to do our search, so build one */
 	itup_scankey = _bt_mkscankey(rel, itup);
@@ -138,14 +137,11 @@ top:
 	}
 
 	/* do the insertion */
-	res = _bt_insertonpg(rel, buf, stack, natts, itup_scankey, btitem,
-						 0, false);
+	_bt_insertonpg(rel, buf, stack, natts, itup_scankey, btitem, 0, false);
 
 	/* be tidy */
 	_bt_freestack(stack);
 	_bt_freeskey(itup_scankey);
-
-	return res;
 }
 
 /*
@@ -357,7 +353,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
  *		insertion on internal pages.
  *----------
  */
-static InsertIndexResult
+static void
 _bt_insertonpg(Relation rel,
 			   Buffer buf,
 			   BTStack stack,
@@ -367,7 +363,6 @@ _bt_insertonpg(Relation rel,
 			   OffsetNumber afteritem,
 			   bool split_only_page)
 {
-	InsertIndexResult res;
 	Page		page;
 	BTPageOpaque lpageop;
 	OffsetNumber itup_off;
@@ -630,12 +625,6 @@ _bt_insertonpg(Relation rel,
 
 		_bt_wrtbuf(rel, buf);
 	}
-
-	/* by here, the new tuple is inserted at itup_blkno/itup_off */
-	res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
-	ItemPointerSet(&(res->pointerData), itup_blkno, itup_off);
-
-	return res;
 }
 
 /*
@@ -1190,7 +1179,6 @@ _bt_insert_parent(Relation rel,
 		BlockNumber bknum = BufferGetBlockNumber(buf);
 		BlockNumber rbknum = BufferGetBlockNumber(rbuf);
 		Page		page = BufferGetPage(buf);
-		InsertIndexResult newres;
 		BTItem		new_item;
 		BTStackData fakestack;
 		BTItem		ritem;
@@ -1244,12 +1232,11 @@ _bt_insert_parent(Relation rel,
 				 RelationGetRelationName(rel));
 
 		/* Recursively update the parent */
-		newres = _bt_insertonpg(rel, pbuf, stack->bts_parent,
-								0, NULL, new_item, stack->bts_offset,
-								is_only);
+		_bt_insertonpg(rel, pbuf, stack->bts_parent,
+					   0, NULL, new_item, stack->bts_offset,
+					   is_only);
 
 		/* be tidy */
-		pfree(newres);
 		pfree(new_item);
 	}
 }
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 8f6fe7d27ccc3cb72725cdac3f9e18ce0b68edb6..1fc26ea8958e8cc6ff6d5e8b1a3d1a57dad51c46 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.125 2005/03/20 22:00:50 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.126 2005/03/21 01:23:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -52,8 +52,8 @@ bool		FastBuild = true;	/* use SORT instead of insertion build */
 static void _bt_restscan(IndexScanDesc scan);
 static void btbuildCallback(Relation index,
 				HeapTuple htup,
-				Datum *attdata,
-				char *nulls,
+				Datum *values,
+				bool *isnull,
 				bool tupleIsAlive,
 				void *state);
 
@@ -178,18 +178,17 @@ btbuild(PG_FUNCTION_ARGS)
 static void
 btbuildCallback(Relation index,
 				HeapTuple htup,
-				Datum *attdata,
-				char *nulls,
+				Datum *values,
+				bool *isnull,
 				bool tupleIsAlive,
 				void *state)
 {
 	BTBuildState *buildstate = (BTBuildState *) state;
 	IndexTuple	itup;
 	BTItem		btitem;
-	InsertIndexResult res;
 
 	/* form an index tuple and point it at the heap tuple */
-	itup = index_formtuple(RelationGetDescr(index), attdata, nulls);
+	itup = index_form_tuple(RelationGetDescr(index), values, isnull);
 	itup->t_tid = htup->t_self;
 
 	btitem = _bt_formitem(itup);
@@ -212,10 +211,8 @@ btbuildCallback(Relation index,
 	}
 	else
 	{
-		res = _bt_doinsert(index, btitem,
-						   buildstate->isUnique, buildstate->heapRel);
-		if (res)
-			pfree(res);
+		_bt_doinsert(index, btitem,
+					 buildstate->isUnique, buildstate->heapRel);
 	}
 
 	buildstate->indtuples += 1;
@@ -228,33 +225,31 @@ btbuildCallback(Relation index,
  *	btinsert() -- insert an index tuple into a btree.
  *
  *		Descend the tree recursively, find the appropriate location for our
- *		new tuple, put it there, set its unique OID as appropriate, and
- *		return an InsertIndexResult to the caller.
+ *		new tuple, and put it there.
  */
 Datum
 btinsert(PG_FUNCTION_ARGS)
 {
 	Relation	rel = (Relation) PG_GETARG_POINTER(0);
-	Datum	   *datum = (Datum *) PG_GETARG_POINTER(1);
-	char	   *nulls = (char *) PG_GETARG_POINTER(2);
+	Datum	   *values = (Datum *) PG_GETARG_POINTER(1);
+	bool	   *isnull = (bool *) PG_GETARG_POINTER(2);
 	ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
 	Relation	heapRel = (Relation) PG_GETARG_POINTER(4);
 	bool		checkUnique = PG_GETARG_BOOL(5);
-	InsertIndexResult res;
 	BTItem		btitem;
 	IndexTuple	itup;
 
 	/* generate an index tuple */
-	itup = index_formtuple(RelationGetDescr(rel), datum, nulls);
+	itup = index_form_tuple(RelationGetDescr(rel), values, isnull);
 	itup->t_tid = *ht_ctid;
 	btitem = _bt_formitem(itup);
 
-	res = _bt_doinsert(rel, btitem, checkUnique, heapRel);
+	_bt_doinsert(rel, btitem, checkUnique, heapRel);
 
 	pfree(btitem);
 	pfree(itup);
 
-	PG_RETURN_POINTER(res);
+	PG_RETURN_BOOL(true);
 }
 
 /*
diff --git a/src/backend/access/rtree/rtree.c b/src/backend/access/rtree/rtree.c
index 5f799fd48a4bd3376f011189bebf4f0ce9799147..32f4ebaf800d0a49c3c9d29d7724d0cbbb581dc0 100644
--- a/src/backend/access/rtree/rtree.c
+++ b/src/backend/access/rtree/rtree.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/rtree/rtree.c,v 1.87 2005/01/24 02:47:26 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/rtree/rtree.c,v 1.88 2005/03/21 01:24:00 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -81,15 +81,14 @@ typedef struct
 /* non-export function prototypes */
 static void rtbuildCallback(Relation index,
 				HeapTuple htup,
-				Datum *attdata,
-				char *nulls,
+				Datum *values,
+				bool *isnull,
 				bool tupleIsAlive,
 				void *state);
-static InsertIndexResult rtdoinsert(Relation r, IndexTuple itup,
-		   RTSTATE *rtstate);
+static void rtdoinsert(Relation r, IndexTuple itup, RTSTATE *rtstate);
 static void rttighten(Relation r, RTSTACK *stk, Datum datum, int att_size,
 		  RTSTATE *rtstate);
-static InsertIndexResult rtdosplit(Relation r, Buffer buffer, RTSTACK *stack,
+static void rtdosplit(Relation r, Buffer buffer, RTSTACK *stack,
 		  IndexTuple itup, RTSTATE *rtstate);
 static void rtintinsert(Relation r, RTSTACK *stk, IndexTuple ltup,
 			IndexTuple rtup, RTSTATE *rtstate);
@@ -174,17 +173,16 @@ rtbuild(PG_FUNCTION_ARGS)
 static void
 rtbuildCallback(Relation index,
 				HeapTuple htup,
-				Datum *attdata,
-				char *nulls,
+				Datum *values,
+				bool *isnull,
 				bool tupleIsAlive,
 				void *state)
 {
 	RTBuildState *buildstate = (RTBuildState *) state;
 	IndexTuple	itup;
-	InsertIndexResult res;
 
 	/* form an index tuple and point it at the heap tuple */
-	itup = index_formtuple(RelationGetDescr(index), attdata, nulls);
+	itup = index_form_tuple(RelationGetDescr(index), values, isnull);
 	itup->t_tid = htup->t_self;
 
 	/* rtree indexes don't index nulls, see notes in rtinsert */
@@ -201,10 +199,7 @@ rtbuildCallback(Relation index,
 	 * if you're inserting single tups, but not when you're initializing
 	 * the whole index at once.
 	 */
-	res = rtdoinsert(index, itup, &buildstate->rtState);
-
-	if (res)
-		pfree(res);
+	rtdoinsert(index, itup, &buildstate->rtState);
 
 	buildstate->indtuples += 1;
 
@@ -221,20 +216,19 @@ Datum
 rtinsert(PG_FUNCTION_ARGS)
 {
 	Relation	r = (Relation) PG_GETARG_POINTER(0);
-	Datum	   *datum = (Datum *) PG_GETARG_POINTER(1);
-	char	   *nulls = (char *) PG_GETARG_POINTER(2);
+	Datum	   *values = (Datum *) PG_GETARG_POINTER(1);
+	bool	   *isnull = (bool *) PG_GETARG_POINTER(2);
 	ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
 
 #ifdef NOT_USED
 	Relation	heapRel = (Relation) PG_GETARG_POINTER(4);
 	bool		checkUnique = PG_GETARG_BOOL(5);
 #endif
-	InsertIndexResult res;
 	IndexTuple	itup;
 	RTSTATE		rtState;
 
 	/* generate an index tuple */
-	itup = index_formtuple(RelationGetDescr(r), datum, nulls);
+	itup = index_form_tuple(RelationGetDescr(r), values, isnull);
 	itup->t_tid = *ht_ctid;
 
 	/*
@@ -245,7 +239,7 @@ rtinsert(PG_FUNCTION_ARGS)
 	if (IndexTupleHasNulls(itup))
 	{
 		pfree(itup);
-		PG_RETURN_POINTER(NULL);
+		PG_RETURN_BOOL(false);
 	}
 
 	initRtstate(&rtState, r);
@@ -255,13 +249,12 @@ rtinsert(PG_FUNCTION_ARGS)
 	 * have acquired exclusive lock on index relation.	We need no locking
 	 * here.
 	 */
+	rtdoinsert(r, itup, &rtState);
 
-	res = rtdoinsert(r, itup, &rtState);
-
-	PG_RETURN_POINTER(res);
+	PG_RETURN_BOOL(true);
 }
 
-static InsertIndexResult
+static void
 rtdoinsert(Relation r, IndexTuple itup, RTSTATE *rtstate)
 {
 	Page		page;
@@ -270,7 +263,6 @@ rtdoinsert(Relation r, IndexTuple itup, RTSTATE *rtstate)
 	IndexTuple	which;
 	OffsetNumber l;
 	RTSTACK    *stack;
-	InsertIndexResult res;
 	RTreePageOpaque opaque;
 	Datum		datum;
 
@@ -305,10 +297,10 @@ rtdoinsert(Relation r, IndexTuple itup, RTSTATE *rtstate)
 	if (nospace(page, itup))
 	{
 		/* need to do a split */
-		res = rtdosplit(r, buffer, stack, itup, rtstate);
+		rtdosplit(r, buffer, stack, itup, rtstate);
 		freestack(stack);
 		WriteBuffer(buffer);	/* don't forget to release buffer! */
-		return res;
+		return;
 	}
 
 	/* add the item and write the buffer */
@@ -335,12 +327,6 @@ rtdoinsert(Relation r, IndexTuple itup, RTSTATE *rtstate)
 	/* now expand the page boundary in the parent to include the new child */
 	rttighten(r, stack, datum, IndexTupleAttSize(itup), rtstate);
 	freestack(stack);
-
-	/* build and return an InsertIndexResult for this insertion */
-	res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
-	ItemPointerSet(&(res->pointerData), blk, l);
-
-	return res;
 }
 
 static void
@@ -422,7 +408,7 @@ rttighten(Relation r,
  *	  rtpicksplit does the interesting work of choosing the split.
  *	  This routine just does the bit-pushing.
  */
-static InsertIndexResult
+static void
 rtdosplit(Relation r,
 		  Buffer buffer,
 		  RTSTACK *stack,
@@ -446,9 +432,7 @@ rtdosplit(Relation r,
 				rbknum;
 	BlockNumber bufblock;
 	RTreePageOpaque opaque;
-	int			blank;
-	InsertIndexResult res;
-	char	   *isnull;
+	bool	   *isnull;
 	SPLITVEC	v;
 	OffsetNumber *spl_left,
 			   *spl_right;
@@ -493,9 +477,6 @@ rtdosplit(Relation r,
 	maxoff = PageGetMaxOffsetNumber(p);
 	newitemoff = OffsetNumberNext(maxoff);
 
-	/* build an InsertIndexResult for this insertion */
-	res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
-
 	/*
 	 * spl_left contains a list of the offset numbers of the tuples that
 	 * will go to the left page.  For each offset number, get the tuple
@@ -521,9 +502,6 @@ rtdosplit(Relation r,
 				 RelationGetRelationName(r));
 		leftoff = OffsetNumberNext(leftoff);
 
-		if (i == newitemoff)
-			ItemPointerSet(&(res->pointerData), lbknum, leftoff);
-
 		spl_left++;				/* advance in left split vector */
 	}
 
@@ -545,9 +523,6 @@ rtdosplit(Relation r,
 				 RelationGetRelationName(r));
 		rightoff = OffsetNumberNext(rightoff);
 
-		if (i == newitemoff)
-			ItemPointerSet(&(res->pointerData), rbknum, rightoff);
-
 		spl_right++;			/* advance in right split vector */
 	}
 
@@ -582,14 +557,12 @@ rtdosplit(Relation r,
 	rtadjscans(r, RTOP_SPLIT, bufblock, FirstOffsetNumber);
 
 	tupDesc = r->rd_att;
-	isnull = (char *) palloc(r->rd_rel->relnatts);
-	for (blank = 0; blank < r->rd_rel->relnatts; blank++)
-		isnull[blank] = ' ';
-
-	ltup = (IndexTuple) index_formtuple(tupDesc,
-										&(v.spl_ldatum), isnull);
-	rtup = (IndexTuple) index_formtuple(tupDesc,
-										&(v.spl_rdatum), isnull);
+	isnull = (bool *) palloc(r->rd_rel->relnatts * sizeof(bool));
+	memset(isnull, false, r->rd_rel->relnatts * sizeof(bool));
+
+	ltup = index_form_tuple(tupDesc, &(v.spl_ldatum), isnull);
+	rtup = index_form_tuple(tupDesc, &(v.spl_rdatum), isnull);
+
 	pfree(isnull);
 	pfree(DatumGetPointer(v.spl_ldatum));
 	pfree(DatumGetPointer(v.spl_rdatum));
@@ -602,8 +575,6 @@ rtdosplit(Relation r,
 
 	pfree(ltup);
 	pfree(rtup);
-
-	return res;
 }
 
 static void
@@ -619,7 +590,6 @@ rtintinsert(Relation r,
 	Datum		ldatum,
 				rdatum,
 				newdatum;
-	InsertIndexResult res;
 
 	if (stk == NULL)
 	{
@@ -651,10 +621,9 @@ rtintinsert(Relation r,
 		newdatum = IndexTupleGetDatum(ltup);
 		rttighten(r, stk->rts_parent, newdatum,
 				  IndexTupleAttSize(ltup), rtstate);
-		res = rtdosplit(r, b, stk->rts_parent, rtup, rtstate);
+		rtdosplit(r, b, stk->rts_parent, rtup, rtstate);
 		WriteBuffer(b);			/* don't forget to release buffer!  -
 								 * 01/31/94 */
-		pfree(res);
 	}
 	else
 	{
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 3ea8a99f8f45c518dba17279adb7efb2c6f10052..2f6eb1bac4f68caf1a26d4b09a48696f0915a4b2 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.248 2005/03/20 22:00:51 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.249 2005/03/21 01:24:01 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -889,28 +889,29 @@ BuildIndexInfo(Relation index)
 
 /* ----------------
  *		FormIndexDatum
- *			Construct Datum[] and nullv[] arrays for a new index tuple.
+ *			Construct values[] and isnull[] arrays for a new index tuple.
  *
  *	indexInfo		Info about the index
  *	slot			Heap tuple for which we must prepare an index entry
  *	estate			executor state for evaluating any index expressions
- *	datum			Array of index Datums (output area)
- *	nullv			Array of is-null indicators (output area)
+ *	values			Array of index Datums (output area)
+ *	isnull			Array of is-null indicators (output area)
  *
  * When there are no index expressions, estate may be NULL.  Otherwise it
  * must be supplied, *and* the ecxt_scantuple slot of its per-tuple expr
  * context must point to the heap tuple passed in.
  *
- * For largely historical reasons, we don't actually call index_formtuple()
- * here, we just prepare its input arrays datum[] and nullv[].
+ * Notice we don't actually call index_form_tuple() here; we just prepare
+ * its input arrays values[] and isnull[].  This is because the index AM
+ * may wish to alter the data before storage.
  * ----------------
  */
 void
 FormIndexDatum(IndexInfo *indexInfo,
 			   TupleTableSlot *slot,
 			   EState *estate,
-			   Datum *datum,
-			   char *nullv)
+			   Datum *values,
+			   bool *isnull)
 {
 	ListCell   *indexpr_item;
 	int			i;
@@ -954,8 +955,8 @@ FormIndexDatum(IndexInfo *indexInfo,
 											   NULL);
 			indexpr_item = lnext(indexpr_item);
 		}
-		datum[i] = iDatum;
-		nullv[i] = (isNull) ? 'n' : ' ';
+		values[i] = iDatum;
+		isnull[i] = isNull;
 	}
 
 	if (indexpr_item != NULL)
@@ -1332,8 +1333,8 @@ IndexBuildHeapScan(Relation heapRelation,
 {
 	HeapScanDesc scan;
 	HeapTuple	heapTuple;
-	Datum		attdata[INDEX_MAX_KEYS];
-	char		nulls[INDEX_MAX_KEYS];
+	Datum		values[INDEX_MAX_KEYS];
+	bool		isnull[INDEX_MAX_KEYS];
 	double		reltuples;
 	List	   *predicate;
 	TupleTableSlot *slot;
@@ -1509,17 +1510,17 @@ IndexBuildHeapScan(Relation heapRelation,
 		FormIndexDatum(indexInfo,
 					   slot,
 					   estate,
-					   attdata,
-					   nulls);
+					   values,
+					   isnull);
 
 		/*
 		 * You'd think we should go ahead and build the index tuple here,
 		 * but some index AMs want to do further processing on the data
-		 * first.  So pass the attdata and nulls arrays, instead.
+		 * first.  So pass the values[] and isnull[] arrays, instead.
 		 */
 
 		/* Call the AM's callback routine to process the tuple */
-		callback(indexRelation, heapTuple, attdata, nulls, tupleIsAlive,
+		callback(indexRelation, heapTuple, values, isnull, tupleIsAlive,
 				 callback_state);
 	}
 
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 90ffbe828a73bd06cbd304dd65895d33d5a2c273..905d99d9469029cdf877d6609fd1e1785a63d798 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/indexing.c,v 1.108 2005/03/16 21:38:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/indexing.c,v 1.109 2005/03/21 01:24:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,8 +75,8 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
 	Relation	heapRelation;
 	TupleTableSlot *slot;
 	IndexInfo **indexInfoArray;
-	Datum		datum[INDEX_MAX_KEYS];
-	char		nullv[INDEX_MAX_KEYS];
+	Datum		values[INDEX_MAX_KEYS];
+	bool		isnull[INDEX_MAX_KEYS];
 
 	/*
 	 * Get information from the state structure.  Fall out if nothing to do.
@@ -98,7 +98,6 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
 	for (i = 0; i < numIndexes; i++)
 	{
 		IndexInfo  *indexInfo;
-		InsertIndexResult result;
 
 		indexInfo = indexInfoArray[i];
 
@@ -110,27 +109,24 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
 		Assert(indexInfo->ii_Predicate == NIL);
 
 		/*
-		 * FormIndexDatum fills in its datum and null parameters with
-		 * attribute information taken from the given tuple.
+		 * FormIndexDatum fills in its values and isnull parameters with
+		 * the appropriate values for the column(s) of the index.
 		 */
 		FormIndexDatum(indexInfo,
 					   slot,
 					   NULL,	/* no expression eval to do */
-					   datum,
-					   nullv);
+					   values,
+					   isnull);
 
 		/*
 		 * The index AM does the rest.
 		 */
-		result = index_insert(relationDescs[i], /* index relation */
-							  datum,	/* array of heaptuple Datums */
-							  nullv,	/* info on nulls */
-							  &(heapTuple->t_self),		/* tid of heap tuple */
-							  heapRelation,
-							  relationDescs[i]->rd_index->indisunique);
-
-		if (result)
-			pfree(result);
+		index_insert(relationDescs[i],	/* index relation */
+					 values,			/* array of index Datums */
+					 isnull,			/* is-null flags */
+					 &(heapTuple->t_self),		/* tid of heap tuple */
+					 heapRelation,
+					 relationDescs[i]->rd_index->indisunique);
 	}
 
 	ExecDropSingleTupleTableSlot(slot);
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index b757512b4632def51cd95245597fade97923f19f..94e1971a4dfefa3d99f553dee4fad10a8d986d1d 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.83 2005/03/16 21:38:05 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.84 2005/03/21 01:24:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -448,8 +448,8 @@ compute_index_stats(Relation onerel, double totalrows,
 {
 	MemoryContext ind_context,
 				old_context;
-	Datum		attdata[INDEX_MAX_KEYS];
-	char		nulls[INDEX_MAX_KEYS];
+	Datum		values[INDEX_MAX_KEYS];
+	bool		isnull[INDEX_MAX_KEYS];
 	int			ind,
 				i;
 
@@ -528,8 +528,8 @@ compute_index_stats(Relation onerel, double totalrows,
 				FormIndexDatum(indexInfo,
 							   slot,
 							   estate,
-							   attdata,
-							   nulls);
+							   values,
+							   isnull);
 
 				/*
 				 * Save just the columns we care about.
@@ -539,8 +539,8 @@ compute_index_stats(Relation onerel, double totalrows,
 					VacAttrStats *stats = thisdata->vacattrstats[i];
 					int			attnum = stats->attr->attnum;
 
-					exprvals[tcnt] = attdata[attnum - 1];
-					exprnulls[tcnt] = (nulls[attnum - 1] == 'n');
+					exprvals[tcnt] = values[attnum - 1];
+					exprnulls[tcnt] = isnull[attnum - 1];
 					tcnt++;
 				}
 			}
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 74567b04417cac4c14cfd2d7b3efe72dec1304b8..b1840b45cf963ec833a95aa5e013e5486cb60be0 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.118 2005/03/16 21:38:07 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.119 2005/03/21 01:24:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -861,8 +861,8 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
 	Relation	heapRelation;
 	IndexInfo **indexInfoArray;
 	ExprContext *econtext;
-	Datum		datum[INDEX_MAX_KEYS];
-	char		nullv[INDEX_MAX_KEYS];
+	Datum		values[INDEX_MAX_KEYS];
+	bool		isnull[INDEX_MAX_KEYS];
 
 	/*
 	 * Get information from the result relation info structure.
@@ -889,7 +889,6 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
 	for (i = 0; i < numIndices; i++)
 	{
 		IndexInfo  *indexInfo;
-		InsertIndexResult result;
 
 		if (relationDescs[i] == NULL)
 			continue;
@@ -920,35 +919,31 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
 		}
 
 		/*
-		 * FormIndexDatum fills in its datum and null parameters with
-		 * attribute information taken from the given tuple. It also
-		 * computes any expressions needed.
+		 * FormIndexDatum fills in its values and isnull parameters with
+		 * the appropriate values for the column(s) of the index.
 		 */
 		FormIndexDatum(indexInfo,
 					   slot,
 					   estate,
-					   datum,
-					   nullv);
+					   values,
+					   isnull);
 
 		/*
 		 * The index AM does the rest.	Note we suppress unique-index
 		 * checks if we are being called from VACUUM, since VACUUM may
 		 * need to move dead tuples that have the same keys as live ones.
 		 */
-		result = index_insert(relationDescs[i], /* index relation */
-							  datum,	/* array of index Datums */
-							  nullv,	/* info on nulls */
-							  tupleid,	/* tid of heap tuple */
-							  heapRelation,
-				  relationDescs[i]->rd_index->indisunique && !is_vacuum);
+		index_insert(relationDescs[i],	/* index relation */
+					 values,			/* array of index Datums */
+					 isnull,			/* null flags */
+					 tupleid,			/* tid of heap tuple */
+					 heapRelation,
+					 relationDescs[i]->rd_index->indisunique && !is_vacuum);
 
 		/*
 		 * keep track of index inserts for debugging
 		 */
 		IncrIndexInserted();
-
-		if (result)
-			pfree(result);
 	}
 }
 
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index 573ad6d1a84a2dca81036e3617354dc9e95b3ad8..84daf30878c3f99aabbed0f8d8ff2bffa038351a 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.47 2004/12/31 22:03:21 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.48 2005/03/21 01:24:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -72,8 +72,8 @@ extern Relation index_open(Oid relationId);
 extern Relation index_openrv(const RangeVar *relation);
 extern Relation index_openr(const char *sysRelationName);
 extern void index_close(Relation relation);
-extern InsertIndexResult index_insert(Relation indexRelation,
-			 Datum *datums, char *nulls,
+extern bool index_insert(Relation indexRelation,
+			 Datum *values, bool *isnull,
 			 ItemPointer heap_t_ctid,
 			 Relation heapRelation,
 			 bool check_uniqueness);
diff --git a/src/include/access/hash.h b/src/include/access/hash.h
index 6d4668bdbe48f635a5d1dee52c64fc91c91fd1d5..0b7c1a5f0f2f932a2e757e649a343b93cd342e87 100644
--- a/src/include/access/hash.h
+++ b/src/include/access/hash.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.59 2004/12/31 22:03:21 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.60 2005/03/21 01:24:04 tgl Exp $
  *
  * NOTES
  *		modeled after Margo Seltzer's hash implementation for unix.
@@ -266,7 +266,7 @@ extern Datum hash_any(register const unsigned char *k, register int keylen);
 /* private routines */
 
 /* hashinsert.c */
-extern InsertIndexResult _hash_doinsert(Relation rel, HashItem hitem);
+extern void _hash_doinsert(Relation rel, HashItem hitem);
 
 /* hashovfl.c */
 extern Buffer _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 6de107b76fcfbbc298b0b6b9d2646615650b67e0..5bc9eed5606e47d67154f5184b2f77e8ce0fb43f 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.97 2005/03/20 23:40:29 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.98 2005/03/21 01:24:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -180,13 +180,9 @@ extern XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf,
 /* in common/heaptuple.c */
 extern Size heap_compute_data_size(TupleDesc tupleDesc,
 								   Datum *values, bool *isnull);
-extern Size ComputeDataSize(TupleDesc tupleDesc, Datum *values, char *nulls);
 extern void heap_fill_tuple(TupleDesc tupleDesc,
 							Datum *values, bool *isnull,
 							char *data, uint16 *infomask, bits8 *bit);
-extern void DataFill(char *data, TupleDesc tupleDesc,
-		 Datum *values, char *nulls, uint16 *infomask,
-		 bits8 *bit);
 extern bool heap_attisnull(HeapTuple tup, int attnum);
 extern Datum nocachegetattr(HeapTuple tup, int attnum,
 			   TupleDesc att, bool *isnull);
diff --git a/src/include/access/itup.h b/src/include/access/itup.h
index ca54dab8ef03962e8069d21df6c7e5d4aec9e726..68b7d94cf3200d98375ce092e16f88f777f7e640 100644
--- a/src/include/access/itup.h
+++ b/src/include/access/itup.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/itup.h,v 1.41 2004/12/31 22:03:21 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/access/itup.h,v 1.42 2005/03/21 01:24:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,14 +46,6 @@ typedef struct IndexTupleData
 typedef IndexTupleData *IndexTuple;
 
 
-typedef struct InsertIndexResultData
-{
-	ItemPointerData pointerData;
-} InsertIndexResultData;
-
-typedef InsertIndexResultData *InsertIndexResult;
-
-
 /* ----------------
  *		externs
  * ----------------
@@ -73,7 +65,7 @@ typedef InsertIndexResultData *InsertIndexResult;
 
 /*
  * Takes an infomask as argument (primarily because this needs to be usable
- * at index_formtuple time so enough space is allocated).
+ * at index_form_tuple time so enough space is allocated).
  *
  * Change me if adding an attribute to IndexTuples!!!!!!!!!!!
  */
@@ -134,8 +126,8 @@ typedef InsertIndexResultData *InsertIndexResult;
 
 
 /* routines in indextuple.c */
-extern IndexTuple index_formtuple(TupleDesc tupleDescriptor,
-				Datum *value, char *null);
+extern IndexTuple index_form_tuple(TupleDesc tupleDescriptor,
+				Datum *values, bool *isnull);
 extern Datum nocache_index_getattr(IndexTuple tup, int attnum,
 					  TupleDesc tupleDesc, bool *isnull);
 extern IndexTuple CopyIndexTuple(IndexTuple source);
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h
index 7ed91f51ddd1d018bca08e5419958951874e57a7..8486fabcb519e231fc2a43351a98253b08f29ed3 100644
--- a/src/include/access/nbtree.h
+++ b/src/include/access/nbtree.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.83 2004/12/31 22:03:21 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.84 2005/03/21 01:24:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -416,7 +416,7 @@ extern Datum btvacuumcleanup(PG_FUNCTION_ARGS);
 /*
  * prototypes for functions in nbtinsert.c
  */
-extern InsertIndexResult _bt_doinsert(Relation rel, BTItem btitem,
+extern void _bt_doinsert(Relation rel, BTItem btitem,
 			 bool index_is_unique, Relation heapRel);
 extern Buffer _bt_getstackbuf(Relation rel, BTStack stack, int access);
 extern void _bt_insert_parent(Relation rel, Buffer buf, Buffer rbuf,
diff --git a/src/include/access/tuptoaster.h b/src/include/access/tuptoaster.h
index 421b5a00ac7ad33eebde92b7598b58b01635280d..1cf3b4debe64e09e1373dd6a796110c3337a423d 100644
--- a/src/include/access/tuptoaster.h
+++ b/src/include/access/tuptoaster.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.21 2005/01/01 05:43:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.22 2005/03/21 01:24:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -41,7 +41,7 @@
 /*
  * If an index value is larger than TOAST_INDEX_TARGET, we will try to
  * compress it (we can't move it out-of-line, however).  Note that this
- * number is per-datum, not per-tuple, for simplicity in index_formtuple().
+ * number is per-datum, not per-tuple, for simplicity in index_form_tuple().
  */
 #define TOAST_INDEX_TARGET		(MaxTupleSize / 16)
 
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 12924b6dbed740e6c806b3d396dc0a93bd67f8cb..3e72d05c99f4928b2e3c96617dd158f8e8b5287a 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.258 2005/03/16 22:59:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.259 2005/03/21 01:24:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200503161
+#define CATALOG_VERSION_NO	200503201
 
 #endif
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index b7484f4450b2d238d542849d917911d2e5d93cea..cd69d0f2508acea0022bc03cc68b733118dbeff2 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/index.h,v 1.60 2005/03/16 21:38:09 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/index.h,v 1.61 2005/03/21 01:24:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,11 +23,11 @@
 
 /* Typedef for callback function for IndexBuildHeapScan */
 typedef void (*IndexBuildCallback) (Relation index,
-												HeapTuple htup,
-												Datum *attdata,
-												char *nulls,
-												bool tupleIsAlive,
-												void *state);
+									HeapTuple htup,
+									Datum *values,
+									bool *isnull,
+									bool tupleIsAlive,
+									void *state);
 
 
 extern Oid index_create(Oid heapRelationId,
@@ -48,8 +48,8 @@ extern IndexInfo *BuildIndexInfo(Relation index);
 extern void FormIndexDatum(IndexInfo *indexInfo,
 			   TupleTableSlot *slot,
 			   EState *estate,
-			   Datum *datum,
-			   char *nullv);
+			   Datum *values,
+			   bool *isnull);
 
 extern void UpdateStats(Oid relid, double reltuples);
 
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index c2abf30bdec202ea5387bce48e66670557f9e537..c3edcab22b17996d48a5849cdc17c8e6e6307d52 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.352 2005/02/28 03:45:22 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.353 2005/03/21 01:24:04 tgl Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -660,7 +660,7 @@ DESCR("convert int4 to float4");
 DATA(insert OID = 319 (  int4			   PGNSP PGUID 12 f f t f i 1  23 "700" _null_	ftoi4 - _null_ ));
 DESCR("convert float4 to int4");
 
-DATA(insert OID = 320 (  rtinsert		   PGNSP PGUID 12 f f t f v 6 2281 "2281 2281 2281 2281 2281 2281" _null_	rtinsert - _null_ ));
+DATA(insert OID = 320 (  rtinsert		   PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_	rtinsert - _null_ ));
 DESCR("r-tree(internal)");
 DATA(insert OID = 322 (  rtgettuple		   PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_  rtgettuple - _null_ ));
 DESCR("r-tree(internal)");
@@ -683,7 +683,7 @@ DESCR("r-tree(internal)");
 
 DATA(insert OID = 330 (  btgettuple		   PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_  btgettuple - _null_ ));
 DESCR("btree(internal)");
-DATA(insert OID = 331 (  btinsert		   PGNSP PGUID 12 f f t f v 6 2281 "2281 2281 2281 2281 2281 2281" _null_	btinsert - _null_ ));
+DATA(insert OID = 331 (  btinsert		   PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_	btinsert - _null_ ));
 DESCR("btree(internal)");
 DATA(insert OID = 333 (  btbeginscan	   PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_	btbeginscan - _null_ ));
 DESCR("btree(internal)");
@@ -798,7 +798,7 @@ DESCR("convert char(n) to name");
 
 DATA(insert OID = 440 (  hashgettuple	   PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_  hashgettuple - _null_ ));
 DESCR("hash(internal)");
-DATA(insert OID = 441 (  hashinsert		   PGNSP PGUID 12 f f t f v 6 2281 "2281 2281 2281 2281 2281 2281" _null_	hashinsert - _null_ ));
+DATA(insert OID = 441 (  hashinsert		   PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_	hashinsert - _null_ ));
 DESCR("hash(internal)");
 DATA(insert OID = 443 (  hashbeginscan	   PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_	hashbeginscan - _null_ ));
 DESCR("hash(internal)");
@@ -1060,7 +1060,7 @@ DESCR("smaller of two");
 
 DATA(insert OID = 774 (  gistgettuple	   PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_  gistgettuple - _null_ ));
 DESCR("gist(internal)");
-DATA(insert OID = 775 (  gistinsert		   PGNSP PGUID 12 f f t f v 6 2281 "2281 2281 2281 2281 2281 2281" _null_	gistinsert - _null_ ));
+DATA(insert OID = 775 (  gistinsert		   PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_	gistinsert - _null_ ));
 DESCR("gist(internal)");
 DATA(insert OID = 777 (  gistbeginscan	   PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_	gistbeginscan - _null_ ));
 DESCR("gist(internal)");