PostgreSQL Source Code git master
Loading...
Searching...
No Matches
function.c
Go to the documentation of this file.
1/*
2 * function.c
3 *
4 * server-side function support
5 *
6 * Copyright (c) 2010-2026, PostgreSQL Global Development Group
7 * src/bin/pg_upgrade/function.c
8 */
9
10#include "postgres_fe.h"
11
12#include "access/transam.h"
13#include "catalog/pg_language_d.h"
14#include "common/int.h"
15#include "pg_upgrade.h"
16
17/*
18 * qsort comparator for pointers to library names
19 *
20 * We sort first by name length, then alphabetically for names of the
21 * same length, then database array index. This is to ensure that, eg,
22 * "hstore_plpython" sorts after both "hstore" and "plpython"; otherwise
23 * transform modules will probably fail their LOAD tests. (The backend
24 * ought to cope with that consideration, but it doesn't yet, and even
25 * when it does it'll still be a good idea to have a predictable order of
26 * probing here.)
27 */
28static int
29library_name_compare(const void *p1, const void *p2)
30{
31 const char *str1 = ((const LibraryInfo *) p1)->name;
32 const char *str2 = ((const LibraryInfo *) p2)->name;
33 size_t slen1 = strlen(str1);
34 size_t slen2 = strlen(str2);
35 int cmp = strcmp(str1, str2);
36
37 if (slen1 != slen2)
38 return pg_cmp_size(slen1, slen2);
39 if (cmp != 0)
40 return cmp;
41 return pg_cmp_s32(((const LibraryInfo *) p1)->dbnum,
42 ((const LibraryInfo *) p2)->dbnum);
43}
44
45/*
46 * Private state for get_loadable_libraries()'s UpgradeTask.
47 */
49{
50 PGresult **ress; /* results for each database */
51 int totaltups; /* number of tuples in all results */
52};
53
54/*
55 * Callback function for processing results of query for
56 * get_loadable_libraries()'s UpgradeTask. This function stores the results
57 * for later use within get_loadable_libraries().
58 */
59static void
61{
63
64 state->ress[dbinfo - old_cluster.dbarr.dbs] = res;
65 state->totaltups += PQntuples(res);
66}
67
68/*
69 * get_loadable_libraries()
70 *
71 * Fetch the names of all old libraries containing either C-language functions
72 * or are corresponding to logical replication output plugins.
73 *
74 * We will later check that they all exist in the new installation.
75 */
76void
78{
79 int totaltups;
80 int dbnum;
81 int n_libinfos;
84 char *query;
85
87 state.totaltups = 0;
88
89 query = psprintf("SELECT DISTINCT probin "
90 "FROM pg_catalog.pg_proc "
91 "WHERE prolang = %u AND "
92 "probin IS NOT NULL AND "
93 "oid >= %u",
96
98 false, &state);
99
102
103 /*
104 * Allocate memory for required libraries and logical replication output
105 * plugins.
106 */
109 totaltups = 0;
110
111 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
112 {
113 PGresult *res = state.ress[dbnum];
114 int ntups;
115 int rowno;
116 LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
117
118 ntups = PQntuples(res);
119 for (rowno = 0; rowno < ntups; rowno++)
120 {
121 char *lib = PQgetvalue(res, rowno, 0);
122
123 /*
124 * Starting with version 19, for extensions with hardcoded
125 * '$libdir/' library names, we strip the prefix to allow the
126 * library search path to be used.
127 */
128 if (strncmp(lib, "$libdir/", 8) == 0)
129 lib += 8;
130
133
134 totaltups++;
135 }
136 PQclear(res);
137
138 /*
139 * Store the names of output plugins as well. There is a possibility
140 * that duplicated plugins are set, but the consumer function
141 * check_loadable_libraries() will avoid checking the same library, so
142 * we do not have to consider their uniqueness here.
143 */
144 for (int slotno = 0; slotno < slot_arr->nslots; slotno++)
145 {
146 if (slot_arr->slots[slotno].invalid)
147 continue;
148
151
152 totaltups++;
153 }
154 }
155
156 pg_free(state.ress);
157 pg_free(query);
158
160}
161
162
163/*
164 * check_loadable_libraries()
165 *
166 * Check that the new cluster contains all required libraries.
167 * We do this by actually trying to LOAD each one, thereby testing
168 * compatibility as well as presence.
169 */
170void
172{
173 PGconn *conn = connectToServer(&new_cluster, "template1");
174 int libnum;
175 int was_load_failure = false;
176 FILE *script = NULL;
178
179 prep_status("Checking for presence of required libraries");
180
181 snprintf(output_path, sizeof(output_path), "%s/%s",
182 log_opts.basedir, "loadable_libraries.txt");
183
184 /*
185 * Now we want to sort the library names into order. This avoids multiple
186 * probes of the same library, and ensures that libraries are probed in a
187 * consistent order, which is important for reproducible behavior if one
188 * library depends on another.
189 */
192
194 {
196 int llen = strlen(lib);
197 char cmd[7 + 2 * MAXPGPATH + 1];
198 PGresult *res;
199
200 /* Did the library name change? Probe it. */
201 if (libnum == 0 || strcmp(lib, os_info.libraries[libnum - 1].name) != 0)
202 {
203 strcpy(cmd, "LOAD '");
204 PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
205 strcat(cmd, "'");
206
207 res = PQexec(conn, cmd);
208
210 {
211 was_load_failure = true;
212
213 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
214 pg_fatal("could not open file \"%s\": %m", output_path);
215 fprintf(script, _("could not load library \"%s\": %s"),
216 lib,
218 }
219 else
220 was_load_failure = false;
221
222 PQclear(res);
223 }
224
226 fprintf(script, _("In database: %s\n"),
228 }
229
230 PQfinish(conn);
231
232 if (script)
233 {
234 fclose(script);
235 pg_log(PG_REPORT, "fatal");
236 pg_fatal("Your installation references loadable libraries that are missing from the\n"
237 "new installation. You can add these libraries to the new installation,\n"
238 "or remove the functions using them from the old installation. A list of\n"
239 "problem libraries is in the file:\n"
240 " %s", output_path);
241 }
242 else
243 check_ok();
244}
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
Datum arg
Definition elog.c:1322
#define _(x)
Definition elog.c:95
void PQfinish(PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
Definition fe-exec.c:4194
PGresult * PQexec(PGconn *conn, const char *query)
Definition fe-exec.c:2279
char * pg_strdup(const char *in)
Definition fe_memutils.c:85
void pg_free(void *ptr)
#define pg_malloc_array(type, count)
Definition fe_memutils.h:56
void check_loadable_libraries(void)
Definition function.c:171
static void process_loadable_libraries(DbInfo *dbinfo, PGresult *res, void *arg)
Definition function.c:60
static int library_name_compare(const void *p1, const void *p2)
Definition function.c:29
void get_loadable_libraries(void)
Definition function.c:77
int count_old_cluster_logical_slots(void)
Definition info.c:824
static void check_ok(void)
Definition initdb.c:2132
static int pg_cmp_s32(int32 a, int32 b)
Definition int.h:713
static int pg_cmp_size(size_t a, size_t b)
Definition int.h:737
#define PQgetvalue
#define PQclear
#define PQresultStatus
#define PQntuples
@ PGRES_COMMAND_OK
Definition libpq-fe.h:131
#define pg_fatal(...)
#define MAXPGPATH
OSInfo os_info
Definition pg_upgrade.c:75
ClusterInfo new_cluster
Definition pg_upgrade.c:74
ClusterInfo old_cluster
Definition pg_upgrade.c:73
UpgradeTask * upgrade_task_create(void)
Definition task.c:117
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition server.c:28
void upgrade_task_run(const UpgradeTask *task, const ClusterInfo *cluster)
Definition task.c:421
void void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2
LogOpts log_opts
Definition util.c:17
void upgrade_task_free(UpgradeTask *task)
Definition task.c:133
#define fopen_priv(path, mode)
Definition pg_upgrade.h:439
@ PG_REPORT
Definition pg_upgrade.h:283
void prep_status(const char *fmt,...) pg_attribute_printf(1
void upgrade_task_add_step(UpgradeTask *task, const char *query, UpgradeTaskProcessCB process_cb, bool free_result, void *arg)
Definition task.c:151
#define snprintf
Definition port.h:260
#define qsort(a, b, c, d)
Definition port.h:495
static int fb(int x)
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
static int cmp(const chr *x, const chr *y, size_t len)
PGconn * conn
Definition streamutil.c:52
DbInfoArr dbarr
Definition pg_upgrade.h:298
DbInfo * dbs
Definition pg_upgrade.h:227
LogicalSlotInfoArr slot_arr
Definition pg_upgrade.h:210
char * db_name
Definition pg_upgrade.h:206
char * name
Definition pg_upgrade.h:356
char * basedir
Definition pg_upgrade.h:329
LogicalSlotInfo * slots
Definition pg_upgrade.h:181
LibraryInfo * libraries
Definition pg_upgrade.h:368
int num_libraries
Definition pg_upgrade.h:369
#define FirstNormalObjectId
Definition transam.h:197