PostgreSQL Source Code  git master
function.c File Reference
#include "postgres_fe.h"
#include "access/transam.h"
#include "catalog/pg_language_d.h"
#include "common/int.h"
#include "pg_upgrade.h"
Include dependency graph for function.c:

Go to the source code of this file.

Data Structures

struct  loadable_libraries_state
 

Functions

static int library_name_compare (const void *p1, const void *p2)
 
static void process_loadable_libraries (DbInfo *dbinfo, PGresult *res, void *arg)
 
void get_loadable_libraries (void)
 
void check_loadable_libraries (void)
 

Function Documentation

◆ check_loadable_libraries()

void check_loadable_libraries ( void  )

Definition at line 165 of file function.c.

166 {
167  PGconn *conn = connectToServer(&new_cluster, "template1");
168  int libnum;
169  int was_load_failure = false;
170  FILE *script = NULL;
171  char output_path[MAXPGPATH];
172 
173  prep_status("Checking for presence of required libraries");
174 
175  snprintf(output_path, sizeof(output_path), "%s/%s",
176  log_opts.basedir, "loadable_libraries.txt");
177 
178  /*
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.
183  */
186 
187  for (libnum = 0; libnum < os_info.num_libraries; libnum++)
188  {
189  char *lib = os_info.libraries[libnum].name;
190  int llen = strlen(lib);
191  char cmd[7 + 2 * MAXPGPATH + 1];
192  PGresult *res;
193 
194  /* Did the library name change? Probe it. */
195  if (libnum == 0 || strcmp(lib, os_info.libraries[libnum - 1].name) != 0)
196  {
197  strcpy(cmd, "LOAD '");
198  PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
199  strcat(cmd, "'");
200 
201  res = PQexec(conn, cmd);
202 
204  {
205  was_load_failure = true;
206 
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"),
210  lib,
212  }
213  else
214  was_load_failure = false;
215 
216  PQclear(res);
217  }
218 
219  if (was_load_failure)
220  fprintf(script, _("In database: %s\n"),
222  }
223 
224  PQfinish(conn);
225 
226  if (script)
227  {
228  fclose(script);
229  pg_log(PG_REPORT, "fatal");
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"
234  " %s", output_path);
235  }
236  else
237  check_ok();
238 }
#define _(x)
Definition: elog.c:90
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7212
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4893
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
Definition: fe-exec.c:4145
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3411
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2262
static int library_name_compare(const void *p1, const void *p2)
Definition: function.c:29
static void check_ok(void)
Definition: initdb.c:2091
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:120
#define pg_fatal(...)
#define MAXPGPATH
OSInfo os_info
Definition: pg_upgrade.c:69
ClusterInfo new_cluster
Definition: pg_upgrade.c:68
ClusterInfo old_cluster
Definition: pg_upgrade.c:67
void void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2
LogOpts log_opts
Definition: util.c:17
#define fopen_priv(path, mode)
Definition: pg_upgrade.h:419
@ PG_REPORT
Definition: pg_upgrade.h:269
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:28
void prep_status(const char *fmt,...) pg_attribute_printf(1
#define snprintf
Definition: port.h:238
#define fprintf
Definition: port.h:242
#define qsort(a, b, c, d)
Definition: port.h:447
PGconn * conn
Definition: streamutil.c:55
DbInfoArr dbarr
Definition: pg_upgrade.h:284
DbInfo * dbs
Definition: pg_upgrade.h:215
char * db_name
Definition: pg_upgrade.h:194
char * name
Definition: pg_upgrade.h:334
char * basedir
Definition: pg_upgrade.h:311
LibraryInfo * libraries
Definition: pg_upgrade.h:348
int num_libraries
Definition: pg_upgrade.h:349

References _, LogOpts::basedir, check_ok(), conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, LibraryInfo::dbnum, DbInfoArr::dbs, fopen_priv, fprintf, OSInfo::libraries, library_name_compare(), log_opts, MAXPGPATH, LibraryInfo::name, new_cluster, OSInfo::num_libraries, old_cluster, os_info, pg_fatal, pg_log(), PG_REPORT, PGRES_COMMAND_OK, PQclear(), PQerrorMessage(), PQescapeStringConn(), PQexec(), PQfinish(), PQresultStatus(), prep_status(), qsort, res, and snprintf.

Referenced by check_new_cluster().

◆ get_loadable_libraries()

void get_loadable_libraries ( void  )

Definition at line 79 of file function.c.

80 {
81  int totaltups;
82  int dbnum;
83  int n_libinfos;
86  char *query;
87 
88  state.ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
89  state.totaltups = 0;
90 
91  query = psprintf("SELECT DISTINCT probin "
92  "FROM pg_catalog.pg_proc "
93  "WHERE prolang = %u AND "
94  "probin IS NOT NULL AND "
95  "oid >= %u",
96  ClanguageId,
98 
100  false, &state);
101 
103  upgrade_task_free(task);
104 
105  /*
106  * Allocate memory for required libraries and logical replication output
107  * plugins.
108  */
109  n_libinfos = state.totaltups + count_old_cluster_logical_slots();
110  os_info.libraries = (LibraryInfo *) pg_malloc(sizeof(LibraryInfo) * n_libinfos);
111  totaltups = 0;
112 
113  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
114  {
115  PGresult *res = state.ress[dbnum];
116  int ntups;
117  int rowno;
118  LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
119 
120  ntups = PQntuples(res);
121  for (rowno = 0; rowno < ntups; rowno++)
122  {
123  char *lib = PQgetvalue(res, rowno, 0);
124 
126  os_info.libraries[totaltups].dbnum = dbnum;
127 
128  totaltups++;
129  }
130  PQclear(res);
131 
132  /*
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.
137  */
138  for (int slotno = 0; slotno < slot_arr->nslots; slotno++)
139  {
140  if (slot_arr->slots[slotno].invalid)
141  continue;
142 
143  os_info.libraries[totaltups].name = pg_strdup(slot_arr->slots[slotno].plugin);
144  os_info.libraries[totaltups].dbnum = dbnum;
145 
146  totaltups++;
147  }
148  }
149 
150  pg_free(state.ress);
151  pg_free(query);
152 
154 }
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void pg_free(void *ptr)
Definition: fe_memutils.c:105
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
static void process_loadable_libraries(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: function.c:60
int count_old_cluster_logical_slots(void)
Definition: info.c:742
UpgradeTask * upgrade_task_create(void)
Definition: task.c:117
void upgrade_task_run(const UpgradeTask *task, const ClusterInfo *cluster)
Definition: task.c:420
void upgrade_task_free(UpgradeTask *task)
Definition: task.c:133
void upgrade_task_add_step(UpgradeTask *task, const char *query, UpgradeTaskProcessCB process_cb, bool free_result, void *arg)
Definition: task.c:151
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
LogicalSlotInfoArr slot_arr
Definition: pg_upgrade.h:198
LogicalSlotInfo * slots
Definition: pg_upgrade.h:169
Definition: regguts.h:323
#define FirstNormalObjectId
Definition: transam.h:197

References count_old_cluster_logical_slots(), ClusterInfo::dbarr, LibraryInfo::dbnum, DbInfoArr::dbs, FirstNormalObjectId, LogicalSlotInfo::invalid, OSInfo::libraries, LibraryInfo::name, DbInfoArr::ndbs, LogicalSlotInfoArr::nslots, OSInfo::num_libraries, old_cluster, os_info, pg_free(), pg_malloc(), pg_strdup(), LogicalSlotInfo::plugin, PQclear(), PQgetvalue(), PQntuples(), process_loadable_libraries(), psprintf(), res, DbInfo::slot_arr, LogicalSlotInfoArr::slots, loadable_libraries_state::totaltups, upgrade_task_add_step(), upgrade_task_create(), upgrade_task_free(), and upgrade_task_run().

Referenced by check_and_dump_old_cluster().

◆ library_name_compare()

static int library_name_compare ( const void *  p1,
const void *  p2 
)
static

Definition at line 29 of file function.c.

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 }
static int pg_cmp_s32(int32 a, int32 b)
Definition: int.h:598
static int pg_cmp_size(size_t a, size_t b)
Definition: int.h:622
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743

References cmp(), p2, pg_cmp_s32(), and pg_cmp_size().

Referenced by check_loadable_libraries().

◆ process_loadable_libraries()

static void process_loadable_libraries ( DbInfo dbinfo,
PGresult res,
void *  arg 
)
static

Definition at line 60 of file function.c.

61 {
63 
65 
66  state->ress[dbinfo - old_cluster.dbarr.dbs] = res;
67  state->totaltups += PQntuples(res);
68 }
#define AssertVariableIsOfType(varname, typename)
Definition: c.h:984
void * arg
static struct LogicalRepInfo * dbinfo
void(* UpgradeTaskProcessCB)(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: pg_upgrade.h:500

References arg, AssertVariableIsOfType, ClusterInfo::dbarr, dbinfo, DbInfoArr::dbs, old_cluster, PQntuples(), and res.

Referenced by get_loadable_libraries().