aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/indexcmds.c10
-rw-r--r--src/backend/commands/tablecmds.c6
-rw-r--r--src/backend/commands/tablespace.c143
-rw-r--r--src/backend/executor/execMain.c6
-rw-r--r--src/backend/storage/file/fd.c68
-rw-r--r--src/backend/utils/misc/guc.c13
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample2
-rw-r--r--src/include/commands/tablespace.h3
-rw-r--r--src/include/utils/guc.h6
9 files changed, 242 insertions, 15 deletions
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 2d51dfb11fe..a7183127110 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -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 */
}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index ced08506bce..a11cde3647e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -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();
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index cd86aef4019..d2cb245f150 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -65,9 +65,12 @@
#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
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 06bc519dde3..29916550af4 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -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();
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 53ba25115a2..486dd06bdc5 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -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;
}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 7962c992acc..9f2cdc43f77 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -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
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 5e6ecacb744..3b9730c75bb 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -399,6 +399,8 @@
#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
diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h
index 7456eb2445e..6d3a333cf29 100644
--- a/src/include/commands/tablespace.h
+++ b/src/include/commands/tablespace.h
@@ -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);
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index d324d66c22a..51cc05a7a73 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -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 */