diff options
Diffstat (limited to 'src/bin/pg_dump/common.c')
-rw-r--r-- | src/bin/pg_dump/common.c | 158 |
1 files changed, 128 insertions, 30 deletions
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c index 3b4e478ad94..f798b15e3c4 100644 --- a/src/bin/pg_dump/common.c +++ b/src/bin/pg_dump/common.c @@ -40,30 +40,30 @@ static int numCatalogIds = 0; /* * These variables are static to avoid the notational cruft of having to pass - * them into findTableByOid() and friends. For each of these arrays, we - * build a sorted-by-OID index array immediately after it's built, and then - * we use binary search in findTableByOid() and friends. (qsort'ing the base - * arrays themselves would be simpler, but it doesn't work because pg_dump.c - * may have already established pointers between items.) - */ -static TableInfo *tblinfo; -static TypeInfo *typinfo; -static FuncInfo *funinfo; -static OprInfo *oprinfo; -static NamespaceInfo *nspinfo; -static int numTables; -static int numTypes; -static int numFuncs; -static int numOperators; -static int numCollations; -static int numNamespaces; + * them into findTableByOid() and friends. For each of these arrays, we build + * a sorted-by-OID index array immediately after the objects are fetched, + * and then we use binary search in findTableByOid() and friends. (qsort'ing + * the object arrays themselves would be simpler, but it doesn't work because + * pg_dump.c may have already established pointers between items.) + */ static DumpableObject **tblinfoindex; static DumpableObject **typinfoindex; static DumpableObject **funinfoindex; static DumpableObject **oprinfoindex; static DumpableObject **collinfoindex; static DumpableObject **nspinfoindex; +static DumpableObject **extinfoindex; +static int numTables; +static int numTypes; +static int numFuncs; +static int numOperators; +static int numCollations; +static int numNamespaces; +static int numExtensions; +/* This is an array of object identities, not actual DumpableObjects */ +static ExtensionMemberId *extmembers; +static int numextmembers; static void flagInhTables(TableInfo *tbinfo, int numTables, InhInfo *inhinfo, int numInherits); @@ -71,6 +71,7 @@ static void flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables); static DumpableObject **buildIndexArray(void *objArray, int numObjs, Size objSize); static int DOCatalogIdCompare(const void *p1, const void *p2); +static int ExtensionMemberIdCompare(const void *p1, const void *p2); static void findParentsByOid(TableInfo *self, InhInfo *inhinfo, int numInherits); static int strInArray(const char *pattern, char **arr, int arr_size); @@ -83,10 +84,14 @@ static int strInArray(const char *pattern, char **arr, int arr_size); TableInfo * getSchemaData(Archive *fout, int *numTablesPtr) { + TableInfo *tblinfo; + TypeInfo *typinfo; + FuncInfo *funinfo; + OprInfo *oprinfo; + CollInfo *collinfo; + NamespaceInfo *nspinfo; ExtensionInfo *extinfo; InhInfo *inhinfo; - CollInfo *collinfo; - int numExtensions; int numAggregates; int numInherits; int numRules; @@ -105,6 +110,20 @@ getSchemaData(Archive *fout, int *numTablesPtr) int numDefaultACLs; int numEventTriggers; + /* + * We must read extensions and extension membership info first, because + * extension membership needs to be consultable during decisions about + * whether other objects are to be dumped. + */ + if (g_verbose) + write_msg(NULL, "reading extensions\n"); + extinfo = getExtensions(fout, &numExtensions); + extinfoindex = buildIndexArray(extinfo, numExtensions, sizeof(ExtensionInfo)); + + if (g_verbose) + write_msg(NULL, "identifying extension members\n"); + getExtensionMembership(fout, extinfo, numExtensions); + if (g_verbose) write_msg(NULL, "reading schemas\n"); nspinfo = getNamespaces(fout, &numNamespaces); @@ -125,10 +144,6 @@ getSchemaData(Archive *fout, int *numTablesPtr) getOwnedSeqs(fout, tblinfo, numTables); if (g_verbose) - write_msg(NULL, "reading extensions\n"); - extinfo = getExtensions(fout, &numExtensions); - - if (g_verbose) write_msg(NULL, "reading user-defined functions\n"); funinfo = getFuncs(fout, &numFuncs); funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo)); @@ -214,14 +229,10 @@ getSchemaData(Archive *fout, int *numTablesPtr) write_msg(NULL, "reading event triggers\n"); getEventTriggers(fout, &numEventTriggers); - /* - * Identify extension member objects and mark them as not to be dumped. - * This must happen after reading all objects that can be direct members - * of extensions, but before we begin to process table subsidiary objects. - */ + /* Identify extension configuration tables that should be dumped */ if (g_verbose) - write_msg(NULL, "finding extension members\n"); - getExtensionMembership(fout, extinfo, numExtensions); + write_msg(NULL, "finding extension tables\n"); + processExtensionTables(fout, extinfo, numExtensions); /* Link tables to parents, mark parents of target tables interesting */ if (g_verbose) @@ -764,6 +775,93 @@ findNamespaceByOid(Oid oid) return (NamespaceInfo *) findObjectByOid(oid, nspinfoindex, numNamespaces); } +/* + * findExtensionByOid + * finds the entry (in extinfo) of the extension with the given oid + * returns NULL if not found + */ +ExtensionInfo * +findExtensionByOid(Oid oid) +{ + return (ExtensionInfo *) findObjectByOid(oid, extinfoindex, numExtensions); +} + + +/* + * setExtensionMembership + * accept and save data about which objects belong to extensions + */ +void +setExtensionMembership(ExtensionMemberId *extmems, int nextmems) +{ + /* Sort array in preparation for binary searches */ + if (nextmems > 1) + qsort((void *) extmems, nextmems, sizeof(ExtensionMemberId), + ExtensionMemberIdCompare); + /* And save */ + extmembers = extmems; + numextmembers = nextmems; +} + +/* + * findOwningExtension + * return owning extension for specified catalog ID, or NULL if none + */ +ExtensionInfo * +findOwningExtension(CatalogId catalogId) +{ + ExtensionMemberId *low; + ExtensionMemberId *high; + + /* + * We could use bsearch() here, but the notational cruft of calling + * bsearch is nearly as bad as doing it ourselves; and the generalized + * bsearch function is noticeably slower as well. + */ + if (numextmembers <= 0) + return NULL; + low = extmembers; + high = extmembers + (numextmembers - 1); + while (low <= high) + { + ExtensionMemberId *middle; + int difference; + + middle = low + (high - low) / 2; + /* comparison must match ExtensionMemberIdCompare, below */ + difference = oidcmp(middle->catId.oid, catalogId.oid); + if (difference == 0) + difference = oidcmp(middle->catId.tableoid, catalogId.tableoid); + if (difference == 0) + return middle->ext; + else if (difference < 0) + low = middle + 1; + else + high = middle - 1; + } + return NULL; +} + +/* + * qsort comparator for ExtensionMemberIds + */ +static int +ExtensionMemberIdCompare(const void *p1, const void *p2) +{ + const ExtensionMemberId *obj1 = (const ExtensionMemberId *) p1; + const ExtensionMemberId *obj2 = (const ExtensionMemberId *) p2; + int cmpval; + + /* + * Compare OID first since it's usually unique, whereas there will only be + * a few distinct values of tableoid. + */ + cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid); + if (cmpval == 0) + cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid); + return cmpval; +} + /* * findParentsByOid |