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

Commit7393208

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 parent2281575 commit7393208

File tree

3 files changed

+312
-163
lines changed

3 files changed

+312
-163
lines changed

‎src/bin/pg_dump/common.c

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

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

61+
/* This is an array of object identities, not actual DumpableObjects */
62+
staticExtensionMemberId*extmembers;
63+
staticintnumextmembers;
6464

6565
staticvoidflagInhTables(TableInfo*tbinfo,intnumTables,
6666
InhInfo*inhinfo,intnumInherits);
6767
staticvoidflagInhAttrs(TableInfo*tblinfo,intnumTables);
6868
staticDumpableObject**buildIndexArray(void*objArray,intnumObjs,
6969
SizeobjSize);
7070
staticintDOCatalogIdCompare(constvoid*p1,constvoid*p2);
71+
staticintExtensionMemberIdCompare(constvoid*p1,constvoid*p2);
7172
staticvoidfindParentsByOid(TableInfo*self,
7273
InhInfo*inhinfo,intnumInherits);
7374
staticintstrInArray(constchar*pattern,char**arr,intarr_size);
@@ -80,10 +81,14 @@ static intstrInArray(const char *pattern, char **arr, int arr_size);
8081
TableInfo*
8182
getSchemaData(Archive*fout,int*numTablesPtr)
8283
{
84+
TableInfo*tblinfo;
85+
TypeInfo*typinfo;
86+
FuncInfo*funinfo;
87+
OprInfo*oprinfo;
88+
CollInfo*collinfo;
89+
NamespaceInfo*nspinfo;
8390
ExtensionInfo*extinfo;
8491
InhInfo*inhinfo;
85-
CollInfo*collinfo;
86-
intnumExtensions;
8792
intnumAggregates;
8893
intnumInherits;
8994
intnumRules;
@@ -101,6 +106,20 @@ getSchemaData(Archive *fout, int *numTablesPtr)
101106
intnumDefaultACLs;
102107
intnumEventTriggers;
103108

109+
/*
110+
* We must read extensions and extension membership info first, because
111+
* extension membership needs to be consultable during decisions about
112+
* whether other objects are to be dumped.
113+
*/
114+
if (g_verbose)
115+
write_msg(NULL,"reading extensions\n");
116+
extinfo=getExtensions(fout,&numExtensions);
117+
extinfoindex=buildIndexArray(extinfo,numExtensions,sizeof(ExtensionInfo));
118+
119+
if (g_verbose)
120+
write_msg(NULL,"identifying extension members\n");
121+
getExtensionMembership(fout,extinfo,numExtensions);
122+
104123
if (g_verbose)
105124
write_msg(NULL,"reading schemas\n");
106125
nspinfo=getNamespaces(fout,&numNamespaces);
@@ -120,10 +139,6 @@ getSchemaData(Archive *fout, int *numTablesPtr)
120139
/* Do this after we've built tblinfoindex */
121140
getOwnedSeqs(fout,tblinfo,numTables);
122141

123-
if (g_verbose)
124-
write_msg(NULL,"reading extensions\n");
125-
extinfo=getExtensions(fout,&numExtensions);
126-
127142
if (g_verbose)
128143
write_msg(NULL,"reading user-defined functions\n");
129144
funinfo=getFuncs(fout,&numFuncs);
@@ -206,14 +221,10 @@ getSchemaData(Archive *fout, int *numTablesPtr)
206221
write_msg(NULL,"reading event triggers\n");
207222
getEventTriggers(fout,&numEventTriggers);
208223

209-
/*
210-
* Identify extension member objects and mark them as not to be dumped.
211-
* This must happen after reading all objects that can be direct members
212-
* of extensions, but before we begin to process table subsidiary objects.
213-
*/
224+
/* Identify extension configuration tables that should be dumped */
214225
if (g_verbose)
215-
write_msg(NULL,"finding extensionmembers\n");
216-
getExtensionMembership(fout,extinfo,numExtensions);
226+
write_msg(NULL,"finding extensiontables\n");
227+
processExtensionTables(fout,extinfo,numExtensions);
217228

218229
/* Link tables to parents, mark parents of target tables interesting */
219230
if (g_verbose)
@@ -752,6 +763,93 @@ findNamespaceByOid(Oid oid)
752763
return (NamespaceInfo*)findObjectByOid(oid,nspinfoindex,numNamespaces);
753764
}
754765

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

756854
/*
757855
* findParentsByOid

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp