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

Commite72d7d8

Browse files
committed
Handle extension members when first setting object dump flags in pg_dump.
pg_dump's original approach to handling extension member objects was torun around and clear (or set) their dump flags rather late in its datacollection process. Unfortunately, quite a lot of code expects those flagsto be valid before that; which was an entirely reasonable expectationbefore we added extensions. In particular, this explains Karsten Hilbert'srecent report of pg_upgrade failing on a database in which an extensionhas been installed into the pg_catalog schema. Its objects are initiallymarked as not-to-be-dumped on the strength of their schema, and later wechange them to must-dump because we're doing a binary upgrade of theirextension; but we've already skipped essential tasks like making associatedDO_SHELL_TYPE objects.To fix, collect extension membership data first, and incorporate it in theinitial setting of the dump flags, so that those are once again correctfrom the get-go. This has the undesirable side effect of slightlylengthening the time taken before pg_dump acquires table locks, but testingsuggests that the increase in that window is not very much.Along the way, get rid of ugly special-case logic for deciding whetherto dump procedural languages, FDWs, and foreign servers; dump decisionsfor those are now correct up-front, too.In 9.3 and up, this also fixes erroneous logic about when to dump eventtriggers (basically, they were *always* dumped before). In 9.5 and up,transform objects had that problem too.Since this problem came in with extensions, back-patch to all supportedversions.
1 parent5b5fea2 commite72d7d8

File tree

3 files changed

+358
-189
lines changed

3 files changed

+358
-189
lines changed

‎src/bin/pg_dump/common.c

Lines changed: 128 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -40,37 +40,38 @@ static intnumCatalogIds = 0;
4040

4141
/*
4242
* These variables are static to avoid the notational cruft of having to pass
43-
* them into findTableByOid() and friends. For each of these arrays, we
44-
* build a sorted-by-OID index array immediately after it's built, and then
45-
* we use binary search in findTableByOid() and friends. (qsort'ing the base
46-
* arrays themselves would be simpler, but it doesn't work because pg_dump.c
47-
* may have already established pointers between items.)
48-
*/
49-
staticTableInfo*tblinfo;
50-
staticTypeInfo*typinfo;
51-
staticFuncInfo*funinfo;
52-
staticOprInfo*oprinfo;
53-
staticNamespaceInfo*nspinfo;
54-
staticintnumTables;
55-
staticintnumTypes;
56-
staticintnumFuncs;
57-
staticintnumOperators;
58-
staticintnumCollations;
59-
staticintnumNamespaces;
43+
* them into findTableByOid() and friends. For each of these arrays, we build
44+
* a sorted-by-OID index array immediately after the objects are fetched,
45+
* and then we use binary search in findTableByOid() and friends. (qsort'ing
46+
* the object arrays themselves would be simpler, but it doesn't work because
47+
* pg_dump.c may have already established pointers between items.)
48+
*/
6049
staticDumpableObject**tblinfoindex;
6150
staticDumpableObject**typinfoindex;
6251
staticDumpableObject**funinfoindex;
6352
staticDumpableObject**oprinfoindex;
6453
staticDumpableObject**collinfoindex;
6554
staticDumpableObject**nspinfoindex;
55+
staticDumpableObject**extinfoindex;
56+
staticintnumTables;
57+
staticintnumTypes;
58+
staticintnumFuncs;
59+
staticintnumOperators;
60+
staticintnumCollations;
61+
staticintnumNamespaces;
62+
staticintnumExtensions;
6663

64+
/* This is an array of object identities, not actual DumpableObjects */
65+
staticExtensionMemberId*extmembers;
66+
staticintnumextmembers;
6767

6868
staticvoidflagInhTables(TableInfo*tbinfo,intnumTables,
6969
InhInfo*inhinfo,intnumInherits);
7070
staticvoidflagInhAttrs(DumpOptions*dopt,TableInfo*tblinfo,intnumTables);
7171
staticDumpableObject**buildIndexArray(void*objArray,intnumObjs,
7272
SizeobjSize);
7373
staticintDOCatalogIdCompare(constvoid*p1,constvoid*p2);
74+
staticintExtensionMemberIdCompare(constvoid*p1,constvoid*p2);
7475
staticvoidfindParentsByOid(TableInfo*self,
7576
InhInfo*inhinfo,intnumInherits);
7677
staticintstrInArray(constchar*pattern,char**arr,intarr_size);
@@ -83,10 +84,14 @@ static intstrInArray(const char *pattern, char **arr, int arr_size);
8384
TableInfo*
8485
getSchemaData(Archive*fout,int*numTablesPtr)
8586
{
87+
TableInfo*tblinfo;
88+
TypeInfo*typinfo;
89+
FuncInfo*funinfo;
90+
OprInfo*oprinfo;
91+
CollInfo*collinfo;
92+
NamespaceInfo*nspinfo;
8693
ExtensionInfo*extinfo;
8794
InhInfo*inhinfo;
88-
CollInfo*collinfo;
89-
intnumExtensions;
9095
intnumAggregates;
9196
intnumInherits;
9297
intnumRules;
@@ -105,6 +110,20 @@ getSchemaData(Archive *fout, int *numTablesPtr)
105110
intnumDefaultACLs;
106111
intnumEventTriggers;
107112

113+
/*
114+
* We must read extensions and extension membership info first, because
115+
* extension membership needs to be consultable during decisions about
116+
* whether other objects are to be dumped.
117+
*/
118+
if (g_verbose)
119+
write_msg(NULL,"reading extensions\n");
120+
extinfo=getExtensions(fout,&numExtensions);
121+
extinfoindex=buildIndexArray(extinfo,numExtensions,sizeof(ExtensionInfo));
122+
123+
if (g_verbose)
124+
write_msg(NULL,"identifying extension members\n");
125+
getExtensionMembership(fout,extinfo,numExtensions);
126+
108127
if (g_verbose)
109128
write_msg(NULL,"reading schemas\n");
110129
nspinfo=getNamespaces(fout,&numNamespaces);
@@ -124,10 +143,6 @@ getSchemaData(Archive *fout, int *numTablesPtr)
124143
/* Do this after we've built tblinfoindex */
125144
getOwnedSeqs(fout,tblinfo,numTables);
126145

127-
if (g_verbose)
128-
write_msg(NULL,"reading extensions\n");
129-
extinfo=getExtensions(fout,&numExtensions);
130-
131146
if (g_verbose)
132147
write_msg(NULL,"reading user-defined functions\n");
133148
funinfo=getFuncs(fout,&numFuncs);
@@ -214,14 +229,10 @@ getSchemaData(Archive *fout, int *numTablesPtr)
214229
write_msg(NULL,"reading event triggers\n");
215230
getEventTriggers(fout,&numEventTriggers);
216231

217-
/*
218-
* Identify extension member objects and mark them as not to be dumped.
219-
* This must happen after reading all objects that can be direct members
220-
* of extensions, but before we begin to process table subsidiary objects.
221-
*/
232+
/* Identify extension configuration tables that should be dumped */
222233
if (g_verbose)
223-
write_msg(NULL,"finding extensionmembers\n");
224-
getExtensionMembership(fout,extinfo,numExtensions);
234+
write_msg(NULL,"finding extensiontables\n");
235+
processExtensionTables(fout,extinfo,numExtensions);
225236

226237
/* Link tables to parents, mark parents of target tables interesting */
227238
if (g_verbose)
@@ -764,6 +775,93 @@ findNamespaceByOid(Oid oid)
764775
return (NamespaceInfo*)findObjectByOid(oid,nspinfoindex,numNamespaces);
765776
}
766777

778+
/*
779+
* findExtensionByOid
780+
* finds the entry (in extinfo) of the extension with the given oid
781+
* returns NULL if not found
782+
*/
783+
ExtensionInfo*
784+
findExtensionByOid(Oidoid)
785+
{
786+
return (ExtensionInfo*)findObjectByOid(oid,extinfoindex,numExtensions);
787+
}
788+
789+
790+
/*
791+
* setExtensionMembership
792+
* accept and save data about which objects belong to extensions
793+
*/
794+
void
795+
setExtensionMembership(ExtensionMemberId*extmems,intnextmems)
796+
{
797+
/* Sort array in preparation for binary searches */
798+
if (nextmems>1)
799+
qsort((void*)extmems,nextmems,sizeof(ExtensionMemberId),
800+
ExtensionMemberIdCompare);
801+
/* And save */
802+
extmembers=extmems;
803+
numextmembers=nextmems;
804+
}
805+
806+
/*
807+
* findOwningExtension
808+
* return owning extension for specified catalog ID, or NULL if none
809+
*/
810+
ExtensionInfo*
811+
findOwningExtension(CatalogIdcatalogId)
812+
{
813+
ExtensionMemberId*low;
814+
ExtensionMemberId*high;
815+
816+
/*
817+
* We could use bsearch() here, but the notational cruft of calling
818+
* bsearch is nearly as bad as doing it ourselves; and the generalized
819+
* bsearch function is noticeably slower as well.
820+
*/
821+
if (numextmembers <=0)
822+
returnNULL;
823+
low=extmembers;
824+
high=extmembers+ (numextmembers-1);
825+
while (low <=high)
826+
{
827+
ExtensionMemberId*middle;
828+
intdifference;
829+
830+
middle=low+ (high-low) /2;
831+
/* comparison must match ExtensionMemberIdCompare, below */
832+
difference=oidcmp(middle->catId.oid,catalogId.oid);
833+
if (difference==0)
834+
difference=oidcmp(middle->catId.tableoid,catalogId.tableoid);
835+
if (difference==0)
836+
returnmiddle->ext;
837+
elseif (difference<0)
838+
low=middle+1;
839+
else
840+
high=middle-1;
841+
}
842+
returnNULL;
843+
}
844+
845+
/*
846+
* qsort comparator for ExtensionMemberIds
847+
*/
848+
staticint
849+
ExtensionMemberIdCompare(constvoid*p1,constvoid*p2)
850+
{
851+
constExtensionMemberId*obj1= (constExtensionMemberId*)p1;
852+
constExtensionMemberId*obj2= (constExtensionMemberId*)p2;
853+
intcmpval;
854+
855+
/*
856+
* Compare OID first since it's usually unique, whereas there will only be
857+
* a few distinct values of tableoid.
858+
*/
859+
cmpval=oidcmp(obj1->catId.oid,obj2->catId.oid);
860+
if (cmpval==0)
861+
cmpval=oidcmp(obj1->catId.tableoid,obj2->catId.tableoid);
862+
returncmpval;
863+
}
864+
767865

768866
/*
769867
* findParentsByOid

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp