18
18
/*
19
19
* qsort comparator for pointers to library names
20
20
*
21
- * We sort first by name length, then alphabetically for names of the same
22
- * length. This is to ensure that, eg, "hstore_plpython" sorts after both
23
- * "hstore" and "plpython"; otherwise transform modules will probably fail
24
- * their LOAD tests. (The backend ought to cope with that consideration,
25
- * but it doesn't yet, and even when it does it'll still be a good idea
26
- * to have a predictable order of probing here.)
21
+ * We sort first by name length, then alphabetically for names of the
22
+ * same length, then database array index. This is to ensure that, eg,
23
+ * "hstore_plpython" sorts after both "hstore" and "plpython"; otherwise
24
+ * transform modules will probably fail their LOAD tests. (The backend
25
+ * ought to cope with that consideration, but it doesn't yet, and even
26
+ * when it does it'll still be a good idea to have a predictable order of
27
+ * probing here.)
27
28
*/
28
29
static int
29
30
library_name_compare (const void * p1 , const void * p2 )
30
31
{
31
- const char * str1 = * ( const char * const * ) p1 ;
32
- const char * str2 = * ( const char * const * ) p2 ;
32
+ const char * str1 = (( const LibraryInfo * ) p1 ) -> name ;
33
+ const char * str2 = (( const LibraryInfo * ) p2 ) -> name ;
33
34
int slen1 = strlen (str1 );
34
35
int slen2 = strlen (str2 );
35
-
36
+ int cmp = strcmp (str1 , str2 );
37
+
36
38
if (slen1 != slen2 )
37
39
return slen1 - slen2 ;
38
- return strcmp (str1 , str2 );
40
+ if (cmp != 0 )
41
+ return cmp ;
42
+ else
43
+ return ((const LibraryInfo * ) p1 )-> dbnum -
44
+ ((const LibraryInfo * ) p2 )-> dbnum ;
39
45
}
40
46
41
47
@@ -137,18 +143,7 @@ get_loadable_libraries(void)
137
143
if (found_public_plpython_handler )
138
144
pg_fatal ("Remove the problem functions from the old cluster to continue.\n" );
139
145
140
- /*
141
- * Now we want to remove duplicates across DBs and sort the library names
142
- * into order. This avoids multiple probes of the same library, and
143
- * ensures that libraries are probed in a consistent order, which is
144
- * important for reproducible behavior if one library depends on another.
145
- *
146
- * First transfer all the names into one array, then sort, then remove
147
- * duplicates. Note: we strdup each name in the first loop so that we can
148
- * safely clear the PGresults in the same loop. This is a bit wasteful
149
- * but it's unlikely there are enough names to matter.
150
- */
151
- os_info .libraries = (char * * ) pg_malloc (totaltups * sizeof (char * ));
146
+ os_info .libraries = (LibraryInfo * ) pg_malloc (totaltups * sizeof (LibraryInfo ));
152
147
totaltups = 0 ;
153
148
154
149
for (dbnum = 0 ; dbnum < old_cluster .dbarr .ndbs ; dbnum ++ )
@@ -162,32 +157,16 @@ get_loadable_libraries(void)
162
157
{
163
158
char * lib = PQgetvalue (res , rowno , 0 );
164
159
165
- os_info .libraries [totaltups ++ ] = pg_strdup (lib );
160
+ os_info .libraries [totaltups ].name = pg_strdup (lib );
161
+ os_info .libraries [totaltups ].dbnum = dbnum ;
162
+
163
+ totaltups ++ ;
166
164
}
167
165
PQclear (res );
168
166
}
169
167
170
168
pg_free (ress );
171
169
172
- if (totaltups > 1 )
173
- {
174
- int i ,
175
- lastnondup ;
176
-
177
- qsort ((void * ) os_info .libraries , totaltups , sizeof (char * ),
178
- library_name_compare );
179
-
180
- for (i = 1 , lastnondup = 0 ; i < totaltups ; i ++ )
181
- {
182
- if (strcmp (os_info .libraries [i ],
183
- os_info .libraries [lastnondup ]) != 0 )
184
- os_info .libraries [++ lastnondup ] = os_info .libraries [i ];
185
- else
186
- pg_free (os_info .libraries [i ]);
187
- }
188
- totaltups = lastnondup + 1 ;
189
- }
190
-
191
170
os_info .num_libraries = totaltups ;
192
171
}
193
172
@@ -204,6 +183,7 @@ check_loadable_libraries(void)
204
183
{
205
184
PGconn * conn = connectToServer (& new_cluster , "template1" );
206
185
int libnum ;
186
+ int was_load_failure = false;
207
187
FILE * script = NULL ;
208
188
bool found = false;
209
189
char output_path [MAXPGPATH ];
@@ -212,52 +192,72 @@ check_loadable_libraries(void)
212
192
213
193
snprintf (output_path , sizeof (output_path ), "loadable_libraries.txt" );
214
194
195
+ /*
196
+ * Now we want to sort the library names into order. This avoids multiple
197
+ * probes of the same library, and ensures that libraries are probed in a
198
+ * consistent order, which is important for reproducible behavior if one
199
+ * library depends on another.
200
+ */
201
+ qsort ((void * ) os_info .libraries , os_info .num_libraries ,
202
+ sizeof (LibraryInfo ), library_name_compare );
203
+
215
204
for (libnum = 0 ; libnum < os_info .num_libraries ; libnum ++ )
216
205
{
217
- char * lib = os_info .libraries [libnum ];
206
+ char * lib = os_info .libraries [libnum ]. name ;
218
207
int llen = strlen (lib );
219
208
char cmd [7 + 2 * MAXPGPATH + 1 ];
220
209
PGresult * res ;
221
210
222
- /*
223
- * In Postgres 9.0, Python 3 support was added, and to do that, a
224
- * plpython2u language was created with library name plpython2.so as a
225
- * symbolic link to plpython.so. In Postgres 9.1, only the
226
- * plpython2.so library was created, and both plpythonu and plpython2u
227
- * pointing to it. For this reason, any reference to library name
228
- * "plpython" in an old PG <= 9.1 cluster must look for "plpython2" in
229
- * the new cluster.
230
- *
231
- * For this case, we could check pg_pltemplate, but that only works
232
- * for languages, and does not help with function shared objects, so
233
- * we just do a general fix.
234
- */
235
- if (GET_MAJOR_VERSION (old_cluster .major_version ) < 901 &&
236
- strcmp (lib , "$libdir/plpython" ) == 0 )
237
- {
238
- lib = "$libdir/plpython2" ;
239
- llen = strlen (lib );
240
- }
241
-
242
- strcpy (cmd , "LOAD '" );
243
- PQescapeStringConn (conn , cmd + strlen (cmd ), lib , llen , NULL );
244
- strcat (cmd , "'" );
245
-
246
- res = PQexec (conn , cmd );
247
-
248
- if (PQresultStatus (res ) != PGRES_COMMAND_OK )
211
+ /* Did the library name change? Probe it. */
212
+ if (libnum == 0 || strcmp (lib , os_info .libraries [libnum - 1 ].name ) != 0 )
249
213
{
250
- found = true;
251
-
252
- if (script == NULL && (script = fopen_priv (output_path , "w" )) == NULL )
253
- pg_fatal ("could not open file \"%s\": %s\n" ,
254
- output_path , strerror (errno ));
255
- fprintf (script , _ ("could not load library \"%s\": %s" ),
256
- lib ,
257
- PQerrorMessage (conn ));
214
+ /*
215
+ * In Postgres 9.0, Python 3 support was added, and to do that, a
216
+ * plpython2u language was created with library name plpython2.so as a
217
+ * symbolic link to plpython.so. In Postgres 9.1, only the
218
+ * plpython2.so library was created, and both plpythonu and plpython2u
219
+ * pointing to it. For this reason, any reference to library name
220
+ * "plpython" in an old PG <= 9.1 cluster must look for "plpython2" in
221
+ * the new cluster.
222
+ *
223
+ * For this case, we could check pg_pltemplate, but that only works
224
+ * for languages, and does not help with function shared objects, so
225
+ * we just do a general fix.
226
+ */
227
+ if (GET_MAJOR_VERSION (old_cluster .major_version ) < 901 &&
228
+ strcmp (lib , "$libdir/plpython" ) == 0 )
229
+ {
230
+ lib = "$libdir/plpython2" ;
231
+ llen = strlen (lib );
232
+ }
233
+
234
+ strcpy (cmd , "LOAD '" );
235
+ PQescapeStringConn (conn , cmd + strlen (cmd ), lib , llen , NULL );
236
+ strcat (cmd , "'" );
237
+
238
+ res = PQexec (conn , cmd );
239
+
240
+ if (PQresultStatus (res ) != PGRES_COMMAND_OK )
241
+ {
242
+ found = true;
243
+ was_load_failure = true;
244
+
245
+ if (script == NULL && (script = fopen_priv (output_path , "w" )) == NULL )
246
+ pg_fatal ("could not open file \"%s\": %s\n" ,
247
+ output_path , strerror (errno ));
248
+ fprintf (script , _ ("could not load library \"%s\": %s" ),
249
+ lib ,
250
+ PQerrorMessage (conn ));
251
+ }
252
+ else
253
+ was_load_failure = false;
254
+
255
+ PQclear (res );
258
256
}
259
257
260
- PQclear (res );
258
+ if (was_load_failure )
259
+ fprintf (script , _ ("Database: %s\n" ),
260
+ old_cluster .dbarr .dbs [os_info .libraries [libnum ].dbnum ].db_name );
261
261
}
262
262
263
263
PQfinish (conn );
0 commit comments