Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * version.c
3 : : *
4 : : * Postgres-version-specific routines
5 : : *
6 : : * Copyright (c) 2010-2025, 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
536 dgustafsson@postgres 21 :GIC 13 : jsonb_9_4_check_applicable(ClusterInfo *cluster)
22 : : {
23 : : /* JSONB changed its storage format during 9.4 beta */
24 [ - + ]: 13 : if (GET_MAJOR_VERSION(cluster->major_version) == 904 &&
536 dgustafsson@postgres 25 [ # # ]:UIC 0 : cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER)
26 : 0 : return true;
27 : :
536 dgustafsson@postgres 28 :GIC 13 : 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
3032 rhaas@postgresql.org 37 :UIC 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)
543 michael@paquier.xyz 79 : 0 : pg_fatal("could not open file \"%s\": %m", output_path);
3032 rhaas@postgresql.org 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
355 nathan@postgresql.or 148 :GIC 28 : process_extension_updates(DbInfo *dbinfo, PGresult *res, void *arg)
149 : : {
150 : 28 : int ntups = PQntuples(res);
151 : 28 : int i_name = PQfnumber(res, "name");
152 : 28 : UpgradeTaskReport *report = (UpgradeTaskReport *) arg;
153 : : PQExpBufferData connectbuf;
154 : :
155 : : AssertVariableIsOfType(&process_extension_updates, UpgradeTaskProcessCB);
156 : :
345 157 [ + - ]: 28 : if (ntups == 0)
158 : 28 : return;
159 : :
345 nathan@postgresql.or 160 [ # # ]:UIC 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++)
355 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
1495 bruce@momjian.us 179 :GIC 8 : report_extension_updates(ClusterInfo *cluster)
180 : : {
181 : : UpgradeTaskReport report;
355 nathan@postgresql.or 182 : 8 : UpgradeTask *task = upgrade_task_create();
183 : 8 : const char *query = "SELECT name "
184 : : "FROM pg_available_extensions "
185 : : "WHERE installed_version != default_version";
186 : :
1495 bruce@momjian.us 187 : 8 : prep_status("Checking for extension updates");
188 : :
355 nathan@postgresql.or 189 : 8 : report.file = NULL;
190 : 8 : strcpy(report.path, "update_extensions.sql");
191 : :
192 : 8 : upgrade_task_add_step(task, query, process_extension_updates,
193 : : true, &report);
194 : :
195 : 8 : upgrade_task_run(task, cluster);
196 : 8 : upgrade_task_free(task);
197 : :
198 [ - + ]: 8 : if (report.file)
199 : : {
355 nathan@postgresql.or 200 :UIC 0 : fclose(report.file);
1495 bruce@momjian.us 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
1495 bruce@momjian.us 211 :GIC 8 : check_ok();
212 : 8 : }
|