/* * PrepareTempTablespaces -- prepare to use temp tablespaces * * 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. */ void PrepareTempTablespaces(void) { char *rawname; List *namelist; Oid *tblSpcs; int numSpcs; ListCell *l; /* No work if already done in current transaction */ if (TempTablespacesAreSet()) return; /* * 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); /* Parse string into list of identifiers */ if (!SplitIdentifierString(rawname, ',', &namelist)) { /* syntax error in name list */ SetTempTablespaces(NULL, 0); pfree(rawname); list_free(namelist); return; } /* Store tablespace OIDs in an array in TopTransactionContext */ 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 */ 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 (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; }
/* 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; /* 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; } /* * 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 (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 */ 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); }