Age Owner TLA Line data Source code
1 : /*
2 : * tablespace.c
3 : *
4 : * tablespace functions
5 : *
6 : * Copyright (c) 2010-2023, PostgreSQL Global Development Group
7 : * src/bin/pg_upgrade/tablespace.c
8 : */
9 :
10 : #include "postgres_fe.h"
11 :
12 : #include "pg_upgrade.h"
13 :
14 : static void get_tablespace_paths(void);
15 : static void set_tablespace_directory_suffix(ClusterInfo *cluster);
16 :
17 :
18 : void
4555 bruce 19 CBC 2 : init_tablespaces(void)
20 : {
21 2 : get_tablespace_paths();
22 :
4481 23 2 : set_tablespace_directory_suffix(&old_cluster);
24 2 : set_tablespace_directory_suffix(&new_cluster);
25 :
3742 26 2 : if (os_info.num_old_tablespaces > 0 &&
2118 tgl 27 UBC 0 : strcmp(old_cluster.tablespace_suffix, new_cluster.tablespace_suffix) == 0)
3477 peter_e 28 0 : pg_fatal("Cannot upgrade to/from the same system catalog version when\n"
29 : "using tablespaces.");
4715 bruce 30 CBC 2 : }
31 :
32 :
33 : /*
34 : * get_tablespace_paths()
35 : *
36 : * Scans pg_tablespace and returns a malloc'ed array of all tablespace
37 : * paths. It's the caller's responsibility to free the array.
38 : */
39 : static void
4555 40 2 : get_tablespace_paths(void)
41 : {
4481 42 2 : PGconn *conn = connectToServer(&old_cluster, "template1");
43 : PGresult *res;
44 : int tblnum;
45 : int i_spclocation;
46 : char query[QUERY_ALLOC];
47 :
4141 magnus 48 2 : snprintf(query, sizeof(query),
49 : "SELECT pg_catalog.pg_tablespace_location(oid) AS spclocation "
50 : "FROM pg_catalog.pg_tablespace "
51 : "WHERE spcname != 'pg_default' AND "
52 : " spcname != 'pg_global'");
53 :
54 2 : res = executeQueryOrDie(conn, "%s", query);
55 :
3742 bruce 56 2 : if ((os_info.num_old_tablespaces = PQntuples(res)) != 0)
1165 alvherre 57 UBC 0 : os_info.old_tablespaces =
58 0 : (char **) pg_malloc(os_info.num_old_tablespaces * sizeof(char *));
59 : else
3742 bruce 60 CBC 2 : os_info.old_tablespaces = NULL;
61 :
4715 62 2 : i_spclocation = PQfnumber(res, "spclocation");
63 :
3742 64 2 : for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
65 : {
66 : struct stat statBuf;
67 :
1165 alvherre 68 UBC 0 : os_info.old_tablespaces[tblnum] = pg_strdup(PQgetvalue(res, tblnum, i_spclocation));
69 :
70 : /*
71 : * Check that the tablespace path exists and is a directory.
72 : * Effectively, this is checking only for tables/indexes in
73 : * non-existent tablespace directories. Databases located in
74 : * non-existent tablespaces already throw a backend error.
75 : * Non-existent tablespace directories can occur when a data directory
76 : * that contains user tablespaces is moved as part of pg_upgrade
77 : * preparation and the symbolic links are not updated.
78 : */
3279 bruce 79 0 : if (stat(os_info.old_tablespaces[tblnum], &statBuf) != 0)
80 : {
81 0 : if (errno == ENOENT)
82 0 : report_status(PG_FATAL,
83 : "tablespace directory \"%s\" does not exist",
84 0 : os_info.old_tablespaces[tblnum]);
85 : else
86 0 : report_status(PG_FATAL,
87 : "could not stat tablespace directory \"%s\": %s",
2118 tgl 88 0 : os_info.old_tablespaces[tblnum], strerror(errno));
89 : }
3279 bruce 90 0 : if (!S_ISDIR(statBuf.st_mode))
3260 91 0 : report_status(PG_FATAL,
92 : "tablespace path \"%s\" is not a directory",
93 0 : os_info.old_tablespaces[tblnum]);
94 : }
95 :
4715 bruce 96 CBC 2 : PQclear(res);
97 :
98 2 : PQfinish(conn);
99 2 : }
100 :
101 :
102 : static void
4481 103 4 : set_tablespace_directory_suffix(ClusterInfo *cluster)
104 : {
105 : /* This cluster has a version-specific subdirectory */
106 :
107 : /* The leading slash is needed to start a new directory. */
481 tgl 108 8 : cluster->tablespace_suffix = psprintf("/PG_%s_%d",
109 4 : cluster->major_version_str,
110 : cluster->controldata.cat_ver);
4715 bruce 111 4 : }
|