Line data Source code
1 : /*
2 : * version.c
3 : *
4 : * Postgres-version-specific routines
5 : *
6 : * Copyright (c) 2010-2024, PostgreSQL Global Development Group
7 : * src/bin/pg_upgrade/version.c
8 : */
9 :
10 : #include "postgres_fe.h"
11 :
12 : #include "fe_utils/string_utils.h"
13 : #include "pg_upgrade.h"
14 :
15 : /*
16 : * version_hook functions for check_for_data_types_usage in order to determine
17 : * whether a data type check should be executed for the cluster in question or
18 : * not.
19 : */
20 : bool
21 12 : jsonb_9_4_check_applicable(ClusterInfo *cluster)
22 : {
23 : /* JSONB changed its storage format during 9.4 beta */
24 12 : if (GET_MAJOR_VERSION(cluster->major_version) == 904 &&
25 0 : cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER)
26 0 : return true;
27 :
28 12 : return false;
29 : }
30 :
31 : /*
32 : * old_9_6_invalidate_hash_indexes()
33 : * 9.6 -> 10
34 : * Hash index binary format has changed from 9.6->10.0
35 : */
36 : void
37 0 : old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
38 : {
39 : int dbnum;
40 0 : FILE *script = NULL;
41 0 : bool found = false;
42 0 : char *output_path = "reindex_hash.sql";
43 :
44 0 : prep_status("Checking for hash indexes");
45 :
46 0 : for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
47 : {
48 : PGresult *res;
49 0 : bool db_used = false;
50 : int ntups;
51 : int rowno;
52 : int i_nspname,
53 : i_relname;
54 0 : DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
55 0 : PGconn *conn = connectToServer(cluster, active_db->db_name);
56 :
57 : /* find hash indexes */
58 0 : res = executeQueryOrDie(conn,
59 : "SELECT n.nspname, c.relname "
60 : "FROM pg_catalog.pg_class c, "
61 : " pg_catalog.pg_index i, "
62 : " pg_catalog.pg_am a, "
63 : " pg_catalog.pg_namespace n "
64 : "WHERE i.indexrelid = c.oid AND "
65 : " c.relam = a.oid AND "
66 : " c.relnamespace = n.oid AND "
67 : " a.amname = 'hash'"
68 : );
69 :
70 0 : ntups = PQntuples(res);
71 0 : i_nspname = PQfnumber(res, "nspname");
72 0 : i_relname = PQfnumber(res, "relname");
73 0 : for (rowno = 0; rowno < ntups; rowno++)
74 : {
75 0 : found = true;
76 0 : if (!check_mode)
77 : {
78 0 : if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
79 0 : pg_fatal("could not open file \"%s\": %m", output_path);
80 0 : if (!db_used)
81 : {
82 : PQExpBufferData connectbuf;
83 :
84 0 : initPQExpBuffer(&connectbuf);
85 0 : appendPsqlMetaConnect(&connectbuf, active_db->db_name);
86 0 : fputs(connectbuf.data, script);
87 0 : termPQExpBuffer(&connectbuf);
88 0 : db_used = true;
89 : }
90 0 : fprintf(script, "REINDEX INDEX %s.%s;\n",
91 0 : quote_identifier(PQgetvalue(res, rowno, i_nspname)),
92 0 : quote_identifier(PQgetvalue(res, rowno, i_relname)));
93 : }
94 : }
95 :
96 0 : PQclear(res);
97 :
98 0 : if (!check_mode && db_used)
99 : {
100 : /* mark hash indexes as invalid */
101 0 : PQclear(executeQueryOrDie(conn,
102 : "UPDATE pg_catalog.pg_index i "
103 : "SET indisvalid = false "
104 : "FROM pg_catalog.pg_class c, "
105 : " pg_catalog.pg_am a, "
106 : " pg_catalog.pg_namespace n "
107 : "WHERE i.indexrelid = c.oid AND "
108 : " c.relam = a.oid AND "
109 : " c.relnamespace = n.oid AND "
110 : " a.amname = 'hash'"));
111 : }
112 :
113 0 : PQfinish(conn);
114 : }
115 :
116 0 : if (script)
117 0 : fclose(script);
118 :
119 0 : if (found)
120 : {
121 0 : report_status(PG_WARNING, "warning");
122 0 : if (check_mode)
123 0 : pg_log(PG_WARNING, "\n"
124 : "Your installation contains hash indexes. These indexes have different\n"
125 : "internal formats between your old and new clusters, so they must be\n"
126 : "reindexed with the REINDEX command. After upgrading, you will be given\n"
127 : "REINDEX instructions.");
128 : else
129 0 : pg_log(PG_WARNING, "\n"
130 : "Your installation contains hash indexes. These indexes have different\n"
131 : "internal formats between your old and new clusters, so they must be\n"
132 : "reindexed with the REINDEX command. The file\n"
133 : " %s\n"
134 : "when executed by psql by the database superuser will recreate all invalid\n"
135 : "indexes; until then, none of these indexes will be used.",
136 : output_path);
137 : }
138 : else
139 0 : check_ok();
140 0 : }
141 :
142 : /*
143 : * Callback function for processing results of query for
144 : * report_extension_updates()'s UpgradeTask. If the query returned any rows,
145 : * write the details to the report file.
146 : */
147 : static void
148 20 : process_extension_updates(DbInfo *dbinfo, PGresult *res, void *arg)
149 : {
150 20 : int ntups = PQntuples(res);
151 20 : int i_name = PQfnumber(res, "name");
152 20 : UpgradeTaskReport *report = (UpgradeTaskReport *) arg;
153 : PQExpBufferData connectbuf;
154 :
155 : AssertVariableIsOfType(&process_extension_updates, UpgradeTaskProcessCB);
156 :
157 20 : if (ntups == 0)
158 20 : return;
159 :
160 0 : if (report->file == NULL &&
161 0 : (report->file = fopen_priv(report->path, "w")) == NULL)
162 0 : pg_fatal("could not open file \"%s\": %m", report->path);
163 :
164 0 : initPQExpBuffer(&connectbuf);
165 0 : appendPsqlMetaConnect(&connectbuf, dbinfo->db_name);
166 0 : fputs(connectbuf.data, report->file);
167 0 : termPQExpBuffer(&connectbuf);
168 :
169 0 : for (int rowno = 0; rowno < ntups; rowno++)
170 0 : fprintf(report->file, "ALTER EXTENSION %s UPDATE;\n",
171 0 : quote_identifier(PQgetvalue(res, rowno, i_name)));
172 : }
173 :
174 : /*
175 : * report_extension_updates()
176 : * Report extensions that should be updated.
177 : */
178 : void
179 6 : report_extension_updates(ClusterInfo *cluster)
180 : {
181 : UpgradeTaskReport report;
182 6 : UpgradeTask *task = upgrade_task_create();
183 6 : const char *query = "SELECT name "
184 : "FROM pg_available_extensions "
185 : "WHERE installed_version != default_version";
186 :
187 6 : prep_status("Checking for extension updates");
188 :
189 6 : report.file = NULL;
190 6 : strcpy(report.path, "update_extensions.sql");
191 :
192 6 : upgrade_task_add_step(task, query, process_extension_updates,
193 : true, &report);
194 :
195 6 : upgrade_task_run(task, cluster);
196 6 : upgrade_task_free(task);
197 :
198 6 : if (report.file)
199 : {
200 0 : fclose(report.file);
201 0 : report_status(PG_REPORT, "notice");
202 0 : pg_log(PG_REPORT, "\n"
203 : "Your installation contains extensions that should be updated\n"
204 : "with the ALTER EXTENSION command. The file\n"
205 : " %s\n"
206 : "when executed by psql by the database superuser will update\n"
207 : "these extensions.",
208 : report.path);
209 : }
210 : else
211 6 : check_ok();
212 6 : }
|