PostgreSQL Source Code  git master
function.c File Reference
#include "postgres_fe.h"
#include "access/transam.h"
#include "catalog/pg_language_d.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 120 of file function.c.

121 {
122  PGconn *conn = connectToServer(&new_cluster, "template1");
123  int libnum;
124  int was_load_failure = false;
125  FILE *script = NULL;
126  char output_path[MAXPGPATH];
127 
128  prep_status("Checking for presence of required libraries");
129 
130  snprintf(output_path, sizeof(output_path), "%s/%s",
131  log_opts.basedir, "loadable_libraries.txt");
132 
133  /*
134  * Now we want to sort the library names into order. This avoids multiple
135  * probes of the same library, and ensures that libraries are probed in a
136  * consistent order, which is important for reproducible behavior if one
137  * library depends on another.
138  */
141 
142  for (libnum = 0; libnum < os_info.num_libraries; libnum++)
143  {
144  char *lib = os_info.libraries[libnum].name;
145  int llen = strlen(lib);
146  char cmd[7 + 2 * MAXPGPATH + 1];
147  PGresult *res;
148 
149  /* Did the library name change? Probe it. */
150  if (libnum == 0 || strcmp(lib, os_info.libraries[libnum - 1].name) != 0)
151  {
152  strcpy(cmd, "LOAD '");
153  PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
154  strcat(cmd, "'");
155 
156  res = PQexec(conn, cmd);
157 
159  {
160  was_load_failure = true;
161 
162  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
163  pg_fatal("could not open file \"%s\": %s",
164  output_path, strerror(errno));
165  fprintf(script, _("could not load library \"%s\": %s"),
166  lib,
168  }
169  else
170  was_load_failure = false;
171 
172  PQclear(res);
173  }
174 
175  if (was_load_failure)
176  fprintf(script, _("In database: %s\n"),
178  }
179 
180  PQfinish(conn);
181 
182  if (script)
183  {
184  fclose(script);
185  pg_log(PG_REPORT, "fatal");
186  pg_fatal("Your installation references loadable libraries that are missing from the\n"
187  "new installation. You can add these libraries to the new installation,\n"
188  "or remove the functions using them from the old installation. A list of\n"
189  "problem libraries is in the file:\n"
190  " %s", output_path);
191  }
192  else
193  check_ok();
194 }
#define _(x)
Definition: elog.c:91
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7245
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4599
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
Definition: fe-exec.c:3982
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3244
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2228
static int library_name_compare(const void *p1, const void *p2)
Definition: function.c:28
static void check_ok(void)
Definition: initdb.c:2034
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:97
#define pg_fatal(...)
#define MAXPGPATH
OSInfo os_info
Definition: pg_upgrade.c:65
ClusterInfo new_cluster
Definition: pg_upgrade.c:64
ClusterInfo old_cluster
Definition: pg_upgrade.c:63
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:390
@ PG_REPORT
Definition: pg_upgrade.h:248
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:28
void prep_status(const char *fmt,...) pg_attribute_printf(1
#define strerror
Definition: port.h:251
#define snprintf
Definition: port.h:238
#define fprintf
Definition: port.h:242
#define qsort(a, b, c, d)
Definition: port.h:445
PGconn * conn
Definition: streamutil.c:54
DbInfoArr dbarr
Definition: pg_upgrade.h:263
DbInfo * dbs
Definition: pg_upgrade.h:195
char * db_name
Definition: pg_upgrade.h:175
char * name
Definition: pg_upgrade.h:311
char * basedir
Definition: pg_upgrade.h:289
LibraryInfo * libraries
Definition: pg_upgrade.h:325
int num_libraries
Definition: pg_upgrade.h:326

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, snprintf, and strerror.

Referenced by check_new_cluster().

◆ get_loadable_libraries()

void get_loadable_libraries ( void  )

Definition at line 53 of file function.c.

54 {
55  PGresult **ress;
56  int totaltups;
57  int dbnum;
58 
59  ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
60  totaltups = 0;
61 
62  /* Fetch all library names, removing duplicates within each DB */
63  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
64  {
65  DbInfo *active_db = &old_cluster.dbarr.dbs[dbnum];
67 
68  /*
69  * Fetch all libraries containing non-built-in C functions in this DB.
70  */
71  ress[dbnum] = executeQueryOrDie(conn,
72  "SELECT DISTINCT probin "
73  "FROM pg_catalog.pg_proc "
74  "WHERE prolang = %u AND "
75  "probin IS NOT NULL AND "
76  "oid >= %u;",
77  ClanguageId,
79  totaltups += PQntuples(ress[dbnum]);
80 
81  PQfinish(conn);
82  }
83 
84  os_info.libraries = (LibraryInfo *) pg_malloc(totaltups * sizeof(LibraryInfo));
85  totaltups = 0;
86 
87  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
88  {
89  PGresult *res = ress[dbnum];
90  int ntups;
91  int rowno;
92 
93  ntups = PQntuples(res);
94  for (rowno = 0; rowno < ntups; rowno++)
95  {
96  char *lib = PQgetvalue(res, rowno, 0);
97 
98  os_info.libraries[totaltups].name = pg_strdup(lib);
99  os_info.libraries[totaltups].dbnum = dbnum;
100 
101  totaltups++;
102  }
103  PQclear(res);
104  }
105 
106  pg_free(ress);
107 
108  os_info.num_libraries = totaltups;
109 }
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3314
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3709
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
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
#define FirstNormalObjectId
Definition: transam.h:197

References conn, connectToServer(), DbInfo::db_name, ClusterInfo::dbarr, LibraryInfo::dbnum, DbInfoArr::dbs, executeQueryOrDie(), FirstNormalObjectId, OSInfo::libraries, LibraryInfo::name, DbInfoArr::ndbs, OSInfo::num_libraries, old_cluster, os_info, pg_free(), pg_malloc(), pg_strdup(), PQclear(), PQfinish(), PQgetvalue(), PQntuples(), and res.

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

29 {
30  const char *str1 = ((const LibraryInfo *) p1)->name;
31  const char *str2 = ((const LibraryInfo *) p2)->name;
32  int slen1 = strlen(str1);
33  int slen2 = strlen(str2);
34  int cmp = strcmp(str1, str2);
35 
36  if (slen1 != slen2)
37  return slen1 - slen2;
38  if (cmp != 0)
39  return cmp;
40  else
41  return ((const LibraryInfo *) p1)->dbnum -
42  ((const LibraryInfo *) p2)->dbnum;
43 }
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743

References cmp(), and p2.

Referenced by check_loadable_libraries().