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
86 state.ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
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
125
126 totaltups++;
127 }
128 PQclear(res);
129
130 /*
131 * Store the names of output plugins as well. There is a possibility
132 * that duplicated plugins are set, but the consumer function
133 * check_loadable_libraries() will avoid checking the same library, so
134 * we do not have to consider their uniqueness here.
135 */
136 for (int slotno = 0; slotno < slot_arr->nslots; slotno++)
137 {
138 if (slot_arr->slots[slotno].invalid)
139 continue;
140
143
144 totaltups++;
145 }
146 }
147
148 pg_free(state.ress);
149 pg_free(query);
150
152}
153
154
155/*
156 * check_loadable_libraries()
157 *
158 * Check that the new cluster contains all required libraries.
159 * We do this by actually trying to LOAD each one, thereby testing
160 * compatibility as well as presence.
161 */
162void
164{
165 PGconn *conn = connectToServer(&new_cluster, "template1");
166 int libnum;
167 int was_load_failure = false;
168 FILE *script = NULL;
170
171 prep_status("Checking for presence of required libraries");
172
173 snprintf(output_path, sizeof(output_path), "%s/%s",
174 log_opts.basedir, "loadable_libraries.txt");
175
176 /*
177 * Now we want to sort the library names into order. This avoids multiple
178 * probes of the same library, and ensures that libraries are probed in a
179 * consistent order, which is important for reproducible behavior if one
180 * library depends on another.
181 */
184
186 {
188 int llen = strlen(lib);
189 char cmd[7 + 2 * MAXPGPATH + 1];
190 PGresult *res;
191
192 /* Did the library name change? Probe it. */
193 if (libnum == 0 || strcmp(lib, os_info.libraries[libnum - 1].name) != 0)
194 {
195 strcpy(cmd, "LOAD '");
196 PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
197 strcat(cmd, "'");
198
199 res = PQexec(conn, cmd);
200
202 {
203 was_load_failure = true;
204
205 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
206 pg_fatal("could not open file \"%s\": %m", output_path);
207 fprintf(script, _("could not load library \"%s\": %s"),
208 lib,
210 }
211 else
212 was_load_failure = false;
213
214 PQclear(res);
215 }
216
218 fprintf(script, _("In database: %s\n"),
220 }
221
222 PQfinish(conn);
223
224 if (script)
225 {
226 fclose(script);
227 pg_log(PG_REPORT, "fatal");
228 pg_fatal("Your installation references loadable libraries that are missing from the\n"
229 "new installation. You can add these libraries to the new installation,\n"
230 "or remove the functions using them from the old installation. A list of\n"
231 "problem libraries is in the file:\n"
232 " %s", output_path);
233 }
234 else
235 check_ok();
236}
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
#define _(x)
Definition elog.c:91
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
void * pg_malloc(size_t size)
Definition fe_memutils.c:47
char * pg_strdup(const char *in)
Definition fe_memutils.c:85
void pg_free(void *ptr)
void check_loadable_libraries(void)
Definition function.c:163
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:774
static void check_ok(void)
Definition initdb.c:2108
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:125
void * arg
#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:419
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