OSDN Git Service

Add GUC temp_tablespaces to provide a default location for temporary
authorBruce Momjian <bruce@momjian.us>
Thu, 25 Jan 2007 04:35:11 +0000 (04:35 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 25 Jan 2007 04:35:11 +0000 (04:35 +0000)
objects.

Jaime Casanova

doc/src/sgml/config.sgml
src/backend/commands/indexcmds.c
src/backend/commands/tablecmds.c
src/backend/commands/tablespace.c
src/backend/executor/execMain.c
src/backend/storage/file/fd.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/include/commands/tablespace.h
src/include/utils/guc.h

index 7088c5e..94fc8fd 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.104 2007/01/20 21:30:26 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.105 2007/01/25 04:35:10 momjian Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -3398,6 +3398,35 @@ SELECT * FROM parent WHERE key = 2400;
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-temp-tablespaces" xreflabel="temp_tablespaces">
+      <term><varname>temp_tablespaces</varname> (<type>string</type>)</term>
+      <indexterm>
+       <primary><varname>temp_tablespaces</> configuration parameter</primary>
+      </indexterm>
+      <indexterm><primary>tablespace</><secondary>temp</></>
+      <listitem>
+       <para>
+        This variable specifies tablespaces in which to create temp
+        objects (temp tables and indexes on temp tables) when a 
+        <command>CREATE</> command does not explicitly specify a tablespace 
+        and temp files when necessary (eg. for sorting operations).
+       </para>
+
+       <para>
+        The value is either a list of names of tablespaces, or an empty 
+        string to specify using the default tablespace of the current database.
+        If the value does not match the name of any existing tablespace,
+        <productname>PostgreSQL</> will automatically use the default
+        tablespace of the current database.
+       </para>
+
+       <para>
+        For more information on tablespaces,
+        see <xref linkend="manage-ag-tablespaces">.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="guc-check-function-bodies" xreflabel="check_function_bodies">
       <term><varname>check_function_bodies</varname> (<type>boolean</type>)</term>
       <indexterm>
index 2d51dfb..a718312 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.153 2007/01/20 23:13:01 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.154 2007/01/25 04:35:10 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -209,7 +209,13 @@ DefineIndex(RangeVar *heapRelation,
        }
        else
        {
-               tablespaceId = GetDefaultTablespace();
+               /*
+                * if the target table is temporary then use a temp_tablespace
+                */
+               if (!rel->rd_istemp)
+                       tablespaceId = GetDefaultTablespace();
+               else
+                       tablespaceId = GetTempTablespace();
                /* note InvalidOid is OK in this case */
        }
 
index ced0850..a11cde3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.211 2007/01/25 04:17:45 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.212 2007/01/25 04:35:10 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -334,6 +334,10 @@ DefineRelation(CreateStmt *stmt, char relkind)
                                         errmsg("tablespace \"%s\" does not exist",
                                                        stmt->tablespacename)));
        }
+       else if (stmt->relation->istemp)
+       {
+               tablespaceId = GetTempTablespace();
+       }
        else
        {
                tablespaceId = GetDefaultTablespace();
index cd86aef..d2cb245 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.40 2007/01/05 22:19:26 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.41 2007/01/25 04:35:10 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "utils/lsyscache.h"
 
 
-/* GUC variable */
+/* GUC variables */
 char      *default_tablespace = NULL;
+char       *temp_tablespaces = NULL;
 
+int       next_temp_tablespace;
+int       num_temp_tablespaces;
 
 static bool remove_tablespace_directories(Oid tablespaceoid, bool redo);
 static void set_short_version(const char *path);
@@ -930,6 +933,142 @@ GetDefaultTablespace(void)
        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;
+       List       *namelist;
+       ListCell   *l;
+
+       /* 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 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 tablspace names 
+                        * We do not check for USAGE rights should we?
+                        */
+                       if (get_tablespace_oid(curname) == InvalidOid)
+                               ereport((source == PGC_S_TEST) ? NOTICE : ERROR,
+                                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                               errmsg("tablespace \"%s\" does not exist", curname)));
+               }
+               num_temp_tablespaces++;
+       }
+
+       /*
+        * Select the first tablespace to use
+        */
+       next_temp_tablespace = MyProcPid % num_temp_tablespaces;
+
+       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"
+ *
+ * This exists to hide the temp_tablespace GUC variable.
+ */
+Oid
+GetTempTablespace(void)
+{
+       Oid                     result;
+       char *curname = NULL;
+       char *rawname;
+       List *namelist;
+       ListCell *l;
+       int i = 0;
+       
+       if ( temp_tablespaces == NULL )
+               return InvalidOid;
+
+       /* Need a modifiable version of temp_tablespaces */
+       rawname = pstrdup(temp_tablespaces);
+
+       /* Parse string into list of identifiers */
+       if (!SplitIdentifierString(rawname, ',', &namelist))
+       {
+               /* syntax error in name list */
+               pfree(rawname);
+               list_free(namelist);
+               return InvalidOid;
+       }
+
+       /* 
+        * Iterate through the list of namespaces until the one we need 
+        * (next_temp_tablespace) 
+        */
+       foreach(l, namelist)
+       {
+               curname = (char *) lfirst(l);
+               if ( i == next_temp_tablespace )
+                       break;
+               i++;
+       }
+
+
+       /* Prepare for the next time the function is called */
+       next_temp_tablespace++;
+       if (next_temp_tablespace == num_temp_tablespaces)
+               next_temp_tablespace = 0;
+
+       /* Fast path for temp_tablespaces == "" */
+       if ( curname == NULL || curname[0] == '\0') {
+               list_free(namelist);
+               pfree(rawname);
+               return InvalidOid;
+       }
+
+       /*
+        * It is tempting to cache this lookup for more speed, but then we would
+        * fail to detect the case where the tablespace was dropped since the GUC
+        * variable was set.  Note also that we don't complain if the value fails
+        * to refer to an existing tablespace; we just silently return InvalidOid,
+        * causing the new object to be created in the database's tablespace.
+        */
+       result = get_tablespace_oid(curname);
+
+       /* We don't free rawname before because curname points to a part of it */
+       pfree(rawname);
+
+       /*
+        * Allow explicit specification of database's default tablespace in
+        * default_tablespace without triggering permissions checks.
+        */
+       if (result == MyDatabaseTableSpace)
+               result = InvalidOid;
+       
+       list_free(namelist);
+       return result;
+}
 
 /*
  * get_tablespace_oid - given a tablespace name, look up the OID
index 06bc519..2991655 100644 (file)
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.284 2007/01/25 02:17:26 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.285 2007/01/25 04:35:10 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2409,6 +2409,10 @@ OpenIntoRel(QueryDesc *queryDesc)
                                         errmsg("tablespace \"%s\" does not exist",
                                                        parseTree->intoTableSpaceName)));
        }
+       else if (parseTree->into->istemp)
+       {
+               tablespaceId = GetTempTablespace();
+       }
        else
        {
                tablespaceId = GetDefaultTablespace();
index 53ba251..486dd06 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.134 2007/01/09 22:03:51 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.135 2007/01/25 04:35:10 momjian Exp $
  *
  * NOTES:
  *
@@ -46,6 +46,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 
+#include "commands/tablespace.h"
+
 #include "miscadmin.h"
 #include "access/xact.h"
 #include "storage/fd.h"
@@ -76,6 +78,7 @@
  */
 #define FD_MINFREE                             10
 
+#define OIDCHARS        10                      /* max chars printed by %u */
 
 /*
  * A number of platforms allow individual processes to open many more files
@@ -880,13 +883,51 @@ OpenTemporaryFile(bool interXact)
 {
        char            tempfilepath[MAXPGPATH];
        File            file;
+       Oid             oid;
+       char            *path;
+       int             pathlen;
 
        /*
-        * Generate a tempfile name that should be unique within the current
-        * database instance.
+        * Take a look what should be the path of the temporary file
         */
-       snprintf(tempfilepath, sizeof(tempfilepath),
-                        "%s/%s%d.%ld", PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
+       oid = GetTempTablespace();
+       if (oid != InvalidOid)
+       {
+               /*
+                * As we got a valid tablespace, try to create the
+                * file there
+                */
+
+               pathlen = strlen("pg_tblspc/") + OIDCHARS + 1;
+               path = (char *) palloc(pathlen);
+               snprintf(path, pathlen, "pg_tblspc/%u", oid );
+
+               /*
+                * Generate a tempfile name that should be unique within the current
+                * database instance.
+                */
+               snprintf(tempfilepath, sizeof(tempfilepath),
+                                "%s/%s%d.%ld", path, PG_TEMP_FILE_PREFIX,
+                                MyProcPid, tempFileCounter++);
+               pfree(path);
+               file = PathNameOpenFile(tempfilepath,
+                                                       O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
+                                                       0600);
+       }
+
+       /*
+        * Create a normal temporary file if no tablespace returned or
+        * couldn't create the file in the tablespace "oid"
+        */
+       if (oid == InvalidOid || file <= 0) 
+       {
+               path = PG_TEMP_FILES_DIR;
+               /*
+                * Generate a tempfile name that should be unique within the current
+                * database instance.
+                */
+               snprintf(tempfilepath, sizeof(tempfilepath),
+                                "%s/%s%d.%ld", path, PG_TEMP_FILE_PREFIX,
                         MyProcPid, tempFileCounter++);
 
        /*
@@ -918,7 +959,8 @@ OpenTemporaryFile(bool interXact)
                if (file <= 0)
                        elog(ERROR, "could not create temporary file \"%s\": %m",
                                 tempfilepath);
-       }
+               }
+       }
 
        /* Mark it for deletion at close */
        VfdCache[file].fdstate |= FD_TEMPORARY;
@@ -1292,6 +1334,20 @@ TryAgain:
                errno = save_errno;
        }
 
+       /*
+        * TEMPORARY hack to log the Windows error code on fopen failures, in
+        * hopes of diagnosing some hard-to-reproduce problems.
+        */
+#ifdef WIN32
+       {
+               int                     save_errno = errno;
+
+               elog(LOG, "Windows fopen(\"%s\",\"%s\") failed: code %lu, errno %d",
+                        name, mode, GetLastError(), save_errno);
+               errno = save_errno;
+       }
+#endif
+
        return NULL;
 }
 
index 7962c99..9f2cdc4 100644 (file)
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.369 2007/01/19 16:58:46 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.370 2007/01/25 04:35:11 momjian Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -99,6 +99,7 @@ extern bool Log_disconnections;
 extern int     CommitDelay;
 extern int     CommitSiblings;
 extern char *default_tablespace;
+extern char *temp_tablespaces;
 extern bool fullPageWrites;
 
 #ifdef TRACE_SORT
@@ -2291,6 +2292,16 @@ static struct config_string ConfigureNamesString[] =
                "base64", assign_xmlbinary, NULL
        },
 
+       {
+               {"temp_tablespaces", PGC_USERSET, PGC_S_FILE,
+                       gettext_noop("Sets the tablespaces suitable for creating new objects and sort files."),
+                       NULL,
+                       GUC_LIST_INPUT | GUC_LIST_QUOTE 
+               },
+               &temp_tablespaces,
+               NULL, assign_temp_tablespaces, NULL
+       },
+
        /* End-of-list marker */
        {
                {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL
index 5e6ecac..3b9730c 100644 (file)
 #search_path = '"$user",public'                # schema names
 #default_tablespace = ''               # a tablespace name, '' uses
                                        # the default
+#temp_tablespaces = ''                 # a list of tablespace names, 
+                                       # '' uses default_tablespace
 #check_function_bodies = on
 #default_transaction_isolation = 'read committed'
 #default_transaction_read_only = off
index 7456eb2..6d3a333 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.14 2007/01/05 22:19:54 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.15 2007/01/25 04:35:11 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -41,6 +41,7 @@ extern void AlterTableSpaceOwner(const char *name, Oid newOwnerId);
 extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
 
 extern Oid     GetDefaultTablespace(void);
+extern Oid     GetTempTablespace(void);
 
 extern Oid     get_tablespace_oid(const char *tablespacename);
 extern char *get_tablespace_name(Oid spc_oid);
index d324d66..51cc05a 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 2000-2007, PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
- * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.78 2007/01/09 21:31:17 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.79 2007/01/25 04:35:11 momjian Exp $
  *--------------------------------------------------------------------
  */
 #ifndef GUC_H
@@ -238,4 +238,8 @@ extern const char *assign_search_path(const char *newval,
 extern const char *assign_xlog_sync_method(const char *method,
                                                bool doit, GucSource source);
 
+/* in commands/tablespace.c */
+extern const char *assign_temp_tablespaces(const char *newval,
+                                                 bool doit, GucSource source);
+
 #endif   /* GUC_H */