diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index 2f95f718e0bf17e3ba9819f4621de6ce19df0041..61d588c52bdb96917dde2daf53333c2528c2bf43 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -15,6 +15,7 @@
 #include "postgres.h"
 
 #include "access/gin_private.h"
+#include "access/heapam_xlog.h"
 #include "catalog/index.h"
 #include "miscadmin.h"
 #include "storage/bufmgr.h"
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index f28026be0fb68f0059f1b1778fa80757a32e915d..f56b5774eec9e5d5c090dc5e39debffd1721fc26 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -41,6 +41,7 @@
 #include "postgres.h"
 
 #include "access/heapam.h"
+#include "access/heapam_xlog.h"
 #include "access/hio.h"
 #include "access/multixact.h"
 #include "access/relscan.h"
diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index a89ef077ce8acbcd4b08bd5743ece5adaa5323f2..e0209c9aeaff08cc3bc6f96a82cf0d741ee69b0d 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -15,6 +15,7 @@
 #include "postgres.h"
 
 #include "access/heapam.h"
+#include "access/heapam_xlog.h"
 #include "access/transam.h"
 #include "miscadmin.h"
 #include "pgstat.h"
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 9a8f05d933168f919f968df1ebde25d2c23b819b..0f67a807be21ceaf962533106b5384331e280481 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -103,6 +103,7 @@
 #include "postgres.h"
 
 #include "access/heapam.h"
+#include "access/heapam_xlog.h"
 #include "access/rewriteheap.h"
 #include "access/transam.h"
 #include "access/tuptoaster.h"
diff --git a/src/backend/access/heap/visibilitymap.c b/src/backend/access/heap/visibilitymap.c
index eb5625906f12904b3248b9b0364998f03a625318..d7a291640e976c2dd830ef0f6b3bb26235a432c1 100644
--- a/src/backend/access/heap/visibilitymap.c
+++ b/src/backend/access/heap/visibilitymap.c
@@ -82,7 +82,7 @@
  */
 #include "postgres.h"
 
-#include "access/heapam.h"
+#include "access/heapam_xlog.h"
 #include "access/visibilitymap.h"
 #include "miscadmin.h"
 #include "storage/bufmgr.h"
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index 26fd9b6e11438eb67b1cb234a9cb2ebbb540cc97..0da1a5a867daedbc27bac4aea9e24c5e46c93cc3 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -22,6 +22,7 @@
 #include "access/relscan.h"
 #include "access/transam.h"
 #include "catalog/index.h"
+#include "lib/stringinfo.h"
 #include "miscadmin.h"
 #include "storage/bufmgr.h"
 #include "utils/builtins.h"
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 41d06edb15487130104a19457b96dacd7ccc0331..0fd595a2d4ebefb541dc35b00bcb3cae7e510e31 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -18,6 +18,7 @@
  */
 #include "postgres.h"
 
+#include "access/heapam_xlog.h"
 #include "access/nbtree.h"
 #include "access/relscan.h"
 #include "catalog/index.h"
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index 9aa3a135b576b4e761b213035ef158792f1dff6e..cf73b616aea88d8f7b08c9ec5cf87d8117354109 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -66,6 +66,7 @@
 
 #include "postgres.h"
 
+#include "access/heapam_xlog.h"
 #include "access/nbtree.h"
 #include "miscadmin.h"
 #include "storage/smgr.h"
diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c
index 55d7f96c857dc60934366f0d03dde3ebf196320c..72ea1719e7d2c3ca230c8f755261b9a439ec2a99 100644
--- a/src/backend/access/nbtree/nbtxlog.c
+++ b/src/backend/access/nbtree/nbtxlog.c
@@ -14,6 +14,7 @@
  */
 #include "postgres.h"
 
+#include "access/heapam_xlog.h"
 #include "access/nbtree.h"
 #include "access/transam.h"
 #include "storage/procarray.h"
diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c
index 456a71fbba5dabb557510167baaccccea4fa6c9b..d2893c6f3a9817654f99cc09871a80acef609498 100644
--- a/src/backend/access/spgist/spginsert.c
+++ b/src/backend/access/spgist/spginsert.c
@@ -17,6 +17,7 @@
 #include "postgres.h"
 
 #include "access/genam.h"
+#include "access/heapam_xlog.h"
 #include "access/spgist_private.h"
 #include "catalog/index.h"
 #include "miscadmin.h"
diff --git a/src/backend/access/transam/rmgr.c b/src/backend/access/transam/rmgr.c
index ed8754e6f226bf37d7c53804d42cae4a1b2744f3..aafd73fbd5bcfc4a0e90412f4fdb862fdca21ca2 100644
--- a/src/backend/access/transam/rmgr.c
+++ b/src/backend/access/transam/rmgr.c
@@ -11,7 +11,7 @@
 #include "access/gin.h"
 #include "access/gist_private.h"
 #include "access/hash.h"
-#include "access/heapam.h"
+#include "access/heapam_xlog.h"
 #include "access/multixact.h"
 #include "access/nbtree.h"
 #include "access/spgist.h"
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 00fe1138b2e5f6e0158eee3128355bdb14ace868..0d3a74ea3720eb38f644515e98535732f248c40d 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -15,7 +15,7 @@
 #include "postgres.h"
 
 #include "access/genam.h"
-#include "access/heapam.h"
+#include "access/heapam_xlog.h"
 #include "access/reloptions.h"
 #include "access/relscan.h"
 #include "access/sysattr.h"
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index 5e902211649e2d0526664470054e015557098dab..703b476bdfd5cf5688f69e92e62a3b772c91baf7 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -39,6 +39,7 @@
 
 #include "access/genam.h"
 #include "access/heapam.h"
+#include "access/heapam_xlog.h"
 #include "access/transam.h"
 #include "access/visibilitymap.h"
 #include "catalog/storage.h"
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 4b8746f4f2611d84f80a97178c677002f5710f63..474758140b62e7566c9f22ed4d64cc0686fee295 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -18,6 +18,7 @@
  */
 #include "postgres.h"
 
+#include <limits.h>
 #include <math.h>
 
 #include "executor/executor.h"
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index f27b55a66e4b7aab3ce264ceb0701ba16f8aaaad..6f9f77cc11f5e238b481866484ee2009507b20af 100644
--- a/src/backend/foreign/foreign.c
+++ b/src/backend/foreign/foreign.c
@@ -19,6 +19,7 @@
 #include "catalog/pg_user_mapping.h"
 #include "foreign/fdwapi.h"
 #include "foreign/foreign.h"
+#include "lib/stringinfo.h"
 #include "miscadmin.h"
 #include "utils/builtins.h"
 #include "utils/syscache.h"
diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c
index 8a5e59526d24ac8110156e98c3994878ae4d920d..379999cc3ad6510fe699dabe866409d1a2bdfd0b 100644
--- a/src/backend/nodes/print.c
+++ b/src/backend/nodes/print.c
@@ -20,6 +20,7 @@
 #include "postgres.h"
 
 #include "access/printtup.h"
+#include "lib/stringinfo.h"
 #include "nodes/print.h"
 #include "optimizer/clauses.h"
 #include "parser/parsetree.h"
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 9e8d942f6f35a60eea13e23bbcd8cf6899a5901e..2e50cb7548c4052bdaf065f22ba63bff1b4313b8 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -28,6 +28,7 @@
  */
 #include "postgres.h"
 
+#include <limits.h>
 
 #include "access/heapam.h"
 #include "access/sysattr.h"
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 1818a2a8718cf6fa3e32ad9397e436bcef788cbc..71e1e73b0c6eb30e215156b4348382ae3a0afcc5 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -21,6 +21,7 @@
 #include "access/heapam.h"
 #include "access/sysattr.h"
 #include "access/transam.h"
+#include "access/xlog.h"
 #include "catalog/catalog.h"
 #include "catalog/heap.h"
 #include "miscadmin.h"
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index b051707d7e1b0ccd98542c3d1fb1e08fc29ff128..2b1a13a693ef6f65d4a37e2abe8bb14091bfc07f 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -17,6 +17,7 @@
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "funcapi.h"
+#include "lib/stringinfo.h"
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
 #include "parser/parse_agg.h"
diff --git a/src/backend/utils/adt/domains.c b/src/backend/utils/adt/domains.c
index 591d9922e9207f2f29b01f7aa1c85557e8e5a764..8b51ccf0673632bed4e2c9e601852f1c782ff7af 100644
--- a/src/backend/utils/adt/domains.c
+++ b/src/backend/utils/adt/domains.c
@@ -33,6 +33,7 @@
 
 #include "commands/typecmds.h"
 #include "executor/executor.h"
+#include "lib/stringinfo.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 58dc985b2cf5ff0cdce43535fb5addd1b13bf76e..11b3f571935f8778b4177228e500de7df5094ad7 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -31,6 +31,7 @@
 #include "catalog/pg_ts_config.h"
 #include "catalog/pg_ts_dict.h"
 #include "catalog/pg_type.h"
+#include "lib/stringinfo.h"
 #include "miscadmin.h"
 #include "parser/parse_type.h"
 #include "utils/builtins.h"
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 660a854b0e6439648ccad90c165a8926bc1bf279..2d73ae8fb881b4eeded5c420f974f98df651a2b7 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -16,7 +16,6 @@
 
 #include "access/sdir.h"
 #include "access/skey.h"
-#include "access/xlog.h"
 #include "nodes/primnodes.h"
 #include "storage/lock.h"
 #include "utils/relcache.h"
@@ -125,27 +124,6 @@ extern void heap_restrpos(HeapScanDesc scan);
 
 extern void heap_sync(Relation relation);
 
-extern void heap_redo(XLogRecPtr lsn, XLogRecord *rptr);
-extern void heap_desc(StringInfo buf, uint8 xl_info, char *rec);
-extern void heap2_redo(XLogRecPtr lsn, XLogRecord *rptr);
-extern void heap2_desc(StringInfo buf, uint8 xl_info, char *rec);
-
-extern XLogRecPtr log_heap_cleanup_info(RelFileNode rnode,
-					  TransactionId latestRemovedXid);
-extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
-			   OffsetNumber *redirected, int nredirected,
-			   OffsetNumber *nowdead, int ndead,
-			   OffsetNumber *nowunused, int nunused,
-			   TransactionId latestRemovedXid);
-extern XLogRecPtr log_heap_freeze(Relation reln, Buffer buffer,
-				TransactionId cutoff_xid,
-				OffsetNumber *offsets, int offcnt);
-extern XLogRecPtr log_heap_visible(RelFileNode rnode, BlockNumber block,
-				 Buffer vm_buffer, TransactionId cutoff_xid);
-extern XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum,
-			BlockNumber blk, Page page);
-extern XLogRecPtr log_newpage_buffer(Buffer buffer);
-
 /* in heap/pruneheap.c */
 extern void heap_page_prune_opt(Relation relation, Buffer buffer,
 					TransactionId OldestXmin);
diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h
new file mode 100644
index 0000000000000000000000000000000000000000..4ccea5ce4e896c248cc7bd56a2afe30b483684df
--- /dev/null
+++ b/src/include/access/heapam_xlog.h
@@ -0,0 +1,264 @@
+/*-------------------------------------------------------------------------
+ *
+ * heapam_xlog.h
+ *	  POSTGRES heap access XLOG definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/heapam_xlog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HEAPAM_XLOG_H
+#define HEAPAM_XLOG_H
+
+#include "access/htup.h"
+#include "access/xlog.h"
+#include "storage/relfilenode.h"
+#include "utils/relcache.h"
+
+
+/*
+ * WAL record definitions for heapam.c's WAL operations
+ *
+ * XLOG allows to store some information in high 4 bits of log
+ * record xl_info field.  We use 3 for opcode and one for init bit.
+ */
+#define XLOG_HEAP_INSERT		0x00
+#define XLOG_HEAP_DELETE		0x10
+#define XLOG_HEAP_UPDATE		0x20
+/* 0x030 is free, was XLOG_HEAP_MOVE */
+#define XLOG_HEAP_HOT_UPDATE	0x40
+#define XLOG_HEAP_NEWPAGE		0x50
+#define XLOG_HEAP_LOCK			0x60
+#define XLOG_HEAP_INPLACE		0x70
+
+#define XLOG_HEAP_OPMASK		0x70
+/*
+ * When we insert 1st item on new page in INSERT, UPDATE, HOT_UPDATE,
+ * or MULTI_INSERT, we can (and we do) restore entire page in redo
+ */
+#define XLOG_HEAP_INIT_PAGE		0x80
+/*
+ * We ran out of opcodes, so heapam.c now has a second RmgrId.	These opcodes
+ * are associated with RM_HEAP2_ID, but are not logically different from
+ * the ones above associated with RM_HEAP_ID.  XLOG_HEAP_OPMASK applies to
+ * these, too.
+ */
+#define XLOG_HEAP2_FREEZE		0x00
+#define XLOG_HEAP2_CLEAN		0x10
+/* 0x20 is free, was XLOG_HEAP2_CLEAN_MOVE */
+#define XLOG_HEAP2_CLEANUP_INFO 0x30
+#define XLOG_HEAP2_VISIBLE		0x40
+#define XLOG_HEAP2_MULTI_INSERT 0x50
+
+/*
+ * All what we need to find changed tuple
+ *
+ * NB: on most machines, sizeof(xl_heaptid) will include some trailing pad
+ * bytes for alignment.  We don't want to store the pad space in the XLOG,
+ * so use SizeOfHeapTid for space calculations.  Similar comments apply for
+ * the other xl_FOO structs.
+ */
+typedef struct xl_heaptid
+{
+	RelFileNode node;
+	ItemPointerData tid;		/* changed tuple id */
+} xl_heaptid;
+
+#define SizeOfHeapTid		(offsetof(xl_heaptid, tid) + SizeOfIptrData)
+
+/* This is what we need to know about delete */
+typedef struct xl_heap_delete
+{
+	xl_heaptid	target;			/* deleted tuple id */
+	bool		all_visible_cleared;	/* PD_ALL_VISIBLE was cleared */
+} xl_heap_delete;
+
+#define SizeOfHeapDelete	(offsetof(xl_heap_delete, all_visible_cleared) + sizeof(bool))
+
+/*
+ * We don't store the whole fixed part (HeapTupleHeaderData) of an inserted
+ * or updated tuple in WAL; we can save a few bytes by reconstructing the
+ * fields that are available elsewhere in the WAL record, or perhaps just
+ * plain needn't be reconstructed.  These are the fields we must store.
+ * NOTE: t_hoff could be recomputed, but we may as well store it because
+ * it will come for free due to alignment considerations.
+ */
+typedef struct xl_heap_header
+{
+	uint16		t_infomask2;
+	uint16		t_infomask;
+	uint8		t_hoff;
+} xl_heap_header;
+
+#define SizeOfHeapHeader	(offsetof(xl_heap_header, t_hoff) + sizeof(uint8))
+
+/* This is what we need to know about insert */
+typedef struct xl_heap_insert
+{
+	xl_heaptid	target;			/* inserted tuple id */
+	bool		all_visible_cleared;	/* PD_ALL_VISIBLE was cleared */
+	/* xl_heap_header & TUPLE DATA FOLLOWS AT END OF STRUCT */
+} xl_heap_insert;
+
+#define SizeOfHeapInsert	(offsetof(xl_heap_insert, all_visible_cleared) + sizeof(bool))
+
+/*
+ * This is what we need to know about a multi-insert. The record consists of
+ * xl_heap_multi_insert header, followed by a xl_multi_insert_tuple and tuple
+ * data for each tuple. 'offsets' array is omitted if the whole page is
+ * reinitialized (XLOG_HEAP_INIT_PAGE)
+ */
+typedef struct xl_heap_multi_insert
+{
+	RelFileNode node;
+	BlockNumber blkno;
+	bool		all_visible_cleared;
+	uint16		ntuples;
+	OffsetNumber offsets[1];
+
+	/* TUPLE DATA (xl_multi_insert_tuples) FOLLOW AT END OF STRUCT */
+} xl_heap_multi_insert;
+
+#define SizeOfHeapMultiInsert	offsetof(xl_heap_multi_insert, offsets)
+
+typedef struct xl_multi_insert_tuple
+{
+	uint16		datalen;		/* size of tuple data that follows */
+	uint16		t_infomask2;
+	uint16		t_infomask;
+	uint8		t_hoff;
+	/* TUPLE DATA FOLLOWS AT END OF STRUCT */
+} xl_multi_insert_tuple;
+
+#define SizeOfMultiInsertTuple	(offsetof(xl_multi_insert_tuple, t_hoff) + sizeof(uint8))
+
+/* This is what we need to know about update|hot_update */
+typedef struct xl_heap_update
+{
+	xl_heaptid	target;			/* deleted tuple id */
+	ItemPointerData newtid;		/* new inserted tuple id */
+	bool		all_visible_cleared;	/* PD_ALL_VISIBLE was cleared */
+	bool		new_all_visible_cleared;		/* same for the page of newtid */
+	/* NEW TUPLE xl_heap_header AND TUPLE DATA FOLLOWS AT END OF STRUCT */
+} xl_heap_update;
+
+#define SizeOfHeapUpdate	(offsetof(xl_heap_update, new_all_visible_cleared) + sizeof(bool))
+
+/*
+ * This is what we need to know about vacuum page cleanup/redirect
+ *
+ * The array of OffsetNumbers following the fixed part of the record contains:
+ *	* for each redirected item: the item offset, then the offset redirected to
+ *	* for each now-dead item: the item offset
+ *	* for each now-unused item: the item offset
+ * The total number of OffsetNumbers is therefore 2*nredirected+ndead+nunused.
+ * Note that nunused is not explicitly stored, but may be found by reference
+ * to the total record length.
+ */
+typedef struct xl_heap_clean
+{
+	RelFileNode node;
+	BlockNumber block;
+	TransactionId latestRemovedXid;
+	uint16		nredirected;
+	uint16		ndead;
+	/* OFFSET NUMBERS FOLLOW */
+} xl_heap_clean;
+
+#define SizeOfHeapClean (offsetof(xl_heap_clean, ndead) + sizeof(uint16))
+
+/*
+ * Cleanup_info is required in some cases during a lazy VACUUM.
+ * Used for reporting the results of HeapTupleHeaderAdvanceLatestRemovedXid()
+ * see vacuumlazy.c for full explanation
+ */
+typedef struct xl_heap_cleanup_info
+{
+	RelFileNode node;
+	TransactionId latestRemovedXid;
+} xl_heap_cleanup_info;
+
+#define SizeOfHeapCleanupInfo (sizeof(xl_heap_cleanup_info))
+
+/* This is for replacing a page's contents in toto */
+/* NB: this is used for indexes as well as heaps */
+typedef struct xl_heap_newpage
+{
+	RelFileNode node;
+	ForkNumber	forknum;
+	BlockNumber blkno;			/* location of new page */
+	/* entire page contents follow at end of record */
+} xl_heap_newpage;
+
+#define SizeOfHeapNewpage	(offsetof(xl_heap_newpage, blkno) + sizeof(BlockNumber))
+
+/* This is what we need to know about lock */
+typedef struct xl_heap_lock
+{
+	xl_heaptid	target;			/* locked tuple id */
+	TransactionId locking_xid;	/* might be a MultiXactId not xid */
+	bool		xid_is_mxact;	/* is it? */
+	bool		shared_lock;	/* shared or exclusive row lock? */
+} xl_heap_lock;
+
+#define SizeOfHeapLock	(offsetof(xl_heap_lock, shared_lock) + sizeof(bool))
+
+/* This is what we need to know about in-place update */
+typedef struct xl_heap_inplace
+{
+	xl_heaptid	target;			/* updated tuple id */
+	/* TUPLE DATA FOLLOWS AT END OF STRUCT */
+} xl_heap_inplace;
+
+#define SizeOfHeapInplace	(offsetof(xl_heap_inplace, target) + SizeOfHeapTid)
+
+/* This is what we need to know about tuple freezing during vacuum */
+typedef struct xl_heap_freeze
+{
+	RelFileNode node;
+	BlockNumber block;
+	TransactionId cutoff_xid;
+	/* TUPLE OFFSET NUMBERS FOLLOW AT THE END */
+} xl_heap_freeze;
+
+#define SizeOfHeapFreeze (offsetof(xl_heap_freeze, cutoff_xid) + sizeof(TransactionId))
+
+/* This is what we need to know about setting a visibility map bit */
+typedef struct xl_heap_visible
+{
+	RelFileNode node;
+	BlockNumber block;
+	TransactionId cutoff_xid;
+} xl_heap_visible;
+
+#define SizeOfHeapVisible (offsetof(xl_heap_visible, cutoff_xid) + sizeof(TransactionId))
+
+extern void HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple,
+									   TransactionId *latestRemovedXid);
+
+extern void heap_redo(XLogRecPtr lsn, XLogRecord *rptr);
+extern void heap_desc(StringInfo buf, uint8 xl_info, char *rec);
+extern void heap2_redo(XLogRecPtr lsn, XLogRecord *rptr);
+extern void heap2_desc(StringInfo buf, uint8 xl_info, char *rec);
+
+extern XLogRecPtr log_heap_cleanup_info(RelFileNode rnode,
+					  TransactionId latestRemovedXid);
+extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
+			   OffsetNumber *redirected, int nredirected,
+			   OffsetNumber *nowdead, int ndead,
+			   OffsetNumber *nowunused, int nunused,
+			   TransactionId latestRemovedXid);
+extern XLogRecPtr log_heap_freeze(Relation reln, Buffer buffer,
+				TransactionId cutoff_xid,
+				OffsetNumber *offsets, int offcnt);
+extern XLogRecPtr log_heap_visible(RelFileNode rnode, BlockNumber block,
+				 Buffer vm_buffer, TransactionId cutoff_xid);
+extern XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum,
+			BlockNumber blk, Page page);
+extern XLogRecPtr log_newpage_buffer(Buffer buffer);
+
+#endif   /* HEAPAM_XLOG_H */
diff --git a/src/include/access/htup.h b/src/include/access/htup.h
index b289e149269e180b7ee2e95893ee65071d0b606b..74cad2bb2b370a55dd9907ff4ef83e35b88982e2 100644
--- a/src/include/access/htup.h
+++ b/src/include/access/htup.h
@@ -576,225 +576,6 @@ typedef HeapTupleData *HeapTuple;
 		HeapTupleHeaderSetOid((tuple)->t_data, (oid))
 
 
-/*
- * WAL record definitions for heapam.c's WAL operations
- *
- * XLOG allows to store some information in high 4 bits of log
- * record xl_info field.  We use 3 for opcode and one for init bit.
- */
-#define XLOG_HEAP_INSERT		0x00
-#define XLOG_HEAP_DELETE		0x10
-#define XLOG_HEAP_UPDATE		0x20
-/* 0x030 is free, was XLOG_HEAP_MOVE */
-#define XLOG_HEAP_HOT_UPDATE	0x40
-#define XLOG_HEAP_NEWPAGE		0x50
-#define XLOG_HEAP_LOCK			0x60
-#define XLOG_HEAP_INPLACE		0x70
-
-#define XLOG_HEAP_OPMASK		0x70
-/*
- * When we insert 1st item on new page in INSERT, UPDATE, HOT_UPDATE,
- * or MULTI_INSERT, we can (and we do) restore entire page in redo
- */
-#define XLOG_HEAP_INIT_PAGE		0x80
-/*
- * We ran out of opcodes, so heapam.c now has a second RmgrId.	These opcodes
- * are associated with RM_HEAP2_ID, but are not logically different from
- * the ones above associated with RM_HEAP_ID.  XLOG_HEAP_OPMASK applies to
- * these, too.
- */
-#define XLOG_HEAP2_FREEZE		0x00
-#define XLOG_HEAP2_CLEAN		0x10
-/* 0x20 is free, was XLOG_HEAP2_CLEAN_MOVE */
-#define XLOG_HEAP2_CLEANUP_INFO 0x30
-#define XLOG_HEAP2_VISIBLE		0x40
-#define XLOG_HEAP2_MULTI_INSERT 0x50
-
-/*
- * All what we need to find changed tuple
- *
- * NB: on most machines, sizeof(xl_heaptid) will include some trailing pad
- * bytes for alignment.  We don't want to store the pad space in the XLOG,
- * so use SizeOfHeapTid for space calculations.  Similar comments apply for
- * the other xl_FOO structs.
- */
-typedef struct xl_heaptid
-{
-	RelFileNode node;
-	ItemPointerData tid;		/* changed tuple id */
-} xl_heaptid;
-
-#define SizeOfHeapTid		(offsetof(xl_heaptid, tid) + SizeOfIptrData)
-
-/* This is what we need to know about delete */
-typedef struct xl_heap_delete
-{
-	xl_heaptid	target;			/* deleted tuple id */
-	bool		all_visible_cleared;	/* PD_ALL_VISIBLE was cleared */
-} xl_heap_delete;
-
-#define SizeOfHeapDelete	(offsetof(xl_heap_delete, all_visible_cleared) + sizeof(bool))
-
-/*
- * We don't store the whole fixed part (HeapTupleHeaderData) of an inserted
- * or updated tuple in WAL; we can save a few bytes by reconstructing the
- * fields that are available elsewhere in the WAL record, or perhaps just
- * plain needn't be reconstructed.  These are the fields we must store.
- * NOTE: t_hoff could be recomputed, but we may as well store it because
- * it will come for free due to alignment considerations.
- */
-typedef struct xl_heap_header
-{
-	uint16		t_infomask2;
-	uint16		t_infomask;
-	uint8		t_hoff;
-} xl_heap_header;
-
-#define SizeOfHeapHeader	(offsetof(xl_heap_header, t_hoff) + sizeof(uint8))
-
-/* This is what we need to know about insert */
-typedef struct xl_heap_insert
-{
-	xl_heaptid	target;			/* inserted tuple id */
-	bool		all_visible_cleared;	/* PD_ALL_VISIBLE was cleared */
-	/* xl_heap_header & TUPLE DATA FOLLOWS AT END OF STRUCT */
-} xl_heap_insert;
-
-#define SizeOfHeapInsert	(offsetof(xl_heap_insert, all_visible_cleared) + sizeof(bool))
-
-/*
- * This is what we need to know about a multi-insert. The record consists of
- * xl_heap_multi_insert header, followed by a xl_multi_insert_tuple and tuple
- * data for each tuple. 'offsets' array is omitted if the whole page is
- * reinitialized (XLOG_HEAP_INIT_PAGE)
- */
-typedef struct xl_heap_multi_insert
-{
-	RelFileNode node;
-	BlockNumber blkno;
-	bool		all_visible_cleared;
-	uint16		ntuples;
-	OffsetNumber offsets[1];
-
-	/* TUPLE DATA (xl_multi_insert_tuples) FOLLOW AT END OF STRUCT */
-} xl_heap_multi_insert;
-
-#define SizeOfHeapMultiInsert	offsetof(xl_heap_multi_insert, offsets)
-
-typedef struct xl_multi_insert_tuple
-{
-	uint16		datalen;		/* size of tuple data that follows */
-	uint16		t_infomask2;
-	uint16		t_infomask;
-	uint8		t_hoff;
-	/* TUPLE DATA FOLLOWS AT END OF STRUCT */
-} xl_multi_insert_tuple;
-
-#define SizeOfMultiInsertTuple	(offsetof(xl_multi_insert_tuple, t_hoff) + sizeof(uint8))
-
-/* This is what we need to know about update|hot_update */
-typedef struct xl_heap_update
-{
-	xl_heaptid	target;			/* deleted tuple id */
-	ItemPointerData newtid;		/* new inserted tuple id */
-	bool		all_visible_cleared;	/* PD_ALL_VISIBLE was cleared */
-	bool		new_all_visible_cleared;		/* same for the page of newtid */
-	/* NEW TUPLE xl_heap_header AND TUPLE DATA FOLLOWS AT END OF STRUCT */
-} xl_heap_update;
-
-#define SizeOfHeapUpdate	(offsetof(xl_heap_update, new_all_visible_cleared) + sizeof(bool))
-
-/*
- * This is what we need to know about vacuum page cleanup/redirect
- *
- * The array of OffsetNumbers following the fixed part of the record contains:
- *	* for each redirected item: the item offset, then the offset redirected to
- *	* for each now-dead item: the item offset
- *	* for each now-unused item: the item offset
- * The total number of OffsetNumbers is therefore 2*nredirected+ndead+nunused.
- * Note that nunused is not explicitly stored, but may be found by reference
- * to the total record length.
- */
-typedef struct xl_heap_clean
-{
-	RelFileNode node;
-	BlockNumber block;
-	TransactionId latestRemovedXid;
-	uint16		nredirected;
-	uint16		ndead;
-	/* OFFSET NUMBERS FOLLOW */
-} xl_heap_clean;
-
-#define SizeOfHeapClean (offsetof(xl_heap_clean, ndead) + sizeof(uint16))
-
-/*
- * Cleanup_info is required in some cases during a lazy VACUUM.
- * Used for reporting the results of HeapTupleHeaderAdvanceLatestRemovedXid()
- * see vacuumlazy.c for full explanation
- */
-typedef struct xl_heap_cleanup_info
-{
-	RelFileNode node;
-	TransactionId latestRemovedXid;
-} xl_heap_cleanup_info;
-
-#define SizeOfHeapCleanupInfo (sizeof(xl_heap_cleanup_info))
-
-/* This is for replacing a page's contents in toto */
-/* NB: this is used for indexes as well as heaps */
-typedef struct xl_heap_newpage
-{
-	RelFileNode node;
-	ForkNumber	forknum;
-	BlockNumber blkno;			/* location of new page */
-	/* entire page contents follow at end of record */
-} xl_heap_newpage;
-
-#define SizeOfHeapNewpage	(offsetof(xl_heap_newpage, blkno) + sizeof(BlockNumber))
-
-/* This is what we need to know about lock */
-typedef struct xl_heap_lock
-{
-	xl_heaptid	target;			/* locked tuple id */
-	TransactionId locking_xid;	/* might be a MultiXactId not xid */
-	bool		xid_is_mxact;	/* is it? */
-	bool		shared_lock;	/* shared or exclusive row lock? */
-} xl_heap_lock;
-
-#define SizeOfHeapLock	(offsetof(xl_heap_lock, shared_lock) + sizeof(bool))
-
-/* This is what we need to know about in-place update */
-typedef struct xl_heap_inplace
-{
-	xl_heaptid	target;			/* updated tuple id */
-	/* TUPLE DATA FOLLOWS AT END OF STRUCT */
-} xl_heap_inplace;
-
-#define SizeOfHeapInplace	(offsetof(xl_heap_inplace, target) + SizeOfHeapTid)
-
-/* This is what we need to know about tuple freezing during vacuum */
-typedef struct xl_heap_freeze
-{
-	RelFileNode node;
-	BlockNumber block;
-	TransactionId cutoff_xid;
-	/* TUPLE OFFSET NUMBERS FOLLOW AT THE END */
-} xl_heap_freeze;
-
-#define SizeOfHeapFreeze (offsetof(xl_heap_freeze, cutoff_xid) + sizeof(TransactionId))
-
-/* This is what we need to know about setting a visibility map bit */
-typedef struct xl_heap_visible
-{
-	RelFileNode node;
-	BlockNumber block;
-	TransactionId cutoff_xid;
-} xl_heap_visible;
-
-#define SizeOfHeapVisible (offsetof(xl_heap_visible, cutoff_xid) + sizeof(TransactionId))
-
-extern void HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple,
-									   TransactionId *latestRemovedXid);
 
 /* HeapTupleHeader functions implemented in utils/time/combocid.c */
 extern CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup);
diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h
index cd1d56d6e8d0e57394779179ce863925def3300d..c4215da1e329102df3289f9c88a732f51f90503e 100644
--- a/src/include/commands/explain.h
+++ b/src/include/commands/explain.h
@@ -14,6 +14,7 @@
 #define EXPLAIN_H
 
 #include "executor/executor.h"
+#include "lib/stringinfo.h"
 
 typedef enum ExplainFormat
 {
diff --git a/src/include/commands/prepare.h b/src/include/commands/prepare.h
index f688be77a322d72e670194c4089e613a6bf9d736..a15cba2cc3f1c0e90b146b1730b41f8097288e57 100644
--- a/src/include/commands/prepare.h
+++ b/src/include/commands/prepare.h
@@ -14,6 +14,7 @@
 #define PREPARE_H
 
 #include "commands/explain.h"
+#include "datatype/timestamp.h"
 #include "utils/plancache.h"
 
 /*