LCOV - differential code coverage report
Current view: top level - src/backend/commands - tablespace.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 74.8 % 409 306 2 14 63 24 21 203 10 72 58 209 11
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 17 17 15 2 13 3
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (120,180] days: 66.7 % 6 4 2 4
Legend: Lines: hit not hit (180,240] days: 100.0 % 1 1 1
(240..) days: 74.9 % 402 301 14 63 24 20 203 6 72 58 209
Function coverage date bins:
(240..) days: 56.7 % 30 17 15 2 13

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * tablespace.c
                                  4                 :  *    Commands to manipulate table spaces
                                  5                 :  *
                                  6                 :  * Tablespaces in PostgreSQL are designed to allow users to determine
                                  7                 :  * where the data file(s) for a given database object reside on the file
                                  8                 :  * system.
                                  9                 :  *
                                 10                 :  * A tablespace represents a directory on the file system. At tablespace
                                 11                 :  * creation time, the directory must be empty. To simplify things and
                                 12                 :  * remove the possibility of having file name conflicts, we isolate
                                 13                 :  * files within a tablespace into database-specific subdirectories.
                                 14                 :  *
                                 15                 :  * To support file access via the information given in RelFileLocator, we
                                 16                 :  * maintain a symbolic-link map in $PGDATA/pg_tblspc. The symlinks are
                                 17                 :  * named by tablespace OIDs and point to the actual tablespace directories.
                                 18                 :  * There is also a per-cluster version directory in each tablespace.
                                 19                 :  * Thus the full path to an arbitrary file is
                                 20                 :  *          $PGDATA/pg_tblspc/spcoid/PG_MAJORVER_CATVER/dboid/relfilenumber
                                 21                 :  * e.g.
                                 22                 :  *          $PGDATA/pg_tblspc/20981/PG_9.0_201002161/719849/83292814
                                 23                 :  *
                                 24                 :  * There are two tablespaces created at initdb time: pg_global (for shared
                                 25                 :  * tables) and pg_default (for everything else).  For backwards compatibility
                                 26                 :  * and to remain functional on platforms without symlinks, these tablespaces
                                 27                 :  * are accessed specially: they are respectively
                                 28                 :  *          $PGDATA/global/relfilenumber
                                 29                 :  *          $PGDATA/base/dboid/relfilenumber
                                 30                 :  *
                                 31                 :  * To allow CREATE DATABASE to give a new database a default tablespace
                                 32                 :  * that's different from the template database's default, we make the
                                 33                 :  * provision that a zero in pg_class.reltablespace means the database's
                                 34                 :  * default tablespace.  Without this, CREATE DATABASE would have to go in
                                 35                 :  * and munge the system catalogs of the new database.
                                 36                 :  *
                                 37                 :  *
                                 38                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                 39                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                 40                 :  *
                                 41                 :  *
                                 42                 :  * IDENTIFICATION
                                 43                 :  *    src/backend/commands/tablespace.c
                                 44                 :  *
                                 45                 :  *-------------------------------------------------------------------------
                                 46                 :  */
                                 47                 : #include "postgres.h"
                                 48                 : 
                                 49                 : #include <unistd.h>
                                 50                 : #include <dirent.h>
                                 51                 : #include <sys/stat.h>
                                 52                 : 
                                 53                 : #include "access/heapam.h"
                                 54                 : #include "access/htup_details.h"
                                 55                 : #include "access/reloptions.h"
                                 56                 : #include "access/sysattr.h"
                                 57                 : #include "access/tableam.h"
                                 58                 : #include "access/xact.h"
                                 59                 : #include "access/xloginsert.h"
                                 60                 : #include "access/xlogutils.h"
                                 61                 : #include "catalog/binary_upgrade.h"
                                 62                 : #include "catalog/catalog.h"
                                 63                 : #include "catalog/dependency.h"
                                 64                 : #include "catalog/indexing.h"
                                 65                 : #include "catalog/namespace.h"
                                 66                 : #include "catalog/objectaccess.h"
                                 67                 : #include "catalog/pg_namespace.h"
                                 68                 : #include "catalog/pg_tablespace.h"
                                 69                 : #include "commands/comment.h"
                                 70                 : #include "commands/seclabel.h"
                                 71                 : #include "commands/tablecmds.h"
                                 72                 : #include "commands/tablespace.h"
                                 73                 : #include "common/file_perm.h"
                                 74                 : #include "miscadmin.h"
                                 75                 : #include "postmaster/bgwriter.h"
                                 76                 : #include "storage/fd.h"
                                 77                 : #include "storage/lmgr.h"
                                 78                 : #include "storage/standby.h"
                                 79                 : #include "utils/acl.h"
                                 80                 : #include "utils/builtins.h"
                                 81                 : #include "utils/fmgroids.h"
                                 82                 : #include "utils/guc_hooks.h"
                                 83                 : #include "utils/lsyscache.h"
                                 84                 : #include "utils/memutils.h"
                                 85                 : #include "utils/rel.h"
                                 86                 : #include "utils/varlena.h"
                                 87                 : 
                                 88                 : /* GUC variables */
                                 89                 : char       *default_tablespace = NULL;
                                 90                 : char       *temp_tablespaces = NULL;
                                 91                 : bool        allow_in_place_tablespaces = false;
                                 92                 : 
                                 93                 : Oid         binary_upgrade_next_pg_tablespace_oid = InvalidOid;
                                 94                 : 
                                 95                 : static void create_tablespace_directories(const char *location,
                                 96                 :                                           const Oid tablespaceoid);
                                 97                 : static bool destroy_tablespace_directories(Oid tablespaceoid, bool redo);
                                 98                 : 
                                 99                 : 
                                100                 : /*
                                101                 :  * Each database using a table space is isolated into its own name space
                                102                 :  * by a subdirectory named for the database OID.  On first creation of an
                                103                 :  * object in the tablespace, create the subdirectory.  If the subdirectory
                                104                 :  * already exists, fall through quietly.
                                105                 :  *
                                106                 :  * isRedo indicates that we are creating an object during WAL replay.
                                107                 :  * In this case we will cope with the possibility of the tablespace
                                108                 :  * directory not being there either --- this could happen if we are
                                109                 :  * replaying an operation on a table in a subsequently-dropped tablespace.
                                110                 :  * We handle this by making a directory in the place where the tablespace
                                111                 :  * symlink would normally be.  This isn't an exact replay of course, but
                                112                 :  * it's the best we can do given the available information.
                                113                 :  *
                                114                 :  * If tablespaces are not supported, we still need it in case we have to
                                115                 :  * re-create a database subdirectory (of $PGDATA/base) during WAL replay.
                                116                 :  */
                                117                 : void
  277 rhaas                     118 GNC      218866 : TablespaceCreateDbspace(Oid spcOid, Oid dbOid, bool isRedo)
                                119                 : {
                                120                 :     struct stat st;
                                121                 :     char       *dir;
                                122                 : 
                                123                 :     /*
                                124                 :      * The global tablespace doesn't have per-database subdirectories, so
                                125                 :      * nothing to do for it.
                                126                 :      */
                                127          218866 :     if (spcOid == GLOBALTABLESPACE_OID)
 6869 tgl                       128 CBC       18612 :         return;
                                129                 : 
  277 rhaas                     130 GNC      200254 :     Assert(OidIsValid(spcOid));
                                131          200254 :     Assert(OidIsValid(dbOid));
                                132                 : 
                                133          200254 :     dir = GetDatabasePath(dbOid, spcOid);
                                134                 : 
 6869 tgl                       135 CBC      200254 :     if (stat(dir, &st) < 0)
                                136                 :     {
                                137                 :         /* Directory does not exist? */
                                138              20 :         if (errno == ENOENT)
                                139                 :         {
                                140                 :             /*
                                141                 :              * Acquire TablespaceCreateLock to ensure that no DROP TABLESPACE
                                142                 :              * or TablespaceCreateDbspace is running concurrently.
                                143                 :              */
 6289                           144              20 :             LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE);
                                145                 : 
                                146                 :             /*
                                147                 :              * Recheck to see if someone created the directory while we were
                                148                 :              * waiting for lock.
                                149                 :              */
 6869                           150              20 :             if (stat(dir, &st) == 0 && S_ISDIR(st.st_mode))
                                151                 :             {
                                152                 :                 /* Directory was created */
                                153                 :             }
                                154                 :             else
                                155                 :             {
                                156                 :                 /* Directory creation failed? */
 1828 sfrost                    157              20 :                 if (MakePGDirectory(dir) < 0)
                                158                 :                 {
                                159                 :                     /* Failure other than not exists or not in WAL replay? */
 6797 tgl                       160 UBC           0 :                     if (errno != ENOENT || !isRedo)
                                161               0 :                         ereport(ERROR,
                                162                 :                                 (errcode_for_file_access(),
                                163                 :                                  errmsg("could not create directory \"%s\": %m",
                                164                 :                                         dir)));
                                165                 : 
                                166                 :                     /*
                                167                 :                      * During WAL replay, it's conceivable that several levels
                                168                 :                      * of directories are missing if tablespaces are dropped
                                169                 :                      * further ahead of the WAL stream than we're currently
                                170                 :                      * replaying.  An easy way forward is to create them as
                                171                 :                      * plain directories and hope they are removed by further
                                172                 :                      * WAL replay if necessary.  If this also fails, there is
                                173                 :                      * trouble we cannot get out of, so just report that and
                                174                 :                      * bail out.
                                175                 :                      */
  255 alvherre                  176               0 :                     if (pg_mkdir_p(dir, pg_dir_create_mode) < 0)
 6797 tgl                       177               0 :                         ereport(ERROR,
                                178                 :                                 (errcode_for_file_access(),
                                179                 :                                  errmsg("could not create directory \"%s\": %m",
                                180                 :                                         dir)));
                                181                 :                 }
                                182                 :             }
                                183                 : 
 6289 tgl                       184 CBC          20 :             LWLockRelease(TablespaceCreateLock);
                                185                 :         }
                                186                 :         else
                                187                 :         {
 6869 tgl                       188 UBC           0 :             ereport(ERROR,
                                189                 :                     (errcode_for_file_access(),
                                190                 :                      errmsg("could not stat directory \"%s\": %m", dir)));
                                191                 :         }
                                192                 :     }
                                193                 :     else
                                194                 :     {
                                195                 :         /* Is it not a directory? */
 6869 tgl                       196 CBC      200234 :         if (!S_ISDIR(st.st_mode))
 6869 tgl                       197 UBC           0 :             ereport(ERROR,
                                198                 :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                199                 :                      errmsg("\"%s\" exists but is not a directory",
                                200                 :                             dir)));
                                201                 :     }
                                202                 : 
 6869 tgl                       203 CBC      200254 :     pfree(dir);
                                204                 : }
                                205                 : 
                                206                 : /*
                                207                 :  * Create a table space
                                208                 :  *
                                209                 :  * Only superusers can create a tablespace. This seems a reasonable restriction
                                210                 :  * since we're determining the system layout and, anyway, we probably have
                                211                 :  * root if we're doing this kind of activity
                                212                 :  */
                                213                 : Oid
                                214              48 : CreateTableSpace(CreateTableSpaceStmt *stmt)
                                215                 : {
                                216                 :     Relation    rel;
 6797 bruce                     217 ECB             :     Datum       values[Natts_pg_tablespace];
  267 peter                     218 GNC          48 :     bool        nulls[Natts_pg_tablespace] = {0};
                                219                 :     HeapTuple   tuple;
                                220                 :     Oid         tablespaceoid;
                                221                 :     char       *location;
                                222                 :     Oid         ownerId;
                                223                 :     Datum       newOptions;
                                224                 :     bool        in_place;
                                225                 : 
  578 dgustafsson               226 ECB             :     /* Must be superuser */
 6869 tgl                       227 GBC          48 :     if (!superuser())
 6869 tgl                       228 UIC           0 :         ereport(ERROR,
                                229                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                230                 :                  errmsg("permission denied to create tablespace \"%s\"",
                                231                 :                         stmt->tablespacename),
                                232                 :                  errhint("Must be superuser to create a tablespace.")));
                                233                 : 
 6869 tgl                       234 ECB             :     /* However, the eventual owner of the tablespace need not be */
 6869 tgl                       235 GBC          48 :     if (stmt->owner)
 2953 alvherre                  236 UIC           0 :         ownerId = get_rolespec_oid(stmt->owner, false);
 6869 tgl                       237 ECB             :     else
 6494 tgl                       238 GIC          48 :         ownerId = GetUserId();
                                239                 : 
 6869 tgl                       240 ECB             :     /* Unix-ify the offered path, and strip any trailing slashes */
 6869 tgl                       241 CBC          48 :     location = pstrdup(stmt->location);
 6869 tgl                       242 GIC          48 :     canonicalize_path(location);
                                243                 : 
 6869 tgl                       244 ECB             :     /* disallow quotes, else CREATE DATABASE would be at risk */
 6869 tgl                       245 GBC          48 :     if (strchr(location, '\''))
 6869 tgl                       246 UIC           0 :         ereport(ERROR,
                                247                 :                 (errcode(ERRCODE_INVALID_NAME),
                                248                 :                  errmsg("tablespace location cannot contain single quotes")));
 6869 tgl                       249 ECB             : 
  450 tmunro                    250 GIC          48 :     in_place = allow_in_place_tablespaces && strlen(location) == 0;
                                251                 : 
                                252                 :     /*
                                253                 :      * Allowing relative paths seems risky
                                254                 :      *
                                255                 :      * This also helps us ensure that location is not empty or whitespace,
                                256                 :      * unless specifying a developer-only in-place tablespace.
 6869 tgl                       257 ECB             :      */
  450 tmunro                    258 CBC          48 :     if (!in_place && !is_absolute_path(location))
 6869 tgl                       259 GIC           6 :         ereport(ERROR,
                                260                 :                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                261                 :                  errmsg("tablespace location must be an absolute path")));
                                262                 : 
                                263                 :     /*
                                264                 :      * Check that location isn't too long. Remember that we're going to append
                                265                 :      * 'PG_XXX/<dboid>/<relid>_<fork>.<nnn>'.  FYI, we never actually
                                266                 :      * reference the whole path here, but MakePGDirectory() uses the first two
                                267                 :      * parts.
 6869 tgl                       268 ECB             :      */
 4835 bruce                     269 CBC          42 :     if (strlen(location) + 1 + strlen(TABLESPACE_VERSION_DIRECTORY) + 1 +
  193 rhaas                     270 GBC          42 :         OIDCHARS + 1 + OIDCHARS + 1 + FORKNAMECHARS + 1 + OIDCHARS > MAXPGPATH)
 6869 tgl                       271 UIC           0 :         ereport(ERROR,
                                272                 :                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                273                 :                  errmsg("tablespace location \"%s\" is too long",
                                274                 :                         location)));
                                275                 : 
 2903 bruce                     276 ECB             :     /* Warn if the tablespace is in the data directory. */
 2903 bruce                     277 GBC          42 :     if (path_is_prefix_of_path(DataDir, location))
 2903 bruce                     278 UIC           0 :         ereport(WARNING,
                                279                 :                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                280                 :                  errmsg("tablespace location should not be inside the data directory")));
                                281                 : 
                                282                 :     /*
                                283                 :      * Disallow creation of tablespaces named "pg_xxx"; we reserve this
                                284                 :      * namespace for system purposes.
 6866 tgl                       285 ECB             :      */
 6866 tgl                       286 CBC          42 :     if (!allowSystemTableMods && IsReservedName(stmt->tablespacename))
 6866 tgl                       287 GIC           1 :         ereport(ERROR,
                                288                 :                 (errcode(ERRCODE_RESERVED_NAME),
                                289                 :                  errmsg("unacceptable tablespace name \"%s\"",
                                290                 :                         stmt->tablespacename),
                                291                 :                  errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
                                292                 : 
                                293                 :     /*
                                294                 :      * If built with appropriate switch, whine when regression-testing
                                295                 :      * conventions for tablespace names are violated.
                                296                 :      */
                                297                 : #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
                                298                 :     if (strncmp(stmt->tablespacename, "regress_", 8) != 0)
                                299                 :         elog(WARNING, "tablespaces created by regression test cases should have names starting with \"regress_\"");
                                300                 : #endif
                                301                 : 
                                302                 :     /*
                                303                 :      * Check that there is no other tablespace by this name.  (The unique
                                304                 :      * index would catch this anyway, but might as well give a friendlier
                                305                 :      * message.)
 6869 tgl                       306 ECB             :      */
 4630 rhaas                     307 CBC          41 :     if (OidIsValid(get_tablespace_oid(stmt->tablespacename, true)))
 6869 tgl                       308 GIC           1 :         ereport(ERROR,
                                309                 :                 (errcode(ERRCODE_DUPLICATE_OBJECT),
                                310                 :                  errmsg("tablespace \"%s\" already exists",
                                311                 :                         stmt->tablespacename)));
                                312                 : 
                                313                 :     /*
                                314                 :      * Insert tuple into pg_tablespace.  The purpose of doing this first is to
                                315                 :      * lock the proposed tablename against other would-be creators. The
                                316                 :      * insertion will roll back if we find problems below.
 6869 tgl                       317 ECB             :      */
 1539 andres                    318 GIC          40 :     rel = table_open(TableSpaceRelationId, RowExclusiveLock);
 6869 tgl                       319 ECB             : 
  447 rhaas                     320 GBC          40 :     if (IsBinaryUpgrade)
  447 rhaas                     321 EUB             :     {
                                322                 :         /* Use binary-upgrade override for tablespace oid */
  447 rhaas                     323 UIC           0 :         if (!OidIsValid(binary_upgrade_next_pg_tablespace_oid))
                                324               0 :             ereport(ERROR,
  447 rhaas                     325 EUB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                326                 :                      errmsg("pg_tablespace OID value not set when in binary upgrade mode")));
                                327                 : 
  447 rhaas                     328 UIC           0 :         tablespaceoid = binary_upgrade_next_pg_tablespace_oid;
  447 rhaas                     329 LBC           0 :         binary_upgrade_next_pg_tablespace_oid = InvalidOid;
                                330                 :     }
  447 rhaas                     331 ECB             :     else
  447 rhaas                     332 CBC          40 :         tablespaceoid = GetNewOidWithIndex(rel, TablespaceOidIndexId,
  447 rhaas                     333 ECB             :                                            Anum_pg_tablespace_oid);
 1601 andres                    334 CBC          40 :     values[Anum_pg_tablespace_oid - 1] = ObjectIdGetDatum(tablespaceoid);
 6869 tgl                       335              40 :     values[Anum_pg_tablespace_spcname - 1] =
                                336              40 :         DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename));
 6869 tgl                       337 GIC          40 :     values[Anum_pg_tablespace_spcowner - 1] =
 6494                           338              40 :         ObjectIdGetDatum(ownerId);
 5271 tgl                       339 CBC          40 :     nulls[Anum_pg_tablespace_spcacl - 1] = true;
                                340                 : 
                                341                 :     /* Generate new proposed spcoptions (text array) */
 3368 sfrost                    342              40 :     newOptions = transformRelOptions((Datum) 0,
 3368 sfrost                    343 ECB             :                                      stmt->options,
                                344                 :                                      NULL, NULL, false, false);
 3368 sfrost                    345 GIC          40 :     (void) tablespace_reloptions(newOptions, true);
 3368 sfrost                    346 CBC          37 :     if (newOptions != (Datum) 0)
 3368 sfrost                    347 GIC           3 :         values[Anum_pg_tablespace_spcoptions - 1] = newOptions;
 3368 sfrost                    348 ECB             :     else
 3368 sfrost                    349 GIC          34 :         nulls[Anum_pg_tablespace_spcoptions - 1] = true;
 6869 tgl                       350 ECB             : 
 5271 tgl                       351 GIC          37 :     tuple = heap_form_tuple(rel->rd_att, values, nulls);
 6869 tgl                       352 ECB             : 
 1601 andres                    353 GIC          37 :     CatalogTupleInsert(rel, tuple);
                                354                 : 
 6869 tgl                       355 CBC          37 :     heap_freetuple(tuple);
                                356                 : 
                                357                 :     /* Record dependency on owner */
 6485                           358              37 :     recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId);
                                359                 : 
 4518 rhaas                     360 ECB             :     /* Post creation hook for new tablespace */
 3686 rhaas                     361 GIC          37 :     InvokeObjectPostCreateHook(TableSpaceRelationId, tablespaceoid, 0);
                                362                 : 
 4835 bruce                     363              37 :     create_tablespace_directories(location, tablespaceoid);
                                364                 : 
                                365                 :     /* Record the filesystem change in XLOG */
 6797 tgl                       366 ECB             :     {
                                367                 :         xl_tblspc_create_rec xlrec;
                                368                 : 
 6797 tgl                       369 CBC          33 :         xlrec.ts_id = tablespaceoid;
                                370                 : 
 3062 heikki.linnakangas        371              33 :         XLogBeginInsert();
 3062 heikki.linnakangas        372 GIC          33 :         XLogRegisterData((char *) &xlrec,
 3062 heikki.linnakangas        373 ECB             :                          offsetof(xl_tblspc_create_rec, ts_path));
 3062 heikki.linnakangas        374 GIC          33 :         XLogRegisterData((char *) location, strlen(location) + 1);
                                375                 : 
                                376              33 :         (void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_CREATE);
                                377                 :     }
                                378                 : 
                                379                 :     /*
                                380                 :      * Force synchronous commit, to minimize the window between creating the
                                381                 :      * symlink on-disk and marking the transaction committed.  It's not great
 5624 bruce                     382 ECB             :      * that there is any window at all, but definitely we don't want to make
                                383                 :      * it larger than necessary.
 5730 tgl                       384                 :      */
 5730 tgl                       385 GIC          33 :     ForceSyncCommit();
                                386                 : 
 6869 tgl                       387 CBC          33 :     pfree(location);
                                388                 : 
 6797 tgl                       389 ECB             :     /* We keep the lock on pg_tablespace until commit */
 1539 andres                    390 GIC          33 :     table_close(rel, NoLock);
                                391                 : 
 2773 tgl                       392              33 :     return tablespaceoid;
                                393                 : }
 6869 tgl                       394 ECB             : 
                                395                 : /*
                                396                 :  * Drop a table space
                                397                 :  *
                                398                 :  * Be careful to check that the tablespace is empty.
                                399                 :  */
                                400                 : void
 6869 tgl                       401 GIC          30 : DropTableSpace(DropTableSpaceStmt *stmt)
                                402                 : {
 6797 bruce                     403              30 :     char       *tablespacename = stmt->tablespacename;
                                404                 :     TableScanDesc scandesc;
                                405                 :     Relation    rel;
 6797 bruce                     406 ECB             :     HeapTuple   tuple;
                                407                 :     Form_pg_tablespace spcform;
                                408                 :     ScanKeyData entry[1];
                                409                 :     Oid         tablespaceoid;
                                410                 :     char       *detail;
                                411                 :     char       *detail_log;
 6869 tgl                       412                 : 
                                413                 :     /*
                                414                 :      * Find the target tuple
                                415                 :      */
 1539 andres                    416 GIC          30 :     rel = table_open(TableSpaceRelationId, RowExclusiveLock);
 6289 tgl                       417 EUB             : 
 6869 tgl                       418 GIC          30 :     ScanKeyInit(&entry[0],
 6869 tgl                       419 EUB             :                 Anum_pg_tablespace_spcname,
                                420                 :                 BTEqualStrategyNumber, F_NAMEEQ,
                                421                 :                 CStringGetDatum(tablespacename));
 1490 andres                    422 GIC          30 :     scandesc = table_beginscan_catalog(rel, 1, entry);
 6869 tgl                       423              30 :     tuple = heap_getnext(scandesc, ForwardScanDirection);
                                424                 : 
                                425              30 :     if (!HeapTupleIsValid(tuple))
 6141 andrew                    426 EUB             :     {
 6031 bruce                     427 UIC           0 :         if (!stmt->missing_ok)
                                428                 :         {
 6141 andrew                    429 UBC           0 :             ereport(ERROR,
 6141 andrew                    430 EUB             :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
                                431                 :                      errmsg("tablespace \"%s\" does not exist",
                                432                 :                             tablespacename)));
                                433                 :         }
                                434                 :         else
 6141 andrew                    435 ECB             :         {
 6141 andrew                    436 LBC           0 :             ereport(NOTICE,
                                437                 :                     (errmsg("tablespace \"%s\" does not exist, skipping",
                                438                 :                             tablespacename)));
 1490 andres                    439               0 :             table_endscan(scandesc);
 1539 andres                    440 UBC           0 :             table_close(rel, NoLock);
                                441                 :         }
 6141 andrew                    442 UIC           0 :         return;
                                443                 :     }
 6869 tgl                       444 ECB             : 
 1601 andres                    445 GBC          30 :     spcform = (Form_pg_tablespace) GETSTRUCT(tuple);
 1601 andres                    446 GIC          30 :     tablespaceoid = spcform->oid;
                                447                 : 
                                448                 :     /* Must be tablespace owner */
  147 peter                     449 GNC          30 :     if (!object_ownercheck(TableSpaceRelationId, tablespaceoid, GetUserId()))
 1954 peter_e                   450 UIC           0 :         aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLESPACE,
 6869 tgl                       451 ECB             :                        tablespacename);
                                452                 : 
                                453                 :     /* Disallow drop of the standard tablespaces, even by superuser */
  633 tgl                       454 GIC          30 :     if (IsPinnedObject(TableSpaceRelationId, tablespaceoid))
 1954 peter_e                   455 UIC           0 :         aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_TABLESPACE,
                                456                 :                        tablespacename);
                                457                 : 
                                458                 :     /* Check for pg_shdepend entries depending on this tablespace */
  815 alvherre                  459 CBC          30 :     if (checkSharedDependencies(TableSpaceRelationId, tablespaceoid,
                                460                 :                                 &detail, &detail_log))
  815 alvherre                  461 GIC           3 :         ereport(ERROR,
                                462                 :                 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
                                463                 :                  errmsg("tablespace \"%s\" cannot be dropped because some objects depend on it",
  815 alvherre                  464 ECB             :                         tablespacename),
                                465                 :                  errdetail_internal("%s", detail),
                                466                 :                  errdetail_log("%s", detail_log)));
                                467                 : 
                                468                 :     /* DROP hook for the tablespace being removed */
 3686 rhaas                     469 GIC          27 :     InvokeObjectDropHook(TableSpaceRelationId, tablespaceoid, 0);
                                470                 : 
 6797 tgl                       471 ECB             :     /*
 6385 bruce                     472                 :      * Remove the pg_tablespace tuple (this will roll back if we fail below)
                                473                 :      */
 2258 tgl                       474 GIC          27 :     CatalogTupleDelete(rel, &tuple->t_self);
                                475                 : 
 1490 andres                    476              27 :     table_endscan(scandesc);
 6797 tgl                       477 ECB             : 
                                478                 :     /*
                                479                 :      * Remove any comments or security labels on this tablespace.
                                480                 :      */
 6265 bruce                     481 GIC          27 :     DeleteSharedComments(tablespaceoid, TableSpaceRelationId);
 4281 rhaas                     482              27 :     DeleteSharedSecurityLabel(tablespaceoid, TableSpaceRelationId);
 6265 bruce                     483 ECB             : 
                                484                 :     /*
                                485                 :      * Remove dependency on owner.
                                486                 :      */
 5190 tgl                       487 GIC          27 :     deleteSharedDependencyRecordsFor(TableSpaceRelationId, tablespaceoid, 0);
 6431 tgl                       488 ECB             : 
                                489                 :     /*
                                490                 :      * Acquire TablespaceCreateLock to ensure that no TablespaceCreateDbspace
                                491                 :      * is running concurrently.
                                492                 :      */
 6289 tgl                       493 GIC          27 :     LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE);
                                494                 : 
                                495                 :     /*
                                496                 :      * Try to remove the physical infrastructure.
                                497                 :      */
 4835 bruce                     498              27 :     if (!destroy_tablespace_directories(tablespaceoid, false))
 5624 tgl                       499 ECB             :     {
                                500                 :         /*
                                501                 :          * Not all files deleted?  However, there can be lingering empty files
                                502                 :          * in the directories, left behind by for example DROP TABLE, that
                                503                 :          * have been scheduled for deletion at next checkpoint (see comments
                                504                 :          * in mdunlink() for details).  We could just delete them immediately,
                                505                 :          * but we can't tell them apart from important data files that we
                                506                 :          * mustn't delete.  So instead, we force a checkpoint which will clean
                                507                 :          * out any lingering files, and try again.
                                508                 :          */
  421 tmunro                    509 GIC          13 :         RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
  421 tmunro                    510 ECB             : 
                                511                 :         /*
                                512                 :          * On Windows, an unlinked file persists in the directory listing
                                513                 :          * until no process retains an open handle for the file.  The DDL
                                514                 :          * commands that schedule files for unlink send invalidation messages
                                515                 :          * directing other PostgreSQL processes to close the files, but
                                516                 :          * nothing guarantees they'll be processed in time.  So, we'll also
                                517                 :          * use a global barrier to ask all backends to close all files, and
                                518                 :          * wait until they're finished.
                                519                 :          */
  421 tmunro                    520 GIC          13 :         LWLockRelease(TablespaceCreateLock);
                                521              13 :         WaitForProcSignalBarrier(EmitProcSignalBarrier(PROCSIGNAL_BARRIER_SMGRRELEASE));
                                522              13 :         LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE);
                                523                 : 
                                524                 :         /* And now try again. */
 4835 bruce                     525              13 :         if (!destroy_tablespace_directories(tablespaceoid, false))
                                526                 :         {
                                527                 :             /* Still not empty, the files must be important then */
 5624 tgl                       528               4 :             ereport(ERROR,
 5624 tgl                       529 ECB             :                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                                530                 :                      errmsg("tablespace \"%s\" is not empty",
                                531                 :                             tablespacename)));
                                532                 :         }
                                533                 :     }
 6797                           534                 : 
                                535                 :     /* Record the filesystem change in XLOG */
                                536                 :     {
                                537                 :         xl_tblspc_drop_rec xlrec;
                                538                 : 
 6797 tgl                       539 GIC          23 :         xlrec.ts_id = tablespaceoid;
                                540                 : 
 3062 heikki.linnakangas        541              23 :         XLogBeginInsert();
                                542              23 :         XLogRegisterData((char *) &xlrec, sizeof(xl_tblspc_drop_rec));
                                543                 : 
                                544              23 :         (void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_DROP);
                                545                 :     }
                                546                 : 
                                547                 :     /*
                                548                 :      * Note: because we checked that the tablespace was empty, there should be
 6031 bruce                     549 ECB             :      * no need to worry about flushing shared buffers or free space map
                                550                 :      * entries for relations in the tablespace.
                                551                 :      */
                                552                 : 
                                553                 :     /*
 5624                           554                 :      * Force synchronous commit, to minimize the window between removing the
                                555                 :      * files on-disk and marking the transaction committed.  It's not great
                                556                 :      * that there is any window at all, but definitely we don't want to make
                                557                 :      * it larger than necessary.
                                558                 :      */
 5730 tgl                       559 GIC          23 :     ForceSyncCommit();
                                560                 : 
                                561                 :     /*
                                562                 :      * Allow TablespaceCreateDbspace again.
                                563                 :      */
 6289                           564              23 :     LWLockRelease(TablespaceCreateLock);
                                565                 : 
                                566                 :     /* We keep the lock on pg_tablespace until commit */
 1539 andres                    567              23 :     table_close(rel, NoLock);
                                568                 : }
                                569                 : 
 4835 bruce                     570 ECB             : 
                                571                 : /*
                                572                 :  * create_tablespace_directories
                                573                 :  *
                                574                 :  *  Attempt to create filesystem infrastructure linking $PGDATA/pg_tblspc/
                                575                 :  *  to the specified directory
                                576                 :  */
                                577                 : static void
 4835 bruce                     578 GIC          43 : create_tablespace_directories(const char *location, const Oid tablespaceoid)
 4835 bruce                     579 ECB             : {
                                580                 :     char       *linkloc;
 3465 peter_e                   581                 :     char       *location_with_version_dir;
 3292 tgl                       582 EUB             :     struct stat st;
                                583                 :     bool        in_place;
                                584                 : 
 3465 peter_e                   585 GIC          43 :     linkloc = psprintf("pg_tblspc/%u", tablespaceoid);
                                586                 : 
                                587                 :     /*
  450 tmunro                    588 ECB             :      * If we're asked to make an 'in place' tablespace, create the directory
                                589                 :      * directly where the symlink would normally go.  This is a developer-only
                                590                 :      * option for now, to facilitate regression testing.
                                591                 :      */
  450 tmunro                    592 GIC          43 :     in_place = strlen(location) == 0;
                                593                 : 
                                594              43 :     if (in_place)
                                595                 :     {
                                596              25 :         if (MakePGDirectory(linkloc) < 0 && errno != EEXIST)
  450 tmunro                    597 LBC           0 :             ereport(ERROR,
                                598                 :                     (errcode_for_file_access(),
  450 tmunro                    599 ECB             :                      errmsg("could not create directory \"%s\": %m",
                                600                 :                             linkloc)));
                                601                 :     }
                                602                 : 
  450 tmunro                    603 GIC          43 :     location_with_version_dir = psprintf("%s/%s", in_place ? linkloc : location,
                                604                 :                                          TABLESPACE_VERSION_DIRECTORY);
                                605                 : 
 4835 bruce                     606 EUB             :     /*
                                607                 :      * Attempt to coerce target directory to safe permissions.  If this fails,
                                608                 :      * it doesn't exist or has the wrong owner.  Not needed for in-place mode,
                                609                 :      * because in that case we created the directory with the desired
                                610                 :      * permissions.
                                611                 :      */
  450 tmunro                    612 GIC          43 :     if (!in_place && chmod(location, pg_dir_create_mode) != 0)
                                613                 :     {
 4835 bruce                     614               4 :         if (errno == ENOENT)
                                615               4 :             ereport(ERROR,
                                616                 :                     (errcode(ERRCODE_UNDEFINED_FILE),
                                617                 :                      errmsg("directory \"%s\" does not exist", location),
                                618                 :                      InRecovery ? errhint("Create this directory for the tablespace before "
 4382 bruce                     619 ECB             :                                           "restarting the server.") : 0));
                                620                 :         else
 4835 bruce                     621 LBC           0 :             ereport(ERROR,
 4790 bruce                     622 EUB             :                     (errcode_for_file_access(),
                                623                 :                      errmsg("could not set permissions on directory \"%s\": %m",
                                624                 :                             location)));
                                625                 :     }
 4835 bruce                     626 ECB             : 
 4835 bruce                     627 EUB             :     /*
                                628                 :      * The creation of the version directory prevents more than one tablespace
                                629                 :      * in a single location.  This imitates TablespaceCreateDbspace(), but it
                                630                 :      * ignores concurrency and missing parent directories.  The chmod() would
                                631                 :      * have failed in the absence of a parent.  pg_tablespace_spcname_index
  590 noah                      632 ECB             :      * prevents concurrency.
 4835 bruce                     633 EUB             :      */
  590 noah                      634 GIC          39 :     if (stat(location_with_version_dir, &st) < 0)
                                635                 :     {
                                636              36 :         if (errno != ENOENT)
 4835 bruce                     637 LBC           0 :             ereport(ERROR,
  590 noah                      638 EUB             :                     (errcode_for_file_access(),
                                639                 :                      errmsg("could not stat directory \"%s\": %m",
                                640                 :                             location_with_version_dir)));
  590 noah                      641 GIC          36 :         else if (MakePGDirectory(location_with_version_dir) < 0)
 4835 bruce                     642 UIC           0 :             ereport(ERROR,
                                643                 :                     (errcode_for_file_access(),
                                644                 :                      errmsg("could not create directory \"%s\": %m",
                                645                 :                             location_with_version_dir)));
 4835 bruce                     646 ECB             :     }
  590 noah                      647 CBC           3 :     else if (!S_ISDIR(st.st_mode))
  590 noah                      648 UIC           0 :         ereport(ERROR,
                                649                 :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                650                 :                  errmsg("\"%s\" exists but is not a directory",
                                651                 :                         location_with_version_dir)));
  590 noah                      652 CBC           3 :     else if (!InRecovery)
  590 noah                      653 UBC           0 :         ereport(ERROR,
                                654                 :                 (errcode(ERRCODE_OBJECT_IN_USE),
                                655                 :                  errmsg("directory \"%s\" already in use as a tablespace",
                                656                 :                         location_with_version_dir)));
                                657                 : 
 3292 tgl                       658 ECB             :     /*
                                659                 :      * In recovery, remove old symlink, in case it points to the wrong place.
                                660                 :      */
  450 tmunro                    661 GIC          39 :     if (!in_place && InRecovery)
 2844 rhaas                     662               3 :         remove_tablespace_symlink(linkloc);
                                663                 : 
                                664                 :     /*
                                665                 :      * Create the symlink under PGDATA
                                666                 :      */
  450 tmunro                    667              39 :     if (!in_place && symlink(location, linkloc) < 0)
 4835 bruce                     668 UIC           0 :         ereport(ERROR,
                                669                 :                 (errcode_for_file_access(),
                                670                 :                  errmsg("could not create symbolic link \"%s\": %m",
                                671                 :                         linkloc)));
                                672                 : 
 4835 bruce                     673 GIC          39 :     pfree(linkloc);
                                674              39 :     pfree(location_with_version_dir);
                                675              39 : }
                                676                 : 
 4835 bruce                     677 ECB             : 
                                678                 : /*
                                679                 :  * destroy_tablespace_directories
                                680                 :  *
                                681                 :  * Attempt to remove filesystem infrastructure for the tablespace.
                                682                 :  *
                                683                 :  * 'redo' indicates we are redoing a drop from XLOG; in that case we should
                                684                 :  * not throw an ERROR for problems, just LOG them.  The worst consequence of
                                685                 :  * not removing files here would be failure to release some disk space, which
 4080 tgl                       686                 :  * does not justify throwing an error that would require manual intervention
                                687                 :  * to get the database running again.
                                688                 :  *
                                689                 :  * Returns true if successful, false if some subdirectory is not empty
                                690                 :  */
                                691                 : static bool
 4835 bruce                     692 GIC          47 : destroy_tablespace_directories(Oid tablespaceoid, bool redo)
                                693                 : {
                                694                 :     char       *linkloc;
                                695                 :     char       *linkloc_with_version_dir;
                                696                 :     DIR        *dirdesc;
                                697                 :     struct dirent *de;
                                698                 :     char       *subfile;
                                699                 :     struct stat st;
                                700                 : 
 3465 peter_e                   701              47 :     linkloc_with_version_dir = psprintf("pg_tblspc/%u/%s", tablespaceoid,
                                702                 :                                         TABLESPACE_VERSION_DIRECTORY);
                                703                 : 
                                704                 :     /*
                                705                 :      * Check if the tablespace still contains any files.  We try to rmdir each
                                706                 :      * per-database directory we find in it.  rmdir failure implies there are
                                707                 :      * still files in that subdirectory, so give up.  (We do not have to worry
                                708                 :      * about undoing any already completed rmdirs, since the next attempt to
                                709                 :      * use the tablespace from that database will simply recreate the
                                710                 :      * subdirectory via TablespaceCreateDbspace.)
 6869 tgl                       711 ECB             :      *
 6289                           712                 :      * Since we hold TablespaceCreateLock, no one else should be creating any
                                713                 :      * fresh subdirectories in parallel. It is possible that new files are
                                714                 :      * being created within subdirectories, though, so the rmdir call could
                                715                 :      * fail.  Worst consequence is a less friendly error message.
 5862                           716                 :      *
 5862 tgl                       717 EUB             :      * If redo is true then ENOENT is a likely outcome here, and we allow it
                                718                 :      * to pass without comment.  In normal operation we still allow it, but
                                719                 :      * with a warning.  This is because even though ProcessUtility disallows
                                720                 :      * DROP TABLESPACE in a transaction block, it's possible that a previous
                                721                 :      * DROP failed and rolled back after removing the tablespace directories
 3260 bruce                     722 ECB             :      * and/or symlink.  We want to allow a new DROP attempt to succeed at
                                723                 :      * removing the catalog entries (and symlink if still present), so we
 3983 tgl                       724 EUB             :      * should not give a hard error here.
                                725                 :      */
 4835 bruce                     726 GIC          47 :     dirdesc = AllocateDir(linkloc_with_version_dir);
 6869 tgl                       727 GBC          47 :     if (dirdesc == NULL)
                                728                 :     {
 5862 tgl                       729 GIC           2 :         if (errno == ENOENT)
                                730                 :         {
 5862 tgl                       731 GBC           2 :             if (!redo)
 5862 tgl                       732 UBC           0 :                 ereport(WARNING,
                                733                 :                         (errcode_for_file_access(),
                                734                 :                          errmsg("could not open directory \"%s\": %m",
                                735                 :                                 linkloc_with_version_dir)));
                                736                 :             /* The symlink might still exist, so go try to remove it */
 3983 tgl                       737 CBC           2 :             goto remove_symlink;
                                738                 :         }
 4080 tgl                       739 LBC           0 :         else if (redo)
 4080 tgl                       740 ECB             :         {
                                741                 :             /* in redo, just log other types of error */
 4080 tgl                       742 UIC           0 :             ereport(LOG,
 4080 tgl                       743 ECB             :                     (errcode_for_file_access(),
                                744                 :                      errmsg("could not open directory \"%s\": %m",
                                745                 :                             linkloc_with_version_dir)));
 4080 tgl                       746 LBC           0 :             pfree(linkloc_with_version_dir);
 4080 tgl                       747 UIC           0 :             return false;
 4080 tgl                       748 ECB             :         }
 6503                           749                 :         /* else let ReadDir report the error */
 6797                           750                 :     }
 6869                           751                 : 
 4835 bruce                     752 GIC         144 :     while ((de = ReadDir(dirdesc, linkloc_with_version_dir)) != NULL)
                                753                 :     {
 6869 tgl                       754             116 :         if (strcmp(de->d_name, ".") == 0 ||
 4835 bruce                     755 CBC          79 :             strcmp(de->d_name, "..") == 0)
 6869 tgl                       756              82 :             continue;
                                757                 : 
 3465 peter_e                   758 GIC          34 :         subfile = psprintf("%s/%s", linkloc_with_version_dir, de->d_name);
                                759                 : 
                                760                 :         /* This check is just to deliver a friendlier error message */
 4080 tgl                       761 CBC          34 :         if (!redo && !directory_is_empty(subfile))
                                762                 :         {
 6797 tgl                       763 GIC          17 :             FreeDir(dirdesc);
 4835 bruce                     764 CBC          17 :             pfree(subfile);
 4835 bruce                     765 GIC          17 :             pfree(linkloc_with_version_dir);
 6797 tgl                       766              17 :             return false;
 6797 tgl                       767 ECB             :         }
                                768                 : 
 4835 bruce                     769                 :         /* remove empty directory */
 6869 tgl                       770 GIC          17 :         if (rmdir(subfile) < 0)
 4080                           771               1 :             ereport(redo ? LOG : ERROR,
                                772                 :                     (errcode_for_file_access(),
 5792 peter_e                   773 ECB             :                      errmsg("could not remove directory \"%s\": %m",
 6869 tgl                       774                 :                             subfile)));
                                775                 : 
 6869 tgl                       776 GIC          17 :         pfree(subfile);
                                777                 :     }
                                778                 : 
                                779              28 :     FreeDir(dirdesc);
                                780                 : 
                                781                 :     /* remove version directory */
 4835 bruce                     782              28 :     if (rmdir(linkloc_with_version_dir) < 0)
                                783                 :     {
 4080 tgl                       784               1 :         ereport(redo ? LOG : ERROR,
                                785                 :                 (errcode_for_file_access(),
 4835 bruce                     786 ECB             :                  errmsg("could not remove directory \"%s\": %m",
                                787                 :                         linkloc_with_version_dir)));
 4080 tgl                       788 CBC           1 :         pfree(linkloc_with_version_dir);
                                789               1 :         return false;
                                790                 :     }
 4790 bruce                     791 ECB             : 
                                792                 :     /*
                                793                 :      * Try to remove the symlink.  We must however deal with the possibility
                                794                 :      * that it's a directory instead of a symlink --- this could happen during
                                795                 :      * WAL replay (see TablespaceCreateDbspace).
                                796                 :      *
 4080 tgl                       797                 :      * Note: in the redo case, we'll return true if this final step fails;
                                798                 :      * there's no point in retrying it.  Also, ENOENT should provoke no more
 3983                           799                 :      * than a warning.
                                800                 :      */
 3983 tgl                       801 GBC          27 : remove_symlink:
 4835 bruce                     802 GIC          29 :     linkloc = pstrdup(linkloc_with_version_dir);
 4835 bruce                     803 GBC          29 :     get_parent_directory(linkloc);
 2557 tgl                       804 GIC          29 :     if (lstat(linkloc, &st) < 0)
                                805                 :     {
                                806               2 :         int         saved_errno = errno;
                                807                 : 
                                808               2 :         ereport(redo ? LOG : (saved_errno == ENOENT ? WARNING : ERROR),
 2557 tgl                       809 ECB             :                 (errcode_for_file_access(),
                                810                 :                  errmsg("could not stat file \"%s\": %m",
                                811                 :                         linkloc)));
                                812                 :     }
 2557 tgl                       813 GBC          27 :     else if (S_ISDIR(st.st_mode))
                                814                 :     {
 4835 bruce                     815              20 :         if (rmdir(linkloc) < 0)
                                816                 :         {
 2557 tgl                       817 UIC           0 :             int         saved_errno = errno;
                                818                 : 
                                819               0 :             ereport(redo ? LOG : (saved_errno == ENOENT ? WARNING : ERROR),
                                820                 :                     (errcode_for_file_access(),
                                821                 :                      errmsg("could not remove directory \"%s\": %m",
                                822                 :                             linkloc)));
                                823                 :         }
 6797 tgl                       824 EUB             :     }
 2844 rhaas                     825 GIC           7 :     else if (S_ISLNK(st.st_mode))
                                826                 :     {
 4835 bruce                     827               7 :         if (unlink(linkloc) < 0)
                                828                 :         {
 3357 tgl                       829 LBC           0 :             int         saved_errno = errno;
 3357 tgl                       830 ECB             : 
 3357 tgl                       831 UIC           0 :             ereport(redo ? LOG : (saved_errno == ENOENT ? WARNING : ERROR),
 6797 tgl                       832 ECB             :                     (errcode_for_file_access(),
                                833                 :                      errmsg("could not remove symbolic link \"%s\": %m",
                                834                 :                             linkloc)));
                                835                 :         }
                                836                 :     }
                                837                 :     else
                                838                 :     {
                                839                 :         /* Refuse to remove anything that's not a directory or symlink */
 2844 rhaas                     840 UIC           0 :         ereport(redo ? LOG : ERROR,
 2557 tgl                       841 ECB             :                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                                842                 :                  errmsg("\"%s\" is not a directory or symbolic link",
                                843                 :                         linkloc)));
                                844                 :     }
                                845                 : 
 4835 bruce                     846 CBC          29 :     pfree(linkloc_with_version_dir);
 4835 bruce                     847 GIC          29 :     pfree(linkloc);
 6869 tgl                       848 ECB             : 
 6797 tgl                       849 GIC          29 :     return true;
 6869 tgl                       850 ECB             : }
                                851                 : 
                                852                 : 
                                853                 : /*
                                854                 :  * Check if a directory is empty.
                                855                 :  *
                                856                 :  * This probably belongs somewhere else, but not sure where...
                                857                 :  */
 6748                           858                 : bool
 6869 tgl                       859 GIC         659 : directory_is_empty(const char *path)
                                860                 : {
                                861                 :     DIR        *dirdesc;
                                862                 :     struct dirent *de;
                                863                 : 
                                864             659 :     dirdesc = AllocateDir(path);
                                865                 : 
 6503                           866             703 :     while ((de = ReadDir(dirdesc, path)) != NULL)
                                867                 :     {
 6869                           868             689 :         if (strcmp(de->d_name, ".") == 0 ||
                                869             667 :             strcmp(de->d_name, "..") == 0)
                                870              44 :             continue;
 6869 tgl                       871 CBC         645 :         FreeDir(dirdesc);
 6869 tgl                       872 GIC         645 :         return false;
                                873                 :     }
                                874                 : 
 6869 tgl                       875 CBC          14 :     FreeDir(dirdesc);
 6869 tgl                       876 GIC          14 :     return true;
 6869 tgl                       877 ECB             : }
                                878                 : 
 2844 rhaas                     879 EUB             : /*
                                880                 :  *  remove_tablespace_symlink
                                881                 :  *
                                882                 :  * This function removes symlinks in pg_tblspc.  On Windows, junction points
                                883                 :  * act like directories so we must be able to apply rmdir.  This function
 2844 rhaas                     884 ECB             :  * works like the symlink removal code in destroy_tablespace_directories,
                                885                 :  * except that failure to remove is always an ERROR.  But if the file doesn't
                                886                 :  * exist at all, that's OK.
                                887                 :  */
                                888                 : void
 2844 rhaas                     889 GIC           4 : remove_tablespace_symlink(const char *linkloc)
 2844 rhaas                     890 EUB             : {
                                891                 :     struct stat st;
                                892                 : 
 2557 tgl                       893 GIC           4 :     if (lstat(linkloc, &st) < 0)
                                894                 :     {
 2844 rhaas                     895               1 :         if (errno == ENOENT)
 2844 rhaas                     896 CBC           1 :             return;
 2844 rhaas                     897 UIC           0 :         ereport(ERROR,
 2844 rhaas                     898 ECB             :                 (errcode_for_file_access(),
 2720 peter_e                   899 EUB             :                  errmsg("could not stat file \"%s\": %m", linkloc)));
                                900                 :     }
                                901                 : 
 2844 rhaas                     902 GIC           3 :     if (S_ISDIR(st.st_mode))
                                903                 :     {
                                904                 :         /*
                                905                 :          * This will fail if the directory isn't empty, but not if it's a
                                906                 :          * junction point.
 2844 rhaas                     907 EUB             :          */
 2557 tgl                       908 UIC           0 :         if (rmdir(linkloc) < 0 && errno != ENOENT)
 2844 rhaas                     909               0 :             ereport(ERROR,
                                910                 :                     (errcode_for_file_access(),
                                911                 :                      errmsg("could not remove directory \"%s\": %m",
                                912                 :                             linkloc)));
                                913                 :     }
 2844 rhaas                     914 GIC           3 :     else if (S_ISLNK(st.st_mode))
                                915                 :     {
                                916               3 :         if (unlink(linkloc) < 0 && errno != ENOENT)
 2844 rhaas                     917 LBC           0 :             ereport(ERROR,
                                918                 :                     (errcode_for_file_access(),
                                919                 :                      errmsg("could not remove symbolic link \"%s\": %m",
                                920                 :                             linkloc)));
                                921                 :     }
                                922                 :     else
                                923                 :     {
                                924                 :         /* Refuse to remove anything that's not a directory or symlink */
 2844 rhaas                     925 UIC           0 :         ereport(ERROR,
                                926                 :                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                                927                 :                  errmsg("\"%s\" is not a directory or symbolic link",
 2844 rhaas                     928 ECB             :                         linkloc)));
                                929                 :     }
                                930                 : }
                                931                 : 
                                932                 : /*
                                933                 :  * Rename a tablespace
 6862 tgl                       934                 :  */
 2959 alvherre                  935                 : ObjectAddress
 6862 tgl                       936 CBC           3 : RenameTableSpace(const char *oldname, const char *newname)
 6862 tgl                       937 EUB             : {
                                938                 :     Oid         tspId;
                                939                 :     Relation    rel;
                                940                 :     ScanKeyData entry[1];
                                941                 :     TableScanDesc scan;
 6862 tgl                       942 ECB             :     HeapTuple   tup;
                                943                 :     HeapTuple   newtuple;
                                944                 :     Form_pg_tablespace newform;
                                945                 :     ObjectAddress address;
                                946                 : 
                                947                 :     /* Search pg_tablespace */
 1539 andres                    948 GIC           3 :     rel = table_open(TableSpaceRelationId, RowExclusiveLock);
 6862 tgl                       949 ECB             : 
 6862 tgl                       950 GBC           3 :     ScanKeyInit(&entry[0],
                                951                 :                 Anum_pg_tablespace_spcname,
                                952                 :                 BTEqualStrategyNumber, F_NAMEEQ,
 6862 tgl                       953 ECB             :                 CStringGetDatum(oldname));
 1490 andres                    954 GBC           3 :     scan = table_beginscan_catalog(rel, 1, entry);
 6862 tgl                       955 GIC           3 :     tup = heap_getnext(scan, ForwardScanDirection);
                                956               3 :     if (!HeapTupleIsValid(tup))
 6862 tgl                       957 UIC           0 :         ereport(ERROR,
                                958                 :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
                                959                 :                  errmsg("tablespace \"%s\" does not exist",
                                960                 :                         oldname)));
                                961                 : 
 6862 tgl                       962 GIC           3 :     newtuple = heap_copytuple(tup);
                                963               3 :     newform = (Form_pg_tablespace) GETSTRUCT(newtuple);
 1601 andres                    964               3 :     tspId = newform->oid;
                                965                 : 
 1490                           966               3 :     table_endscan(scan);
                                967                 : 
                                968                 :     /* Must be owner */
  147 peter                     969 GNC           3 :     if (!object_ownercheck(TableSpaceRelationId, tspId, GetUserId()))
 1954 peter_e                   970 UIC           0 :         aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_TABLESPACE, oldname);
                                971                 : 
                                972                 :     /* Validate new name */
 6862 tgl                       973 CBC           3 :     if (!allowSystemTableMods && IsReservedName(newname))
 6862 tgl                       974 LBC           0 :         ereport(ERROR,
 6862 tgl                       975 ECB             :                 (errcode(ERRCODE_RESERVED_NAME),
 6862 tgl                       976 EUB             :                  errmsg("unacceptable tablespace name \"%s\"", newname),
                                977                 :                  errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
                                978                 : 
                                979                 :     /*
                                980                 :      * If built with appropriate switch, whine when regression-testing
 1380 tgl                       981 ECB             :      * conventions for tablespace names are violated.
                                982                 :      */
                                983                 : #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
                                984                 :     if (strncmp(newname, "regress_", 8) != 0)
                                985                 :         elog(WARNING, "tablespaces created by regression test cases should have names starting with \"regress_\"");
                                986                 : #endif
                                987                 : 
 6862                           988                 :     /* Make sure the new name doesn't exist */
 6862 tgl                       989 GIC           3 :     ScanKeyInit(&entry[0],
 6862 tgl                       990 ECB             :                 Anum_pg_tablespace_spcname,
                                991                 :                 BTEqualStrategyNumber, F_NAMEEQ,
                                992                 :                 CStringGetDatum(newname));
 1490 andres                    993 GIC           3 :     scan = table_beginscan_catalog(rel, 1, entry);
 6862 tgl                       994 CBC           3 :     tup = heap_getnext(scan, ForwardScanDirection);
 6862 tgl                       995 GIC           3 :     if (HeapTupleIsValid(tup))
 6862 tgl                       996 UIC           0 :         ereport(ERROR,
                                997                 :                 (errcode(ERRCODE_DUPLICATE_OBJECT),
                                998                 :                  errmsg("tablespace \"%s\" already exists",
                                999                 :                         newname)));
                               1000                 : 
 1490 andres                   1001 CBC           3 :     table_endscan(scan);
                               1002                 : 
                               1003                 :     /* OK, update the entry */
 6862 tgl                      1004 GIC           3 :     namestrcpy(&(newform->spcname), newname);
                               1005                 : 
 2259 alvherre                 1006               3 :     CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
                               1007                 : 
 3675 rhaas                    1008               3 :     InvokeObjectPostAlterHook(TableSpaceRelationId, tspId, 0);
                               1009                 : 
 2959 alvherre                 1010               3 :     ObjectAddressSet(address, TableSpaceRelationId, tspId);
                               1011                 : 
 1539 andres                   1012               3 :     table_close(rel, NoLock);
                               1013                 : 
 2959 alvherre                 1014               3 :     return address;
                               1015                 : }
                               1016                 : 
 4842 rhaas                    1017 ECB             : /*
                               1018                 :  * Alter table space options
                               1019                 :  */
                               1020                 : Oid
 4842 rhaas                    1021 GIC          12 : AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
 4842 rhaas                    1022 ECB             : {
                               1023                 :     Relation    rel;
                               1024                 :     ScanKeyData entry[1];
 1490 andres                   1025                 :     TableScanDesc scandesc;
 4842 rhaas                    1026 EUB             :     HeapTuple   tup;
                               1027                 :     Oid         tablespaceoid;
                               1028                 :     Datum       datum;
                               1029                 :     Datum       newOptions;
                               1030                 :     Datum       repl_val[Natts_pg_tablespace];
 4842 rhaas                    1031 ECB             :     bool        isnull;
                               1032                 :     bool        repl_null[Natts_pg_tablespace];
                               1033                 :     bool        repl_repl[Natts_pg_tablespace];
                               1034                 :     HeapTuple   newtuple;
 4842 rhaas                    1035 EUB             : 
                               1036                 :     /* Search pg_tablespace */
 1539 andres                   1037 GIC          12 :     rel = table_open(TableSpaceRelationId, RowExclusiveLock);
                               1038                 : 
 4842 rhaas                    1039 CBC          12 :     ScanKeyInit(&entry[0],
                               1040                 :                 Anum_pg_tablespace_spcname,
 4842 rhaas                    1041 ECB             :                 BTEqualStrategyNumber, F_NAMEEQ,
 4842 rhaas                    1042 GIC          12 :                 CStringGetDatum(stmt->tablespacename));
 1490 andres                   1043 CBC          12 :     scandesc = table_beginscan_catalog(rel, 1, entry);
 4842 rhaas                    1044              12 :     tup = heap_getnext(scandesc, ForwardScanDirection);
 4842 rhaas                    1045 GIC          12 :     if (!HeapTupleIsValid(tup))
 4842 rhaas                    1046 UIC           0 :         ereport(ERROR,
 4842 rhaas                    1047 ECB             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
                               1048                 :                  errmsg("tablespace \"%s\" does not exist",
 4790 bruce                    1049                 :                         stmt->tablespacename)));
 4842 rhaas                    1050                 : 
 1601 andres                   1051 GIC          12 :     tablespaceoid = ((Form_pg_tablespace) GETSTRUCT(tup))->oid;
 3753 rhaas                    1052 EUB             : 
 4842 rhaas                    1053 ECB             :     /* Must be owner of the existing object */
  147 peter                    1054 GNC          12 :     if (!object_ownercheck(TableSpaceRelationId, tablespaceoid, GetUserId()))
 1954 peter_e                  1055 UIC           0 :         aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLESPACE,
 4842 rhaas                    1056               0 :                        stmt->tablespacename);
                               1057                 : 
 4842 rhaas                    1058 ECB             :     /* Generate new proposed spcoptions (text array) */
 4842 rhaas                    1059 GIC          12 :     datum = heap_getattr(tup, Anum_pg_tablespace_spcoptions,
 4842 rhaas                    1060 ECB             :                          RelationGetDescr(rel), &isnull);
 4842 rhaas                    1061 GIC          12 :     newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
 4842 rhaas                    1062 ECB             :                                      stmt->options, NULL, NULL, false,
 4842 rhaas                    1063 GIC          12 :                                      stmt->isReset);
                               1064               9 :     (void) tablespace_reloptions(newOptions, true);
 4842 rhaas                    1065 ECB             : 
                               1066                 :     /* Build new tuple. */
 4842 rhaas                    1067 GIC           6 :     memset(repl_null, false, sizeof(repl_null));
 4842 rhaas                    1068 CBC           6 :     memset(repl_repl, false, sizeof(repl_repl));
 4842 rhaas                    1069 GIC           6 :     if (newOptions != (Datum) 0)
                               1070               6 :         repl_val[Anum_pg_tablespace_spcoptions - 1] = newOptions;
                               1071                 :     else
 4842 rhaas                    1072 UIC           0 :         repl_null[Anum_pg_tablespace_spcoptions - 1] = true;
 4842 rhaas                    1073 GIC           6 :     repl_repl[Anum_pg_tablespace_spcoptions - 1] = true;
                               1074               6 :     newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val,
                               1075                 :                                  repl_null, repl_repl);
                               1076                 : 
 4842 rhaas                    1077 ECB             :     /* Update system catalog. */
 2259 alvherre                 1078 GIC           6 :     CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
                               1079                 : 
 1601 andres                   1080               6 :     InvokeObjectPostAlterHook(TableSpaceRelationId, tablespaceoid, 0);
                               1081                 : 
 4842 rhaas                    1082               6 :     heap_freetuple(newtuple);
                               1083                 : 
 4842 rhaas                    1084 ECB             :     /* Conclude heap scan. */
 1490 andres                   1085 GIC           6 :     table_endscan(scandesc);
 1539 andres                   1086 CBC           6 :     table_close(rel, NoLock);
 3753 rhaas                    1087 ECB             : 
 3753 rhaas                    1088 GIC           6 :     return tablespaceoid;
                               1089                 : }
                               1090                 : 
                               1091                 : /*
                               1092                 :  * Routines for handling the GUC variable 'default_tablespace'.
 6729 tgl                      1093 EUB             :  */
                               1094                 : 
 4385                          1095                 : /* check_hook: validate new default_tablespace */
                               1096                 : bool
 4385 tgl                      1097 GIC        2149 : check_default_tablespace(char **newval, void **extra, GucSource source)
                               1098                 : {
                               1099                 :     /*
                               1100                 :      * If we aren't inside a transaction, or connected to a database, we
                               1101                 :      * cannot do the catalog accesses necessary to verify the name.  Must
 1399 andres                   1102 EUB             :      * accept the value on faith.
                               1103                 :      */
 1399 andres                   1104 GBC        2149 :     if (IsTransactionState() && MyDatabaseId != InvalidOid)
                               1105                 :     {
 4385 tgl                      1106 GIC         316 :         if (**newval != '\0' &&
                               1107              24 :             !OidIsValid(get_tablespace_oid(*newval, true)))
                               1108                 :         {
 4087 heikki.linnakangas       1109 ECB             :             /*
                               1110                 :              * When source == PGC_S_TEST, don't throw a hard error for a
                               1111                 :              * nonexistent tablespace, only a NOTICE.  See comments in guc.h.
                               1112                 :              */
 4087 heikki.linnakangas       1113 UIC           0 :             if (source == PGC_S_TEST)
                               1114                 :             {
                               1115               0 :                 ereport(NOTICE,
                               1116                 :                         (errcode(ERRCODE_UNDEFINED_OBJECT),
                               1117                 :                          errmsg("tablespace \"%s\" does not exist",
                               1118                 :                                 *newval)));
                               1119                 :             }
                               1120                 :             else
                               1121                 :             {
                               1122               0 :                 GUC_check_errdetail("Tablespace \"%s\" does not exist.",
                               1123                 :                                     *newval);
                               1124               0 :                 return false;
                               1125                 :             }
                               1126                 :         }
                               1127                 :     }
                               1128                 : 
 4385 tgl                      1129 CBC        2149 :     return true;
                               1130                 : }
                               1131                 : 
                               1132                 : /*
                               1133                 :  * GetDefaultTablespace -- get the OID of the current default tablespace
 6729 tgl                      1134 ECB             :  *
                               1135                 :  * Temporary objects have different default tablespaces, hence the
 1445 alvherre                 1136                 :  * relpersistence parameter must be specified.  Also, for partitioned tables,
                               1137                 :  * we disallow specifying the database default, so that needs to be specified
                               1138                 :  * too.
                               1139                 :  *
                               1140                 :  * May return InvalidOid to indicate "use the database's default tablespace".
 5789 tgl                      1141                 :  *
                               1142                 :  * Note that caller is expected to check appropriate permissions for any
                               1143                 :  * result other than InvalidOid.
                               1144                 :  *
                               1145                 :  * This exists to hide (and possibly optimize the use of) the
                               1146                 :  * default_tablespace GUC variable.
                               1147                 :  */
                               1148                 : Oid
 1445 alvherre                 1149 GIC      108196 : GetDefaultTablespace(char relpersistence, bool partitioned)
                               1150                 : {
 6729 tgl                      1151 ECB             :     Oid         result;
                               1152                 : 
                               1153                 :     /* The temp-table case is handled elsewhere */
 4500 rhaas                    1154 GIC      108196 :     if (relpersistence == RELPERSISTENCE_TEMP)
                               1155                 :     {
 5785 tgl                      1156            1895 :         PrepareTempTablespaces();
                               1157            1895 :         return GetNextTempTableSpace();
                               1158                 :     }
 5789 tgl                      1159 ECB             : 
                               1160                 :     /* Fast path for default_tablespace == "" */
 6729 tgl                      1161 CBC      106301 :     if (default_tablespace == NULL || default_tablespace[0] == '\0')
                               1162          106274 :         return InvalidOid;
                               1163                 : 
                               1164                 :     /*
 6729 tgl                      1165 EUB             :      * It is tempting to cache this lookup for more speed, but then we would
                               1166                 :      * fail to detect the case where the tablespace was dropped since the GUC
 6385 bruce                    1167 ECB             :      * variable was set.  Note also that we don't complain if the value fails
                               1168                 :      * to refer to an existing tablespace; we just silently return InvalidOid,
                               1169                 :      * causing the new object to be created in the database's tablespace.
                               1170                 :      */
 4630 rhaas                    1171 GIC          27 :     result = get_tablespace_oid(default_tablespace, true);
                               1172                 : 
                               1173                 :     /*
                               1174                 :      * Allow explicit specification of database's default tablespace in
                               1175                 :      * default_tablespace without triggering permissions checks.  Don't allow
                               1176                 :      * specifying that when creating a partitioned table, however, since the
                               1177                 :      * result is confusing.
                               1178                 :      */
 6729 tgl                      1179              27 :     if (result == MyDatabaseTableSpace)
                               1180                 :     {
 1445 alvherre                 1181               6 :         if (partitioned)
                               1182               6 :             ereport(ERROR,
                               1183                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 1445 alvherre                 1184 ECB             :                      errmsg("cannot specify default tablespace for partitioned relations")));
 6729 tgl                      1185 UIC           0 :         result = InvalidOid;
                               1186                 :     }
 6729 tgl                      1187 GIC          21 :     return result;
                               1188                 : }
                               1189                 : 
 6729 tgl                      1190 ECB             : 
                               1191                 : /*
                               1192                 :  * Routines for handling the GUC variable 'temp_tablespaces'.
 5789                          1193                 :  */
                               1194                 : 
                               1195                 : typedef struct
 4385 tgl                      1196 EUB             : {
 1010                          1197                 :     /* Array of OIDs to be passed to SetTempTablespaces() */
 4385                          1198                 :     int         numSpcs;
 2970                          1199                 :     Oid         tblSpcs[FLEXIBLE_ARRAY_MEMBER];
                               1200                 : } temp_tablespaces_extra;
                               1201                 : 
                               1202                 : /* check_hook: validate new temp_tablespaces */
                               1203                 : bool
 4385 tgl                      1204 GIC        1861 : check_temp_tablespaces(char **newval, void **extra, GucSource source)
                               1205                 : {
                               1206                 :     char       *rawname;
                               1207                 :     List       *namelist;
 5789 tgl                      1208 ECB             : 
                               1209                 :     /* Need a modifiable copy of string */
 4385 tgl                      1210 GIC        1861 :     rawname = pstrdup(*newval);
                               1211                 : 
                               1212                 :     /* Parse string into list of identifiers */
 5789                          1213            1861 :     if (!SplitIdentifierString(rawname, ',', &namelist))
                               1214                 :     {
                               1215                 :         /* syntax error in name list */
 4385 tgl                      1216 UBC           0 :         GUC_check_errdetail("List syntax is invalid.");
 5789                          1217               0 :         pfree(rawname);
                               1218               0 :         list_free(namelist);
 4385 tgl                      1219 UIC           0 :         return false;
 5789 tgl                      1220 EUB             :     }
                               1221                 : 
                               1222                 :     /*
                               1223                 :      * If we aren't inside a transaction, or connected to a database, we
                               1224                 :      * cannot do the catalog accesses necessary to verify the name.  Must
 1378                          1225                 :      * accept the value on faith. Fortunately, there's then also no need to
                               1226                 :      * pass the data to fd.c.
                               1227                 :      */
 1399 andres                   1228 GBC        1861 :     if (IsTransactionState() && MyDatabaseId != InvalidOid)
 5789 tgl                      1229 EUB             :     {
                               1230                 :         temp_tablespaces_extra *myextra;
                               1231                 :         Oid        *tblSpcs;
                               1232                 :         int         numSpcs;
                               1233                 :         ListCell   *l;
                               1234                 : 
                               1235                 :         /* temporary workspace until we are done verifying the list */
 4385 tgl                      1236 UIC           0 :         tblSpcs = (Oid *) palloc(list_length(namelist) * sizeof(Oid));
 5785 tgl                      1237 UBC           0 :         numSpcs = 0;
 5789                          1238               0 :         foreach(l, namelist)
                               1239                 :         {
                               1240               0 :             char       *curname = (char *) lfirst(l);
 5785 tgl                      1241 EUB             :             Oid         curoid;
                               1242                 :             AclResult   aclresult;
                               1243                 : 
                               1244                 :             /* Allow an empty string (signifying database default) */
 5789 tgl                      1245 UBC           0 :             if (curname[0] == '\0')
                               1246                 :             {
                               1247                 :                 /* InvalidOid signifies database's default tablespace */
 5785 tgl                      1248 UIC           0 :                 tblSpcs[numSpcs++] = InvalidOid;
 5789                          1249               0 :                 continue;
                               1250                 :             }
                               1251                 : 
 4630 rhaas                    1252 EUB             :             /*
                               1253                 :              * In an interactive SET command, we ereport for bad info.  When
                               1254                 :              * source == PGC_S_TEST, don't throw a hard error for a
 3505 tgl                      1255                 :              * nonexistent tablespace, only a NOTICE.  See comments in guc.h.
 4630 rhaas                    1256                 :              */
 4087 heikki.linnakangas       1257 UIC           0 :             curoid = get_tablespace_oid(curname, source <= PGC_S_TEST);
 5785 tgl                      1258               0 :             if (curoid == InvalidOid)
                               1259                 :             {
 4087 heikki.linnakangas       1260 UBC           0 :                 if (source == PGC_S_TEST)
 4087 heikki.linnakangas       1261 UIC           0 :                     ereport(NOTICE,
 4087 heikki.linnakangas       1262 EUB             :                             (errcode(ERRCODE_UNDEFINED_OBJECT),
                               1263                 :                              errmsg("tablespace \"%s\" does not exist",
                               1264                 :                                     curname)));
 5785 tgl                      1265 UBC           0 :                 continue;
 4087 heikki.linnakangas       1266 EUB             :             }
                               1267                 : 
                               1268                 :             /*
 5785 tgl                      1269                 :              * Allow explicit specification of database's default tablespace
                               1270                 :              * in temp_tablespaces without triggering permissions checks.
                               1271                 :              */
 5785 tgl                      1272 UIC           0 :             if (curoid == MyDatabaseTableSpace)
 5785 tgl                      1273 EUB             :             {
                               1274                 :                 /* InvalidOid signifies database's default tablespace */
 5785 tgl                      1275 UBC           0 :                 tblSpcs[numSpcs++] = InvalidOid;
                               1276               0 :                 continue;
 5785 tgl                      1277 EUB             :             }
                               1278                 : 
 4385                          1279                 :             /* Check permissions, similarly complaining only if interactive */
  147 peter                    1280 UNC           0 :             aclresult = object_aclcheck(TableSpaceRelationId, curoid, GetUserId(),
 5785 tgl                      1281 EUB             :                                                ACL_CREATE);
 5785 tgl                      1282 UIC           0 :             if (aclresult != ACLCHECK_OK)
                               1283                 :             {
 5785 tgl                      1284 LBC           0 :                 if (source >= PGC_S_INTERACTIVE)
 1954 peter_e                  1285               0 :                     aclcheck_error(aclresult, OBJECT_TABLESPACE, curname);
 5785 tgl                      1286 UIC           0 :                 continue;
 5785 tgl                      1287 ECB             :             }
                               1288                 : 
 5785 tgl                      1289 UIC           0 :             tblSpcs[numSpcs++] = curoid;
                               1290                 :         }
                               1291                 : 
 4385 tgl                      1292 ECB             :         /* Now prepare an "extra" struct for assign_temp_tablespaces */
  177 tgl                      1293 UNC           0 :         myextra = guc_malloc(LOG, offsetof(temp_tablespaces_extra, tblSpcs) +
                               1294                 :                              numSpcs * sizeof(Oid));
 4385 tgl                      1295 UIC           0 :         if (!myextra)
                               1296               0 :             return false;
                               1297               0 :         myextra->numSpcs = numSpcs;
                               1298               0 :         memcpy(myextra->tblSpcs, tblSpcs, numSpcs * sizeof(Oid));
                               1299               0 :         *extra = (void *) myextra;
                               1300                 : 
                               1301               0 :         pfree(tblSpcs);
                               1302                 :     }
 5789 tgl                      1303 ECB             : 
 5789 tgl                      1304 GBC        1861 :     pfree(rawname);
 5789 tgl                      1305 GIC        1861 :     list_free(namelist);
 5789 tgl                      1306 ECB             : 
 4385 tgl                      1307 CBC        1861 :     return true;
                               1308                 : }
                               1309                 : 
                               1310                 : /* assign_hook: do extra actions as needed */
                               1311                 : void
 4385 tgl                      1312 GIC        1861 : assign_temp_tablespaces(const char *newval, void *extra)
                               1313                 : {
                               1314            1861 :     temp_tablespaces_extra *myextra = (temp_tablespaces_extra *) extra;
                               1315                 : 
                               1316                 :     /*
 4385 tgl                      1317 ECB             :      * If check_temp_tablespaces was executed inside a transaction, then pass
                               1318                 :      * the list it made to fd.c.  Otherwise, clear fd.c's list; we must be
                               1319                 :      * still outside a transaction, or else restoring during transaction exit,
                               1320                 :      * and in either case we can just let the next PrepareTempTablespaces call
                               1321                 :      * make things sane.
                               1322                 :      */
 4385 tgl                      1323 GIC        1861 :     if (myextra)
 4385 tgl                      1324 UIC           0 :         SetTempTablespaces(myextra->tblSpcs, myextra->numSpcs);
                               1325                 :     else
 4385 tgl                      1326 CBC        1861 :         SetTempTablespaces(NULL, 0);
 5789                          1327            1861 : }
                               1328                 : 
                               1329                 : /*
                               1330                 :  * PrepareTempTablespaces -- prepare to use temp tablespaces
                               1331                 :  *
                               1332                 :  * If we have not already done so in the current transaction, parse the
                               1333                 :  * temp_tablespaces GUC variable and tell fd.c which tablespace(s) to use
                               1334                 :  * for temp files.
                               1335                 :  */
 5785 tgl                      1336 ECB             : void
 5785 tgl                      1337 CBC        4351 : PrepareTempTablespaces(void)
                               1338                 : {
                               1339                 :     char       *rawname;
 5789 tgl                      1340 ECB             :     List       *namelist;
                               1341                 :     Oid        *tblSpcs;
                               1342                 :     int         numSpcs;
 5785                          1343                 :     ListCell   *l;
                               1344                 : 
                               1345                 :     /* No work if already done in current transaction */
 5785 tgl                      1346 GBC        4351 :     if (TempTablespacesAreSet())
                               1347            2567 :         return;
 5789 tgl                      1348 EUB             : 
                               1349                 :     /*
                               1350                 :      * Can't do catalog access unless within a transaction.  This is just a
                               1351                 :      * safety check in case this function is called by low-level code that
                               1352                 :      * could conceivably execute outside a transaction.  Note that in such a
 5624 bruce                    1353 ECB             :      * scenario, fd.c will fall back to using the current database's default
 5785 tgl                      1354                 :      * tablespace, which should always be OK.
 5789                          1355                 :      */
 5785 tgl                      1356 CBC        1909 :     if (!IsTransactionState())
 5785 tgl                      1357 GIC         125 :         return;
 5789 tgl                      1358 ECB             : 
                               1359                 :     /* Need a modifiable copy of string */
 5789 tgl                      1360 GIC        1784 :     rawname = pstrdup(temp_tablespaces);
                               1361                 : 
                               1362                 :     /* Parse string into list of identifiers */
 5789 tgl                      1363 CBC        1784 :     if (!SplitIdentifierString(rawname, ',', &namelist))
                               1364                 :     {
                               1365                 :         /* syntax error in name list */
 5785 tgl                      1366 UBC           0 :         SetTempTablespaces(NULL, 0);
 5789                          1367               0 :         pfree(rawname);
 5789 tgl                      1368 UIC           0 :         list_free(namelist);
 5785                          1369               0 :         return;
                               1370                 :     }
 5789 tgl                      1371 ECB             : 
 5785                          1372                 :     /* Store tablespace OIDs in an array in TopTransactionContext */
 5785 tgl                      1373 GIC        1784 :     tblSpcs = (Oid *) MemoryContextAlloc(TopTransactionContext,
 5624 bruce                    1374            1784 :                                          list_length(namelist) * sizeof(Oid));
 5785 tgl                      1375 GBC        1784 :     numSpcs = 0;
 5785 tgl                      1376 GIC        1785 :     foreach(l, namelist)
                               1377                 :     {
                               1378               1 :         char       *curname = (char *) lfirst(l);
                               1379                 :         Oid         curoid;
                               1380                 :         AclResult   aclresult;
                               1381                 : 
 5785 tgl                      1382 ECB             :         /* Allow an empty string (signifying database default) */
 5785 tgl                      1383 GIC           1 :         if (curname[0] == '\0')
                               1384                 :         {
 1010 tgl                      1385 EUB             :             /* InvalidOid signifies database's default tablespace */
 5785 tgl                      1386 UBC           0 :             tblSpcs[numSpcs++] = InvalidOid;
 5785 tgl                      1387 UIC           0 :             continue;
                               1388                 :         }
                               1389                 : 
 5785 tgl                      1390 ECB             :         /* Else verify that name is a valid tablespace name */
 4630 rhaas                    1391 GIC           1 :         curoid = get_tablespace_oid(curname, true);
 5785 tgl                      1392 CBC           1 :         if (curoid == InvalidOid)
 5785 tgl                      1393 EUB             :         {
                               1394                 :             /* Skip any bad list elements */
 5785 tgl                      1395 LBC           0 :             continue;
                               1396                 :         }
                               1397                 : 
 5785 tgl                      1398 ECB             :         /*
                               1399                 :          * Allow explicit specification of database's default tablespace in
 5624 bruce                    1400                 :          * temp_tablespaces without triggering permissions checks.
 5785 tgl                      1401                 :          */
 5785 tgl                      1402 GIC           1 :         if (curoid == MyDatabaseTableSpace)
                               1403                 :         {
                               1404                 :             /* InvalidOid signifies database's default tablespace */
 1010 tgl                      1405 UIC           0 :             tblSpcs[numSpcs++] = InvalidOid;
 5785                          1406               0 :             continue;
                               1407                 :         }
                               1408                 : 
                               1409                 :         /* Check permissions similarly */
  147 peter                    1410 GNC           1 :         aclresult = object_aclcheck(TableSpaceRelationId, curoid, GetUserId(),
                               1411                 :                                            ACL_CREATE);
 5785 tgl                      1412 CBC           1 :         if (aclresult != ACLCHECK_OK)
 5785 tgl                      1413 UIC           0 :             continue;
                               1414                 : 
 5785 tgl                      1415 GIC           1 :         tblSpcs[numSpcs++] = curoid;
                               1416                 :     }
                               1417                 : 
                               1418            1784 :     SetTempTablespaces(tblSpcs, numSpcs);
                               1419                 : 
 5789                          1420            1784 :     pfree(rawname);
                               1421            1784 :     list_free(namelist);
                               1422                 : }
                               1423                 : 
                               1424                 : 
 6729 tgl                      1425 ECB             : /*
                               1426                 :  * get_tablespace_oid - given a tablespace name, look up the OID
                               1427                 :  *
                               1428                 :  * If missing_ok is false, throw an error if tablespace name not found.  If
                               1429                 :  * true, just return InvalidOid.
                               1430                 :  */
                               1431                 : Oid
 4630 rhaas                    1432 CBC         437 : get_tablespace_oid(const char *tablespacename, bool missing_ok)
                               1433                 : {
                               1434                 :     Oid         result;
 6729 tgl                      1435 ECB             :     Relation    rel;
 1490 andres                   1436                 :     TableScanDesc scandesc;
                               1437                 :     HeapTuple   tuple;
 6729 tgl                      1438                 :     ScanKeyData entry[1];
                               1439                 : 
 5789                          1440                 :     /*
                               1441                 :      * Search pg_tablespace.  We use a heapscan here even though there is an
                               1442                 :      * index on name, on the theory that pg_tablespace will usually have just
                               1443                 :      * a few entries and so an indexed lookup is a waste of effort.
                               1444                 :      */
 1539 andres                   1445 GIC         437 :     rel = table_open(TableSpaceRelationId, AccessShareLock);
                               1446                 : 
 6729 tgl                      1447             437 :     ScanKeyInit(&entry[0],
                               1448                 :                 Anum_pg_tablespace_spcname,
 6729 tgl                      1449 ECB             :                 BTEqualStrategyNumber, F_NAMEEQ,
                               1450                 :                 CStringGetDatum(tablespacename));
 1490 andres                   1451 GIC         437 :     scandesc = table_beginscan_catalog(rel, 1, entry);
 6729 tgl                      1452             437 :     tuple = heap_getnext(scandesc, ForwardScanDirection);
                               1453                 : 
                               1454                 :     /* We assume that there can be at most one matching tuple */
                               1455             437 :     if (HeapTupleIsValid(tuple))
 1601 andres                   1456             391 :         result = ((Form_pg_tablespace) GETSTRUCT(tuple))->oid;
                               1457                 :     else
 6729 tgl                      1458 CBC          46 :         result = InvalidOid;
                               1459                 : 
 1490 andres                   1460 GIC         437 :     table_endscan(scandesc);
 1539                          1461             437 :     table_close(rel, AccessShareLock);
                               1462                 : 
 4630 rhaas                    1463             437 :     if (!OidIsValid(result) && !missing_ok)
 4382 bruce                    1464               6 :         ereport(ERROR,
                               1465                 :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
                               1466                 :                  errmsg("tablespace \"%s\" does not exist",
                               1467                 :                         tablespacename)));
                               1468                 : 
 6729 tgl                      1469             431 :     return result;
                               1470                 : }
 6729 tgl                      1471 ECB             : 
                               1472                 : /*
                               1473                 :  * get_tablespace_name - given a tablespace OID, look up the name
                               1474                 :  *
                               1475                 :  * Returns a palloc'd string, or NULL if no such tablespace.
                               1476                 :  */
                               1477                 : char *
 6729 tgl                      1478 CBC         128 : get_tablespace_name(Oid spc_oid)
                               1479                 : {
                               1480                 :     char       *result;
 6729 tgl                      1481 ECB             :     Relation    rel;
 1490 andres                   1482                 :     TableScanDesc scandesc;
                               1483                 :     HeapTuple   tuple;
 6729 tgl                      1484                 :     ScanKeyData entry[1];
                               1485                 : 
 5789                          1486                 :     /*
                               1487                 :      * Search pg_tablespace.  We use a heapscan here even though there is an
                               1488                 :      * index on oid, on the theory that pg_tablespace will usually have just a
 5624 bruce                    1489                 :      * few entries and so an indexed lookup is a waste of effort.
                               1490                 :      */
 1539 andres                   1491 GIC         128 :     rel = table_open(TableSpaceRelationId, AccessShareLock);
                               1492                 : 
 6729 tgl                      1493             128 :     ScanKeyInit(&entry[0],
                               1494                 :                 Anum_pg_tablespace_oid,
                               1495                 :                 BTEqualStrategyNumber, F_OIDEQ,
                               1496                 :                 ObjectIdGetDatum(spc_oid));
 1490 andres                   1497 CBC         128 :     scandesc = table_beginscan_catalog(rel, 1, entry);
 6729 tgl                      1498 GIC         128 :     tuple = heap_getnext(scandesc, ForwardScanDirection);
 6729 tgl                      1499 ECB             : 
                               1500                 :     /* We assume that there can be at most one matching tuple */
 6729 tgl                      1501 GIC         128 :     if (HeapTupleIsValid(tuple))
 6729 tgl                      1502 CBC         119 :         result = pstrdup(NameStr(((Form_pg_tablespace) GETSTRUCT(tuple))->spcname));
                               1503                 :     else
                               1504               9 :         result = NULL;
                               1505                 : 
 1490 andres                   1506             128 :     table_endscan(scandesc);
 1539                          1507             128 :     table_close(rel, AccessShareLock);
                               1508                 : 
 6729 tgl                      1509             128 :     return result;
                               1510                 : }
 6729 tgl                      1511 ECB             : 
                               1512                 : 
 6797                          1513                 : /*
                               1514                 :  * TABLESPACE resource manager's routines
                               1515                 :  */
                               1516                 : void
 3062 heikki.linnakangas       1517 GIC          12 : tblspc_redo(XLogReaderState *record)
                               1518                 : {
                               1519              12 :     uint8       info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
                               1520                 : 
                               1521                 :     /* Backup blocks are not used in tblspc records */
                               1522              12 :     Assert(!XLogRecHasAnyBlockRefs(record));
                               1523                 : 
 6797 tgl                      1524              12 :     if (info == XLOG_TBLSPC_CREATE)
                               1525                 :     {
                               1526               6 :         xl_tblspc_create_rec *xlrec = (xl_tblspc_create_rec *) XLogRecGetData(record);
                               1527               6 :         char       *location = xlrec->ts_path;
                               1528                 : 
 4835 bruce                    1529               6 :         create_tablespace_directories(location, xlrec->ts_id);
                               1530                 :     }
 6797 tgl                      1531               6 :     else if (info == XLOG_TBLSPC_DROP)
                               1532                 :     {
 6797 tgl                      1533 CBC           6 :         xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) XLogRecGetData(record);
                               1534                 : 
  337 tmunro                   1535 ECB             :         /* Close all smgr fds in all backends. */
  337 tmunro                   1536 GIC           6 :         WaitForProcSignalBarrier(EmitProcSignalBarrier(PROCSIGNAL_BARRIER_SMGRRELEASE));
                               1537                 : 
                               1538                 :         /*
                               1539                 :          * If we issued a WAL record for a drop tablespace it implies that
                               1540                 :          * there were no files in it at all when the DROP was done. That means
                               1541                 :          * that no permanent objects can exist in it at this point.
                               1542                 :          *
                               1543                 :          * It is possible for standby users to be using this tablespace as a
                               1544                 :          * location for their temporary files, so if we fail to remove all
 4790 bruce                    1545 ECB             :          * files then do conflict processing and try again, if currently
 4790 bruce                    1546 EUB             :          * enabled.
                               1547                 :          *
                               1548                 :          * Other possible reasons for failure include bollixed file
                               1549                 :          * permissions on a standby server when they were okay on the primary,
                               1550                 :          * etc etc. There's not much we can do about that, so just remove what
                               1551                 :          * we can and press on.
                               1552                 :          */
 4835 bruce                    1553 GIC           6 :         if (!destroy_tablespace_directories(xlrec->ts_id, true))
 4859 simon                    1554 EUB             :         {
 4833 simon                    1555 CBC           1 :             ResolveRecoveryConflictWithTablespace(xlrec->ts_id);
                               1556                 : 
                               1557                 :             /*
                               1558                 :              * If we did recovery processing then hopefully the backends who
                               1559                 :              * wrote temp files should have cleaned up and exited by now.  So
                               1560                 :              * retry before complaining.  If we fail again, this is just a LOG
                               1561                 :              * condition, because it's not worth throwing an ERROR for (as
                               1562                 :              * that would crash the database and require manual intervention
                               1563                 :              * before we could get past this WAL record on restart).
                               1564                 :              */
 4835 bruce                    1565 GIC           1 :             if (!destroy_tablespace_directories(xlrec->ts_id, true))
 4080 tgl                      1566 UIC           0 :                 ereport(LOG,
                               1567                 :                         (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                               1568                 :                          errmsg("directories for tablespace %u could not be removed",
                               1569                 :                                 xlrec->ts_id),
                               1570                 :                          errhint("You can remove the directories manually if necessary.")));
                               1571                 :         }
                               1572                 :     }
                               1573                 :     else
 6797                          1574               0 :         elog(PANIC, "tblspc_redo: unknown op code %u", info);
 6797 tgl                      1575 GIC          12 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a