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

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:3415
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3810
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:747

References cmp(), and p2.

Referenced by check_loadable_libraries().