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-2006, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
14 * $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.94 2006/10/09 23:36:59 tgl Exp $
16 *-------------------------------------------------------------------------
19 #include "postgres_fe.h"
20 #include "pg_backup_archiver.h"
23 #include "catalog/pg_class.h"
29 * Variables for mapping DumpId to DumpableObject
31 static DumpableObject **dumpIdMap = NULL;
32 static int allocedDumpIds = 0;
33 static DumpId lastDumpId = 0;
36 * Variables for mapping CatalogId to DumpableObject
38 static bool catalogIdMapValid = false;
39 static DumpableObject **catalogIdMap = NULL;
40 static int numCatalogIds = 0;
43 * These variables are static to avoid the notational cruft of having to pass
44 * them into findTableByOid() and friends.
46 static TableInfo *tblinfo;
47 static TypeInfo *typinfo;
48 static FuncInfo *funinfo;
49 static OprInfo *oprinfo;
53 static int numOperators;
56 static void flagInhTables(TableInfo *tbinfo, int numTables,
57 InhInfo *inhinfo, int numInherits);
58 static void flagInhAttrs(TableInfo *tbinfo, int numTables,
59 InhInfo *inhinfo, int numInherits);
60 static int DOCatalogIdCompare(const void *p1, const void *p2);
61 static void findParentsByOid(TableInfo *self,
62 InhInfo *inhinfo, int numInherits);
63 static int strInArray(const char *pattern, char **arr, int arr_size);
68 * Collect information about all potentially dumpable objects
71 getSchemaData(int *numTablesPtr)
73 NamespaceInfo *nsinfo;
77 ProcLangInfo *proclanginfo;
91 write_msg(NULL, "reading schemas\n");
92 nsinfo = getNamespaces(&numNamespaces);
95 write_msg(NULL, "reading user-defined functions\n");
96 funinfo = getFuncs(&numFuncs);
98 /* this must be after getFuncs */
100 write_msg(NULL, "reading user-defined types\n");
101 typinfo = getTypes(&numTypes);
103 /* this must be after getFuncs, too */
105 write_msg(NULL, "reading procedural languages\n");
106 proclanginfo = getProcLangs(&numProcLangs);
109 write_msg(NULL, "reading user-defined aggregate functions\n");
110 agginfo = getAggregates(&numAggregates);
113 write_msg(NULL, "reading user-defined operators\n");
114 oprinfo = getOperators(&numOperators);
117 write_msg(NULL, "reading user-defined operator classes\n");
118 opcinfo = getOpclasses(&numOpclasses);
121 write_msg(NULL, "reading user-defined conversions\n");
122 convinfo = getConversions(&numConversions);
125 write_msg(NULL, "reading user-defined tables\n");
126 tblinfo = getTables(&numTables);
129 write_msg(NULL, "reading table inheritance information\n");
130 inhinfo = getInherits(&numInherits);
133 write_msg(NULL, "reading rewrite rules\n");
134 ruleinfo = getRules(&numRules);
137 write_msg(NULL, "reading type casts\n");
138 castinfo = getCasts(&numCasts);
140 /* Link tables to parents, mark parents of target tables interesting */
142 write_msg(NULL, "finding inheritance relationships\n");
143 flagInhTables(tblinfo, numTables, inhinfo, numInherits);
146 write_msg(NULL, "reading column info for interesting tables\n");
147 getTableAttrs(tblinfo, numTables);
150 write_msg(NULL, "flagging inherited columns in subtables\n");
151 flagInhAttrs(tblinfo, numTables, inhinfo, numInherits);
154 write_msg(NULL, "reading indexes\n");
155 getIndexes(tblinfo, numTables);
158 write_msg(NULL, "reading constraints\n");
159 getConstraints(tblinfo, numTables);
162 write_msg(NULL, "reading triggers\n");
163 getTriggers(tblinfo, numTables);
165 *numTablesPtr = numTables;
170 * Fill in parent link fields of every target table, and mark
171 * parents of target tables as interesting
173 * Note that only direct ancestors of targets are marked interesting.
174 * This is sufficient; we don't much care whether they inherited their
180 flagInhTables(TableInfo *tblinfo, int numTables,
181 InhInfo *inhinfo, int numInherits)
188 for (i = 0; i < numTables; i++)
190 /* Sequences and views never have parents */
191 if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
192 tblinfo[i].relkind == RELKIND_VIEW)
195 /* Don't bother computing anything for non-target tables, either */
196 if (!tblinfo[i].dobj.dump)
199 /* Find all the immediate parent tables */
200 findParentsByOid(&tblinfo[i], inhinfo, numInherits);
202 /* Mark the parents as interesting for getTableAttrs */
203 numParents = tblinfo[i].numParents;
204 parents = tblinfo[i].parents;
205 for (j = 0; j < numParents; j++)
206 parents[j]->interesting = true;
211 * for each dumpable table in tblinfo, flag its inherited attributes
212 * so when we dump the table out, we don't dump out the inherited attributes
217 flagInhAttrs(TableInfo *tblinfo, int numTables,
218 InhInfo *inhinfo, int numInherits)
224 for (i = 0; i < numTables; i++)
226 TableInfo *tbinfo = &(tblinfo[i]);
231 /* Sequences and views never have parents */
232 if (tbinfo->relkind == RELKIND_SEQUENCE ||
233 tbinfo->relkind == RELKIND_VIEW)
236 /* Don't bother computing anything for non-target tables, either */
237 if (!tbinfo->dobj.dump)
240 numParents = tbinfo->numParents;
241 parents = tbinfo->parents;
244 continue; /* nothing to see here, move along */
246 /*----------------------------------------------------------------
247 * For each attr, check the parent info: if no parent has an attr
248 * with the same name, then it's not inherited. If there *is* an
249 * attr with the same name, then only dump it if:
251 * - it is NOT NULL and zero parents are NOT NULL
253 * - it has a default value AND the default value does not match
254 * all parent default values, or no parents specify a default.
256 * See discussion on -hackers around 2-Apr-2001.
257 *----------------------------------------------------------------
259 for (j = 0; j < tbinfo->numatts; j++)
261 bool foundAttr; /* Attr was found in a parent */
262 bool foundNotNull; /* Attr was NOT NULL in a parent */
263 bool defaultsMatch; /* All non-empty defaults match */
264 bool defaultsFound; /* Found a default in a parent */
265 AttrDefInfo *attrDef;
268 foundNotNull = false;
269 defaultsMatch = true;
270 defaultsFound = false;
272 attrDef = tbinfo->attrdefs[j];
274 for (k = 0; k < numParents; k++)
279 inhAttrInd = strInArray(tbinfo->attnames[j],
283 if (inhAttrInd != -1)
286 foundNotNull |= parent->notnull[inhAttrInd];
287 if (attrDef != NULL) /* If we have a default, check
292 inhDef = parent->attrdefs[inhAttrInd];
295 defaultsFound = true;
296 defaultsMatch &= (strcmp(attrDef->adef_expr,
297 inhDef->adef_expr) == 0);
304 * Based on the scan of the parents, decide if we can rely on the
307 if (foundAttr) /* Attr was inherited */
309 /* Set inherited flag by default */
310 tbinfo->inhAttrs[j] = true;
311 tbinfo->inhAttrDef[j] = true;
312 tbinfo->inhNotNull[j] = true;
315 * Clear it if attr had a default, but parents did not, or
318 if ((attrDef != NULL) && (!defaultsFound || !defaultsMatch))
320 tbinfo->inhAttrs[j] = false;
321 tbinfo->inhAttrDef[j] = false;
325 * Clear it if NOT NULL and none of the parents were NOT NULL
327 if (tbinfo->notnull[j] && !foundNotNull)
329 tbinfo->inhAttrs[j] = false;
330 tbinfo->inhNotNull[j] = false;
333 /* Clear it if attr has local definition */
334 if (tbinfo->attislocal[j])
335 tbinfo->inhAttrs[j] = false;
340 * Check for inherited CHECK constraints. We assume a constraint is
341 * inherited if its name matches the name of any constraint in the
342 * parent. Originally this code tried to compare the expression
343 * texts, but that can fail if the parent and child tables are in
344 * different schemas, because reverse-listing of function calls may
345 * produce different text (schema-qualified or not) depending on
346 * search path. We really need a more bulletproof way of detecting
347 * inherited constraints --- pg_constraint should record this
350 for (j = 0; j < tbinfo->ncheck; j++)
352 ConstraintInfo *constr;
354 constr = &(tbinfo->checkexprs[j]);
356 for (k = 0; k < numParents; k++)
361 for (l = 0; l < parent->ncheck; l++)
363 ConstraintInfo *pconstr = &(parent->checkexprs[l]);
365 if (strcmp(pconstr->dobj.name, constr->dobj.name) == 0)
367 constr->coninherited = true;
371 if (constr->coninherited)
380 * Given a newly-created dumpable object, assign a dump ID,
381 * and enter the object into the lookup table.
383 * The caller is expected to have filled in objType and catId,
384 * but not any of the other standard fields of a DumpableObject.
387 AssignDumpId(DumpableObject *dobj)
389 dobj->dumpId = ++lastDumpId;
390 dobj->name = NULL; /* must be set later */
391 dobj->namespace = NULL; /* may be set later */
392 dobj->dump = true; /* default assumption */
393 dobj->dependencies = NULL;
397 while (dobj->dumpId >= allocedDumpIds)
401 if (allocedDumpIds <= 0)
404 dumpIdMap = (DumpableObject **)
405 pg_malloc(newAlloc * sizeof(DumpableObject *));
409 newAlloc = allocedDumpIds * 2;
410 dumpIdMap = (DumpableObject **)
411 pg_realloc(dumpIdMap, newAlloc * sizeof(DumpableObject *));
413 memset(dumpIdMap + allocedDumpIds, 0,
414 (newAlloc - allocedDumpIds) * sizeof(DumpableObject *));
415 allocedDumpIds = newAlloc;
417 dumpIdMap[dobj->dumpId] = dobj;
419 /* mark catalogIdMap invalid, but don't rebuild it yet */
420 catalogIdMapValid = false;
424 * Assign a DumpId that's not tied to a DumpableObject.
426 * This is used when creating a "fixed" ArchiveEntry that doesn't need to
427 * participate in the sorting logic.
436 * Return the largest DumpId so far assigned
445 * Find a DumpableObject by dump ID
447 * Returns NULL for invalid ID
450 findObjectByDumpId(DumpId dumpId)
452 if (dumpId <= 0 || dumpId >= allocedDumpIds)
453 return NULL; /* out of range? */
454 return dumpIdMap[dumpId];
458 * Find a DumpableObject by catalog ID
460 * Returns NULL for unknown ID
462 * We use binary search in a sorted list that is built on first call.
463 * If AssignDumpId() and findObjectByCatalogId() calls were intermixed,
464 * the code would work, but possibly be very slow. In the current usage
465 * pattern that does not happen, indeed we only need to build the list once.
468 findObjectByCatalogId(CatalogId catalogId)
470 DumpableObject **low;
471 DumpableObject **high;
473 if (!catalogIdMapValid)
477 getDumpableObjects(&catalogIdMap, &numCatalogIds);
478 if (numCatalogIds > 1)
479 qsort((void *) catalogIdMap, numCatalogIds,
480 sizeof(DumpableObject *), DOCatalogIdCompare);
481 catalogIdMapValid = true;
485 * We could use bsearch() here, but the notational cruft of calling
486 * bsearch is nearly as bad as doing it ourselves; and the generalized
487 * bsearch function is noticeably slower as well.
489 if (numCatalogIds <= 0)
492 high = catalogIdMap + (numCatalogIds - 1);
495 DumpableObject **middle;
498 middle = low + (high - low) / 2;
499 /* comparison must match DOCatalogIdCompare, below */
500 difference = oidcmp((*middle)->catId.oid, catalogId.oid);
502 difference = oidcmp((*middle)->catId.tableoid, catalogId.tableoid);
505 else if (difference < 0)
514 DOCatalogIdCompare(const void *p1, const void *p2)
516 DumpableObject *obj1 = *(DumpableObject **) p1;
517 DumpableObject *obj2 = *(DumpableObject **) p2;
521 * Compare OID first since it's usually unique, whereas there will only be
522 * a few distinct values of tableoid.
524 cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid);
526 cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid);
531 * Build an array of pointers to all known dumpable objects
533 * This simply creates a modifiable copy of the internal map.
536 getDumpableObjects(DumpableObject ***objs, int *numObjs)
541 *objs = (DumpableObject **)
542 pg_malloc(allocedDumpIds * sizeof(DumpableObject *));
544 for (i = 1; i < allocedDumpIds; i++)
547 (*objs)[j++] = dumpIdMap[i];
553 * Add a dependency link to a DumpableObject
555 * Note: duplicate dependencies are currently not eliminated
558 addObjectDependency(DumpableObject *dobj, DumpId refId)
560 if (dobj->nDeps >= dobj->allocDeps)
562 if (dobj->allocDeps <= 0)
564 dobj->allocDeps = 16;
565 dobj->dependencies = (DumpId *)
566 pg_malloc(dobj->allocDeps * sizeof(DumpId));
570 dobj->allocDeps *= 2;
571 dobj->dependencies = (DumpId *)
572 pg_realloc(dobj->dependencies,
573 dobj->allocDeps * sizeof(DumpId));
576 dobj->dependencies[dobj->nDeps++] = refId;
580 * Remove a dependency link from a DumpableObject
582 * If there are multiple links, all are removed
585 removeObjectDependency(DumpableObject *dobj, DumpId refId)
590 for (i = 0; i < dobj->nDeps; i++)
592 if (dobj->dependencies[i] != refId)
593 dobj->dependencies[j++] = dobj->dependencies[i];
601 * finds the entry (in tblinfo) of the table with the given oid
602 * returns NULL if not found
604 * NOTE: should hash this, but just do linear search for now
607 findTableByOid(Oid oid)
611 for (i = 0; i < numTables; i++)
613 if (tblinfo[i].dobj.catId.oid == oid)
621 * finds the entry (in typinfo) of the type with the given oid
622 * returns NULL if not found
624 * NOTE: should hash this, but just do linear search for now
627 findTypeByOid(Oid oid)
631 for (i = 0; i < numTypes; i++)
633 if (typinfo[i].dobj.catId.oid == oid)
641 * finds the entry (in funinfo) of the function with the given oid
642 * returns NULL if not found
644 * NOTE: should hash this, but just do linear search for now
647 findFuncByOid(Oid oid)
651 for (i = 0; i < numFuncs; i++)
653 if (funinfo[i].dobj.catId.oid == oid)
661 * finds the entry (in oprinfo) of the operator with the given oid
662 * returns NULL if not found
664 * NOTE: should hash this, but just do linear search for now
667 findOprByOid(Oid oid)
671 for (i = 0; i < numOperators; i++)
673 if (oprinfo[i].dobj.catId.oid == oid)
682 * find a table's parents in tblinfo[]
685 findParentsByOid(TableInfo *self,
686 InhInfo *inhinfo, int numInherits)
688 Oid oid = self->dobj.catId.oid;
694 for (i = 0; i < numInherits; i++)
696 if (inhinfo[i].inhrelid == oid)
700 self->numParents = numParents;
704 self->parents = (TableInfo **)
705 pg_malloc(sizeof(TableInfo *) * numParents);
707 for (i = 0; i < numInherits; i++)
709 if (inhinfo[i].inhrelid == oid)
713 parent = findTableByOid(inhinfo[i].inhparent);
716 write_msg(NULL, "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found\n",
717 inhinfo[i].inhparent,
722 self->parents[j++] = parent;
727 self->parents = NULL;
732 * parse a string of numbers delimited by spaces into a character array
734 * Note: actually this is used for both Oids and potentially-signed
735 * attribute numbers. This should cause no trouble, but we could split
736 * the function into two functions with different argument types if it does.
740 parseOidArray(const char *str, Oid *array, int arraysize)
752 if (s == ' ' || s == '\0')
756 if (argNum >= arraysize)
758 write_msg(NULL, "could not parse numeric array \"%s\": too many numbers\n", str);
762 array[argNum++] = atooid(temp);
770 if (!(isdigit((unsigned char) s) || s == '-') ||
771 j >= sizeof(temp) - 1)
773 write_msg(NULL, "could not parse numeric array \"%s\": invalid character in number\n", str);
780 while (argNum < arraysize)
781 array[argNum++] = InvalidOid;
787 * takes in a string and a string array and the number of elements in the
789 * returns the index if the string is somewhere in the array, -1 otherwise
793 strInArray(const char *pattern, char **arr, int arr_size)
797 for (i = 0; i < arr_size; i++)
799 if (strcmp(pattern, arr[i]) == 0)
807 * Support for simple list operations
811 simple_oid_list_append(SimpleOidList *list, Oid val)
813 SimpleOidListCell *cell;
815 cell = (SimpleOidListCell *) pg_malloc(sizeof(SimpleOidListCell));
820 list->tail->next = cell;
827 simple_string_list_append(SimpleStringList *list, const char *val)
829 SimpleStringListCell *cell;
831 /* this calculation correctly accounts for the null trailing byte */
832 cell = (SimpleStringListCell *)
833 pg_malloc(sizeof(SimpleStringListCell) + strlen(val));
835 strcpy(cell->val, val);
838 list->tail->next = cell;
845 simple_oid_list_member(SimpleOidList *list, Oid val)
847 SimpleOidListCell *cell;
849 for (cell = list->head; cell; cell = cell->next)
851 if (cell->val == val)
858 simple_string_list_member(SimpleStringList *list, const char *val)
860 SimpleStringListCell *cell;
862 for (cell = list->head; cell; cell = cell->next)
864 if (strcmp(cell->val, val) == 0)
872 * Safer versions of some standard C library functions. If an
873 * out-of-memory condition occurs, these functions will bail out
874 * safely; therefore, their return value is guaranteed to be non-NULL.
876 * XXX need to refactor things so that these can be in a file that can be
877 * shared by pg_dumpall and pg_restore as well as pg_dump.
881 pg_strdup(const char *string)
886 exit_horribly(NULL, NULL, "cannot duplicate null pointer\n");
887 tmp = strdup(string);
889 exit_horribly(NULL, NULL, "out of memory\n");
894 pg_malloc(size_t size)
900 exit_horribly(NULL, NULL, "out of memory\n");
905 pg_calloc(size_t nmemb, size_t size)
909 tmp = calloc(nmemb, size);
911 exit_horribly(NULL, NULL, "out of memory\n");
916 pg_realloc(void *ptr, size_t size)
920 tmp = realloc(ptr, size);
922 exit_horribly(NULL, NULL, "out of memory\n");