Index: tablespace.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/tablespace.c,v
retrieving revision 1.45
diff -c -B -r1.45 tablespace.c
*** tablespace.c	22 Mar 2007 19:51:44 -0000	1.45
--- tablespace.c	25 May 2007 15:27:23 -0000
***************
*** 63,73 ****
  #include "utils/fmgroids.h"
  #include "utils/guc.h"
  #include "utils/lsyscache.h"
  
  
! /* GUC variable */
  char	   *default_tablespace = NULL;
  
  
  static bool remove_tablespace_directories(Oid tablespaceoid, bool redo);
  static void set_short_version(const char *path);
--- 63,80 ----
  #include "utils/fmgroids.h"
  #include "utils/guc.h"
  #include "utils/lsyscache.h"
+ #include "utils/memutils.h"
  
  
! /* GUC variables */
  char	   *default_tablespace = NULL;
+ char       *temp_tablespaces = NULL;
  
+ static int	   next_temp_tablespace;
+ static int	   num_temp_tablespaces;
+ 
+ /* OID list of current temp tablespaces */
+ static List *tmp_tblspc_lookup = NIL;
  
  static bool remove_tablespace_directories(Oid tablespaceoid, bool redo);
  static void set_short_version(const char *path);
***************
*** 935,940 ****
--- 942,1080 ----
  	return result;
  }
  
+ /*
+  * Routines for handling the GUC variable 'temp_tablespaces'.
+  */
+ 
+ /* assign_hook: validate new temp_tablespaces, do extra actions as needed */
+ const char *
+ assign_temp_tablespaces(const char *newval, bool doit, GucSource source)
+ {
+ 	char	   *rawname;
+ 	ListCell   *l;
+ 	MemoryContext cur_cntxt;
+ 	List	   *namelist = NIL;
+ 	List       *oidlist = NIL;
+ 
+ 	/* Need a modifiable copy of string */
+ 	rawname = pstrdup(newval);
+ 
+ 	/* Parse string into list of identifiers */
+ 	if (!SplitIdentifierString(rawname, ',', &namelist))
+ 	{
+ 		/* syntax error in name list */
+ 		pfree(rawname);
+ 		list_free(namelist);
+ 		return NULL;
+ 	}
+
+ 	num_temp_tablespaces = 0;
+
+ 	foreach(l, namelist)
+ 	{
+ 		char	   *curname = (char *) lfirst(l);
+ 		if (curname[0] == '\0')
+ 			continue;
+ 
+ 		/*
+ 		 * If we aren't inside a transaction, we cannot do database access so
+ 		 * cannot verify the individual names.	Must accept the list on faith.
+ 		 */
+ 		if (source >= PGC_S_INTERACTIVE && IsTransactionState())
+ 		{
+ 			/*
+ 			 * Verify that all the names are valid tablespace names 
+ 			 * We do not check for USAGE rights should we?
+ 			 */
+ 			Oid cur_tblspc = get_tablespace_oid(curname);
+ 			if (cur_tblspc == InvalidOid)
+ 			{
+ 				ereport((source == PGC_S_TEST) ? NOTICE : ERROR,
+ 						(errcode(ERRCODE_UNDEFINED_OBJECT),
+ 						 errmsg("tablespace \"%s\" does not exist", curname)));
+ 			}
+ 			else
+ 			{
+ 				/* 
+ 				 * Append new OID to temporary list. We can't
+ 				 * use the lookup table directly, because there could
+ 				 * be an ereport() in subsequent loops. 
+ 				 */
+ 				oidlist = lappend_oid(oidlist, cur_tblspc);
+ 			}
+ 		}
+ 		num_temp_tablespaces++;
+ 	}
+ 
+ 	/*
+ 	 * Select the first tablespace to use
+ 	 */
+ 	Assert(num_temp_tablespaces >= 0);
+ 	if (num_temp_tablespaces != 0)
+ 		next_temp_tablespace = MyProcPid % num_temp_tablespaces;
+ 
+ 	/* Looks good for now, free any old lookup table and copy new OID
+ 	   list to our lookup table in permanent storage */
+ 	cur_cntxt = MemoryContextSwitchTo(TopMemoryContext);
+
+ 	if (tmp_tblspc_lookup != NIL)
+ 	{
+ 		list_free(tmp_tblspc_lookup);
+ 	}
+ 
+ 	tmp_tblspc_lookup = list_copy(oidlist);
+ 	MemoryContextSwitchTo(cur_cntxt);
+
+ 	pfree(rawname);
+ 	list_free(namelist);
+ 	return newval;
+ }
+ 
+ /*
+  * GetTempTablespace -- get the OID of the tablespace for temporary objects
+  *
+  * May return InvalidOid to indicate "use the database's default tablespace"
+  */
+ Oid
+ GetTempTablespace(void)
+ {
+ 	Oid	     result;
+ 	char     *curname;
+
+ 	if ( temp_tablespaces == NULL )
+ 		return InvalidOid;
+
+ 	/* OID lookup cache not available */
+ 	if ( tmp_tblspc_lookup == NIL)
+ 		return InvalidOid;
+ 
+ 	/* get next OID */
+ 	result = list_nth_oid(tmp_tblspc_lookup, next_temp_tablespace);
+ 
+ 	/* validate cached OID, if still available ... */
+ 	curname = get_tablespace_name(result);
+ 
+ 	/* Prepare for the next time the function is called */
+ 	next_temp_tablespace++;
+ 	if (next_temp_tablespace == num_temp_tablespaces)
+ 		next_temp_tablespace = 0;
+ 
+ 	/* If the cached OID is invalid, return InvalidOid immediately.
+ 	   We don't care to try any remaining tablespaces now */
+ 
+ 	if ( curname == NULL || curname[0] == '\0') {
+ 		return InvalidOid;
+ 	}
+ 
+ 	/*
+ 	 * Allow explicit specification of database's default tablespace in
+ 	 * default_tablespace without triggering permissions checks.
+ 	 */
+ 	if (result == MyDatabaseTableSpace)
+ 		result = InvalidOid;
+ 
+ 	return result;
+ }
  
  /*
   * get_tablespace_oid - given a tablespace name, look up the OID
