Today, pg_dump does a lot of internal lookups via binary search in presorted arrays. I thought it might improve matters to replace those binary searches with hash tables, theoretically converting O(log N) searches into O(1) searches. So I tried making a hash table indexed by CatalogId (tableoid+oid) with simplehash.h, and replacing as many data structures as I could with that.
This makes the code shorter and (IMO anyway) cleaner, but (a) the executable size increases by a few KB --- apparently, even the minimum subset of simplehash.h's functionality is code-wasteful. (b) I couldn't measure any change in performance at all. I tried it on the regression database and on a toy DB with 10000 simple tables. Maybe on a really large DB you'd notice some difference, but I'm not very optimistic now. So this experiment feels like a failure, but I thought I'd post the patch and results for the archives' sake. Maybe somebody will think of a way to improve matters. Or maybe it's worth doing just to shorten the code? regards, tom lane
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c index 1f24e79665..49932fd598 100644 --- a/src/bin/pg_dump/common.c +++ b/src/bin/pg_dump/common.c @@ -18,6 +18,14 @@ #include <ctype.h> #include "catalog/pg_class_d.h" +#include "catalog/pg_collation_d.h" +#include "catalog/pg_extension_d.h" +#include "catalog/pg_namespace_d.h" +#include "catalog/pg_operator_d.h" +#include "catalog/pg_proc_d.h" +#include "catalog/pg_publication_d.h" +#include "catalog/pg_type_d.h" +#include "common/hashfn.h" #include "fe_utils/string_utils.h" #include "pg_backup_archiver.h" #include "pg_backup_utils.h" @@ -31,54 +39,54 @@ static int allocedDumpIds = 0; static DumpId lastDumpId = 0; /* Note: 0 is InvalidDumpId */ /* - * Variables for mapping CatalogId to DumpableObject - */ -static bool catalogIdMapValid = false; -static DumpableObject **catalogIdMap = NULL; -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 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.) + * Infrastructure for mapping CatalogId to DumpableObject + * + * We use a hash table generated by simplehash.h. That infrastructure + * requires all the hash table entries to be the same size, and it also + * expects that it can move them around when resizing the table. So we + * cannot make the DumpableObjects be elements of the hash table directly; + * instead, the hash table elements contain pointers to DumpableObjects. + * + * It turns out to be convenient to also use this data structure to map + * CatalogIds to owning extensions, if any. Since extension membership + * data is read before creating most DumpableObjects, either one of dobj + * and ext could be NULL. */ -static DumpableObject **tblinfoindex; -static DumpableObject **typinfoindex; -static DumpableObject **funinfoindex; -static DumpableObject **oprinfoindex; -static DumpableObject **collinfoindex; -static DumpableObject **nspinfoindex; -static DumpableObject **extinfoindex; -static DumpableObject **pubinfoindex; -static int numTables; -static int numTypes; -static int numFuncs; -static int numOperators; -static int numCollations; -static int numNamespaces; -static int numExtensions; -static int numPublications; - -/* This is an array of object identities, not actual DumpableObjects */ -static ExtensionMemberId *extmembers; -static int numextmembers; +typedef struct _catalogIdMapEntry +{ + CatalogId catId; /* the indexed CatalogId */ + uint32 status; /* hash status */ + uint32 hashval; /* hash code for the CatalogId */ + DumpableObject *dobj; /* the associated DumpableObject, if any */ + ExtensionInfo *ext; /* owning extension, if any */ +} CatalogIdMapEntry; + +#define SH_PREFIX catalogid +#define SH_ELEMENT_TYPE CatalogIdMapEntry +#define SH_KEY_TYPE CatalogId +#define SH_KEY catId +#define SH_HASH_KEY(tb, key) hash_bytes((const unsigned char *) &(key), sizeof(CatalogId)) +#define SH_EQUAL(tb, a, b) ((a).oid == (b).oid && (a).tableoid == (b).tableoid) +#define SH_STORE_HASH +#define SH_GET_HASH(tb, a) (a)->hashval +#define SH_SCOPE static inline +#define SH_RAW_ALLOCATOR pg_malloc0 +#define SH_DECLARE +#define SH_DEFINE +#include "lib/simplehash.h" + +#define CATALOGIDHASH_INITIAL_SIZE 10000 + +static catalogid_hash *catalogIdHash = NULL; static void flagInhTables(Archive *fout, TableInfo *tbinfo, int numTables, InhInfo *inhinfo, int numInherits); static void flagInhIndexes(Archive *fout, TableInfo *tblinfo, int numTables); 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); -static IndxInfo *findIndexByOid(Oid oid, DumpableObject **idxinfoindex, - int numIndexes); +static IndxInfo *findIndexByOid(Oid oid); /* @@ -89,14 +97,16 @@ TableInfo * getSchemaData(Archive *fout, int *numTablesPtr) { TableInfo *tblinfo; - TypeInfo *typinfo; - FuncInfo *funinfo; - OprInfo *oprinfo; - CollInfo *collinfo; - NamespaceInfo *nspinfo; ExtensionInfo *extinfo; - PublicationInfo *pubinfo; InhInfo *inhinfo; + int numTables; + int numTypes; + int numFuncs; + int numOperators; + int numCollations; + int numNamespaces; + int numExtensions; + int numPublications; int numAggregates; int numInherits; int numRules; @@ -123,14 +133,12 @@ getSchemaData(Archive *fout, int *numTablesPtr) */ pg_log_info("reading extensions"); extinfo = getExtensions(fout, &numExtensions); - extinfoindex = buildIndexArray(extinfo, numExtensions, sizeof(ExtensionInfo)); pg_log_info("identifying extension members"); getExtensionMembership(fout, extinfo, numExtensions); pg_log_info("reading schemas"); - nspinfo = getNamespaces(fout, &numNamespaces); - nspinfoindex = buildIndexArray(nspinfo, numNamespaces, sizeof(NamespaceInfo)); + (void) getNamespaces(fout, &numNamespaces); /* * getTables should be done as soon as possible, so as to minimize the @@ -140,19 +148,15 @@ getSchemaData(Archive *fout, int *numTablesPtr) */ pg_log_info("reading user-defined tables"); tblinfo = getTables(fout, &numTables); - tblinfoindex = buildIndexArray(tblinfo, numTables, sizeof(TableInfo)); - /* Do this after we've built tblinfoindex */ getOwnedSeqs(fout, tblinfo, numTables); pg_log_info("reading user-defined functions"); - funinfo = getFuncs(fout, &numFuncs); - funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo)); + (void) getFuncs(fout, &numFuncs); /* this must be after getTables and getFuncs */ pg_log_info("reading user-defined types"); - typinfo = getTypes(fout, &numTypes); - typinfoindex = buildIndexArray(typinfo, numTypes, sizeof(TypeInfo)); + (void) getTypes(fout, &numTypes); /* this must be after getFuncs, too */ pg_log_info("reading procedural languages"); @@ -162,8 +166,7 @@ getSchemaData(Archive *fout, int *numTablesPtr) getAggregates(fout, &numAggregates); pg_log_info("reading user-defined operators"); - oprinfo = getOperators(fout, &numOperators); - oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo)); + (void) getOperators(fout, &numOperators); pg_log_info("reading user-defined access methods"); getAccessMethods(fout, &numAccessMethods); @@ -196,8 +199,7 @@ getSchemaData(Archive *fout, int *numTablesPtr) getDefaultACLs(fout, &numDefaultACLs); pg_log_info("reading user-defined collations"); - collinfo = getCollations(fout, &numCollations); - collinfoindex = buildIndexArray(collinfo, numCollations, sizeof(CollInfo)); + (void) getCollations(fout, &numCollations); pg_log_info("reading user-defined conversions"); getConversions(fout, &numConversions); @@ -250,9 +252,7 @@ getSchemaData(Archive *fout, int *numTablesPtr) getPolicies(fout, tblinfo, numTables); pg_log_info("reading publications"); - pubinfo = getPublications(fout, &numPublications); - pubinfoindex = buildIndexArray(pubinfo, numPublications, - sizeof(PublicationInfo)); + (void) getPublications(fout, &numPublications); pg_log_info("reading publication membership"); getPublicationTables(fout, tblinfo, numTables); @@ -375,34 +375,15 @@ flagInhIndexes(Archive *fout, TableInfo tblinfo[], int numTables) int i, j, k; - DumpableObject ***parentIndexArray; - - parentIndexArray = (DumpableObject ***) - pg_malloc0(getMaxDumpId() * sizeof(DumpableObject **)); for (i = 0; i < numTables; i++) { - TableInfo *parenttbl; IndexAttachInfo *attachinfo; if (!tblinfo[i].ispartition || tblinfo[i].numParents == 0) continue; Assert(tblinfo[i].numParents == 1); - parenttbl = tblinfo[i].parents[0]; - - /* - * We need access to each parent table's index list, but there is no - * index to cover them outside of this function. To avoid having to - * sort every parent table's indexes each time we come across each of - * its partitions, create an indexed array for each parent the first - * time it is required. - */ - if (parentIndexArray[parenttbl->dobj.dumpId] == NULL) - parentIndexArray[parenttbl->dobj.dumpId] = - buildIndexArray(parenttbl->indexes, - parenttbl->numIndexes, - sizeof(IndxInfo)); attachinfo = (IndexAttachInfo *) pg_malloc0(tblinfo[i].numIndexes * sizeof(IndexAttachInfo)); @@ -414,9 +395,7 @@ flagInhIndexes(Archive *fout, TableInfo tblinfo[], int numTables) if (index->parentidx == 0) continue; - parentidx = findIndexByOid(index->parentidx, - parentIndexArray[parenttbl->dobj.dumpId], - parenttbl->numIndexes); + parentidx = findIndexByOid(index->parentidx); if (parentidx == NULL) continue; @@ -457,11 +436,6 @@ flagInhIndexes(Archive *fout, TableInfo tblinfo[], int numTables) k++; } } - - for (i = 0; i < numTables; i++) - if (parentIndexArray[i]) - pg_free(parentIndexArray[i]); - pg_free(parentIndexArray); } /* flagInhAttrs - @@ -596,7 +570,7 @@ flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables) /* * AssignDumpId * Given a newly-created dumpable object, assign a dump ID, - * and enter the object into the lookup table. + * and enter the object into the lookup tables. * * The caller is expected to have filled in objType and catId, * but not any of the other standard fields of a DumpableObject. @@ -615,6 +589,7 @@ AssignDumpId(DumpableObject *dobj) dobj->nDeps = 0; dobj->allocDeps = 0; + /* Add object to dumpIdMap[], enlarging that array if need be */ while (dobj->dumpId >= allocedDumpIds) { int newAlloc; @@ -637,8 +612,25 @@ AssignDumpId(DumpableObject *dobj) } dumpIdMap[dobj->dumpId] = dobj; - /* mark catalogIdMap invalid, but don't rebuild it yet */ - catalogIdMapValid = false; + /* If it has a valid CatalogId, enter it into the hash table */ + if (OidIsValid(dobj->catId.tableoid)) + { + CatalogIdMapEntry *entry; + bool found; + + /* Initialize CatalogId hash table if not done yet */ + if (catalogIdHash == NULL) + catalogIdHash = catalogid_create(CATALOGIDHASH_INITIAL_SIZE, NULL); + + entry = catalogid_insert(catalogIdHash, dobj->catId, &found); + if (!found) + { + entry->dobj = NULL; + entry->ext = NULL; + } + Assert(entry->dobj == NULL); + entry->dobj = dobj; + } } /* @@ -679,140 +671,19 @@ findObjectByDumpId(DumpId dumpId) * Find a DumpableObject by catalog ID * * Returns NULL for unknown ID - * - * We use binary search in a sorted list that is built on first call. - * If AssignDumpId() and findObjectByCatalogId() calls were freely intermixed, - * the code would work, but possibly be very slow. In the current usage - * pattern that does not happen, indeed we build the list at most twice. */ DumpableObject * findObjectByCatalogId(CatalogId catalogId) { - DumpableObject **low; - DumpableObject **high; - - if (!catalogIdMapValid) - { - if (catalogIdMap) - free(catalogIdMap); - getDumpableObjects(&catalogIdMap, &numCatalogIds); - if (numCatalogIds > 1) - qsort((void *) catalogIdMap, numCatalogIds, - sizeof(DumpableObject *), DOCatalogIdCompare); - catalogIdMapValid = true; - } - - /* - * 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 (numCatalogIds <= 0) - return NULL; - low = catalogIdMap; - high = catalogIdMap + (numCatalogIds - 1); - while (low <= high) - { - DumpableObject **middle; - int difference; - - middle = low + (high - low) / 2; - /* comparison must match DOCatalogIdCompare, below */ - difference = oidcmp((*middle)->catId.oid, catalogId.oid); - if (difference == 0) - difference = oidcmp((*middle)->catId.tableoid, catalogId.tableoid); - if (difference == 0) - return *middle; - else if (difference < 0) - low = middle + 1; - else - high = middle - 1; - } - return NULL; -} - -/* - * Find a DumpableObject by OID, in a pre-sorted array of one type of object - * - * Returns NULL for unknown OID - */ -static DumpableObject * -findObjectByOid(Oid oid, DumpableObject **indexArray, int numObjs) -{ - DumpableObject **low; - DumpableObject **high; + CatalogIdMapEntry *entry; - /* - * This is the same as findObjectByCatalogId except we assume we need not - * look at table OID because the objects are all the same type. - * - * 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 (numObjs <= 0) - return NULL; - low = indexArray; - high = indexArray + (numObjs - 1); - while (low <= high) - { - DumpableObject **middle; - int difference; - - middle = low + (high - low) / 2; - difference = oidcmp((*middle)->catId.oid, oid); - if (difference == 0) - return *middle; - else if (difference < 0) - low = middle + 1; - else - high = middle - 1; - } - return NULL; -} - -/* - * Build an index array of DumpableObject pointers, sorted by OID - */ -static DumpableObject ** -buildIndexArray(void *objArray, int numObjs, Size objSize) -{ - DumpableObject **ptrs; - int i; + if (catalogIdHash == NULL) + return NULL; /* no objects exist yet */ - if (numObjs <= 0) + entry = catalogid_lookup(catalogIdHash, catalogId); + if (entry == NULL) return NULL; - - ptrs = (DumpableObject **) pg_malloc(numObjs * sizeof(DumpableObject *)); - for (i = 0; i < numObjs; i++) - ptrs[i] = (DumpableObject *) ((char *) objArray + i * objSize); - - /* We can use DOCatalogIdCompare to sort since its first key is OID */ - if (numObjs > 1) - qsort((void *) ptrs, numObjs, sizeof(DumpableObject *), - DOCatalogIdCompare); - - return ptrs; -} - -/* - * qsort comparator for pointers to DumpableObjects - */ -static int -DOCatalogIdCompare(const void *p1, const void *p2) -{ - const DumpableObject *obj1 = *(DumpableObject *const *) p1; - const DumpableObject *obj2 = *(DumpableObject *const *) 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; + return entry->dobj; } /* @@ -886,119 +757,169 @@ removeObjectDependency(DumpableObject *dobj, DumpId refId) /* * findTableByOid - * finds the entry (in tblinfo) of the table with the given oid + * finds the DumpableObject for the table with the given oid * returns NULL if not found */ TableInfo * findTableByOid(Oid oid) { - return (TableInfo *) findObjectByOid(oid, tblinfoindex, numTables); + CatalogId catId; + DumpableObject *dobj; + + catId.tableoid = RelationRelationId; + catId.oid = oid; + dobj = findObjectByCatalogId(catId); + Assert(dobj == NULL || dobj->objType == DO_TABLE); + return (TableInfo *) dobj; +} + +/* + * findIndexByOid + * finds the DumpableObject for the index with the given oid + * returns NULL if not found + */ +static IndxInfo * +findIndexByOid(Oid oid) +{ + CatalogId catId; + DumpableObject *dobj; + + catId.tableoid = RelationRelationId; + catId.oid = oid; + dobj = findObjectByCatalogId(catId); + Assert(dobj == NULL || dobj->objType == DO_INDEX); + return (IndxInfo *) dobj; } /* * findTypeByOid - * finds the entry (in typinfo) of the type with the given oid + * finds the DumpableObject for the type with the given oid * returns NULL if not found */ TypeInfo * findTypeByOid(Oid oid) { - return (TypeInfo *) findObjectByOid(oid, typinfoindex, numTypes); + CatalogId catId; + + catId.tableoid = TypeRelationId; + catId.oid = oid; + return (TypeInfo *) findObjectByCatalogId(catId); } /* * findFuncByOid - * finds the entry (in funinfo) of the function with the given oid + * finds the DumpableObject for the function with the given oid * returns NULL if not found */ FuncInfo * findFuncByOid(Oid oid) { - return (FuncInfo *) findObjectByOid(oid, funinfoindex, numFuncs); + CatalogId catId; + + catId.tableoid = ProcedureRelationId; + catId.oid = oid; + return (FuncInfo *) findObjectByCatalogId(catId); } /* * findOprByOid - * finds the entry (in oprinfo) of the operator with the given oid + * finds the DumpableObject for the operator with the given oid * returns NULL if not found */ OprInfo * findOprByOid(Oid oid) { - return (OprInfo *) findObjectByOid(oid, oprinfoindex, numOperators); + CatalogId catId; + + catId.tableoid = OperatorRelationId; + catId.oid = oid; + return (OprInfo *) findObjectByCatalogId(catId); } /* * findCollationByOid - * finds the entry (in collinfo) of the collation with the given oid + * finds the DumpableObject for the collation with the given oid * returns NULL if not found */ CollInfo * findCollationByOid(Oid oid) { - return (CollInfo *) findObjectByOid(oid, collinfoindex, numCollations); + CatalogId catId; + + catId.tableoid = CollationRelationId; + catId.oid = oid; + return (CollInfo *) findObjectByCatalogId(catId); } /* * findNamespaceByOid - * finds the entry (in nspinfo) of the namespace with the given oid + * finds the DumpableObject for the namespace with the given oid * returns NULL if not found */ NamespaceInfo * findNamespaceByOid(Oid oid) { - return (NamespaceInfo *) findObjectByOid(oid, nspinfoindex, numNamespaces); + CatalogId catId; + + catId.tableoid = NamespaceRelationId; + catId.oid = oid; + return (NamespaceInfo *) findObjectByCatalogId(catId); } /* * findExtensionByOid - * finds the entry (in extinfo) of the extension with the given oid + * finds the DumpableObject for the extension with the given oid * returns NULL if not found */ ExtensionInfo * findExtensionByOid(Oid oid) { - return (ExtensionInfo *) findObjectByOid(oid, extinfoindex, numExtensions); + CatalogId catId; + + catId.tableoid = ExtensionRelationId; + catId.oid = oid; + return (ExtensionInfo *) findObjectByCatalogId(catId); } /* * findPublicationByOid - * finds the entry (in pubinfo) of the publication with the given oid + * finds the DumpableObject for the publication with the given oid * returns NULL if not found */ PublicationInfo * findPublicationByOid(Oid oid) { - return (PublicationInfo *) findObjectByOid(oid, pubinfoindex, numPublications); -} + CatalogId catId; -/* - * findIndexByOid - * find the entry of the index with the given oid - * - * This one's signature is different from the previous ones because we lack a - * global array of all indexes, so caller must pass their array as argument. - */ -static IndxInfo * -findIndexByOid(Oid oid, DumpableObject **idxinfoindex, int numIndexes) -{ - return (IndxInfo *) findObjectByOid(oid, idxinfoindex, numIndexes); + catId.tableoid = PublicationRelationId; + catId.oid = oid; + return (PublicationInfo *) findObjectByCatalogId(catId); } + /* - * setExtensionMembership - * accept and save data about which objects belong to extensions + * recordExtensionMembership + * Record that the object identified by the given catalog ID + * belongs to the given extension */ void -setExtensionMembership(ExtensionMemberId *extmems, int nextmems) +recordExtensionMembership(CatalogId catId, ExtensionInfo *ext) { - /* Sort array in preparation for binary searches */ - if (nextmems > 1) - qsort((void *) extmems, nextmems, sizeof(ExtensionMemberId), - ExtensionMemberIdCompare); - /* And save */ - extmembers = extmems; - numextmembers = nextmems; + CatalogIdMapEntry *entry; + bool found; + + /* CatalogId hash table must exist, if we have an ExtensionInfo */ + Assert(catalogIdHash != NULL); + + /* Add reference to CatalogId hash */ + entry = catalogid_insert(catalogIdHash, catId, &found); + if (!found) + { + entry->dobj = NULL; + entry->ext = NULL; + } + Assert(entry->ext == NULL); + entry->ext = ext; } /* @@ -1008,56 +929,15 @@ setExtensionMembership(ExtensionMemberId *extmems, int nextmems) ExtensionInfo * findOwningExtension(CatalogId catalogId) { - ExtensionMemberId *low; - ExtensionMemberId *high; + CatalogIdMapEntry *entry; - /* - * 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; + if (catalogIdHash == NULL) + return NULL; /* no objects exist yet */ - /* - * 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; + entry = catalogid_lookup(catalogIdHash, catalogId); + if (entry == NULL) + return NULL; + return entry->ext; } diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index 3c1cd858a8..6af10a85a2 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -236,6 +236,7 @@ typedef struct Archive typedef struct { + /* Note: this struct must not contain any unused bytes */ Oid tableoid; Oid oid; } CatalogId; diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index ed8ed2f266..948615a5b9 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -17901,12 +17901,10 @@ getExtensionMembership(Archive *fout, ExtensionInfo extinfo[], PQExpBuffer query; PGresult *res; int ntups, - nextmembers, i; int i_classid, i_objid, i_refobjid; - ExtensionMemberId *extmembers; ExtensionInfo *ext; /* Nothing to do if no extensions */ @@ -17931,12 +17929,7 @@ getExtensionMembership(Archive *fout, ExtensionInfo extinfo[], i_objid = PQfnumber(res, "objid"); i_refobjid = PQfnumber(res, "refobjid"); - extmembers = (ExtensionMemberId *) pg_malloc(ntups * sizeof(ExtensionMemberId)); - nextmembers = 0; - /* - * Accumulate data into extmembers[]. - * * Since we ordered the SELECT by referenced ID, we can expect that * multiple entries for the same extension will appear together; this * saves on searches. @@ -17963,16 +17956,11 @@ getExtensionMembership(Archive *fout, ExtensionInfo extinfo[], continue; } - extmembers[nextmembers].catId = objId; - extmembers[nextmembers].ext = ext; - nextmembers++; + recordExtensionMembership(objId, ext); } PQclear(res); - /* Remember the data for use later */ - setExtensionMembership(extmembers, nextmembers); - destroyPQExpBuffer(query); } diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 29af845ece..cc55e598ec 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -647,16 +647,6 @@ typedef struct _SubscriptionInfo char *subpublications; } SubscriptionInfo; -/* - * We build an array of these with an entry for each object that is an - * extension member according to pg_depend. - */ -typedef struct _extensionMemberId -{ - CatalogId catId; /* tableoid+oid of some member object */ - ExtensionInfo *ext; /* owning extension */ -} ExtensionMemberId; - /* * common utility functions */ @@ -682,7 +672,7 @@ extern NamespaceInfo *findNamespaceByOid(Oid oid); extern ExtensionInfo *findExtensionByOid(Oid oid); extern PublicationInfo *findPublicationByOid(Oid oid); -extern void setExtensionMembership(ExtensionMemberId *extmems, int nextmems); +extern void recordExtensionMembership(CatalogId catId, ExtensionInfo *ext); extern ExtensionInfo *findOwningExtension(CatalogId catalogId); extern void parseOidArray(const char *str, Oid *array, int arraysize);