aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_dump/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_dump/common.c')
-rw-r--r--src/bin/pg_dump/common.c158
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