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.

Functions

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

Function Documentation

◆ check_loadable_libraries()

void check_loadable_libraries ( void  )

Definition at line 146 of file function.c.

147 {
148  PGconn *conn = connectToServer(&new_cluster, "template1");
149  int libnum;
150  int was_load_failure = false;
151  FILE *script = NULL;
152  char output_path[MAXPGPATH];
153 
154  prep_status("Checking for presence of required libraries");
155 
156  snprintf(output_path, sizeof(output_path), "%s/%s",
157  log_opts.basedir, "loadable_libraries.txt");
158 
159  /*
160  * Now we want to sort the library names into order. This avoids multiple
161  * probes of the same library, and ensures that libraries are probed in a
162  * consistent order, which is important for reproducible behavior if one
163  * library depends on another.
164  */
167 
168  for (libnum = 0; libnum < os_info.num_libraries; libnum++)
169  {
170  char *lib = os_info.libraries[libnum].name;
171  int llen = strlen(lib);
172  char cmd[7 + 2 * MAXPGPATH + 1];
173  PGresult *res;
174 
175  /* Did the library name change? Probe it. */
176  if (libnum == 0 || strcmp(lib, os_info.libraries[libnum - 1].name) != 0)
177  {
178  strcpy(cmd, "LOAD '");
179  PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
180  strcat(cmd, "'");
181 
182  res = PQexec(conn, cmd);
183 
185  {
186  was_load_failure = true;
187 
188  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
189  pg_fatal("could not open file \"%s\": %m", output_path);
190  fprintf(script, _("could not load library \"%s\": %s"),
191  lib,
193  }
194  else
195  was_load_failure = false;
196 
197  PQclear(res);
198  }
199 
200  if (was_load_failure)
201  fprintf(script, _("In database: %s\n"),
203  }
204 
205  PQfinish(conn);
206 
207  if (script)
208  {
209  fclose(script);
210  pg_log(PG_REPORT, "fatal");
211  pg_fatal("Your installation references loadable libraries that are missing from the\n"
212  "new installation. You can add these libraries to the new installation,\n"
213  "or remove the functions using them from the old installation. A list of\n"
214  "problem libraries is in the file:\n"
215  " %s", output_path);
216  }
217  else
218  check_ok();
219 }
#define _(x)
Definition: elog.c:90
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7167
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4888
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:2036
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:100
#define pg_fatal(...)
#define MAXPGPATH
OSInfo os_info
Definition: pg_upgrade.c:73
ClusterInfo new_cluster
Definition: pg_upgrade.c:72
ClusterInfo old_cluster
Definition: pg_upgrade.c:71
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:420
@ PG_REPORT
Definition: pg_upgrade.h:271
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:449
PGconn * conn
Definition: streamutil.c:55
DbInfoArr dbarr
Definition: pg_upgrade.h:286
DbInfo * dbs
Definition: pg_upgrade.h:217
char * db_name
Definition: pg_upgrade.h:195
char * name
Definition: pg_upgrade.h:335
char * basedir
Definition: pg_upgrade.h:312
LibraryInfo * libraries
Definition: pg_upgrade.h:349
int num_libraries
Definition: pg_upgrade.h:350

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 55 of file function.c.

56 {
57  PGresult **ress;
58  int totaltups;
59  int dbnum;
60  int n_libinfos;
61 
62  ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
63  totaltups = 0;
64 
65  /* Fetch all library names, removing duplicates within each DB */
66  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
67  {
68  DbInfo *active_db = &old_cluster.dbarr.dbs[dbnum];
70 
71  /*
72  * Fetch all libraries containing non-built-in C functions in this DB.
73  */
74  ress[dbnum] = executeQueryOrDie(conn,
75  "SELECT DISTINCT probin "
76  "FROM pg_catalog.pg_proc "
77  "WHERE prolang = %u AND "
78  "probin IS NOT NULL AND "
79  "oid >= %u;",
80  ClanguageId,
82  totaltups += PQntuples(ress[dbnum]);
83 
84  PQfinish(conn);
85  }
86 
87  /*
88  * Allocate memory for required libraries and logical replication output
89  * plugins.
90  */
91  n_libinfos = totaltups + count_old_cluster_logical_slots();
92  os_info.libraries = (LibraryInfo *) pg_malloc(sizeof(LibraryInfo) * n_libinfos);
93  totaltups = 0;
94 
95  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
96  {
97  PGresult *res = ress[dbnum];
98  int ntups;
99  int rowno;
100  LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
101 
102  ntups = PQntuples(res);
103  for (rowno = 0; rowno < ntups; rowno++)
104  {
105  char *lib = PQgetvalue(res, rowno, 0);
106 
107  os_info.libraries[totaltups].name = pg_strdup(lib);
108  os_info.libraries[totaltups].dbnum = dbnum;
109 
110  totaltups++;
111  }
112  PQclear(res);
113 
114  /*
115  * Store the names of output plugins as well. There is a possibility
116  * that duplicated plugins are set, but the consumer function
117  * check_loadable_libraries() will avoid checking the same library, so
118  * we do not have to consider their uniqueness here.
119  */
120  for (int slotno = 0; slotno < slot_arr->nslots; slotno++)
121  {
122  if (slot_arr->slots[slotno].invalid)
123  continue;
124 
125  os_info.libraries[totaltups].name = pg_strdup(slot_arr->slots[slotno].plugin);
126  os_info.libraries[totaltups].dbnum = dbnum;
127 
128  totaltups++;
129  }
130  }
131 
132  pg_free(ress);
133 
134  os_info.num_libraries = totaltups;
135 }
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
int count_old_cluster_logical_slots(void)
Definition: info.c:740
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
LogicalSlotInfoArr slot_arr
Definition: pg_upgrade.h:199
LogicalSlotInfo * slots
Definition: pg_upgrade.h:170
#define FirstNormalObjectId
Definition: transam.h:197

References conn, connectToServer(), count_old_cluster_logical_slots(), DbInfo::db_name, ClusterInfo::dbarr, LibraryInfo::dbnum, DbInfoArr::dbs, executeQueryOrDie(), 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(), PQfinish(), PQgetvalue(), PQntuples(), res, DbInfo::slot_arr, and LogicalSlotInfoArr::slots.

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:483
static int pg_cmp_size(size_t a, size_t b)
Definition: int.h:507
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().