Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * version.c
3 : : *
4 : : * Postgres-version-specific routines
5 : : *
6 : : * Copyright (c) 2010-2026, 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
726 dgustafsson@postgres 21 :CBC 14 : jsonb_9_4_check_applicable(ClusterInfo *cluster)
22 : : {
23 : : /* JSONB changed its storage format during 9.4 beta */
24 [ - + ]: 14 : if (GET_MAJOR_VERSION(cluster->major_version) == 904 &&
726 dgustafsson@postgres 25 [ # # ]:UBC 0 : cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER)
26 : 0 : return true;
27 : :
726 dgustafsson@postgres 28 :CBC 14 : return false;
29 : : }
30 : :
31 : : /*
32 : : * Older servers can't support newer protocol versions, so their connection
33 : : * strings will need to lock max_protocol_version to 3.0.
34 : : */
35 : : bool
19 jchampion@postgresql 36 : 669 : protocol_negotiation_supported(const ClusterInfo *cluster)
37 : : {
38 : : /*
39 : : * The February 2018 patch release (9.3.21, 9.4.16, 9.5.11, 9.6.7, and
40 : : * 10.2) added support for NegotiateProtocolVersion. But ClusterInfo only
41 : : * has information about the major version number. To ensure we can still
42 : : * upgrade older unpatched servers, just assume anything prior to PG11
43 : : * can't negotiate. It's not possible for those servers to make use of
44 : : * newer protocols anyway, so nothing is lost.
45 : : */
46 : 669 : return (GET_MAJOR_VERSION(cluster->major_version) >= 1100);
47 : : }
48 : :
49 : : /*
50 : : * old_9_6_invalidate_hash_indexes()
51 : : * 9.6 -> 10
52 : : * Hash index binary format has changed from 9.6->10.0
53 : : */
54 : : void
3222 rhaas@postgresql.org 55 :UBC 0 : old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
56 : : {
57 : : int dbnum;
58 : 0 : FILE *script = NULL;
59 : 0 : bool found = false;
60 : 0 : char *output_path = "reindex_hash.sql";
61 : :
62 : 0 : prep_status("Checking for hash indexes");
63 : :
64 [ # # ]: 0 : for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
65 : : {
66 : : PGresult *res;
67 : 0 : bool db_used = false;
68 : : int ntups;
69 : : int rowno;
70 : : int i_nspname,
71 : : i_relname;
72 : 0 : DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
73 : 0 : PGconn *conn = connectToServer(cluster, active_db->db_name);
74 : :
75 : : /* find hash indexes */
76 : 0 : res = executeQueryOrDie(conn,
77 : : "SELECT n.nspname, c.relname "
78 : : "FROM pg_catalog.pg_class c, "
79 : : " pg_catalog.pg_index i, "
80 : : " pg_catalog.pg_am a, "
81 : : " pg_catalog.pg_namespace n "
82 : : "WHERE i.indexrelid = c.oid AND "
83 : : " c.relam = a.oid AND "
84 : : " c.relnamespace = n.oid AND "
85 : : " a.amname = 'hash'"
86 : : );
87 : :
88 : 0 : ntups = PQntuples(res);
89 : 0 : i_nspname = PQfnumber(res, "nspname");
90 : 0 : i_relname = PQfnumber(res, "relname");
91 [ # # ]: 0 : for (rowno = 0; rowno < ntups; rowno++)
92 : : {
93 : 0 : found = true;
94 [ # # ]: 0 : if (!check_mode)
95 : : {
96 [ # # # # ]: 0 : if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
733 michael@paquier.xyz 97 : 0 : pg_fatal("could not open file \"%s\": %m", output_path);
3222 rhaas@postgresql.org 98 [ # # ]: 0 : if (!db_used)
99 : : {
100 : : PQExpBufferData connectbuf;
101 : :
102 : 0 : initPQExpBuffer(&connectbuf);
103 : 0 : appendPsqlMetaConnect(&connectbuf, active_db->db_name);
104 : 0 : fputs(connectbuf.data, script);
105 : 0 : termPQExpBuffer(&connectbuf);
106 : 0 : db_used = true;
107 : : }
108 : 0 : fprintf(script, "REINDEX INDEX %s.%s;\n",
109 : 0 : quote_identifier(PQgetvalue(res, rowno, i_nspname)),
110 : 0 : quote_identifier(PQgetvalue(res, rowno, i_relname)));
111 : : }
112 : : }
113 : :
114 : 0 : PQclear(res);
115 : :
116 [ # # # # ]: 0 : if (!check_mode && db_used)
117 : : {
118 : : /* mark hash indexes as invalid */
119 : 0 : PQclear(executeQueryOrDie(conn,
120 : : "UPDATE pg_catalog.pg_index i "
121 : : "SET indisvalid = false "
122 : : "FROM pg_catalog.pg_class c, "
123 : : " pg_catalog.pg_am a, "
124 : : " pg_catalog.pg_namespace n "
125 : : "WHERE i.indexrelid = c.oid AND "
126 : : " c.relam = a.oid AND "
127 : : " c.relnamespace = n.oid AND "
128 : : " a.amname = 'hash'"));
129 : : }
130 : :
131 : 0 : PQfinish(conn);
132 : : }
133 : :
134 [ # # ]: 0 : if (script)
135 : 0 : fclose(script);
136 : :
137 [ # # ]: 0 : if (found)
138 : : {
139 : 0 : report_status(PG_WARNING, "warning");
140 [ # # ]: 0 : if (check_mode)
141 : 0 : pg_log(PG_WARNING, "\n"
142 : : "Your installation contains hash indexes. These indexes have different\n"
143 : : "internal formats between your old and new clusters, so they must be\n"
144 : : "reindexed with the REINDEX command. After upgrading, you will be given\n"
145 : : "REINDEX instructions.");
146 : : else
147 : 0 : pg_log(PG_WARNING, "\n"
148 : : "Your installation contains hash indexes. These indexes have different\n"
149 : : "internal formats between your old and new clusters, so they must be\n"
150 : : "reindexed with the REINDEX command. The file\n"
151 : : " %s\n"
152 : : "when executed by psql by the database superuser will recreate all invalid\n"
153 : : "indexes; until then, none of these indexes will be used.",
154 : : output_path);
155 : : }
156 : : else
157 : 0 : check_ok();
158 : 0 : }
159 : :
160 : : /*
161 : : * Callback function for processing results of query for
162 : : * report_extension_updates()'s UpgradeTask. If the query returned any rows,
163 : : * write the details to the report file.
164 : : */
165 : : static void
545 nathan@postgresql.or 166 :CBC 30 : process_extension_updates(DbInfo *dbinfo, PGresult *res, void *arg)
167 : : {
168 : 30 : int ntups = PQntuples(res);
169 : 30 : int i_name = PQfnumber(res, "name");
170 : 30 : UpgradeTaskReport *report = (UpgradeTaskReport *) arg;
171 : : PQExpBufferData connectbuf;
172 : :
535 173 [ + - ]: 30 : if (ntups == 0)
174 : 30 : return;
175 : :
535 nathan@postgresql.or 176 [ # # ]:UBC 0 : if (report->file == NULL &&
177 [ # # ]: 0 : (report->file = fopen_priv(report->path, "w")) == NULL)
178 : 0 : pg_fatal("could not open file \"%s\": %m", report->path);
179 : :
180 : 0 : initPQExpBuffer(&connectbuf);
181 : 0 : appendPsqlMetaConnect(&connectbuf, dbinfo->db_name);
182 : 0 : fputs(connectbuf.data, report->file);
183 : 0 : termPQExpBuffer(&connectbuf);
184 : :
185 [ # # ]: 0 : for (int rowno = 0; rowno < ntups; rowno++)
545 186 : 0 : fprintf(report->file, "ALTER EXTENSION %s UPDATE;\n",
187 : 0 : quote_identifier(PQgetvalue(res, rowno, i_name)));
188 : : }
189 : :
190 : : /*
191 : : * report_extension_updates()
192 : : * Report extensions that should be updated.
193 : : */
194 : : void
1685 bruce@momjian.us 195 :CBC 9 : report_extension_updates(ClusterInfo *cluster)
196 : : {
197 : : UpgradeTaskReport report;
545 nathan@postgresql.or 198 : 9 : UpgradeTask *task = upgrade_task_create();
199 : 9 : const char *query = "SELECT name "
200 : : "FROM pg_available_extensions "
201 : : "WHERE installed_version != default_version";
202 : :
1685 bruce@momjian.us 203 : 9 : prep_status("Checking for extension updates");
204 : :
545 nathan@postgresql.or 205 : 9 : report.file = NULL;
206 : 9 : strcpy(report.path, "update_extensions.sql");
207 : :
208 : 9 : upgrade_task_add_step(task, query, process_extension_updates,
209 : : true, &report);
210 : :
211 : 9 : upgrade_task_run(task, cluster);
212 : 9 : upgrade_task_free(task);
213 : :
214 [ - + ]: 9 : if (report.file)
215 : : {
545 nathan@postgresql.or 216 :UBC 0 : fclose(report.file);
1685 bruce@momjian.us 217 : 0 : report_status(PG_REPORT, "notice");
218 : 0 : pg_log(PG_REPORT, "\n"
219 : : "Your installation contains extensions that should be updated\n"
220 : : "with the ALTER EXTENSION command. The file\n"
221 : : " %s\n"
222 : : "when executed by psql by the database superuser will update\n"
223 : : "these extensions.",
224 : : report.path);
225 : : }
226 : : else
1685 bruce@momjian.us 227 :CBC 9 : check_ok();
228 : 9 : }
|