diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c index 81d9cc284c9812c26619724391cd09582c30b95d..45bc90fcccb5784cf7ad26e8825df2a20a16255f 100644 --- a/src/bin/pg_dump/common.c +++ b/src/bin/pg_dump/common.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.78 2003/12/06 03:00:11 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.79 2003/12/07 03:14:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,6 +37,13 @@ static DumpableObject **dumpIdMap = NULL; static int allocedDumpIds = 0; static DumpId lastDumpId = 0; +/* + * 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. @@ -51,12 +58,13 @@ static int numFuncs; static int numOperators; -static void findParentsByOid(TableInfo *self, - InhInfo *inhinfo, int numInherits); static void flagInhTables(TableInfo *tbinfo, int numTables, InhInfo *inhinfo, int numInherits); static void flagInhAttrs(TableInfo *tbinfo, int numTables, InhInfo *inhinfo, int numInherits); +static int DOCatalogIdCompare(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); @@ -413,6 +421,9 @@ AssignDumpId(DumpableObject *dobj) allocedDumpIds = newAlloc; } dumpIdMap[dobj->dumpId] = dobj; + + /* mark catalogIdMap invalid, but don't rebuild it yet */ + catalogIdMapValid = false; } /* @@ -454,25 +465,74 @@ findObjectByDumpId(DumpId dumpId) * * Returns NULL for unknown ID * - * NOTE: should hash this, but just do linear search for now + * We use binary search in a sorted list that is built on first call. + * If AssignDumpId() and findObjectByCatalogId() calls were intermixed, + * the code would work, but possibly be very slow. In the current usage + * pattern that does not happen, indeed we only need to build the list once. */ DumpableObject * findObjectByCatalogId(CatalogId catalogId) { - DumpId i; + DumpableObject **low; + DumpableObject **high; - for (i = 1; i < allocedDumpIds; i++) + if (!catalogIdMapValid) { - DumpableObject *dobj = dumpIdMap[i]; + if (catalogIdMap) + free(catalogIdMap); + getDumpableObjects(&catalogIdMap, &numCatalogIds); + if (numCatalogIds > 1) + qsort((void *) catalogIdMap, numCatalogIds, + sizeof(DumpableObject *), DOCatalogIdCompare); + catalogIdMapValid = true; + } - if (dobj && - dobj->catId.tableoid == catalogId.tableoid && - dobj->catId.oid == catalogId.oid) - return dobj; + /* + * 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; } +static int +DOCatalogIdCompare(const void *p1, const void *p2) +{ + DumpableObject *obj1 = *(DumpableObject **) p1; + DumpableObject *obj2 = *(DumpableObject **) 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; +} + /* * Build an array of pointers to all known dumpable objects *