1 /*-------------------------------------------------------------------------
4 * common routines between pg_dump and pg4_dump
6 * Since pg4_dump is long-dead code, there is no longer any useful distinction
7 * between this file and pg_dump.c.
9 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
14 * src/bin/pg_dump/common.c
16 *-------------------------------------------------------------------------
18 #include "postgres_fe.h"
22 #include "catalog/pg_class.h"
24 #include "pg_backup_archiver.h"
28 * Variables for mapping DumpId to DumpableObject
30 static DumpableObject **dumpIdMap = NULL;
31 static int allocedDumpIds = 0;
32 static DumpId lastDumpId = 0;
35 * Variables for mapping CatalogId to DumpableObject
37 static bool catalogIdMapValid = false;
38 static DumpableObject **catalogIdMap = NULL;
39 static int numCatalogIds = 0;
42 * These variables are static to avoid the notational cruft of having to pass
43 * them into findTableByOid() and friends. For each of these arrays, we
44 * build a sorted-by-OID index array immediately after it's built, and then
45 * we use binary search in findTableByOid() and friends. (qsort'ing the base
46 * arrays themselves would be simpler, but it doesn't work because pg_dump.c
47 * may have already established pointers between items.)
49 static TableInfo *tblinfo;
50 static TypeInfo *typinfo;
51 static FuncInfo *funinfo;
52 static OprInfo *oprinfo;
56 static int numOperators;
57 static int numCollations;
58 static DumpableObject **tblinfoindex;
59 static DumpableObject **typinfoindex;
60 static DumpableObject **funinfoindex;
61 static DumpableObject **oprinfoindex;
62 static DumpableObject **collinfoindex;
65 static void flagInhTables(TableInfo *tbinfo, int numTables,
66 InhInfo *inhinfo, int numInherits);
67 static void flagInhAttrs(TableInfo *tblinfo, int numTables);
68 static DumpableObject **buildIndexArray(void *objArray, int numObjs,
70 static int DOCatalogIdCompare(const void *p1, const void *p2);
71 static void findParentsByOid(TableInfo *self,
72 InhInfo *inhinfo, int numInherits);
73 static int strInArray(const char *pattern, char **arr, int arr_size);
78 * Collect information about all potentially dumpable objects
81 getSchemaData(int *numTablesPtr)
83 NamespaceInfo *nsinfo;
84 ExtensionInfo *extinfo;
88 ProcLangInfo *proclanginfo;
91 OpfamilyInfo *opfinfo;
94 TSParserInfo *prsinfo;
95 TSTemplateInfo *tmplinfo;
97 TSConfigInfo *cfginfo;
99 ForeignServerInfo *srvinfo;
100 DefaultACLInfo *daclinfo;
115 int numForeignDataWrappers;
116 int numForeignServers;
120 write_msg(NULL, "reading schemas\n");
121 nsinfo = getNamespaces(&numNamespaces);
124 write_msg(NULL, "reading extensions\n");
125 extinfo = getExtensions(&numExtensions);
128 write_msg(NULL, "reading user-defined functions\n");
129 funinfo = getFuncs(&numFuncs);
130 funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo));
132 /* this must be after getFuncs */
134 write_msg(NULL, "reading user-defined types\n");
135 typinfo = getTypes(&numTypes);
136 typinfoindex = buildIndexArray(typinfo, numTypes, sizeof(TypeInfo));
138 /* this must be after getFuncs, too */
140 write_msg(NULL, "reading procedural languages\n");
141 proclanginfo = getProcLangs(&numProcLangs);
144 write_msg(NULL, "reading user-defined aggregate functions\n");
145 agginfo = getAggregates(&numAggregates);
148 write_msg(NULL, "reading user-defined operators\n");
149 oprinfo = getOperators(&numOperators);
150 oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo));
153 write_msg(NULL, "reading user-defined operator classes\n");
154 opcinfo = getOpclasses(&numOpclasses);
157 write_msg(NULL, "reading user-defined operator families\n");
158 opfinfo = getOpfamilies(&numOpfamilies);
161 write_msg(NULL, "reading user-defined text search parsers\n");
162 prsinfo = getTSParsers(&numTSParsers);
165 write_msg(NULL, "reading user-defined text search templates\n");
166 tmplinfo = getTSTemplates(&numTSTemplates);
169 write_msg(NULL, "reading user-defined text search dictionaries\n");
170 dictinfo = getTSDictionaries(&numTSDicts);
173 write_msg(NULL, "reading user-defined text search configurations\n");
174 cfginfo = getTSConfigurations(&numTSConfigs);
177 write_msg(NULL, "reading user-defined foreign-data wrappers\n");
178 fdwinfo = getForeignDataWrappers(&numForeignDataWrappers);
181 write_msg(NULL, "reading user-defined foreign servers\n");
182 srvinfo = getForeignServers(&numForeignServers);
185 write_msg(NULL, "reading default privileges\n");
186 daclinfo = getDefaultACLs(&numDefaultACLs);
189 write_msg(NULL, "reading user-defined collations\n");
190 collinfo = getCollations(&numCollations);
191 collinfoindex = buildIndexArray(collinfo, numCollations, sizeof(CollInfo));
194 write_msg(NULL, "reading user-defined conversions\n");
195 convinfo = getConversions(&numConversions);
198 write_msg(NULL, "reading type casts\n");
199 castinfo = getCasts(&numCasts);
202 write_msg(NULL, "reading user-defined tables\n");
203 tblinfo = getTables(&numTables);
204 tblinfoindex = buildIndexArray(tblinfo, numTables, sizeof(TableInfo));
207 write_msg(NULL, "reading table inheritance information\n");
208 inhinfo = getInherits(&numInherits);
211 write_msg(NULL, "reading rewrite rules\n");
212 ruleinfo = getRules(&numRules);
215 * Identify extension member objects and mark them as not to be dumped.
216 * This must happen after reading all objects that can be direct members
217 * of extensions, but before we begin to process table subsidiary objects.
220 write_msg(NULL, "finding extension members\n");
221 getExtensionMembership(extinfo, numExtensions);
223 /* Link tables to parents, mark parents of target tables interesting */
225 write_msg(NULL, "finding inheritance relationships\n");
226 flagInhTables(tblinfo, numTables, inhinfo, numInherits);
229 write_msg(NULL, "reading column info for interesting tables\n");
230 getTableAttrs(tblinfo, numTables);
233 write_msg(NULL, "flagging inherited columns in subtables\n");
234 flagInhAttrs(tblinfo, numTables);
237 write_msg(NULL, "reading indexes\n");
238 getIndexes(tblinfo, numTables);
241 write_msg(NULL, "reading constraints\n");
242 getConstraints(tblinfo, numTables);
245 write_msg(NULL, "reading triggers\n");
246 getTriggers(tblinfo, numTables);
248 *numTablesPtr = numTables;
253 * Fill in parent link fields of every target table, and mark
254 * parents of target tables as interesting
256 * Note that only direct ancestors of targets are marked interesting.
257 * This is sufficient; we don't much care whether they inherited their
263 flagInhTables(TableInfo *tblinfo, int numTables,
264 InhInfo *inhinfo, int numInherits)
271 for (i = 0; i < numTables; i++)
273 /* Sequences and views never have parents */
274 if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
275 tblinfo[i].relkind == RELKIND_VIEW)
278 /* Don't bother computing anything for non-target tables, either */
279 if (!tblinfo[i].dobj.dump)
282 /* Find all the immediate parent tables */
283 findParentsByOid(&tblinfo[i], inhinfo, numInherits);
285 /* Mark the parents as interesting for getTableAttrs */
286 numParents = tblinfo[i].numParents;
287 parents = tblinfo[i].parents;
288 for (j = 0; j < numParents; j++)
289 parents[j]->interesting = true;
294 * for each dumpable table in tblinfo, flag its inherited attributes
295 * so when we dump the table out, we don't dump out the inherited attributes
300 flagInhAttrs(TableInfo *tblinfo, int numTables)
306 for (i = 0; i < numTables; i++)
308 TableInfo *tbinfo = &(tblinfo[i]);
313 /* Sequences and views never have parents */
314 if (tbinfo->relkind == RELKIND_SEQUENCE ||
315 tbinfo->relkind == RELKIND_VIEW)
318 /* Don't bother computing anything for non-target tables, either */
319 if (!tbinfo->dobj.dump)
322 numParents = tbinfo->numParents;
323 parents = tbinfo->parents;
326 continue; /* nothing to see here, move along */
328 /*----------------------------------------------------------------
329 * For each attr, check the parent info: if no parent has an attr
330 * with the same name, then it's not inherited. If there *is* an
331 * attr with the same name, then only dump it if:
333 * - it is NOT NULL and zero parents are NOT NULL
335 * - it has a default value AND the default value does not match
336 * all parent default values, or no parents specify a default.
338 * See discussion on -hackers around 2-Apr-2001.
339 *----------------------------------------------------------------
341 for (j = 0; j < tbinfo->numatts; j++)
343 bool foundAttr; /* Attr was found in a parent */
344 bool foundNotNull; /* Attr was NOT NULL in a parent */
345 bool defaultsMatch; /* All non-empty defaults match */
346 bool defaultsFound; /* Found a default in a parent */
347 AttrDefInfo *attrDef;
350 foundNotNull = false;
351 defaultsMatch = true;
352 defaultsFound = false;
354 attrDef = tbinfo->attrdefs[j];
356 for (k = 0; k < numParents; k++)
361 inhAttrInd = strInArray(tbinfo->attnames[j],
365 if (inhAttrInd != -1)
367 AttrDefInfo *inhDef = parent->attrdefs[inhAttrInd];
370 foundNotNull |= parent->notnull[inhAttrInd];
373 defaultsFound = true;
376 * If any parent has a default and the child doesn't,
377 * we have to emit an explicit DEFAULT NULL clause for
378 * the child, else the parent's default will win.
382 attrDef = (AttrDefInfo *) malloc(sizeof(AttrDefInfo));
383 attrDef->dobj.objType = DO_ATTRDEF;
384 attrDef->dobj.catId.tableoid = 0;
385 attrDef->dobj.catId.oid = 0;
386 AssignDumpId(&attrDef->dobj);
387 attrDef->adtable = tbinfo;
388 attrDef->adnum = j + 1;
389 attrDef->adef_expr = strdup("NULL");
391 attrDef->dobj.name = strdup(tbinfo->dobj.name);
392 attrDef->dobj.namespace = tbinfo->dobj.namespace;
394 attrDef->dobj.dump = tbinfo->dobj.dump;
396 attrDef->separate = false;
397 addObjectDependency(&tbinfo->dobj,
398 attrDef->dobj.dumpId);
400 tbinfo->attrdefs[j] = attrDef;
402 if (strcmp(attrDef->adef_expr, inhDef->adef_expr) != 0)
404 defaultsMatch = false;
407 * Whenever there is a non-matching parent
408 * default, add a dependency to force the parent
409 * default to be dumped first, in case the
410 * defaults end up being dumped as separate
411 * commands. Otherwise the parent default will
412 * override the child's when it is applied.
414 addObjectDependency(&attrDef->dobj,
415 inhDef->dobj.dumpId);
422 * Based on the scan of the parents, decide if we can rely on the
425 if (foundAttr) /* Attr was inherited */
427 /* Set inherited flag by default */
428 tbinfo->inhAttrs[j] = true;
429 tbinfo->inhAttrDef[j] = true;
430 tbinfo->inhNotNull[j] = true;
433 * Clear it if attr had a default, but parents did not, or
436 if ((attrDef != NULL) && (!defaultsFound || !defaultsMatch))
438 tbinfo->inhAttrs[j] = false;
439 tbinfo->inhAttrDef[j] = false;
443 * Clear it if NOT NULL and none of the parents were NOT NULL
445 if (tbinfo->notnull[j] && !foundNotNull)
447 tbinfo->inhAttrs[j] = false;
448 tbinfo->inhNotNull[j] = false;
451 /* Clear it if attr has local definition */
452 if (tbinfo->attislocal[j])
453 tbinfo->inhAttrs[j] = false;
461 * Given a newly-created dumpable object, assign a dump ID,
462 * and enter the object into the lookup table.
464 * The caller is expected to have filled in objType and catId,
465 * but not any of the other standard fields of a DumpableObject.
468 AssignDumpId(DumpableObject *dobj)
470 dobj->dumpId = ++lastDumpId;
471 dobj->name = NULL; /* must be set later */
472 dobj->namespace = NULL; /* may be set later */
473 dobj->dump = true; /* default assumption */
474 dobj->ext_member = false; /* default assumption */
475 dobj->dependencies = NULL;
479 while (dobj->dumpId >= allocedDumpIds)
483 if (allocedDumpIds <= 0)
486 dumpIdMap = (DumpableObject **)
487 pg_malloc(newAlloc * sizeof(DumpableObject *));
491 newAlloc = allocedDumpIds * 2;
492 dumpIdMap = (DumpableObject **)
493 pg_realloc(dumpIdMap, newAlloc * sizeof(DumpableObject *));
495 memset(dumpIdMap + allocedDumpIds, 0,
496 (newAlloc - allocedDumpIds) * sizeof(DumpableObject *));
497 allocedDumpIds = newAlloc;
499 dumpIdMap[dobj->dumpId] = dobj;
501 /* mark catalogIdMap invalid, but don't rebuild it yet */
502 catalogIdMapValid = false;
506 * Assign a DumpId that's not tied to a DumpableObject.
508 * This is used when creating a "fixed" ArchiveEntry that doesn't need to
509 * participate in the sorting logic.
518 * Return the largest DumpId so far assigned
527 * Find a DumpableObject by dump ID
529 * Returns NULL for invalid ID
532 findObjectByDumpId(DumpId dumpId)
534 if (dumpId <= 0 || dumpId >= allocedDumpIds)
535 return NULL; /* out of range? */
536 return dumpIdMap[dumpId];
540 * Find a DumpableObject by catalog ID
542 * Returns NULL for unknown ID
544 * We use binary search in a sorted list that is built on first call.
545 * If AssignDumpId() and findObjectByCatalogId() calls were freely intermixed,
546 * the code would work, but possibly be very slow. In the current usage
547 * pattern that does not happen, indeed we build the list at most twice.
550 findObjectByCatalogId(CatalogId catalogId)
552 DumpableObject **low;
553 DumpableObject **high;
555 if (!catalogIdMapValid)
559 getDumpableObjects(&catalogIdMap, &numCatalogIds);
560 if (numCatalogIds > 1)
561 qsort((void *) catalogIdMap, numCatalogIds,
562 sizeof(DumpableObject *), DOCatalogIdCompare);
563 catalogIdMapValid = true;
567 * We could use bsearch() here, but the notational cruft of calling
568 * bsearch is nearly as bad as doing it ourselves; and the generalized
569 * bsearch function is noticeably slower as well.
571 if (numCatalogIds <= 0)
574 high = catalogIdMap + (numCatalogIds - 1);
577 DumpableObject **middle;
580 middle = low + (high - low) / 2;
581 /* comparison must match DOCatalogIdCompare, below */
582 difference = oidcmp((*middle)->catId.oid, catalogId.oid);
584 difference = oidcmp((*middle)->catId.tableoid, catalogId.tableoid);
587 else if (difference < 0)
596 * Find a DumpableObject by OID, in a pre-sorted array of one type of object
598 * Returns NULL for unknown OID
600 static DumpableObject *
601 findObjectByOid(Oid oid, DumpableObject **indexArray, int numObjs)
603 DumpableObject **low;
604 DumpableObject **high;
607 * This is the same as findObjectByCatalogId except we assume we need not
608 * look at table OID because the objects are all the same type.
610 * We could use bsearch() here, but the notational cruft of calling
611 * bsearch is nearly as bad as doing it ourselves; and the generalized
612 * bsearch function is noticeably slower as well.
617 high = indexArray + (numObjs - 1);
620 DumpableObject **middle;
623 middle = low + (high - low) / 2;
624 difference = oidcmp((*middle)->catId.oid, oid);
627 else if (difference < 0)
636 * Build an index array of DumpableObject pointers, sorted by OID
638 static DumpableObject **
639 buildIndexArray(void *objArray, int numObjs, Size objSize)
641 DumpableObject **ptrs;
644 ptrs = (DumpableObject **) malloc(numObjs * sizeof(DumpableObject *));
645 for (i = 0; i < numObjs; i++)
646 ptrs[i] = (DumpableObject *) ((char *) objArray + i * objSize);
648 /* We can use DOCatalogIdCompare to sort since its first key is OID */
650 qsort((void *) ptrs, numObjs, sizeof(DumpableObject *),
657 * qsort comparator for pointers to DumpableObjects
660 DOCatalogIdCompare(const void *p1, const void *p2)
662 DumpableObject *obj1 = *(DumpableObject **) p1;
663 DumpableObject *obj2 = *(DumpableObject **) p2;
667 * Compare OID first since it's usually unique, whereas there will only be
668 * a few distinct values of tableoid.
670 cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid);
672 cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid);
677 * Build an array of pointers to all known dumpable objects
679 * This simply creates a modifiable copy of the internal map.
682 getDumpableObjects(DumpableObject ***objs, int *numObjs)
687 *objs = (DumpableObject **)
688 pg_malloc(allocedDumpIds * sizeof(DumpableObject *));
690 for (i = 1; i < allocedDumpIds; i++)
693 (*objs)[j++] = dumpIdMap[i];
699 * Add a dependency link to a DumpableObject
701 * Note: duplicate dependencies are currently not eliminated
704 addObjectDependency(DumpableObject *dobj, DumpId refId)
706 if (dobj->nDeps >= dobj->allocDeps)
708 if (dobj->allocDeps <= 0)
710 dobj->allocDeps = 16;
711 dobj->dependencies = (DumpId *)
712 pg_malloc(dobj->allocDeps * sizeof(DumpId));
716 dobj->allocDeps *= 2;
717 dobj->dependencies = (DumpId *)
718 pg_realloc(dobj->dependencies,
719 dobj->allocDeps * sizeof(DumpId));
722 dobj->dependencies[dobj->nDeps++] = refId;
726 * Remove a dependency link from a DumpableObject
728 * If there are multiple links, all are removed
731 removeObjectDependency(DumpableObject *dobj, DumpId refId)
736 for (i = 0; i < dobj->nDeps; i++)
738 if (dobj->dependencies[i] != refId)
739 dobj->dependencies[j++] = dobj->dependencies[i];
747 * finds the entry (in tblinfo) of the table with the given oid
748 * returns NULL if not found
751 findTableByOid(Oid oid)
753 return (TableInfo *) findObjectByOid(oid, tblinfoindex, numTables);
758 * finds the entry (in typinfo) of the type with the given oid
759 * returns NULL if not found
762 findTypeByOid(Oid oid)
764 return (TypeInfo *) findObjectByOid(oid, typinfoindex, numTypes);
769 * finds the entry (in funinfo) of the function with the given oid
770 * returns NULL if not found
773 findFuncByOid(Oid oid)
775 return (FuncInfo *) findObjectByOid(oid, funinfoindex, numFuncs);
780 * finds the entry (in oprinfo) of the operator with the given oid
781 * returns NULL if not found
784 findOprByOid(Oid oid)
786 return (OprInfo *) findObjectByOid(oid, oprinfoindex, numOperators);
791 * finds the entry (in collinfo) of the collation with the given oid
792 * returns NULL if not found
795 findCollationByOid(Oid oid)
797 return (CollInfo *) findObjectByOid(oid, collinfoindex, numCollations);
803 * find a table's parents in tblinfo[]
806 findParentsByOid(TableInfo *self,
807 InhInfo *inhinfo, int numInherits)
809 Oid oid = self->dobj.catId.oid;
815 for (i = 0; i < numInherits; i++)
817 if (inhinfo[i].inhrelid == oid)
821 self->numParents = numParents;
825 self->parents = (TableInfo **)
826 pg_malloc(sizeof(TableInfo *) * numParents);
828 for (i = 0; i < numInherits; i++)
830 if (inhinfo[i].inhrelid == oid)
834 parent = findTableByOid(inhinfo[i].inhparent);
837 write_msg(NULL, "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found\n",
838 inhinfo[i].inhparent,
843 self->parents[j++] = parent;
848 self->parents = NULL;
853 * parse a string of numbers delimited by spaces into a character array
855 * Note: actually this is used for both Oids and potentially-signed
856 * attribute numbers. This should cause no trouble, but we could split
857 * the function into two functions with different argument types if it does.
861 parseOidArray(const char *str, Oid *array, int arraysize)
873 if (s == ' ' || s == '\0')
877 if (argNum >= arraysize)
879 write_msg(NULL, "could not parse numeric array \"%s\": too many numbers\n", str);
883 array[argNum++] = atooid(temp);
891 if (!(isdigit((unsigned char) s) || s == '-') ||
892 j >= sizeof(temp) - 1)
894 write_msg(NULL, "could not parse numeric array \"%s\": invalid character in number\n", str);
901 while (argNum < arraysize)
902 array[argNum++] = InvalidOid;
908 * takes in a string and a string array and the number of elements in the
910 * returns the index if the string is somewhere in the array, -1 otherwise
914 strInArray(const char *pattern, char **arr, int arr_size)
918 for (i = 0; i < arr_size; i++)
920 if (strcmp(pattern, arr[i]) == 0)
928 * Support for simple list operations
932 simple_oid_list_append(SimpleOidList *list, Oid val)
934 SimpleOidListCell *cell;
936 cell = (SimpleOidListCell *) pg_malloc(sizeof(SimpleOidListCell));
941 list->tail->next = cell;
948 simple_string_list_append(SimpleStringList *list, const char *val)
950 SimpleStringListCell *cell;
952 /* this calculation correctly accounts for the null trailing byte */
953 cell = (SimpleStringListCell *)
954 pg_malloc(sizeof(SimpleStringListCell) + strlen(val));
956 strcpy(cell->val, val);
959 list->tail->next = cell;
966 simple_oid_list_member(SimpleOidList *list, Oid val)
968 SimpleOidListCell *cell;
970 for (cell = list->head; cell; cell = cell->next)
972 if (cell->val == val)
979 simple_string_list_member(SimpleStringList *list, const char *val)
981 SimpleStringListCell *cell;
983 for (cell = list->head; cell; cell = cell->next)
985 if (strcmp(cell->val, val) == 0)
993 * Safer versions of some standard C library functions. If an
994 * out-of-memory condition occurs, these functions will bail out
995 * safely; therefore, their return value is guaranteed to be non-NULL.
997 * XXX need to refactor things so that these can be in a file that can be
998 * shared by pg_dumpall and pg_restore as well as pg_dump.
1002 pg_strdup(const char *string)
1007 exit_horribly(NULL, NULL, "cannot duplicate null pointer\n");
1008 tmp = strdup(string);
1010 exit_horribly(NULL, NULL, "out of memory\n");
1015 pg_malloc(size_t size)
1021 exit_horribly(NULL, NULL, "out of memory\n");
1026 pg_calloc(size_t nmemb, size_t size)
1030 tmp = calloc(nmemb, size);
1032 exit_horribly(NULL, NULL, "out of memory\n");
1037 pg_realloc(void *ptr, size_t size)
1041 tmp = realloc(ptr, size);
1043 exit_horribly(NULL, NULL, "out of memory\n");