http://archives.postgresql.org/pgsql-hackers/2006-10/msg01172.php

As discussed on -hackers, its possible to avoid writing any WAL at all
for COPY in these circumstances:

BEGIN;
  CREATE TABLE foo..
  COPY foo...
COMMIT;

BEGIN;
  TRUNCATE foo..
  COPY foo...
COMMIT;

The enclosed patch implements this, as discussed. There is no user
interface to enable/disable, just as with CTAS and CREATE INDEX; no
docs, just code comments.

This plays nicely with the --single-transaction option in psql to allow
fast restores/upgrades.

YMMV but disk bound COPY will benefit greatly from this patch, some
tests showing 100% gain. COPY is still *very* CPU intensive, so some
tests have shown negligible benefit, fyi, but that isn't the typical
case.

Applies cleanly to CVS HEAD, passes make check. 

-- 
  Simon Riggs             
  EnterpriseDB   http://www.enterprisedb.com

Index: src/backend/access/heap/heapam.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/access/heap/heapam.c,v
retrieving revision 1.222
diff -c -r1.222 heapam.c
*** src/backend/access/heap/heapam.c	17 Nov 2006 18:00:14 -0000	1.222
--- src/backend/access/heap/heapam.c	4 Jan 2007 15:24:03 -0000
***************
*** 28,33 ****
--- 28,34 ----
   *		heap_update		- replace a tuple in a relation with another tuple
   *		heap_markpos	- mark scan position
   *		heap_restrpos	- restore position to marked location
+  *	  heap_sync	   - sync heap, for when no WAL has been written
   *
   * NOTES
   *	  This file contains the heap_ routines which implement
***************
*** 50,55 ****
--- 51,57 ----
  #include "miscadmin.h"
  #include "pgstat.h"
  #include "storage/procarray.h"
+ #include "storage/smgr.h"
  #include "utils/inval.h"
  #include "utils/lsyscache.h"
  #include "utils/relcache.h"
***************
*** 1357,1364 ****
   * non-temp relation.  Safe usage of this behavior requires that we arrange
   * that all new tuples go into new pages not containing any tuples from other
   * transactions, that the relation gets fsync'd before commit, and that the
!  * transaction emits at least one WAL record to ensure RecordTransactionCommit
!  * will decide to WAL-log the commit.
   *
   * use_fsm is passed directly to RelationGetBufferForTuple, which see for
   * more info.
--- 1359,1367 ----
   * non-temp relation.  Safe usage of this behavior requires that we arrange
   * that all new tuples go into new pages not containing any tuples from other
   * transactions, that the relation gets fsync'd before commit, and that the
!  * transaction emits at least one WAL record or must mark 
!  * MyXactMadeXLogEntry=true to ensure RecordTransactionCommit will
!  * decide to WAL-log the commit. (see heap_sync() comments also)
   *
   * use_fsm is passed directly to RelationGetBufferForTuple, which see for
   * more info.
***************
*** 1371,1377 ****
   */
  Oid
  heap_insert(Relation relation, HeapTuple tup, CommandId cid,
! 			bool use_wal, bool use_fsm)
  {
  	TransactionId xid = GetCurrentTransactionId();
  	HeapTuple	heaptup;
--- 1374,1380 ----
   */
  Oid
  heap_insert(Relation relation, HeapTuple tup, CommandId cid,
! 			bool use_wal, bool use_fsm, bool force_committed)
  {
  	TransactionId xid = GetCurrentTransactionId();
  	HeapTuple	heaptup;
***************
*** 1408,1413 ****
--- 1411,1419 ----
  	HeapTupleHeaderSetXmax(tup->t_data, 0);		/* zero out Datum fields */
  	HeapTupleHeaderSetCmax(tup->t_data, 0);		/* for cleanliness */
  	tup->t_tableOid = RelationGetRelid(relation);
+	 if (force_committed)
+	 	tup->t_data->t_infomask |= HEAP_XMIN_COMMITTED;
+		 
  
  	/*
  	 * If the new tuple is too big for storage or contains already toasted
***************
*** 1418,1424 ****
  	 */
  	if (HeapTupleHasExternal(tup) ||
  		(MAXALIGN(tup->t_len) > TOAST_TUPLE_THRESHOLD))
! 		heaptup = toast_insert_or_update(relation, tup, NULL);
  	else
  		heaptup = tup;
  
--- 1424,1430 ----
  	 */
  	if (HeapTupleHasExternal(tup) ||
  		(MAXALIGN(tup->t_len) > TOAST_TUPLE_THRESHOLD))
! 		heaptup = toast_insert_or_update(relation, tup, NULL, use_wal);
  	else
  		heaptup = tup;
  
***************
*** 1532,1538 ****
  Oid
  simple_heap_insert(Relation relation, HeapTuple tup)
  {
! 	return heap_insert(relation, tup, GetCurrentCommandId(), true, true);
  }
  
  /*
--- 1538,1556 ----
  Oid
  simple_heap_insert(Relation relation, HeapTuple tup)
  {
! 	return heap_insert(relation, tup, GetCurrentCommandId(), true, true, false);
! }
! 
! /*
!  *	fast_heap_insert - insert a tuple with options to improve speed
!  *
!  * Currently, this routine allows specifying additional options for speed
!  * in certain cases, such as WAL-avoiding COPY command
!  */
! Oid
! fast_heap_insert(Relation relation, HeapTuple tup, bool use_wal, bool force_committed)
! {
! 	return heap_insert(relation, tup, GetCurrentCommandId(), use_wal, use_wal, force_committed);
  }
  
  /*
***************
*** 2086,2096 ****
  		 *
  		 * Note: below this point, heaptup is the data we actually intend to
  		 * store into the relation; newtup is the caller's original untoasted
! 		 * data.
  		 */
  		if (need_toast)
  		{
! 			heaptup = toast_insert_or_update(relation, newtup, &oldtup);
  			newtupsize = MAXALIGN(heaptup->t_len);
  		}
  		else
--- 2104,2114 ----
  		 *
  		 * Note: below this point, heaptup is the data we actually intend to
  		 * store into the relation; newtup is the caller's original untoasted
! 		 * data. (We always use WAL for toast table updates.)
  		 */
  		if (need_toast)
  		{
! 			heaptup = toast_insert_or_update(relation, newtup, &oldtup, true);
  			newtupsize = MAXALIGN(heaptup->t_len);
  		}
  		else
***************
*** 3966,3968 ****
--- 3984,4007 ----
  	else
  		appendStringInfo(buf, "UNKNOWN");
  }
+ 
+ /* ----------------
+  *		heap_sync - sync a heap, for use when no WAL has been written
+  *
+  * ----------------
+  */
+ void
+ heap_sync(Relation rel)
+ {
+	 if (!rel->rd_istemp)
+	 {
+		 /*
+		  * If we skipped using WAL, and it's not a temp relation,
+		  * we must force the relation down to disk before it's
+		  * safe to commit the transaction.  This requires forcing
+		  * out any dirty buffers and then doing a forced fsync.
+		  */
+		 FlushRelationBuffers(rel);
+		 smgrimmedsync(rel->rd_smgr);
+	 }
+ }
Index: src/backend/access/heap/tuptoaster.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v
retrieving revision 1.66
diff -c -r1.66 tuptoaster.c
*** src/backend/access/heap/tuptoaster.c	5 Oct 2006 23:33:33 -0000	1.66
--- src/backend/access/heap/tuptoaster.c	4 Jan 2007 15:24:04 -0000
***************
*** 42,48 ****
  #undef TOAST_DEBUG
  
  static void toast_delete_datum(Relation rel, Datum value);
! static Datum toast_save_datum(Relation rel, Datum value);
  static varattrib *toast_fetch_datum(varattrib *attr);
  static varattrib *toast_fetch_datum_slice(varattrib *attr,
  						int32 sliceoffset, int32 length);
--- 42,48 ----
  #undef TOAST_DEBUG
  
  static void toast_delete_datum(Relation rel, Datum value);
! static Datum toast_save_datum(Relation rel, Datum value, bool use_wal);
  static varattrib *toast_fetch_datum(varattrib *attr);
  static varattrib *toast_fetch_datum_slice(varattrib *attr,
  						int32 sliceoffset, int32 length);
***************
*** 342,348 ****
   * ----------
   */
  HeapTuple
! toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
  {
  	HeapTuple	result_tuple;
  	TupleDesc	tupleDesc;
--- 342,348 ----
   * ----------
   */
  HeapTuple
! toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, bool use_wal)
  {
  	HeapTuple	result_tuple;
  	TupleDesc	tupleDesc;
***************
*** 612,618 ****
  		i = biggest_attno;
  		old_value = toast_values[i];
  		toast_action[i] = 'p';
! 		toast_values[i] = toast_save_datum(rel, toast_values[i]);
  		if (toast_free[i])
  			pfree(DatumGetPointer(old_value));
  
--- 612,618 ----
  		i = biggest_attno;
  		old_value = toast_values[i];
  		toast_action[i] = 'p';
! 		toast_values[i] = toast_save_datum(rel, toast_values[i], use_wal);
  		if (toast_free[i])
  			pfree(DatumGetPointer(old_value));
  
***************
*** 724,730 ****
  		i = biggest_attno;
  		old_value = toast_values[i];
  		toast_action[i] = 'p';
! 		toast_values[i] = toast_save_datum(rel, toast_values[i]);
  		if (toast_free[i])
  			pfree(DatumGetPointer(old_value));
  
--- 724,730 ----
  		i = biggest_attno;
  		old_value = toast_values[i];
  		toast_action[i] = 'p';
! 		toast_values[i] = toast_save_datum(rel, toast_values[i], use_wal);
  		if (toast_free[i])
  			pfree(DatumGetPointer(old_value));
  
***************
*** 972,978 ****
   * ----------
   */
  static Datum
! toast_save_datum(Relation rel, Datum value)
  {
  	Relation	toastrel;
  	Relation	toastidx;
--- 972,978 ----
   * ----------
   */
  static Datum
! toast_save_datum(Relation rel, Datum value, bool use_wal)
  {
  	Relation	toastrel;
  	Relation	toastidx;
***************
*** 1057,1063 ****
  		if (!HeapTupleIsValid(toasttup))
  			elog(ERROR, "failed to build TOAST tuple");
  
! 		simple_heap_insert(toastrel, toasttup);
  
  		/*
  		 * Create the index entry.	We cheat a little here by not using
--- 1057,1064 ----
  		if (!HeapTupleIsValid(toasttup))
  			elog(ERROR, "failed to build TOAST tuple");
  
!		 /* not worried about forcing commit bits to be set for TOAST */
!		 fast_heap_insert(toastrel, toasttup, use_wal, !use_wal);
  
  		/*
  		 * Create the index entry.	We cheat a little here by not using
Index: src/backend/catalog/index.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/index.c,v
retrieving revision 1.274
diff -c -r1.274 index.c
*** src/backend/catalog/index.c	4 Oct 2006 00:29:50 -0000	1.274
--- src/backend/catalog/index.c	4 Jan 2007 15:24:06 -0000
***************
*** 1238,1243 ****
--- 1238,1246 ----
  
  	heap_close(pg_class, RowExclusiveLock);
  
+	 /* Remember we did this in current transaction, to allow later optimisations */
+	 relation->rd_newRelfilenodeSubid = GetCurrentSubTransactionId();
+ 
  	/* Make sure the relfilenode change is visible */
  	CommandCounterIncrement();
  }
Index: src/backend/commands/copy.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/copy.c,v
retrieving revision 1.273
diff -c -r1.273 copy.c
*** src/backend/commands/copy.c	6 Oct 2006 17:13:58 -0000	1.273
--- src/backend/commands/copy.c	4 Jan 2007 15:24:08 -0000
***************
*** 1652,1657 ****
--- 1652,1659 ----
  	ExprContext *econtext;		/* used for ExecEvalExpr for default atts */
  	MemoryContext oldcontext = CurrentMemoryContext;
  	ErrorContextCallback errcontext;
+	 bool		use_wal = true; /* By default, we use WAL to log db changes */
+	 bool		force_committed = false;
  
  	Assert(cstate->rel);
  
***************
*** 1843,1848 ****
--- 1845,1878 ----
  	nfields = file_has_oids ? (attr_count + 1) : attr_count;
  	field_strings = (char **) palloc(nfields * sizeof(char *));
  
+ 	/*
+	  * Check for performance optimization by avoiding WAL writes
+	  *
+	  * If archive logging is not be enabled *and* either
+	  * - table is created in same transaction as this COPY
+	  * - table data is now being written to new relfilenode
+	  * then we can safely avoid writing WAL. Why? 
+	  * The data files for the table plus toast table/index, plus any indexes
+	  * will all be dropped at the end of the transaction if it fails, so we
+	  * do not need to worry about inconsistent states.
+	  * As mentioned in comments in utils/rel.h, the in-same-transaction test is
+	  * not completely reliable, since rd_createSubId can be reset to zero in
+	  * certain cases before the end of the creating transaction. 
+	  * We are doing this for performance only, so we only need to know: 
+	  * if rd_createSubid != InvalidSubTransactionId then it is *always* just 
+	  * created.
+	  * We also want to set HEAP_XMIN_COMMITTED for these tuples, so we
+	  * can only do this when we don't have a previously open portal.
+	  * COPY itself open a portal, so we check for just a single portal.
+	  * If we have PITR enabled, then we must use_wal
+	  */
+ 	if (NumAccessiblePortals() == 1 &&
+		  (cstate->rel->rd_createSubid		 != InvalidSubTransactionId ||
+		   cstate->rel->rd_newRelfilenodeSubid != InvalidSubTransactionId))
+		 force_committed = true;
+ 	if (force_committed && !XLogArchivingActive())
+		 use_wal = false;
+ 
  	/* Initialize state variables */
  	cstate->fe_eof = false;
  	cstate->eol_type = EOL_UNKNOWN;
***************
*** 2076,2082 ****
  				ExecConstraints(resultRelInfo, slot, estate);
  
  			/* OK, store the tuple and create index entries for it */
! 			simple_heap_insert(cstate->rel, tuple);
  
  			if (resultRelInfo->ri_NumIndices > 0)
  				ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
--- 2106,2112 ----
  				ExecConstraints(resultRelInfo, slot, estate);
  
  			/* OK, store the tuple and create index entries for it */
!			 fast_heap_insert(cstate->rel, tuple, use_wal, force_committed);
  
  			if (resultRelInfo->ri_NumIndices > 0)
  				ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
***************
*** 2093,2098 ****
--- 2123,2154 ----
  		}
  	}
  
+	 /* 
+	  * If we skipped writing WAL for heaps, then we need to sync
+	  */
+	 if (!use_wal)
+	 {
+		 /* main heap */
+		 heap_sync(cstate->rel);
+ 
+		 /* main heap indexes, if any */
+		 /* we always use WAL for index inserts, so no need to sync */
+ 
+		 /* toast heap, if any */
+		 if (OidIsValid(cstate->rel->rd_rel->reltoastrelid))
+		 {
+				 Relation		toastrel;
+ 
+				 toastrel = heap_open(cstate->rel->rd_rel->reltoastrelid,
+									  AccessShareLock);
+				 heap_sync(toastrel);
+				 heap_close(toastrel, AccessShareLock);
+		 }
+ 
+		 /* toast index, if toast heap */
+		 /* we always use WAL for index inserts, so no need to sync */
+	 }
+ 
  	/* Done, clean up */
  	error_context_stack = errcontext.previous;
  
Index: src/backend/executor/execMain.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/executor/execMain.c,v
retrieving revision 1.282
diff -c -r1.282 execMain.c
*** src/backend/executor/execMain.c	26 Dec 2006 21:37:19 -0000	1.282
--- src/backend/executor/execMain.c	4 Jan 2007 15:24:08 -0000
***************
*** 1410,1416 ****
  	 */
  	newId = heap_insert(resultRelationDesc, tuple,
  						estate->es_snapshot->curcid,
! 						true, true);
  
  	IncrAppended();
  	(estate->es_processed)++;
--- 1410,1416 ----
  	 */
  	newId = heap_insert(resultRelationDesc, tuple,
  						estate->es_snapshot->curcid,
! 						true, true, false);
  
  	IncrAppended();
  	(estate->es_processed)++;
***************
*** 2516,2526 ****
  		 */
  		if (!estate->es_into_relation_use_wal &&
  			!estate->es_into_relation_descriptor->rd_istemp)
! 		{
! 			FlushRelationBuffers(estate->es_into_relation_descriptor);
! 			/* FlushRelationBuffers will have opened rd_smgr */
! 			smgrimmedsync(estate->es_into_relation_descriptor->rd_smgr);
! 		}
  
  		/* close rel, but keep lock until commit */
  		heap_close(estate->es_into_relation_descriptor, NoLock);
--- 2516,2522 ----
  		 */
  		if (!estate->es_into_relation_use_wal &&
  			!estate->es_into_relation_descriptor->rd_istemp)
!			 heap_sync(estate->es_into_relation_descriptor);
  
  		/* close rel, but keep lock until commit */
  		heap_close(estate->es_into_relation_descriptor, NoLock);
***************
*** 2577,2583 ****
  				tuple,
  				estate->es_snapshot->curcid,
  				estate->es_into_relation_use_wal,
! 				false);			/* never any point in using FSM */
  
  	/* We know this is a newly created relation, so there are no indexes */
  
--- 2573,2580 ----
  				tuple,
  				estate->es_snapshot->curcid,
  				estate->es_into_relation_use_wal,
! 				false,			/* never any point in using FSM */
!				 true);
  
  	/* We know this is a newly created relation, so there are no indexes */
  
Index: src/backend/utils/cache/relcache.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/cache/relcache.c,v
retrieving revision 1.252
diff -c -r1.252 relcache.c
*** src/backend/utils/cache/relcache.c	31 Dec 2006 20:32:04 -0000	1.252
--- src/backend/utils/cache/relcache.c	4 Jan 2007 15:24:10 -0000
***************
*** 836,841 ****
--- 836,842 ----
  	relation->rd_refcnt = 0;
  	relation->rd_isnailed = false;
  	relation->rd_createSubid = InvalidSubTransactionId;
+	 relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
  	relation->rd_istemp = isTempNamespace(relation->rd_rel->relnamespace);
  
  	/*
***************
*** 1342,1347 ****
--- 1343,1349 ----
  	 */
  	relation->rd_isnailed = true;
  	relation->rd_createSubid = InvalidSubTransactionId;
+	 relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
  	relation->rd_istemp = false;
  
  	/*
***************
*** 1753,1758 ****
--- 1755,1761 ----
  		Oid			save_relid = RelationGetRelid(relation);
  		int			old_refcnt = relation->rd_refcnt;
  		SubTransactionId old_createSubid = relation->rd_createSubid;
+ 		SubTransactionId old_newRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
  		TupleDesc	old_att = relation->rd_att;
  		RuleLock   *old_rules = relation->rd_rules;
  		MemoryContext old_rulescxt = relation->rd_rulescxt;
***************
*** 1771,1776 ****
--- 1774,1781 ----
  		}
  		relation->rd_refcnt = old_refcnt;
  		relation->rd_createSubid = old_createSubid;
+		 relation->rd_newRelfilenodeSubid = old_newRelfilenodeSubid;
+ 
  		if (equalTupleDescs(old_att, relation->rd_att))
  		{
  			/* needn't flush typcache here */
***************
*** 1811,1817 ****
  {
  	bool		rebuild;
  
! 	if (relation->rd_createSubid != InvalidSubTransactionId)
  	{
  		/*
  		 * New relcache entries are always rebuilt, not flushed; else we'd
--- 1816,1823 ----
  {
  	bool		rebuild;
  
! 	if (relation->rd_createSubid != InvalidSubTransactionId ||
!		 relation->rd_newRelfilenodeSubid != InvalidSubTransactionId)
  	{
  		/*
  		 * New relcache entries are always rebuilt, not flushed; else we'd
***************
*** 1893,1898 ****
--- 1899,1907 ----
   *	 so we do not touch new-in-transaction relations; they cannot be targets
   *	 of cross-backend SI updates (and our own updates now go through a
   *	 separate linked list that isn't limited by the SI message buffer size).
+  *   We don't do anything special for newRelfilenode-in-transaction relations, 
+  *   though since we have a lock on the relation nobody else should be 
+  *   generating cache invalidation messages for it anyhow.
   *
   *	 We do this in two phases: the first pass deletes deletable items, and
   *	 the second one rebuilds the rebuildable items.  This is essential for
***************
*** 2069,2074 ****
--- 2078,2084 ----
  				continue;
  			}
  		}
+		 relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
  
  		/*
  		 * Flush any temporary index list.
***************
*** 2130,2135 ****
--- 2140,2152 ----
  				continue;
  			}
  		}
+ 		if (relation->rd_newRelfilenodeSubid == mySubid)
+ 		{
+ 			if (isCommit)
+ 				relation->rd_newRelfilenodeSubid = parentSubid;
+ 			else
+				 relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
+		 }
  
  		/*
  		 * Flush any temporary index list.
***************
*** 2219,2224 ****
--- 2236,2242 ----
  
  	/* it's being created in this transaction */
  	rel->rd_createSubid = GetCurrentSubTransactionId();
+	 rel->rd_newRelfilenodeSubid = InvalidSubTransactionId;
  
  	/* must flag that we have rels created in this transaction */
  	need_eoxact_work = true;
***************
*** 3364,3369 ****
--- 3382,3388 ----
  		rel->rd_indexlist = NIL;
  		rel->rd_oidindex = InvalidOid;
  		rel->rd_createSubid = InvalidSubTransactionId;
+		 rel->rd_newRelfilenodeSubid = InvalidSubTransactionId;
  		rel->rd_amcache = NULL;
  		MemSet(&rel->pgstat_info, 0, sizeof(rel->pgstat_info));
  
Index: src/backend/utils/mmgr/portalmem.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v
retrieving revision 1.97
diff -c -r1.97 portalmem.c
*** src/backend/utils/mmgr/portalmem.c	23 Nov 2006 01:14:59 -0000	1.97
--- src/backend/utils/mmgr/portalmem.c	4 Jan 2007 15:24:12 -0000
***************
*** 88,94 ****
  } while(0)
  
  static MemoryContext PortalMemory = NULL;
! 
  
  /* ----------------------------------------------------------------
   *				   public portal interface functions
--- 88,94 ----
  } while(0)
  
  static MemoryContext PortalMemory = NULL;
! static int NPortals = 0;
  
  /* ----------------------------------------------------------------
   *				   public portal interface functions
***************
*** 227,232 ****
--- 227,234 ----
  	/* put portal in table (sets portal->name) */
  	PortalHashTableInsert(portal, name);
  
+	 ++NPortals;
+ 
  	return portal;
  }
  
***************
*** 410,415 ****
--- 412,420 ----
  
  	/* release portal struct (it's in PortalMemory) */
  	pfree(portal);
+ 
+	 if (--NPortals < 0)
+ 		elog(ERROR, "error in number of portals");
  }
  
  /*
***************
*** 548,554 ****
  	HASH_SEQ_STATUS status;
  	PortalHashEnt *hentry;
  
! 	hash_seq_init(&status, PortalHashTable);
  
  	while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
  	{
--- 553,559 ----
  	HASH_SEQ_STATUS status;
  	PortalHashEnt *hentry;
  
!  	hash_seq_init(&status, PortalHashTable);
  
  	while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
  	{
***************
*** 802,807 ****
--- 807,823 ----
  	}
  }
  
+ /*
+  * Get the number of portals from which the backend *could* retrieve
+  * tuples. This is an important number for the safe use of some 
+  * performance optimizations.
+  */
+ int
+ NumAccessiblePortals(void)
+ {
+	 return NPortals;
+ }
+ 
  /* Find all available cursors */
  Datum
  pg_cursor(PG_FUNCTION_ARGS)
Index: src/include/miscadmin.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/miscadmin.h,v
retrieving revision 1.190
diff -c -r1.190 miscadmin.h
*** src/include/miscadmin.h	19 Oct 2006 18:32:47 -0000	1.190
--- src/include/miscadmin.h	4 Jan 2007 15:24:13 -0000
***************
*** 216,221 ****
--- 216,224 ----
  /* in tcop/postgres.c */
  extern void check_stack_depth(void);
  
+ /* in utils/mmgr/portalmem.c */
+ extern int NumAccessiblePortals(void);
+ 
  
  /*****************************************************************************
   *	  pdir.h --																 *
Index: src/include/access/heapam.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/access/heapam.h,v
retrieving revision 1.117
diff -c -r1.117 heapam.h
*** src/include/access/heapam.h	5 Nov 2006 22:42:10 -0000	1.117
--- src/include/access/heapam.h	4 Jan 2007 15:24:13 -0000
***************
*** 157,163 ****
  extern void setLastTid(const ItemPointer tid);
  
  extern Oid heap_insert(Relation relation, HeapTuple tup, CommandId cid,
! 			bool use_wal, bool use_fsm);
  extern HTSU_Result heap_delete(Relation relation, ItemPointer tid,
  			ItemPointer ctid, TransactionId *update_xmax,
  			CommandId cid, Snapshot crosscheck, bool wait);
--- 157,163 ----
  extern void setLastTid(const ItemPointer tid);
  
  extern Oid heap_insert(Relation relation, HeapTuple tup, CommandId cid,
! 			bool use_wal, bool use_fsm, bool force_committed);
  extern HTSU_Result heap_delete(Relation relation, ItemPointer tid,
  			ItemPointer ctid, TransactionId *update_xmax,
  			CommandId cid, Snapshot crosscheck, bool wait);
***************
*** 178,183 ****
--- 178,186 ----
  extern void simple_heap_update(Relation relation, ItemPointer otid,
  				   HeapTuple tup);
  
+ extern Oid fast_heap_insert(Relation relation, HeapTuple tup, bool use_wal, 
+				 bool force_committed);
+ 
  extern void heap_markpos(HeapScanDesc scan);
  extern void heap_restrpos(HeapScanDesc scan);
  
***************
*** 236,239 ****
--- 239,244 ----
  extern HeapTuple heap_addheader(int natts, bool withoid,
  			   Size structlen, void *structure);
  
+ extern void heap_sync(Relation relation);
+ 
  #endif   /* HEAPAM_H */
Index: src/include/access/tuptoaster.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/access/tuptoaster.h,v
retrieving revision 1.28
diff -c -r1.28 tuptoaster.h
*** src/include/access/tuptoaster.h	13 Jul 2006 17:47:01 -0000	1.28
--- src/include/access/tuptoaster.h	4 Jan 2007 15:24:13 -0000
***************
*** 69,75 ****
   * ----------
   */
  extern HeapTuple toast_insert_or_update(Relation rel,
! 					   HeapTuple newtup, HeapTuple oldtup);
  
  /* ----------
   * toast_delete -
--- 69,75 ----
   * ----------
   */
  extern HeapTuple toast_insert_or_update(Relation rel,
! 					   HeapTuple newtup, HeapTuple oldtup, bool use_wal);
  
  /* ----------
   * toast_delete -
Index: src/include/utils/rel.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/rel.h,v
retrieving revision 1.93
diff -c -r1.93 rel.h
*** src/include/utils/rel.h	23 Dec 2006 00:43:13 -0000	1.93
--- src/include/utils/rel.h	4 Jan 2007 15:24:13 -0000
***************
*** 137,142 ****
--- 137,144 ----
  	char		rd_indexvalid;	/* state of rd_indexlist: 0 = not valid, 1 =
  								 * valid, 2 = temporarily forced */
  	SubTransactionId rd_createSubid;	/* rel was created in current xact */
+ 	SubTransactionId rd_newRelfilenodeSubid;	/* rel had new relfilenode in current xact */
+	 
  
  	/*
  	 * rd_createSubid is the ID of the highest subtransaction the rel has
---------------------------(end of broadcast)---------------------------
TIP 5: don't forget to increase your free space map settings

Reply via email to