4 * server-side function support
6 * Copyright (c) 2010-2025, PostgreSQL Global Development Group
7 * src/bin/pg_upgrade/function.c
13#include "catalog/pg_language_d.h"
18 * qsort comparator for pointers to library names
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
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);
46 * Private state for get_loadable_libraries()'s UpgradeTask.
51 int totaltups;
/* number of tuples in all results */
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().
71 * get_loadable_libraries()
73 * Fetch the names of all old libraries containing either C-language functions
74 * or are corresponding to logical replication output plugins.
76 * We will later check that they all exist in the new installation.
91 query =
psprintf(
"SELECT DISTINCT probin "
92 "FROM pg_catalog.pg_proc "
93 "WHERE prolang = %u AND "
94 "probin IS NOT NULL AND "
106 * Allocate memory for required libraries and logical replication output
121 for (rowno = 0; rowno < ntups; rowno++)
133 * Store the names of output plugins as well. There is a possibility
134 * that duplicated plugins are set, but the consumer function
135 * check_loadable_libraries() will avoid checking the same library, so
136 * we do not have to consider their uniqueness here.
138 for (
int slotno = 0; slotno < slot_arr->
nslots; slotno++)
158 * check_loadable_libraries()
160 * Check that the new cluster contains all required libraries.
161 * We do this by actually trying to LOAD each one, thereby testing
162 * compatibility as well as presence.
169 int was_load_failure =
false;
173 prep_status(
"Checking for presence of required libraries");
175 snprintf(output_path,
sizeof(output_path),
"%s/%s",
179 * Now we want to sort the library names into order. This avoids multiple
180 * probes of the same library, and ensures that libraries are probed in a
181 * consistent order, which is important for reproducible behavior if one
182 * library depends on another.
190 int llen = strlen(lib);
194 /* Did the library name change? Probe it. */
197 strcpy(cmd,
"LOAD '");
205 was_load_failure =
true;
207 if (script == NULL && (script =
fopen_priv(output_path,
"w")) == NULL)
208 pg_fatal(
"could not open file \"%s\": %m", output_path);
209 fprintf(script,
_(
"could not load library \"%s\": %s"),
214 was_load_failure =
false;
219 if (was_load_failure)
220 fprintf(script,
_(
"In database: %s\n"),
230 pg_fatal(
"Your installation references loadable libraries that are missing from the\n"
231 "new installation. You can add these libraries to the new installation,\n"
232 "or remove the functions using them from the old installation. A list of\n"
233 "problem libraries is in the file:\n"
#define AssertVariableIsOfType(varname, typename)
#define fprintf(file, fmt, msg)
void PQfinish(PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
PGresult * PQexec(PGconn *conn, const char *query)
void * pg_malloc(size_t size)
char * pg_strdup(const char *in)
void check_loadable_libraries(void)
static void process_loadable_libraries(DbInfo *dbinfo, PGresult *res, void *arg)
static int library_name_compare(const void *p1, const void *p2)
void get_loadable_libraries(void)
int count_old_cluster_logical_slots(void)
static void check_ok(void)
static int pg_cmp_s32(int32 a, int32 b)
static int pg_cmp_size(size_t a, size_t b)
UpgradeTask * upgrade_task_create(void)
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
void upgrade_task_run(const UpgradeTask *task, const ClusterInfo *cluster)
void void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2
void upgrade_task_free(UpgradeTask *task)
#define fopen_priv(path, mode)
void(* UpgradeTaskProcessCB)(DbInfo *dbinfo, PGresult *res, void *arg)
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)
#define qsort(a, b, c, d)
char * psprintf(const char *fmt,...)
static int cmp(const chr *x, const chr *y, size_t len)
LogicalSlotInfoArr slot_arr
#define FirstNormalObjectId