diff --git a/contrib/Makefile b/contrib/Makefile
index 6967767..04cf330 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -30,7 +30,6 @@ SUBDIRS = \
 		pageinspect	\
 		passwordcheck	\
 		pg_archivecleanup \
-		pg_buffercache	\
 		pg_freespacemap \
 		pg_standby	\
 		pg_stat_statements \
diff --git a/contrib/pg_buffercache/Makefile b/contrib/pg_buffercache/Makefile
deleted file mode 100644
index 323c0ac..0000000
--- a/contrib/pg_buffercache/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# contrib/pg_buffercache/Makefile
-
-MODULE_big = pg_buffercache
-OBJS = pg_buffercache_pages.o
-
-EXTENSION = pg_buffercache
-DATA = pg_buffercache--1.0.sql pg_buffercache--unpackaged--1.0.sql
-
-ifdef USE_PGXS
-PG_CONFIG = pg_config
-PGXS := $(shell $(PG_CONFIG) --pgxs)
-include $(PGXS)
-else
-subdir = contrib/pg_buffercache
-top_builddir = ../..
-include $(top_builddir)/src/Makefile.global
-include $(top_srcdir)/contrib/contrib-global.mk
-endif
diff --git a/contrib/pg_buffercache/pg_buffercache--1.0.sql b/contrib/pg_buffercache/pg_buffercache--1.0.sql
deleted file mode 100644
index 9407d21..0000000
--- a/contrib/pg_buffercache/pg_buffercache--1.0.sql
+++ /dev/null
@@ -1,17 +0,0 @@
-/* contrib/pg_buffercache/pg_buffercache--1.0.sql */
-
--- Register the function.
-CREATE FUNCTION pg_buffercache_pages()
-RETURNS SETOF RECORD
-AS 'MODULE_PATHNAME', 'pg_buffercache_pages'
-LANGUAGE C;
-
--- Create a view for convenient access.
-CREATE VIEW pg_buffercache AS
-	SELECT P.* FROM pg_buffercache_pages() AS P
-	(bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid,
-	 relforknumber int2, relblocknumber int8, isdirty bool, usagecount int2);
-
--- Don't want these to be available to public.
-REVOKE ALL ON FUNCTION pg_buffercache_pages() FROM PUBLIC;
-REVOKE ALL ON pg_buffercache FROM PUBLIC;
diff --git a/contrib/pg_buffercache/pg_buffercache--unpackaged--1.0.sql b/contrib/pg_buffercache/pg_buffercache--unpackaged--1.0.sql
deleted file mode 100644
index f00a954..0000000
--- a/contrib/pg_buffercache/pg_buffercache--unpackaged--1.0.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-/* contrib/pg_buffercache/pg_buffercache--unpackaged--1.0.sql */
-
-ALTER EXTENSION pg_buffercache ADD function pg_buffercache_pages();
-ALTER EXTENSION pg_buffercache ADD view pg_buffercache;
diff --git a/contrib/pg_buffercache/pg_buffercache.control b/contrib/pg_buffercache/pg_buffercache.control
deleted file mode 100644
index 709513c..0000000
--- a/contrib/pg_buffercache/pg_buffercache.control
+++ /dev/null
@@ -1,5 +0,0 @@
-# pg_buffercache extension
-comment = 'examine the shared buffer cache'
-default_version = '1.0'
-module_pathname = '$libdir/pg_buffercache'
-relocatable = true
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
deleted file mode 100644
index ed88288..0000000
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * pg_buffercache_pages.c
- *	  display some contents of the buffer cache
- *
- *	  contrib/pg_buffercache/pg_buffercache_pages.c
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "access/heapam.h"
-#include "catalog/pg_type.h"
-#include "funcapi.h"
-#include "storage/buf_internals.h"
-#include "storage/bufmgr.h"
-#include "utils/relcache.h"
-
-
-#define NUM_BUFFERCACHE_PAGES_ELEM	8
-
-PG_MODULE_MAGIC;
-
-Datum		pg_buffercache_pages(PG_FUNCTION_ARGS);
-
-
-/*
- * Record structure holding the to be exposed cache data.
- */
-typedef struct
-{
-	uint32		bufferid;
-	Oid			relfilenode;
-	Oid			reltablespace;
-	Oid			reldatabase;
-	ForkNumber	forknum;
-	BlockNumber blocknum;
-	bool		isvalid;
-	bool		isdirty;
-	uint16		usagecount;
-} BufferCachePagesRec;
-
-
-/*
- * Function context for data persisting over repeated calls.
- */
-typedef struct
-{
-	TupleDesc	tupdesc;
-	BufferCachePagesRec *record;
-} BufferCachePagesContext;
-
-
-/*
- * Function returning data from the shared buffer cache - buffer number,
- * relation node/tablespace/database/blocknum and dirty indicator.
- */
-PG_FUNCTION_INFO_V1(pg_buffercache_pages);
-
-Datum
-pg_buffercache_pages(PG_FUNCTION_ARGS)
-{
-	FuncCallContext *funcctx;
-	Datum		result;
-	MemoryContext oldcontext;
-	BufferCachePagesContext *fctx;		/* User function context. */
-	TupleDesc	tupledesc;
-	HeapTuple	tuple;
-
-	if (SRF_IS_FIRSTCALL())
-	{
-		int			i;
-		volatile BufferDesc *bufHdr;
-
-		funcctx = SRF_FIRSTCALL_INIT();
-
-		/* Switch context when allocating stuff to be used in later calls */
-		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
-
-		/* Create a user function context for cross-call persistence */
-		fctx = (BufferCachePagesContext *) palloc(sizeof(BufferCachePagesContext));
-
-		/* Construct a tuple descriptor for the result rows. */
-		tupledesc = CreateTemplateTupleDesc(NUM_BUFFERCACHE_PAGES_ELEM, false);
-		TupleDescInitEntry(tupledesc, (AttrNumber) 1, "bufferid",
-						   INT4OID, -1, 0);
-		TupleDescInitEntry(tupledesc, (AttrNumber) 2, "relfilenode",
-						   OIDOID, -1, 0);
-		TupleDescInitEntry(tupledesc, (AttrNumber) 3, "reltablespace",
-						   OIDOID, -1, 0);
-		TupleDescInitEntry(tupledesc, (AttrNumber) 4, "reldatabase",
-						   OIDOID, -1, 0);
-		TupleDescInitEntry(tupledesc, (AttrNumber) 5, "relforknumber",
-						   INT2OID, -1, 0);
-		TupleDescInitEntry(tupledesc, (AttrNumber) 6, "relblocknumber",
-						   INT8OID, -1, 0);
-		TupleDescInitEntry(tupledesc, (AttrNumber) 7, "isdirty",
-						   BOOLOID, -1, 0);
-		TupleDescInitEntry(tupledesc, (AttrNumber) 8, "usage_count",
-						   INT2OID, -1, 0);
-
-		fctx->tupdesc = BlessTupleDesc(tupledesc);
-
-		/* Allocate NBuffers worth of BufferCachePagesRec records. */
-		fctx->record = (BufferCachePagesRec *) palloc(sizeof(BufferCachePagesRec) * NBuffers);
-
-		/* Set max calls and remember the user function context. */
-		funcctx->max_calls = NBuffers;
-		funcctx->user_fctx = fctx;
-
-		/* Return to original context when allocating transient memory */
-		MemoryContextSwitchTo(oldcontext);
-
-		/*
-		 * To get a consistent picture of the buffer state, we must lock all
-		 * partitions of the buffer map.  Needless to say, this is horrible
-		 * for concurrency.  Must grab locks in increasing order to avoid
-		 * possible deadlocks.
-		 */
-		for (i = 0; i < NUM_BUFFER_PARTITIONS; i++)
-			LWLockAcquire(FirstBufMappingLock + i, LW_SHARED);
-
-		/*
-		 * Scan though all the buffers, saving the relevant fields in the
-		 * fctx->record structure.
-		 */
-		for (i = 0, bufHdr = BufferDescriptors; i < NBuffers; i++, bufHdr++)
-		{
-			/* Lock each buffer header before inspecting. */
-			LockBufHdr(bufHdr);
-
-			fctx->record[i].bufferid = BufferDescriptorGetBuffer(bufHdr);
-			fctx->record[i].relfilenode = bufHdr->tag.rnode.relNode;
-			fctx->record[i].reltablespace = bufHdr->tag.rnode.spcNode;
-			fctx->record[i].reldatabase = bufHdr->tag.rnode.dbNode;
-			fctx->record[i].forknum = bufHdr->tag.forkNum;
-			fctx->record[i].blocknum = bufHdr->tag.blockNum;
-			fctx->record[i].usagecount = bufHdr->usage_count;
-
-			if (bufHdr->flags & BM_DIRTY)
-				fctx->record[i].isdirty = true;
-			else
-				fctx->record[i].isdirty = false;
-
-			/* Note if the buffer is valid, and has storage created */
-			if ((bufHdr->flags & BM_VALID) && (bufHdr->flags & BM_TAG_VALID))
-				fctx->record[i].isvalid = true;
-			else
-				fctx->record[i].isvalid = false;
-
-			UnlockBufHdr(bufHdr);
-		}
-
-		/*
-		 * And release locks.  We do this in reverse order for two reasons:
-		 * (1) Anyone else who needs more than one of the locks will be trying
-		 * to lock them in increasing order; we don't want to release the
-		 * other process until it can get all the locks it needs. (2) This
-		 * avoids O(N^2) behavior inside LWLockRelease.
-		 */
-		for (i = NUM_BUFFER_PARTITIONS; --i >= 0;)
-			LWLockRelease(FirstBufMappingLock + i);
-	}
-
-	funcctx = SRF_PERCALL_SETUP();
-
-	/* Get the saved state */
-	fctx = funcctx->user_fctx;
-
-	if (funcctx->call_cntr < funcctx->max_calls)
-	{
-		uint32		i = funcctx->call_cntr;
-		Datum		values[NUM_BUFFERCACHE_PAGES_ELEM];
-		bool		nulls[NUM_BUFFERCACHE_PAGES_ELEM];
-
-		values[0] = Int32GetDatum(fctx->record[i].bufferid);
-		nulls[0] = false;
-
-		/*
-		 * Set all fields except the bufferid to null if the buffer is unused
-		 * or not valid.
-		 */
-		if (fctx->record[i].blocknum == InvalidBlockNumber ||
-			fctx->record[i].isvalid == false)
-		{
-			nulls[1] = true;
-			nulls[2] = true;
-			nulls[3] = true;
-			nulls[4] = true;
-			nulls[5] = true;
-			nulls[6] = true;
-			nulls[7] = true;
-		}
-		else
-		{
-			values[1] = ObjectIdGetDatum(fctx->record[i].relfilenode);
-			nulls[1] = false;
-			values[2] = ObjectIdGetDatum(fctx->record[i].reltablespace);
-			nulls[2] = false;
-			values[3] = ObjectIdGetDatum(fctx->record[i].reldatabase);
-			nulls[3] = false;
-			values[4] = ObjectIdGetDatum(fctx->record[i].forknum);
-			nulls[4] = false;
-			values[5] = Int64GetDatum((int64) fctx->record[i].blocknum);
-			nulls[5] = false;
-			values[6] = BoolGetDatum(fctx->record[i].isdirty);
-			nulls[6] = false;
-			values[7] = Int16GetDatum(fctx->record[i].usagecount);
-			nulls[7] = false;
-		}
-
-		/* Build and return the tuple. */
-		tuple = heap_form_tuple(fctx->tupdesc, values, nulls);
-		result = HeapTupleGetDatum(tuple);
-
-		SRF_RETURN_NEXT(funcctx, result);
-	}
-	else
-		SRF_RETURN_DONE(funcctx);
-}
diff --git a/src/extension/Makefile b/src/extension/Makefile
new file mode 100644
index 0000000..5d7a86a
--- /dev/null
+++ b/src/extension/Makefile
@@ -0,0 +1,36 @@
+# $PostgreSQL: pgsql/src/extension/Makefile $
+
+subdir = src/extension
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+
+SUBDIRS = \
+		pg_buffercache
+
+ifeq ($(with_openssl),yes)
+SUBDIRS += sslinfo
+endif
+
+ifeq ($(with_ossp_uuid),yes)
+SUBDIRS += uuid-ossp
+endif
+
+ifeq ($(with_libxml),yes)
+SUBDIRS += xml2
+endif
+
+# Missing:
+#		start-scripts	\ (does not have a makefile)
+
+
+all install installdirs uninstall distprep clean distclean maintainer-clean:
+	@for dir in $(SUBDIRS); do \
+		$(MAKE) -C $$dir $@ || exit; \
+	done
+
+# We'd like check operations to run all the subtests before failing.
+check installcheck:
+	@CHECKERR=0; for dir in $(SUBDIRS); do \
+		$(MAKE) -C $$dir $@ || CHECKERR=$$?; \
+	done; \
+	exit $$CHECKERR
diff --git a/src/extension/extension-global.mk b/src/extension/extension-global.mk
new file mode 100644
index 0000000..cc7643b
--- /dev/null
+++ b/src/extension/extension-global.mk
@@ -0,0 +1,5 @@
+# $PostgreSQL: pgsql/extension/extension-global.mk,v 1.10 2005/09/27 17:43:31 tgl Exp $
+
+NO_PGXS = 1
+MODULEDIR=extension
+include $(top_srcdir)/src/makefiles/pgxs.mk
diff --git a/src/extension/pg_buffercache/Makefile b/src/extension/pg_buffercache/Makefile
new file mode 100644
index 0000000..70d857f
--- /dev/null
+++ b/src/extension/pg_buffercache/Makefile
@@ -0,0 +1,19 @@
+# src/extension/pg_buffercache/Makefile
+
+MODULE_big = pg_buffercache
+OBJS = pg_buffercache_pages.o
+MODULEDIR=extension
+
+EXTENSION = pg_buffercache
+DATA = pg_buffercache--1.0.sql pg_buffercache--unpackaged--1.0.sql
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/extension/pg_buffercache
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/src/extension/extension-global.mk
+endif
diff --git a/src/extension/pg_buffercache/pg_buffercache--1.0.sql b/src/extension/pg_buffercache/pg_buffercache--1.0.sql
new file mode 100644
index 0000000..ceca6ae
--- /dev/null
+++ b/src/extension/pg_buffercache/pg_buffercache--1.0.sql
@@ -0,0 +1,17 @@
+/* src/extension/pg_buffercache/pg_buffercache--1.0.sql */
+
+-- Register the function.
+CREATE FUNCTION pg_buffercache_pages()
+RETURNS SETOF RECORD
+AS 'MODULE_PATHNAME', 'pg_buffercache_pages'
+LANGUAGE C;
+
+-- Create a view for convenient access.
+CREATE VIEW pg_buffercache AS
+	SELECT P.* FROM pg_buffercache_pages() AS P
+	(bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid,
+	 relforknumber int2, relblocknumber int8, isdirty bool, usagecount int2);
+
+-- Don't want these to be available to public.
+REVOKE ALL ON FUNCTION pg_buffercache_pages() FROM PUBLIC;
+REVOKE ALL ON pg_buffercache FROM PUBLIC;
diff --git a/src/extension/pg_buffercache/pg_buffercache--unpackaged--1.0.sql b/src/extension/pg_buffercache/pg_buffercache--unpackaged--1.0.sql
new file mode 100644
index 0000000..0cfa317
--- /dev/null
+++ b/src/extension/pg_buffercache/pg_buffercache--unpackaged--1.0.sql
@@ -0,0 +1,4 @@
+/* src/extension/pg_buffercache/pg_buffercache--unpackaged--1.0.sql */
+
+ALTER EXTENSION pg_buffercache ADD function pg_buffercache_pages();
+ALTER EXTENSION pg_buffercache ADD view pg_buffercache;
diff --git a/src/extension/pg_buffercache/pg_buffercache.control b/src/extension/pg_buffercache/pg_buffercache.control
new file mode 100644
index 0000000..709513c
--- /dev/null
+++ b/src/extension/pg_buffercache/pg_buffercache.control
@@ -0,0 +1,5 @@
+# pg_buffercache extension
+comment = 'examine the shared buffer cache'
+default_version = '1.0'
+module_pathname = '$libdir/pg_buffercache'
+relocatable = true
diff --git a/src/extension/pg_buffercache/pg_buffercache_pages.c b/src/extension/pg_buffercache/pg_buffercache_pages.c
new file mode 100644
index 0000000..a44610f
--- /dev/null
+++ b/src/extension/pg_buffercache/pg_buffercache_pages.c
@@ -0,0 +1,219 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_buffercache_pages.c
+ *	  display some contents of the buffer cache
+ *
+ *	  src/extension/pg_buffercache/pg_buffercache_pages.c
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/pg_type.h"
+#include "funcapi.h"
+#include "storage/buf_internals.h"
+#include "storage/bufmgr.h"
+#include "utils/relcache.h"
+
+
+#define NUM_BUFFERCACHE_PAGES_ELEM	8
+
+PG_MODULE_MAGIC;
+
+Datum		pg_buffercache_pages(PG_FUNCTION_ARGS);
+
+
+/*
+ * Record structure holding the to be exposed cache data.
+ */
+typedef struct
+{
+	uint32		bufferid;
+	Oid			relfilenode;
+	Oid			reltablespace;
+	Oid			reldatabase;
+	ForkNumber	forknum;
+	BlockNumber blocknum;
+	bool		isvalid;
+	bool		isdirty;
+	uint16		usagecount;
+} BufferCachePagesRec;
+
+
+/*
+ * Function context for data persisting over repeated calls.
+ */
+typedef struct
+{
+	TupleDesc	tupdesc;
+	BufferCachePagesRec *record;
+} BufferCachePagesContext;
+
+
+/*
+ * Function returning data from the shared buffer cache - buffer number,
+ * relation node/tablespace/database/blocknum and dirty indicator.
+ */
+PG_FUNCTION_INFO_V1(pg_buffercache_pages);
+
+Datum
+pg_buffercache_pages(PG_FUNCTION_ARGS)
+{
+	FuncCallContext *funcctx;
+	Datum		result;
+	MemoryContext oldcontext;
+	BufferCachePagesContext *fctx;		/* User function context. */
+	TupleDesc	tupledesc;
+	HeapTuple	tuple;
+
+	if (SRF_IS_FIRSTCALL())
+	{
+		int			i;
+		volatile BufferDesc *bufHdr;
+
+		funcctx = SRF_FIRSTCALL_INIT();
+
+		/* Switch context when allocating stuff to be used in later calls */
+		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+		/* Create a user function context for cross-call persistence */
+		fctx = (BufferCachePagesContext *) palloc(sizeof(BufferCachePagesContext));
+
+		/* Construct a tuple descriptor for the result rows. */
+		tupledesc = CreateTemplateTupleDesc(NUM_BUFFERCACHE_PAGES_ELEM, false);
+		TupleDescInitEntry(tupledesc, (AttrNumber) 1, "bufferid",
+						   INT4OID, -1, 0);
+		TupleDescInitEntry(tupledesc, (AttrNumber) 2, "relfilenode",
+						   OIDOID, -1, 0);
+		TupleDescInitEntry(tupledesc, (AttrNumber) 3, "reltablespace",
+						   OIDOID, -1, 0);
+		TupleDescInitEntry(tupledesc, (AttrNumber) 4, "reldatabase",
+						   OIDOID, -1, 0);
+		TupleDescInitEntry(tupledesc, (AttrNumber) 5, "relforknumber",
+						   INT2OID, -1, 0);
+		TupleDescInitEntry(tupledesc, (AttrNumber) 6, "relblocknumber",
+						   INT8OID, -1, 0);
+		TupleDescInitEntry(tupledesc, (AttrNumber) 7, "isdirty",
+						   BOOLOID, -1, 0);
+		TupleDescInitEntry(tupledesc, (AttrNumber) 8, "usage_count",
+						   INT2OID, -1, 0);
+
+		fctx->tupdesc = BlessTupleDesc(tupledesc);
+
+		/* Allocate NBuffers worth of BufferCachePagesRec records. */
+		fctx->record = (BufferCachePagesRec *) palloc(sizeof(BufferCachePagesRec) * NBuffers);
+
+		/* Set max calls and remember the user function context. */
+		funcctx->max_calls = NBuffers;
+		funcctx->user_fctx = fctx;
+
+		/* Return to original context when allocating transient memory */
+		MemoryContextSwitchTo(oldcontext);
+
+		/*
+		 * To get a consistent picture of the buffer state, we must lock all
+		 * partitions of the buffer map.  Needless to say, this is horrible
+		 * for concurrency.  Must grab locks in increasing order to avoid
+		 * possible deadlocks.
+		 */
+		for (i = 0; i < NUM_BUFFER_PARTITIONS; i++)
+			LWLockAcquire(FirstBufMappingLock + i, LW_SHARED);
+
+		/*
+		 * Scan though all the buffers, saving the relevant fields in the
+		 * fctx->record structure.
+		 */
+		for (i = 0, bufHdr = BufferDescriptors; i < NBuffers; i++, bufHdr++)
+		{
+			/* Lock each buffer header before inspecting. */
+			LockBufHdr(bufHdr);
+
+			fctx->record[i].bufferid = BufferDescriptorGetBuffer(bufHdr);
+			fctx->record[i].relfilenode = bufHdr->tag.rnode.relNode;
+			fctx->record[i].reltablespace = bufHdr->tag.rnode.spcNode;
+			fctx->record[i].reldatabase = bufHdr->tag.rnode.dbNode;
+			fctx->record[i].forknum = bufHdr->tag.forkNum;
+			fctx->record[i].blocknum = bufHdr->tag.blockNum;
+			fctx->record[i].usagecount = bufHdr->usage_count;
+
+			if (bufHdr->flags & BM_DIRTY)
+				fctx->record[i].isdirty = true;
+			else
+				fctx->record[i].isdirty = false;
+
+			/* Note if the buffer is valid, and has storage created */
+			if ((bufHdr->flags & BM_VALID) && (bufHdr->flags & BM_TAG_VALID))
+				fctx->record[i].isvalid = true;
+			else
+				fctx->record[i].isvalid = false;
+
+			UnlockBufHdr(bufHdr);
+		}
+
+		/*
+		 * And release locks.  We do this in reverse order for two reasons:
+		 * (1) Anyone else who needs more than one of the locks will be trying
+		 * to lock them in increasing order; we don't want to release the
+		 * other process until it can get all the locks it needs. (2) This
+		 * avoids O(N^2) behavior inside LWLockRelease.
+		 */
+		for (i = NUM_BUFFER_PARTITIONS; --i >= 0;)
+			LWLockRelease(FirstBufMappingLock + i);
+	}
+
+	funcctx = SRF_PERCALL_SETUP();
+
+	/* Get the saved state */
+	fctx = funcctx->user_fctx;
+
+	if (funcctx->call_cntr < funcctx->max_calls)
+	{
+		uint32		i = funcctx->call_cntr;
+		Datum		values[NUM_BUFFERCACHE_PAGES_ELEM];
+		bool		nulls[NUM_BUFFERCACHE_PAGES_ELEM];
+
+		values[0] = Int32GetDatum(fctx->record[i].bufferid);
+		nulls[0] = false;
+
+		/*
+		 * Set all fields except the bufferid to null if the buffer is unused
+		 * or not valid.
+		 */
+		if (fctx->record[i].blocknum == InvalidBlockNumber ||
+			fctx->record[i].isvalid == false)
+		{
+			nulls[1] = true;
+			nulls[2] = true;
+			nulls[3] = true;
+			nulls[4] = true;
+			nulls[5] = true;
+			nulls[6] = true;
+			nulls[7] = true;
+		}
+		else
+		{
+			values[1] = ObjectIdGetDatum(fctx->record[i].relfilenode);
+			nulls[1] = false;
+			values[2] = ObjectIdGetDatum(fctx->record[i].reltablespace);
+			nulls[2] = false;
+			values[3] = ObjectIdGetDatum(fctx->record[i].reldatabase);
+			nulls[3] = false;
+			values[4] = ObjectIdGetDatum(fctx->record[i].forknum);
+			nulls[4] = false;
+			values[5] = Int64GetDatum((int64) fctx->record[i].blocknum);
+			nulls[5] = false;
+			values[6] = BoolGetDatum(fctx->record[i].isdirty);
+			nulls[6] = false;
+			values[7] = Int16GetDatum(fctx->record[i].usagecount);
+			nulls[7] = false;
+		}
+
+		/* Build and return the tuple. */
+		tuple = heap_form_tuple(fctx->tupdesc, values, nulls);
+		result = HeapTupleGetDatum(tuple);
+
+		SRF_RETURN_NEXT(funcctx, result);
+	}
+	else
+		SRF_RETURN_DONE(funcctx);
+}
