-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.125 2007/06/03 17:05:29 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.126 2007/06/07 19:19:56 tgl Exp $ -->
<chapter Id="runtime-config">
<title>Server Configuration</title>
<para>
The value is a list of names of tablespaces. When there is more than
one name in the list, <productname>PostgreSQL</> chooses a random
- member of the list each time a temporary object is to be created.
+ member of the list each time a temporary object is to be created;
+ except that within a transaction, successively created temporary
+ objects are placed in successive tablespaces from the list.
+ If any element of the list is an empty string,
+ <productname>PostgreSQL</> will automatically use the default
+ tablespace of the current database instead.
</para>
<para>
- If any element of the list is an empty string or does not match the
- name of any existing tablespace, <productname>PostgreSQL</> will
- automatically use the default tablespace of the current database
- instead. If a nondefault tablespace
- is specified, the user must have <literal>CREATE</> privilege
- for it, or creation attempts will fail.
+ When <varname>temp_tablespaces</> is set interactively, specifying a
+ nonexistent tablespace is an error, as is specifying a tablespace for
+ which the user does not have <literal>CREATE</> privilege. However,
+ when using a previously set value, nonexistent tablespaces are
+ ignored, as are tablespaces for which the user lacks
+ <literal>CREATE</> privilege. In particular, this rule applies when
+ using a value set in <filename>postgresql.conf</>.
</para>
<para>
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.47 2007/06/03 17:06:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.48 2007/06/07 19:19:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
+#include "utils/memutils.h"
/* GUC variables */
static bool remove_tablespace_directories(Oid tablespaceoid, bool redo);
static void set_short_version(const char *path);
-static Oid getTempTablespace(void);
/*
{
Oid result;
- /* The temp-table case is handled by getTempTablespace() */
+ /* The temp-table case is handled elsewhere */
if (forTemp)
- return getTempTablespace();
+ {
+ PrepareTempTablespaces();
+ return GetNextTempTableSpace();
+ }
/* Fast path for default_tablespace == "" */
if (default_tablespace == NULL || default_tablespace[0] == '\0')
{
char *rawname;
List *namelist;
- ListCell *l;
/* Need a modifiable copy of string */
rawname = pstrdup(newval);
/*
* If we aren't inside a transaction, we cannot do database access so
* cannot verify the individual names. Must accept the list on faith.
+ * Fortunately, there's then also no need to pass the data to fd.c.
*/
- if (source >= PGC_S_INTERACTIVE && IsTransactionState())
+ if (IsTransactionState())
{
+ /*
+ * If we error out below, or if we are called multiple times in one
+ * transaction, we'll leak a bit of TopTransactionContext memory.
+ * Doesn't seem worth worrying about.
+ */
+ Oid *tblSpcs;
+ int numSpcs;
+ ListCell *l;
+
+ tblSpcs = (Oid *) MemoryContextAlloc(TopTransactionContext,
+ list_length(namelist) * sizeof(Oid));
+ numSpcs = 0;
foreach(l, namelist)
{
char *curname = (char *) lfirst(l);
+ Oid curoid;
+ AclResult aclresult;
/* Allow an empty string (signifying database default) */
if (curname[0] == '\0')
+ {
+ tblSpcs[numSpcs++] = InvalidOid;
continue;
+ }
/* Else verify that name is a valid tablespace name */
- if (get_tablespace_oid(curname) == InvalidOid)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("tablespace \"%s\" does not exist",
- curname)));
+ curoid = get_tablespace_oid(curname);
+ if (curoid == InvalidOid)
+ {
+ /*
+ * In an interactive SET command, we ereport for bad info.
+ * Otherwise, silently ignore any bad list elements.
+ */
+ if (source >= PGC_S_INTERACTIVE)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("tablespace \"%s\" does not exist",
+ curname)));
+ continue;
+ }
+
+ /*
+ * Allow explicit specification of database's default tablespace
+ * in temp_tablespaces without triggering permissions checks.
+ */
+ if (curoid == MyDatabaseTableSpace)
+ {
+ tblSpcs[numSpcs++] = InvalidOid;
+ continue;
+ }
+
+ /* Check permissions similarly */
+ aclresult = pg_tablespace_aclcheck(curoid, GetUserId(),
+ ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ {
+ if (source >= PGC_S_INTERACTIVE)
+ aclcheck_error(aclresult, ACL_KIND_TABLESPACE, curname);
+ continue;
+ }
+
+ tblSpcs[numSpcs++] = curoid;
}
+
+ /* If actively "doing it", give the new list to fd.c */
+ if (doit)
+ SetTempTablespaces(tblSpcs, numSpcs);
+ else
+ pfree(tblSpcs);
}
pfree(rawname);
}
/*
- * GetTempTablespace -- get the OID of the next temp tablespace to use
- *
- * May return InvalidOid to indicate "use the database's default tablespace".
+ * PrepareTempTablespaces -- prepare to use temp tablespaces
*
- * This is different from GetDefaultTablespace(true) in just two ways:
- * 1. We check privileges here instead of leaving it to the caller.
- * 2. It's safe to call this outside a transaction (we just return InvalidOid).
- * The transaction state check is used so that this can be called from
- * low-level places that might conceivably run outside a transaction.
+ * If we have not already done so in the current transaction, parse the
+ * temp_tablespaces GUC variable and tell fd.c which tablespace(s) to use
+ * for temp files.
*/
-Oid
-GetTempTablespace(void)
-{
- Oid result;
-
- /* Can't do catalog access unless within a transaction */
- if (!IsTransactionState())
- return InvalidOid;
-
- /* OK, select a temp tablespace */
- result = getTempTablespace();
-
- /* Check permissions except when using database's default */
- if (OidIsValid(result))
- {
- AclResult aclresult;
-
- aclresult = pg_tablespace_aclcheck(result, GetUserId(),
- ACL_CREATE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
- get_tablespace_name(result));
- }
-
- return result;
-}
-
-/*
- * getTempTablespace -- get the OID of the next temp tablespace to use
- *
- * This has exactly the API defined for GetDefaultTablespace(true),
- * in particular that caller is responsible for permissions checks.
- *
- * This exists to hide (and possibly optimize the use of) the
- * temp_tablespaces GUC variable.
- */
-static Oid
-getTempTablespace(void)
+void
+PrepareTempTablespaces(void)
{
- Oid result;
char *rawname;
List *namelist;
- int nnames;
- char *curname;
+ Oid *tblSpcs;
+ int numSpcs;
+ ListCell *l;
- if (temp_tablespaces == NULL)
- return InvalidOid;
+ /* No work if already done in current transaction */
+ if (TempTablespacesAreSet())
+ return;
/*
- * We re-parse the string on each call; this is a bit expensive, but
- * we don't expect this function will be called many times per query,
- * so it's probably not worth being tenser.
+ * Can't do catalog access unless within a transaction. This is just
+ * a safety check in case this function is called by low-level code that
+ * could conceivably execute outside a transaction. Note that in such
+ * a scenario, fd.c will fall back to using the current database's default
+ * tablespace, which should always be OK.
*/
+ if (!IsTransactionState())
+ return;
/* Need a modifiable copy of string */
rawname = pstrdup(temp_tablespaces);
if (!SplitIdentifierString(rawname, ',', &namelist))
{
/* syntax error in name list */
+ SetTempTablespaces(NULL, 0);
pfree(rawname);
list_free(namelist);
- return InvalidOid;
+ return;
}
- nnames = list_length(namelist);
- /* Fast path for temp_tablespaces == "" */
- if (nnames == 0)
+ /* Store tablespace OIDs in an array in TopTransactionContext */
+ tblSpcs = (Oid *) MemoryContextAlloc(TopTransactionContext,
+ list_length(namelist) * sizeof(Oid));
+ numSpcs = 0;
+ foreach(l, namelist)
{
- pfree(rawname);
- list_free(namelist);
- return InvalidOid;
- }
+ char *curname = (char *) lfirst(l);
+ Oid curoid;
+ AclResult aclresult;
- /* Select a random element */
- if (nnames == 1) /* no need for a random() call */
- curname = (char *) linitial(namelist);
- else
- curname = (char *) list_nth(namelist, random() % nnames);
+ /* Allow an empty string (signifying database default) */
+ if (curname[0] == '\0')
+ {
+ tblSpcs[numSpcs++] = InvalidOid;
+ continue;
+ }
- /*
- * Empty string means "database's default", else look up the tablespace.
- *
- * 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.
- */
- if (curname[0] == '\0')
- result = InvalidOid;
- else
- result = get_tablespace_oid(curname);
+ /* Else verify that name is a valid tablespace name */
+ curoid = get_tablespace_oid(curname);
+ if (curoid == InvalidOid)
+ {
+ /* Silently ignore any bad list elements */
+ continue;
+ }
- /*
- * Allow explicit specification of database's default tablespace in
- * temp_tablespaces without triggering permissions checks.
- */
- if (result == MyDatabaseTableSpace)
- result = InvalidOid;
+ /*
+ * Allow explicit specification of database's default tablespace
+ * in temp_tablespaces without triggering permissions checks.
+ */
+ if (curoid == MyDatabaseTableSpace)
+ {
+ tblSpcs[numSpcs++] = InvalidOid;
+ continue;
+ }
+
+ /* Check permissions similarly */
+ aclresult = pg_tablespace_aclcheck(curoid, GetUserId(),
+ ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ continue;
+
+ tblSpcs[numSpcs++] = curoid;
+ }
+
+ SetTempTablespaces(tblSpcs, numSpcs);
pfree(rawname);
list_free(namelist);
-
- return result;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.113 2007/06/03 17:07:14 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.114 2007/06/07 19:19:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
hashtable->totalTuples = 0;
hashtable->innerBatchFile = NULL;
hashtable->outerBatchFile = NULL;
- hashtable->hashTblSpc = InvalidOid;
hashtable->spaceUsed = 0;
hashtable->spaceAllowed = work_mem * 1024L;
hashtable->outerBatchFile = (BufFile **)
palloc0(nbatch * sizeof(BufFile *));
/* The files will not be opened until needed... */
- /* ... but we want to choose the tablespace only once */
- hashtable->hashTblSpc = GetTempTablespace();
+ /* ... but make sure we have temp tablespaces established for them */
+ PrepareTempTablespaces();
}
/*
palloc0(nbatch * sizeof(BufFile *));
hashtable->outerBatchFile = (BufFile **)
palloc0(nbatch * sizeof(BufFile *));
- /* time to choose the tablespace, too */
- hashtable->hashTblSpc = GetTempTablespace();
+ /* time to establish the temp tablespaces, too */
+ PrepareTempTablespaces();
}
else
{
{
/* dump it out */
Assert(batchno > curbatch);
- ExecHashJoinSaveTuple(hashtable,
- HJTUPLE_MINTUPLE(tuple),
+ ExecHashJoinSaveTuple(HJTUPLE_MINTUPLE(tuple),
tuple->hashvalue,
&hashtable->innerBatchFile[batchno]);
/* and remove from hash table */
* put the tuple into a temp file for later batches
*/
Assert(batchno > hashtable->curbatch);
- ExecHashJoinSaveTuple(hashtable,
- tuple,
+ ExecHashJoinSaveTuple(tuple,
hashvalue,
&hashtable->innerBatchFile[batchno]);
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.90 2007/06/03 17:07:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.91 2007/06/07 19:19:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* in the corresponding outer-batch file.
*/
Assert(batchno > hashtable->curbatch);
- ExecHashJoinSaveTuple(hashtable,
- ExecFetchSlotMinimalTuple(outerTupleSlot),
+ ExecHashJoinSaveTuple(ExecFetchSlotMinimalTuple(outerTupleSlot),
hashvalue,
&hashtable->outerBatchFile[batchno]);
node->hj_NeedNewOuter = true;
* will get messed up.
*/
void
-ExecHashJoinSaveTuple(HashJoinTable hashtable,
- MinimalTuple tuple, uint32 hashvalue,
+ExecHashJoinSaveTuple(MinimalTuple tuple, uint32 hashvalue,
BufFile **fileptr)
{
BufFile *file = *fileptr;
if (file == NULL)
{
/* First write to this batch file, so open it. */
- file = BufFileCreateTemp(false, hashtable->hashTblSpc);
+ file = BufFileCreateTemp(false);
*fileptr = file;
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/file/buffile.c,v 1.27 2007/06/03 17:07:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/file/buffile.c,v 1.28 2007/06/07 19:19:57 tgl Exp $
*
* NOTES:
*
* The maximum safe file size is presumed to be RELSEG_SIZE * BLCKSZ.
* Note we adhere to this limit whether or not LET_OS_MANAGE_FILESIZE
* is defined, although md.c ignores it when that symbol is defined.
+ * The reason for doing this is that we'd like large temporary BufFiles
+ * to be spread across multiple tablespaces when available.
*/
#define MAX_PHYSICAL_FILESIZE (RELSEG_SIZE * BLCKSZ)
* offsets[i] is the current seek position of files[i]. We use this to
* avoid making redundant FileSeek calls.
*/
- Oid tblspcOid; /* tablespace to use (InvalidOid = default) */
bool isTemp; /* can only add files if this is TRUE */
bool isInterXact; /* keep open over transactions? */
/*
* Create a BufFile given the first underlying physical file.
- * NOTE: caller must set tblspcOid, isTemp, isInterXact if appropriate.
+ * NOTE: caller must set isTemp and isInterXact if appropriate.
*/
static BufFile *
makeBufFile(File firstfile)
file->files[0] = firstfile;
file->offsets = (long *) palloc(sizeof(long));
file->offsets[0] = 0L;
- file->tblspcOid = InvalidOid;
file->isTemp = false;
file->isInterXact = false;
file->dirty = false;
File pfile;
Assert(file->isTemp);
- pfile = OpenTemporaryFile(file->isInterXact, file->tblspcOid);
+ pfile = OpenTemporaryFile(file->isInterXact);
Assert(pfile >= 0);
file->files = (File *) repalloc(file->files,
* written to it).
*
* If interXact is true, the temp file will not be automatically deleted
- * at end of transaction. If tblspcOid is not InvalidOid, the temp file
- * is created in the specified tablespace instead of the default one.
+ * at end of transaction.
*
* Note: if interXact is true, the caller had better be calling us in a
* memory context that will survive across transaction boundaries.
*/
BufFile *
-BufFileCreateTemp(bool interXact, Oid tblspcOid)
+BufFileCreateTemp(bool interXact)
{
BufFile *file;
File pfile;
- pfile = OpenTemporaryFile(interXact, tblspcOid);
+ pfile = OpenTemporaryFile(interXact);
Assert(pfile >= 0);
file = makeBufFile(pfile);
- file->tblspcOid = tblspcOid;
file->isTemp = true;
file->isInterXact = interXact;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.138 2007/06/03 17:07:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.139 2007/06/07 19:19:57 tgl Exp $
*
* NOTES:
*
*/
static long tempFileCounter = 0;
+/*
+ * Array of OIDs of temp tablespaces. When numTempTableSpaces is -1,
+ * this has not been set in the current transaction.
+ */
+static Oid *tempTableSpaces = NULL;
+static int numTempTableSpaces = -1;
+static int nextTempTableSpace = 0;
+
/*--------------------
*
* that created them, so this should be false -- but if you need
* "somewhat" temporary storage, this might be useful. In either case,
* the file is removed when the File is explicitly closed.
- *
- * tblspcOid: the Oid of the tablespace where the temp file should be created.
- * If InvalidOid, or if the tablespace can't be found, we silently fall back
- * to the database's default tablespace.
*/
File
-OpenTemporaryFile(bool interXact, Oid tblspcOid)
+OpenTemporaryFile(bool interXact)
{
File file = 0;
/*
- * If caller specified a tablespace, try to create there.
+ * If some temp tablespace(s) have been given to us, try to use the next
+ * one. If a given tablespace can't be found, we silently fall back
+ * to the database's default tablespace.
+ *
+ * BUT: if the temp file is slated to outlive the current transaction,
+ * force it into the database's default tablespace, so that it will
+ * not pose a threat to possible tablespace drop attempts.
*/
- if (OidIsValid(tblspcOid))
- file = OpenTemporaryFileInTablespace(tblspcOid, false);
+ if (numTempTableSpaces > 0 && !interXact)
+ {
+ Oid tblspcOid = GetNextTempTableSpace();
+
+ if (OidIsValid(tblspcOid))
+ file = OpenTemporaryFileInTablespace(tblspcOid, false);
+ }
/*
* If not, or if tablespace is bad, create in database's default
}
}
+
+/*
+ * SetTempTablespaces
+ *
+ * Define a list (actually an array) of OIDs of tablespaces to use for
+ * temporary files. This list will be used until end of transaction,
+ * unless this function is called again before then. It is caller's
+ * responsibility that the passed-in array has adequate lifespan (typically
+ * it'd be allocated in TopTransactionContext).
+ */
+void
+SetTempTablespaces(Oid *tableSpaces, int numSpaces)
+{
+ Assert(numSpaces >= 0);
+ tempTableSpaces = tableSpaces;
+ numTempTableSpaces = numSpaces;
+ /*
+ * Select a random starting point in the list. This is to minimize
+ * conflicts between backends that are most likely sharing the same
+ * list of temp tablespaces. Note that if we create multiple temp
+ * files in the same transaction, we'll advance circularly through
+ * the list --- this ensures that large temporary sort files are
+ * nicely spread across all available tablespaces.
+ */
+ if (numSpaces > 1)
+ nextTempTableSpace = random() % numSpaces;
+ else
+ nextTempTableSpace = 0;
+}
+
+/*
+ * TempTablespacesAreSet
+ *
+ * Returns TRUE if SetTempTablespaces has been called in current transaction.
+ * (This is just so that tablespaces.c doesn't need its own per-transaction
+ * state.)
+ */
+bool
+TempTablespacesAreSet(void)
+{
+ return (numTempTableSpaces >= 0);
+}
+
+/*
+ * GetNextTempTableSpace
+ *
+ * Select the next temp tablespace to use. A result of InvalidOid means
+ * to use the current database's default tablespace.
+ */
+Oid
+GetNextTempTableSpace(void)
+{
+ if (numTempTableSpaces > 0)
+ {
+ /* Advance nextTempTableSpace counter with wraparound */
+ if (++nextTempTableSpace >= numTempTableSpaces)
+ nextTempTableSpace = 0;
+ return tempTableSpaces[nextTempTableSpace];
+ }
+ return InvalidOid;
+}
+
+
/*
* AtEOSubXact_Files
*
* particularly care which). All still-open per-transaction temporary file
* VFDs are closed, which also causes the underlying files to be
* deleted. Furthermore, all "allocated" stdio files are closed.
+ * We also forget any transaction-local temp tablespace list.
*/
void
AtEOXact_Files(void)
{
CleanupTempFiles(false);
+ tempTableSpaces = NULL;
+ numTempTableSpaces = -1;
}
/*
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/sort/logtape.c,v 1.24 2007/06/03 17:08:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/sort/logtape.c,v 1.25 2007/06/07 19:19:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
-#include "commands/tablespace.h"
#include "storage/buffile.h"
#include "utils/logtape.h"
Assert(ntapes > 0);
lts = (LogicalTapeSet *) palloc(sizeof(LogicalTapeSet) +
(ntapes - 1) *sizeof(LogicalTape));
- lts->pfile = BufFileCreateTemp(false, GetTempTablespace());
+ lts->pfile = BufFileCreateTemp(false);
lts->nFileBlocks = 0L;
lts->forgetFreeSpace = false;
lts->blocksSorted = true; /* a zero-length array is sorted ... */
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.76 2007/05/04 21:29:53 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.77 2007/06/07 19:19:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "access/nbtree.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_operator.h"
+#include "commands/tablespace.h"
#include "miscadmin.h"
#include "utils/datum.h"
#include "utils/logtape.h"
if (tapeSpace + GetMemoryChunkSpace(state->memtuples) < state->allowedMem)
USEMEM(state, tapeSpace);
+ /*
+ * Make sure that the temp file(s) underlying the tape set are created in
+ * suitable temp tablespaces.
+ */
+ PrepareTempTablespaces();
+
/*
* Create the tape set and allocate the per-tape data arrays.
*/
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.32 2007/06/03 17:08:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.33 2007/06/07 19:19:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
return;
/*
- * Nope; time to switch to tape-based operation.
- *
- * If the temp table is slated to outlive the current transaction,
- * force it into my database's default tablespace, so that it will
- * not pose a threat to possible tablespace drop attempts.
+ * Nope; time to switch to tape-based operation. Make sure that
+ * the temp file(s) are created in suitable temp tablespaces.
*/
- state->myfile = BufFileCreateTemp(state->interXact,
- state->interXact ? InvalidOid :
- GetTempTablespace());
+ PrepareTempTablespaces();
+ state->myfile = BufFileCreateTemp(state->interXact);
state->status = TSS_WRITEFILE;
dumptuples(state);
break;
* 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.17 2007/06/03 17:08:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.18 2007/06/07 19:19:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
extern Oid GetDefaultTablespace(bool forTemp);
-extern Oid GetTempTablespace(void);
+
+extern void PrepareTempTablespaces(void);
extern Oid get_tablespace_oid(const char *tablespacename);
extern char *get_tablespace_name(Oid spc_oid);
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.46 2007/06/03 17:08:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.47 2007/06/07 19:19:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
BufFile **innerBatchFile; /* buffered virtual temp file per batch */
BufFile **outerBatchFile; /* buffered virtual temp file per batch */
- Oid hashTblSpc; /* tablespace to put temp files in */
-
/*
* Info about the datatype-specific hash functions for the datatypes being
* hashed. These are arrays of the same length as the number of hash join
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/executor/nodeHashjoin.h,v 1.35 2007/06/03 17:08:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/executor/nodeHashjoin.h,v 1.36 2007/06/07 19:19:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern void ExecEndHashJoin(HashJoinState *node);
extern void ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt);
-extern void ExecHashJoinSaveTuple(HashJoinTable hashtable,
- MinimalTuple tuple, uint32 hashvalue,
- BufFile **fileptr);
+extern void ExecHashJoinSaveTuple(MinimalTuple tuple, uint32 hashvalue,
+ BufFile **fileptr);
#endif /* NODEHASHJOIN_H */
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/buffile.h,v 1.21 2007/06/03 17:08:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/buffile.h,v 1.22 2007/06/07 19:19:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* prototypes for functions in buffile.c
*/
-extern BufFile *BufFileCreateTemp(bool interXact, Oid tblspcOid);
+extern BufFile *BufFileCreateTemp(bool interXact);
extern void BufFileClose(BufFile *file);
extern size_t BufFileRead(BufFile *file, void *ptr, size_t size);
extern size_t BufFileWrite(BufFile *file, void *ptr, size_t size);
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/fd.h,v 1.58 2007/06/03 17:08:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/fd.h,v 1.59 2007/06/07 19:19:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* Operations on virtual Files --- equivalent to Unix kernel file ops */
extern File PathNameOpenFile(FileName fileName, int fileFlags, int fileMode);
-extern File OpenTemporaryFile(bool interXact, Oid tblspcOid);
+extern File OpenTemporaryFile(bool interXact);
extern void FileClose(File file);
extern void FileUnlink(File file);
extern int FileRead(File file, char *buffer, int amount);
extern void InitFileAccess(void);
extern void set_max_safe_fds(void);
extern void closeAllVfds(void);
+extern void SetTempTablespaces(Oid *tableSpaces, int numSpaces);
+extern bool TempTablespacesAreSet(void);
+extern Oid GetNextTempTableSpace(void);
extern void AtEOXact_Files(void);
extern void AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
SubTransactionId parentSubid);
extern void RemovePgTempFiles(void);
+
extern int pg_fsync(int fd);
extern int pg_fsync_no_writethrough(int fd);
extern int pg_fsync_writethrough(int fd);