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