Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit83c2492

Browse files
committed
Enforce a specific order for probing library loadability in pg_upgrade.
pg_upgrade checks whether all the shared libraries used in the old clusterare also available in the new one by issuing LOAD for each library name.Previously, it cared not what order it did the LOADs in. Ideally itshould not have to care, but currently the transform modules in contribfail unless both the language and datatype modules they depend on areloaded first. A backend-side solution for that looks possible butprobably not back-patchable, so as a stopgap measure, let's do the LOADtests in order by library name length. That should fix the problem forreasonably-named transform modules, eg "hstore_plpython" will be loadedafter both "hstore" and "plpython". (Yeah, it's a hack.)In a larger sense, having a predictable order of these probes is a goodthing, since it will make upgrades predictably work or not work in theface of inter-library dependencies. Also, this patch replaces O(N^2)de-duplication logic with O(N log N) logic, which could matter ininstallations with very many databases. So I don't foresee reverting thiseven after we have a proper fix for the library-dependency problem.In passing, improve a couple of SQL queries used here.Per complaint from Andrew Dunstan that pg_upgrade'ing the transform contribmodules failed. Back-patch to 9.5 where transform modules were introduced.Discussion: <f7ac29f3-515c-2a44-21c5-ec925053265f@dunslane.net>
1 parente94568e commit83c2492

File tree

1 file changed

+67
-30
lines changed

1 file changed

+67
-30
lines changed

‎src/bin/pg_upgrade/function.c

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,31 @@
1212
#include"pg_upgrade.h"
1313

1414
#include"access/transam.h"
15+
#include"catalog/pg_language.h"
16+
17+
18+
/*
19+
* qsort comparator for pointers to library names
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.)
27+
*/
28+
staticint
29+
library_name_compare(constvoid*p1,constvoid*p2)
30+
{
31+
constchar*str1=*(constchar*const*)p1;
32+
constchar*str2=*(constchar*const*)p2;
33+
intslen1=strlen(str1);
34+
intslen2=strlen(str2);
35+
36+
if (slen1!=slen2)
37+
returnslen1-slen2;
38+
returnstrcmp(str1,str2);
39+
}
1540

1641

1742
/*
@@ -38,17 +63,15 @@ get_loadable_libraries(void)
3863
PGconn*conn=connectToServer(&old_cluster,active_db->db_name);
3964

4065
/*
41-
* Fetch all libraries referenced in this DB. We can't exclude the
42-
* "pg_catalog" schema because, while such functions are not
43-
* explicitly dumped by pg_dump, they do reference implicit objects
44-
* that pg_dump does dump, e.g. CREATE LANGUAGE plperl.
66+
* Fetch all libraries containing non-built-in C functions in this DB.
4567
*/
4668
ress[dbnum]=executeQueryOrDie(conn,
4769
"SELECT DISTINCT probin "
48-
"FROMpg_catalog.pg_proc "
49-
"WHEREprolang =13 /* C */ AND "
70+
"FROMpg_catalog.pg_proc "
71+
"WHEREprolang =%u AND "
5072
"probin IS NOT NULL AND "
5173
"oid >= %u;",
74+
ClanguageId,
5275
FirstNormalObjectId);
5376
totaltups+=PQntuples(ress[dbnum]);
5477

@@ -69,13 +92,15 @@ get_loadable_libraries(void)
6992

7093
res=executeQueryOrDie(conn,
7194
"SELECT 1 "
72-
"FROMpg_catalog.pg_proc JOIN pg_namespace "
73-
"ON pronamespace = pg_namespace.oid "
95+
"FROM pg_catalog.pg_proc p "
96+
" JOIN pg_catalog.pg_namespace n "
97+
" ON pronamespace = n.oid "
7498
"WHERE proname = 'plpython_call_handler' AND "
7599
"nspname = 'public' AND "
76-
"prolang =13 /* C */ AND "
100+
"prolang =%u AND "
77101
"probin = '$libdir/plpython' AND "
78-
"pg_proc.oid >= %u;",
102+
"p.oid >= %u;",
103+
ClanguageId,
79104
FirstNormalObjectId);
80105
if (PQntuples(res)>0)
81106
{
@@ -112,13 +137,18 @@ get_loadable_libraries(void)
112137
if (found_public_plpython_handler)
113138
pg_fatal("Remove the problem functions from the old cluster to continue.\n");
114139

115-
/* Allocate what's certainly enough space */
116-
os_info.libraries= (char**)pg_malloc(totaltups*sizeof(char*));
117-
118140
/*
119-
* Now remove duplicates across DBs. This is pretty inefficient code, but
120-
* there probably aren't enough entries to matter.
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.
121150
*/
151+
os_info.libraries= (char**)pg_malloc(totaltups*sizeof(char*));
122152
totaltups=0;
123153

124154
for (dbnum=0;dbnum<old_cluster.dbarr.ndbs;dbnum++)
@@ -131,27 +161,34 @@ get_loadable_libraries(void)
131161
for (rowno=0;rowno<ntups;rowno++)
132162
{
133163
char*lib=PQgetvalue(res,rowno,0);
134-
booldup= false;
135-
intn;
136164

137-
for (n=0;n<totaltups;n++)
138-
{
139-
if (strcmp(lib,os_info.libraries[n])==0)
140-
{
141-
dup= true;
142-
break;
143-
}
144-
}
145-
if (!dup)
146-
os_info.libraries[totaltups++]=pg_strdup(lib);
165+
os_info.libraries[totaltups++]=pg_strdup(lib);
147166
}
148-
149167
PQclear(res);
150168
}
151169

152-
os_info.num_libraries=totaltups;
153-
154170
pg_free(ress);
171+
172+
if (totaltups>1)
173+
{
174+
inti,
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+
os_info.num_libraries=totaltups;
155192
}
156193

157194

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp