PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
common.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * common.c
4  * Catalog routines used by pg_dump; long ago these were shared
5  * by another dump tool, but not anymore.
6  *
7  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  * src/bin/pg_dump/common.c
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres_fe.h"
17 
18 #include "pg_backup_archiver.h"
19 #include "pg_backup_utils.h"
20 #include "pg_dump.h"
21 
22 #include <ctype.h>
23 
24 #include "catalog/pg_class.h"
25 #include "fe_utils/string_utils.h"
26 
27 
28 /*
29  * Variables for mapping DumpId to DumpableObject
30  */
32 static int allocedDumpIds = 0;
33 static DumpId lastDumpId = 0;
34 
35 /*
36  * Variables for mapping CatalogId to DumpableObject
37  */
38 static bool catalogIdMapValid = false;
40 static int numCatalogIds = 0;
41 
42 /*
43  * These variables are static to avoid the notational cruft of having to pass
44  * them into findTableByOid() and friends. For each of these arrays, we build
45  * a sorted-by-OID index array immediately after the objects are fetched,
46  * and then we use binary search in findTableByOid() and friends. (qsort'ing
47  * the object arrays themselves would be simpler, but it doesn't work because
48  * pg_dump.c may have already established pointers between items.)
49  */
57 static int numTables;
58 static int numTypes;
59 static int numFuncs;
60 static int numOperators;
61 static int numCollations;
62 static int numNamespaces;
63 static int numExtensions;
64 
65 /* This is an array of object identities, not actual DumpableObjects */
67 static int numextmembers;
68 
69 static void flagInhTables(Archive *fout, TableInfo *tbinfo, int numTables,
70  InhInfo *inhinfo, int numInherits);
71 static void flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables);
72 static DumpableObject **buildIndexArray(void *objArray, int numObjs,
73  Size objSize);
74 static int DOCatalogIdCompare(const void *p1, const void *p2);
75 static int ExtensionMemberIdCompare(const void *p1, const void *p2);
76 static void findParentsByOid(TableInfo *self,
77  InhInfo *inhinfo, int numInherits);
78 static int strInArray(const char *pattern, char **arr, int arr_size);
79 
80 
81 /*
82  * getSchemaData
83  * Collect information about all potentially dumpable objects
84  */
85 TableInfo *
86 getSchemaData(Archive *fout, int *numTablesPtr)
87 {
88  TableInfo *tblinfo;
90  FuncInfo *funinfo;
91  OprInfo *oprinfo;
92  CollInfo *collinfo;
93  NamespaceInfo *nspinfo;
94  ExtensionInfo *extinfo;
95  InhInfo *inhinfo;
96  int numAggregates;
97  int numInherits;
98  int numRules;
99  int numProcLangs;
100  int numCasts;
101  int numTransforms;
102  int numAccessMethods;
103  int numOpclasses;
104  int numOpfamilies;
105  int numConversions;
106  int numTSParsers;
107  int numTSTemplates;
108  int numTSDicts;
109  int numTSConfigs;
110  int numForeignDataWrappers;
111  int numForeignServers;
112  int numDefaultACLs;
113  int numEventTriggers;
114 
115  /*
116  * We must read extensions and extension membership info first, because
117  * extension membership needs to be consultable during decisions about
118  * whether other objects are to be dumped.
119  */
120  if (g_verbose)
121  write_msg(NULL, "reading extensions\n");
122  extinfo = getExtensions(fout, &numExtensions);
123  extinfoindex = buildIndexArray(extinfo, numExtensions, sizeof(ExtensionInfo));
124 
125  if (g_verbose)
126  write_msg(NULL, "identifying extension members\n");
127  getExtensionMembership(fout, extinfo, numExtensions);
128 
129  if (g_verbose)
130  write_msg(NULL, "reading schemas\n");
131  nspinfo = getNamespaces(fout, &numNamespaces);
132  nspinfoindex = buildIndexArray(nspinfo, numNamespaces, sizeof(NamespaceInfo));
133 
134  /*
135  * getTables should be done as soon as possible, so as to minimize the
136  * window between starting our transaction and acquiring per-table locks.
137  * However, we have to do getNamespaces first because the tables get
138  * linked to their containing namespaces during getTables.
139  */
140  if (g_verbose)
141  write_msg(NULL, "reading user-defined tables\n");
142  tblinfo = getTables(fout, &numTables);
143  tblinfoindex = buildIndexArray(tblinfo, numTables, sizeof(TableInfo));
144 
145  /* Do this after we've built tblinfoindex */
146  getOwnedSeqs(fout, tblinfo, numTables);
147 
148  if (g_verbose)
149  write_msg(NULL, "reading user-defined functions\n");
150  funinfo = getFuncs(fout, &numFuncs);
151  funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo));
152 
153  /* this must be after getTables and getFuncs */
154  if (g_verbose)
155  write_msg(NULL, "reading user-defined types\n");
156  typinfo = getTypes(fout, &numTypes);
157  typinfoindex = buildIndexArray(typinfo, numTypes, sizeof(TypeInfo));
158 
159  /* this must be after getFuncs, too */
160  if (g_verbose)
161  write_msg(NULL, "reading procedural languages\n");
162  getProcLangs(fout, &numProcLangs);
163 
164  if (g_verbose)
165  write_msg(NULL, "reading user-defined aggregate functions\n");
166  getAggregates(fout, &numAggregates);
167 
168  if (g_verbose)
169  write_msg(NULL, "reading user-defined operators\n");
170  oprinfo = getOperators(fout, &numOperators);
171  oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo));
172 
173  if (g_verbose)
174  write_msg(NULL, "reading user-defined access methods\n");
175  getAccessMethods(fout, &numAccessMethods);
176 
177  if (g_verbose)
178  write_msg(NULL, "reading user-defined operator classes\n");
179  getOpclasses(fout, &numOpclasses);
180 
181  if (g_verbose)
182  write_msg(NULL, "reading user-defined operator families\n");
183  getOpfamilies(fout, &numOpfamilies);
184 
185  if (g_verbose)
186  write_msg(NULL, "reading user-defined text search parsers\n");
187  getTSParsers(fout, &numTSParsers);
188 
189  if (g_verbose)
190  write_msg(NULL, "reading user-defined text search templates\n");
191  getTSTemplates(fout, &numTSTemplates);
192 
193  if (g_verbose)
194  write_msg(NULL, "reading user-defined text search dictionaries\n");
195  getTSDictionaries(fout, &numTSDicts);
196 
197  if (g_verbose)
198  write_msg(NULL, "reading user-defined text search configurations\n");
199  getTSConfigurations(fout, &numTSConfigs);
200 
201  if (g_verbose)
202  write_msg(NULL, "reading user-defined foreign-data wrappers\n");
203  getForeignDataWrappers(fout, &numForeignDataWrappers);
204 
205  if (g_verbose)
206  write_msg(NULL, "reading user-defined foreign servers\n");
207  getForeignServers(fout, &numForeignServers);
208 
209  if (g_verbose)
210  write_msg(NULL, "reading default privileges\n");
211  getDefaultACLs(fout, &numDefaultACLs);
212 
213  if (g_verbose)
214  write_msg(NULL, "reading user-defined collations\n");
215  collinfo = getCollations(fout, &numCollations);
216  collinfoindex = buildIndexArray(collinfo, numCollations, sizeof(CollInfo));
217 
218  if (g_verbose)
219  write_msg(NULL, "reading user-defined conversions\n");
220  getConversions(fout, &numConversions);
221 
222  if (g_verbose)
223  write_msg(NULL, "reading type casts\n");
224  getCasts(fout, &numCasts);
225 
226  if (g_verbose)
227  write_msg(NULL, "reading transforms\n");
228  getTransforms(fout, &numTransforms);
229 
230  if (g_verbose)
231  write_msg(NULL, "reading table inheritance information\n");
232  inhinfo = getInherits(fout, &numInherits);
233 
234  if (g_verbose)
235  write_msg(NULL, "reading event triggers\n");
236  getEventTriggers(fout, &numEventTriggers);
237 
238  /* Identify extension configuration tables that should be dumped */
239  if (g_verbose)
240  write_msg(NULL, "finding extension tables\n");
241  processExtensionTables(fout, extinfo, numExtensions);
242 
243  /* Link tables to parents, mark parents of target tables interesting */
244  if (g_verbose)
245  write_msg(NULL, "finding inheritance relationships\n");
246  flagInhTables(fout, tblinfo, numTables, inhinfo, numInherits);
247 
248  if (g_verbose)
249  write_msg(NULL, "reading column info for interesting tables\n");
250  getTableAttrs(fout, tblinfo, numTables);
251 
252  if (g_verbose)
253  write_msg(NULL, "flagging inherited columns in subtables\n");
254  flagInhAttrs(fout->dopt, tblinfo, numTables);
255 
256  if (g_verbose)
257  write_msg(NULL, "reading indexes\n");
258  getIndexes(fout, tblinfo, numTables);
259 
260  if (g_verbose)
261  write_msg(NULL, "reading extended statistics\n");
262  getExtendedStatistics(fout, tblinfo, numTables);
263 
264  if (g_verbose)
265  write_msg(NULL, "reading constraints\n");
266  getConstraints(fout, tblinfo, numTables);
267 
268  if (g_verbose)
269  write_msg(NULL, "reading triggers\n");
270  getTriggers(fout, tblinfo, numTables);
271 
272  if (g_verbose)
273  write_msg(NULL, "reading rewrite rules\n");
274  getRules(fout, &numRules);
275 
276  if (g_verbose)
277  write_msg(NULL, "reading policies\n");
278  getPolicies(fout, tblinfo, numTables);
279 
280  if (g_verbose)
281  write_msg(NULL, "reading publications\n");
282  getPublications(fout);
283 
284  if (g_verbose)
285  write_msg(NULL, "reading publication membership\n");
286  getPublicationTables(fout, tblinfo, numTables);
287 
288  if (g_verbose)
289  write_msg(NULL, "reading subscriptions\n");
290  getSubscriptions(fout);
291 
292  *numTablesPtr = numTables;
293  return tblinfo;
294 }
295 
296 /* flagInhTables -
297  * Fill in parent link fields of tables for which we need that information,
298  * and mark parents of target tables as interesting
299  *
300  * Note that only direct ancestors of targets are marked interesting.
301  * This is sufficient; we don't much care whether they inherited their
302  * attributes or not.
303  *
304  * modifies tblinfo
305  */
306 static void
308  InhInfo *inhinfo, int numInherits)
309 {
310  DumpOptions *dopt = fout->dopt;
311  int i,
312  j;
313 
314  for (i = 0; i < numTables; i++)
315  {
316  bool find_parents = true;
317  bool mark_parents = true;
318 
319  /* Some kinds never have parents */
320  if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
321  tblinfo[i].relkind == RELKIND_VIEW ||
322  tblinfo[i].relkind == RELKIND_MATVIEW)
323  continue;
324 
325  /*
326  * Normally, we don't bother computing anything for non-target tables,
327  * but if load-via-partition-root is specified, we gather information
328  * on every partition in the system so that getRootTableInfo can trace
329  * from any given to leaf partition all the way up to the root. (We
330  * don't need to mark them as interesting for getTableAttrs, though.)
331  */
332  if (!tblinfo[i].dobj.dump)
333  {
334  mark_parents = false;
335 
336  if (!dopt->load_via_partition_root ||
337  !tblinfo[i].ispartition)
338  find_parents = false;
339  }
340 
341  /* If needed, find all the immediate parent tables. */
342  if (find_parents)
343  findParentsByOid(&tblinfo[i], inhinfo, numInherits);
344 
345  /* If needed, mark the parents as interesting for getTableAttrs. */
346  if (mark_parents)
347  {
348  int numParents = tblinfo[i].numParents;
349  TableInfo **parents = tblinfo[i].parents;
350 
351  for (j = 0; j < numParents; j++)
352  parents[j]->interesting = true;
353  }
354  }
355 }
356 
357 /* flagInhAttrs -
358  * for each dumpable table in tblinfo, flag its inherited attributes
359  *
360  * What we need to do here is detect child columns that inherit NOT NULL
361  * bits from their parents (so that we needn't specify that again for the
362  * child) and child columns that have DEFAULT NULL when their parents had
363  * some non-null default. In the latter case, we make up a dummy AttrDefInfo
364  * object so that we'll correctly emit the necessary DEFAULT NULL clause;
365  * otherwise the backend will apply an inherited default to the column.
366  *
367  * modifies tblinfo
368  */
369 static void
371 {
372  int i,
373  j,
374  k;
375 
376  for (i = 0; i < numTables; i++)
377  {
378  TableInfo *tbinfo = &(tblinfo[i]);
379  int numParents;
380  TableInfo **parents;
381 
382  /* Some kinds never have parents */
383  if (tbinfo->relkind == RELKIND_SEQUENCE ||
384  tbinfo->relkind == RELKIND_VIEW ||
385  tbinfo->relkind == RELKIND_MATVIEW)
386  continue;
387 
388  /* Don't bother computing anything for non-target tables, either */
389  if (!tbinfo->dobj.dump)
390  continue;
391 
392  numParents = tbinfo->numParents;
393  parents = tbinfo->parents;
394 
395  if (numParents == 0)
396  continue; /* nothing to see here, move along */
397 
398  /* For each column, search for matching column names in parent(s) */
399  for (j = 0; j < tbinfo->numatts; j++)
400  {
401  bool foundNotNull; /* Attr was NOT NULL in a parent */
402  bool foundDefault; /* Found a default in a parent */
403 
404  /* no point in examining dropped columns */
405  if (tbinfo->attisdropped[j])
406  continue;
407 
408  foundNotNull = false;
409  foundDefault = false;
410  for (k = 0; k < numParents; k++)
411  {
412  TableInfo *parent = parents[k];
413  int inhAttrInd;
414 
415  inhAttrInd = strInArray(tbinfo->attnames[j],
416  parent->attnames,
417  parent->numatts);
418  if (inhAttrInd >= 0)
419  {
420  foundNotNull |= parent->notnull[inhAttrInd];
421  foundDefault |= (parent->attrdefs[inhAttrInd] != NULL);
422  }
423  }
424 
425  /* Remember if we found inherited NOT NULL */
426  tbinfo->inhNotNull[j] = foundNotNull;
427 
428  /* Manufacture a DEFAULT NULL clause if necessary */
429  if (foundDefault && tbinfo->attrdefs[j] == NULL)
430  {
431  AttrDefInfo *attrDef;
432 
433  attrDef = (AttrDefInfo *) pg_malloc(sizeof(AttrDefInfo));
434  attrDef->dobj.objType = DO_ATTRDEF;
435  attrDef->dobj.catId.tableoid = 0;
436  attrDef->dobj.catId.oid = 0;
437  AssignDumpId(&attrDef->dobj);
438  attrDef->dobj.name = pg_strdup(tbinfo->dobj.name);
439  attrDef->dobj.namespace = tbinfo->dobj.namespace;
440  attrDef->dobj.dump = tbinfo->dobj.dump;
441 
442  attrDef->adtable = tbinfo;
443  attrDef->adnum = j + 1;
444  attrDef->adef_expr = pg_strdup("NULL");
445 
446  /* Will column be dumped explicitly? */
447  if (shouldPrintColumn(dopt, tbinfo, j))
448  {
449  attrDef->separate = false;
450  /* No dependency needed: NULL cannot have dependencies */
451  }
452  else
453  {
454  /* column will be suppressed, print default separately */
455  attrDef->separate = true;
456  /* ensure it comes out after the table */
457  addObjectDependency(&attrDef->dobj,
458  tbinfo->dobj.dumpId);
459  }
460 
461  tbinfo->attrdefs[j] = attrDef;
462  }
463  }
464  }
465 }
466 
467 /*
468  * AssignDumpId
469  * Given a newly-created dumpable object, assign a dump ID,
470  * and enter the object into the lookup table.
471  *
472  * The caller is expected to have filled in objType and catId,
473  * but not any of the other standard fields of a DumpableObject.
474  */
475 void
477 {
478  dobj->dumpId = ++lastDumpId;
479  dobj->name = NULL; /* must be set later */
480  dobj->namespace = NULL; /* may be set later */
481  dobj->dump = DUMP_COMPONENT_ALL; /* default assumption */
482  dobj->ext_member = false; /* default assumption */
483  dobj->dependencies = NULL;
484  dobj->nDeps = 0;
485  dobj->allocDeps = 0;
486 
487  while (dobj->dumpId >= allocedDumpIds)
488  {
489  int newAlloc;
490 
491  if (allocedDumpIds <= 0)
492  {
493  newAlloc = 256;
494  dumpIdMap = (DumpableObject **)
495  pg_malloc(newAlloc * sizeof(DumpableObject *));
496  }
497  else
498  {
499  newAlloc = allocedDumpIds * 2;
500  dumpIdMap = (DumpableObject **)
501  pg_realloc(dumpIdMap, newAlloc * sizeof(DumpableObject *));
502  }
503  memset(dumpIdMap + allocedDumpIds, 0,
504  (newAlloc - allocedDumpIds) * sizeof(DumpableObject *));
505  allocedDumpIds = newAlloc;
506  }
507  dumpIdMap[dobj->dumpId] = dobj;
508 
509  /* mark catalogIdMap invalid, but don't rebuild it yet */
510  catalogIdMapValid = false;
511 }
512 
513 /*
514  * Assign a DumpId that's not tied to a DumpableObject.
515  *
516  * This is used when creating a "fixed" ArchiveEntry that doesn't need to
517  * participate in the sorting logic.
518  */
519 DumpId
521 {
522  return ++lastDumpId;
523 }
524 
525 /*
526  * Return the largest DumpId so far assigned
527  */
528 DumpId
530 {
531  return lastDumpId;
532 }
533 
534 /*
535  * Find a DumpableObject by dump ID
536  *
537  * Returns NULL for invalid ID
538  */
541 {
542  if (dumpId <= 0 || dumpId >= allocedDumpIds)
543  return NULL; /* out of range? */
544  return dumpIdMap[dumpId];
545 }
546 
547 /*
548  * Find a DumpableObject by catalog ID
549  *
550  * Returns NULL for unknown ID
551  *
552  * We use binary search in a sorted list that is built on first call.
553  * If AssignDumpId() and findObjectByCatalogId() calls were freely intermixed,
554  * the code would work, but possibly be very slow. In the current usage
555  * pattern that does not happen, indeed we build the list at most twice.
556  */
559 {
560  DumpableObject **low;
561  DumpableObject **high;
562 
563  if (!catalogIdMapValid)
564  {
565  if (catalogIdMap)
566  free(catalogIdMap);
567  getDumpableObjects(&catalogIdMap, &numCatalogIds);
568  if (numCatalogIds > 1)
569  qsort((void *) catalogIdMap, numCatalogIds,
571  catalogIdMapValid = true;
572  }
573 
574  /*
575  * We could use bsearch() here, but the notational cruft of calling
576  * bsearch is nearly as bad as doing it ourselves; and the generalized
577  * bsearch function is noticeably slower as well.
578  */
579  if (numCatalogIds <= 0)
580  return NULL;
581  low = catalogIdMap;
582  high = catalogIdMap + (numCatalogIds - 1);
583  while (low <= high)
584  {
585  DumpableObject **middle;
586  int difference;
587 
588  middle = low + (high - low) / 2;
589  /* comparison must match DOCatalogIdCompare, below */
590  difference = oidcmp((*middle)->catId.oid, catalogId.oid);
591  if (difference == 0)
592  difference = oidcmp((*middle)->catId.tableoid, catalogId.tableoid);
593  if (difference == 0)
594  return *middle;
595  else if (difference < 0)
596  low = middle + 1;
597  else
598  high = middle - 1;
599  }
600  return NULL;
601 }
602 
603 /*
604  * Find a DumpableObject by OID, in a pre-sorted array of one type of object
605  *
606  * Returns NULL for unknown OID
607  */
608 static DumpableObject *
609 findObjectByOid(Oid oid, DumpableObject **indexArray, int numObjs)
610 {
611  DumpableObject **low;
612  DumpableObject **high;
613 
614  /*
615  * This is the same as findObjectByCatalogId except we assume we need not
616  * look at table OID because the objects are all the same type.
617  *
618  * We could use bsearch() here, but the notational cruft of calling
619  * bsearch is nearly as bad as doing it ourselves; and the generalized
620  * bsearch function is noticeably slower as well.
621  */
622  if (numObjs <= 0)
623  return NULL;
624  low = indexArray;
625  high = indexArray + (numObjs - 1);
626  while (low <= high)
627  {
628  DumpableObject **middle;
629  int difference;
630 
631  middle = low + (high - low) / 2;
632  difference = oidcmp((*middle)->catId.oid, oid);
633  if (difference == 0)
634  return *middle;
635  else if (difference < 0)
636  low = middle + 1;
637  else
638  high = middle - 1;
639  }
640  return NULL;
641 }
642 
643 /*
644  * Build an index array of DumpableObject pointers, sorted by OID
645  */
646 static DumpableObject **
647 buildIndexArray(void *objArray, int numObjs, Size objSize)
648 {
649  DumpableObject **ptrs;
650  int i;
651 
652  ptrs = (DumpableObject **) pg_malloc(numObjs * sizeof(DumpableObject *));
653  for (i = 0; i < numObjs; i++)
654  ptrs[i] = (DumpableObject *) ((char *) objArray + i * objSize);
655 
656  /* We can use DOCatalogIdCompare to sort since its first key is OID */
657  if (numObjs > 1)
658  qsort((void *) ptrs, numObjs, sizeof(DumpableObject *),
660 
661  return ptrs;
662 }
663 
664 /*
665  * qsort comparator for pointers to DumpableObjects
666  */
667 static int
668 DOCatalogIdCompare(const void *p1, const void *p2)
669 {
670  const DumpableObject *obj1 = *(DumpableObject *const *) p1;
671  const DumpableObject *obj2 = *(DumpableObject *const *) p2;
672  int cmpval;
673 
674  /*
675  * Compare OID first since it's usually unique, whereas there will only be
676  * a few distinct values of tableoid.
677  */
678  cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid);
679  if (cmpval == 0)
680  cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid);
681  return cmpval;
682 }
683 
684 /*
685  * Build an array of pointers to all known dumpable objects
686  *
687  * This simply creates a modifiable copy of the internal map.
688  */
689 void
690 getDumpableObjects(DumpableObject ***objs, int *numObjs)
691 {
692  int i,
693  j;
694 
695  *objs = (DumpableObject **)
697  j = 0;
698  for (i = 1; i < allocedDumpIds; i++)
699  {
700  if (dumpIdMap[i])
701  (*objs)[j++] = dumpIdMap[i];
702  }
703  *numObjs = j;
704 }
705 
706 /*
707  * Add a dependency link to a DumpableObject
708  *
709  * Note: duplicate dependencies are currently not eliminated
710  */
711 void
713 {
714  if (dobj->nDeps >= dobj->allocDeps)
715  {
716  if (dobj->allocDeps <= 0)
717  {
718  dobj->allocDeps = 16;
719  dobj->dependencies = (DumpId *)
720  pg_malloc(dobj->allocDeps * sizeof(DumpId));
721  }
722  else
723  {
724  dobj->allocDeps *= 2;
725  dobj->dependencies = (DumpId *)
726  pg_realloc(dobj->dependencies,
727  dobj->allocDeps * sizeof(DumpId));
728  }
729  }
730  dobj->dependencies[dobj->nDeps++] = refId;
731 }
732 
733 /*
734  * Remove a dependency link from a DumpableObject
735  *
736  * If there are multiple links, all are removed
737  */
738 void
740 {
741  int i;
742  int j = 0;
743 
744  for (i = 0; i < dobj->nDeps; i++)
745  {
746  if (dobj->dependencies[i] != refId)
747  dobj->dependencies[j++] = dobj->dependencies[i];
748  }
749  dobj->nDeps = j;
750 }
751 
752 
753 /*
754  * findTableByOid
755  * finds the entry (in tblinfo) of the table with the given oid
756  * returns NULL if not found
757  */
758 TableInfo *
760 {
761  return (TableInfo *) findObjectByOid(oid, tblinfoindex, numTables);
762 }
763 
764 /*
765  * findTypeByOid
766  * finds the entry (in typinfo) of the type with the given oid
767  * returns NULL if not found
768  */
769 TypeInfo *
771 {
772  return (TypeInfo *) findObjectByOid(oid, typinfoindex, numTypes);
773 }
774 
775 /*
776  * findFuncByOid
777  * finds the entry (in funinfo) of the function with the given oid
778  * returns NULL if not found
779  */
780 FuncInfo *
782 {
783  return (FuncInfo *) findObjectByOid(oid, funinfoindex, numFuncs);
784 }
785 
786 /*
787  * findOprByOid
788  * finds the entry (in oprinfo) of the operator with the given oid
789  * returns NULL if not found
790  */
791 OprInfo *
793 {
794  return (OprInfo *) findObjectByOid(oid, oprinfoindex, numOperators);
795 }
796 
797 /*
798  * findCollationByOid
799  * finds the entry (in collinfo) of the collation with the given oid
800  * returns NULL if not found
801  */
802 CollInfo *
804 {
805  return (CollInfo *) findObjectByOid(oid, collinfoindex, numCollations);
806 }
807 
808 /*
809  * findNamespaceByOid
810  * finds the entry (in nspinfo) of the namespace with the given oid
811  * returns NULL if not found
812  */
815 {
816  return (NamespaceInfo *) findObjectByOid(oid, nspinfoindex, numNamespaces);
817 }
818 
819 /*
820  * findExtensionByOid
821  * finds the entry (in extinfo) of the extension with the given oid
822  * returns NULL if not found
823  */
826 {
827  return (ExtensionInfo *) findObjectByOid(oid, extinfoindex, numExtensions);
828 }
829 
830 
831 /*
832  * setExtensionMembership
833  * accept and save data about which objects belong to extensions
834  */
835 void
837 {
838  /* Sort array in preparation for binary searches */
839  if (nextmems > 1)
840  qsort((void *) extmems, nextmems, sizeof(ExtensionMemberId),
842  /* And save */
843  extmembers = extmems;
844  numextmembers = nextmems;
845 }
846 
847 /*
848  * findOwningExtension
849  * return owning extension for specified catalog ID, or NULL if none
850  */
853 {
854  ExtensionMemberId *low;
855  ExtensionMemberId *high;
856 
857  /*
858  * We could use bsearch() here, but the notational cruft of calling
859  * bsearch is nearly as bad as doing it ourselves; and the generalized
860  * bsearch function is noticeably slower as well.
861  */
862  if (numextmembers <= 0)
863  return NULL;
864  low = extmembers;
865  high = extmembers + (numextmembers - 1);
866  while (low <= high)
867  {
868  ExtensionMemberId *middle;
869  int difference;
870 
871  middle = low + (high - low) / 2;
872  /* comparison must match ExtensionMemberIdCompare, below */
873  difference = oidcmp(middle->catId.oid, catalogId.oid);
874  if (difference == 0)
875  difference = oidcmp(middle->catId.tableoid, catalogId.tableoid);
876  if (difference == 0)
877  return middle->ext;
878  else if (difference < 0)
879  low = middle + 1;
880  else
881  high = middle - 1;
882  }
883  return NULL;
884 }
885 
886 /*
887  * qsort comparator for ExtensionMemberIds
888  */
889 static int
890 ExtensionMemberIdCompare(const void *p1, const void *p2)
891 {
892  const ExtensionMemberId *obj1 = (const ExtensionMemberId *) p1;
893  const ExtensionMemberId *obj2 = (const ExtensionMemberId *) p2;
894  int cmpval;
895 
896  /*
897  * Compare OID first since it's usually unique, whereas there will only be
898  * a few distinct values of tableoid.
899  */
900  cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid);
901  if (cmpval == 0)
902  cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid);
903  return cmpval;
904 }
905 
906 
907 /*
908  * findParentsByOid
909  * find a table's parents in tblinfo[]
910  */
911 static void
913  InhInfo *inhinfo, int numInherits)
914 {
915  Oid oid = self->dobj.catId.oid;
916  int i,
917  j;
918  int numParents;
919 
920  numParents = 0;
921  for (i = 0; i < numInherits; i++)
922  {
923  if (inhinfo[i].inhrelid == oid)
924  numParents++;
925  }
926 
927  self->numParents = numParents;
928 
929  if (numParents > 0)
930  {
931  self->parents = (TableInfo **)
932  pg_malloc(sizeof(TableInfo *) * numParents);
933  j = 0;
934  for (i = 0; i < numInherits; i++)
935  {
936  if (inhinfo[i].inhrelid == oid)
937  {
938  TableInfo *parent;
939 
940  parent = findTableByOid(inhinfo[i].inhparent);
941  if (parent == NULL)
942  {
943  write_msg(NULL, "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found\n",
944  inhinfo[i].inhparent,
945  self->dobj.name,
946  oid);
947  exit_nicely(1);
948  }
949  self->parents[j++] = parent;
950  }
951  }
952  }
953  else
954  self->parents = NULL;
955 }
956 
957 /*
958  * parseOidArray
959  * parse a string of numbers delimited by spaces into a character array
960  *
961  * Note: actually this is used for both Oids and potentially-signed
962  * attribute numbers. This should cause no trouble, but we could split
963  * the function into two functions with different argument types if it does.
964  */
965 
966 void
967 parseOidArray(const char *str, Oid *array, int arraysize)
968 {
969  int j,
970  argNum;
971  char temp[100];
972  char s;
973 
974  argNum = 0;
975  j = 0;
976  for (;;)
977  {
978  s = *str++;
979  if (s == ' ' || s == '\0')
980  {
981  if (j > 0)
982  {
983  if (argNum >= arraysize)
984  {
985  write_msg(NULL, "could not parse numeric array \"%s\": too many numbers\n", str);
986  exit_nicely(1);
987  }
988  temp[j] = '\0';
989  array[argNum++] = atooid(temp);
990  j = 0;
991  }
992  if (s == '\0')
993  break;
994  }
995  else
996  {
997  if (!(isdigit((unsigned char) s) || s == '-') ||
998  j >= sizeof(temp) - 1)
999  {
1000  write_msg(NULL, "could not parse numeric array \"%s\": invalid character in number\n", str);
1001  exit_nicely(1);
1002  }
1003  temp[j++] = s;
1004  }
1005  }
1006 
1007  while (argNum < arraysize)
1008  array[argNum++] = InvalidOid;
1009 }
1010 
1011 
1012 /*
1013  * strInArray:
1014  * takes in a string and a string array and the number of elements in the
1015  * string array.
1016  * returns the index if the string is somewhere in the array, -1 otherwise
1017  */
1018 
1019 static int
1020 strInArray(const char *pattern, char **arr, int arr_size)
1021 {
1022  int i;
1023 
1024  for (i = 0; i < arr_size; i++)
1025  {
1026  if (strcmp(pattern, arr[i]) == 0)
1027  return i;
1028  }
1029  return -1;
1030 }
FuncInfo * getFuncs(Archive *fout, int *numFuncs)
Definition: pg_dump.c:5333
static DumpableObject ** collinfoindex
Definition: common.c:54
static int numTypes
Definition: common.c:58
char * name
Definition: pg_dump.h:133
TableInfo * findTableByOid(Oid oid)
Definition: common.c:759
ExtensionInfo * ext
Definition: pg_dump.h:621
int DumpId
Definition: pg_backup.h:230
AggInfo * getAggregates(Archive *fout, int *numAggs)
Definition: pg_dump.c:5141
struct _tableInfo ** parents
Definition: pg_dump.h:330
static int allocedDumpIds
Definition: common.c:32
void getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:3614
CollInfo * getCollations(Archive *fout, int *numCollations)
Definition: pg_dump.c:4740
char relkind
Definition: pg_dump.h:267
DumpComponents dump
Definition: pg_dump.h:134
static DumpId lastDumpId
Definition: common.c:33
Oid tableoid
Definition: pg_backup.h:226
static DumpableObject ** dumpIdMap
Definition: common.c:31
#define oidcmp(x, y)
Definition: pg_dump.h:20
void AssignDumpId(DumpableObject *dobj)
Definition: common.c:476
OprInfo * getOperators(Archive *fout, int *numOprs)
Definition: pg_dump.c:4654
static DumpableObject ** oprinfoindex
Definition: common.c:53
DumpId * dependencies
Definition: pg_dump.h:138
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
TransformInfo * getTransforms(Archive *fout, int *numTransforms)
Definition: pg_dump.c:7733
DefaultACLInfo * getDefaultACLs(Archive *fout, int *numDefaultACLs)
Definition: pg_dump.c:8983
static void flagInhTables(Archive *fout, TableInfo *tbinfo, int numTables, InhInfo *inhinfo, int numInherits)
Definition: common.c:307
static int numFuncs
Definition: common.c:59
AccessMethodInfo * getAccessMethods(Archive *fout, int *numAccessMethods)
Definition: pg_dump.c:4899
static int DOCatalogIdCompare(const void *p1, const void *p2)
Definition: common.c:668
bool shouldPrintColumn(DumpOptions *dopt, TableInfo *tbinfo, int colno)
Definition: pg_dump.c:8305
#define RELKIND_MATVIEW
Definition: pg_class.h:165
static int numCatalogIds
Definition: common.c:40
OpclassInfo * getOpclasses(Archive *fout, int *numOpclasses)
Definition: pg_dump.c:4976
bool * inhNotNull
Definition: pg_dump.h:319
TSConfigInfo * getTSConfigurations(Archive *fout, int *numTSConfigs)
Definition: pg_dump.c:8581
static void findParentsByOid(TableInfo *self, InhInfo *inhinfo, int numInherits)
Definition: common.c:912
DumpId dumpId
Definition: pg_dump.h:132
static int numTables
Definition: common.c:57
unsigned int Oid
Definition: postgres_ext.h:31
char ** attnames
Definition: pg_dump.h:304
DumpableObject dobj
Definition: pg_dump.h:261
bool ext_member
Definition: pg_dump.h:137
static DumpableObject ** buildIndexArray(void *objArray, int numObjs, Size objSize)
Definition: common.c:647
TSParserInfo * getTSParsers(Archive *fout, int *numTSParsers)
Definition: pg_dump.c:8321
static DumpableObject * findObjectByOid(Oid oid, DumpableObject **indexArray, int numObjs)
Definition: common.c:609
static int strInArray(const char *pattern, char **arr, int arr_size)
Definition: common.c:1020
static DumpableObject ** typinfoindex
Definition: common.c:51
OprInfo * findOprByOid(Oid oid)
Definition: common.c:792
bool separate
Definition: pg_dump.h:342
void getConstraints(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:6842
InhInfo * getInherits(Archive *fout, int *numInherits)
Definition: pg_dump.c:6405
ExtensionInfo * findOwningExtension(CatalogId catalogId)
Definition: common.c:852
static int numOperators
Definition: common.c:60
DumpOptions * dopt
Definition: pg_backup.h:181
void setExtensionMembership(ExtensionMemberId *extmems, int nextmems)
Definition: common.c:836
DumpableObject * findObjectByDumpId(DumpId dumpId)
Definition: common.c:540
TableInfo * getTables(Archive *fout, int *numTables)
Definition: pg_dump.c:5567
void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:3188
DumpableObject * findObjectByCatalogId(CatalogId catalogId)
Definition: common.c:558
EventTriggerInfo * getEventTriggers(Archive *fout, int *numEventTriggers)
Definition: pg_dump.c:7342
static DumpableObject ** tblinfoindex
Definition: common.c:50
NamespaceInfo * findNamespaceByOid(Oid oid)
Definition: common.c:814
NamespaceInfo * getNamespaces(Archive *fout, int *numNamespaces)
Definition: pg_dump.c:4142
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
bool * attisdropped
Definition: pg_dump.h:310
TableInfo * getSchemaData(Archive *fout, int *numTablesPtr)
Definition: common.c:86
static int numExtensions
Definition: common.c:63
TableInfo * adtable
Definition: pg_dump.h:339
static int numNamespaces
Definition: common.c:62
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
#define atooid(x)
Definition: postgres_ext.h:42
RuleInfo * getRules(Archive *fout, int *numRules)
Definition: pg_dump.c:7026
FuncInfo * findFuncByOid(Oid oid)
Definition: common.c:781
FdwInfo * getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
Definition: pg_dump.c:8661
void processExtensionTables(Archive *fout, ExtensionInfo extinfo[], int numExtensions)
Definition: pg_dump.c:17296
int numatts
Definition: pg_dump.h:303
void getSubscriptions(Archive *fout)
Definition: pg_dump.c:3763
void getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:6459
static int ExtensionMemberIdCompare(const void *p1, const void *p2)
Definition: common.c:890
TSDictInfo * getTSDictionaries(Archive *fout, int *numTSDicts)
Definition: pg_dump.c:8415
#define exit_nicely(code)
Definition: pg_dumpall.c:92
void parseOidArray(const char *str, Oid *array, int arraysize)
Definition: common.c:967
void getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:7142
Datum difference(PG_FUNCTION_ARGS)
static ExtensionMemberId * extmembers
Definition: common.c:66
ExtensionInfo * findExtensionByOid(Oid oid)
Definition: common.c:825
void removeObjectDependency(DumpableObject *dobj, DumpId refId)
Definition: common.c:739
void getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
Definition: pg_dump.c:7833
bool * notnull
Definition: pg_dump.h:318
DumpableObject dobj
Definition: pg_dump.h:338
#define InvalidOid
Definition: postgres_ext.h:36
DumpId getMaxDumpId(void)
Definition: common.c:529
#define free(a)
Definition: header.h:65
void getExtendedStatistics(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:6743
void getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:6354
void write_msg(const char *modulename, const char *fmt,...)
bool ispartition
Definition: pg_dump.h:297
ConvInfo * getConversions(Archive *fout, int *numConversions)
Definition: pg_dump.c:4823
#define NULL
Definition: c.h:229
static DumpableObject ** catalogIdMap
Definition: common.c:39
static bool catalogIdMapValid
Definition: common.c:38
CollInfo * findCollationByOid(Oid oid)
Definition: common.c:803
size_t Size
Definition: c.h:356
struct _attrDefInfo ** attrdefs
Definition: pg_dump.h:320
OpfamilyInfo * getOpfamilies(Archive *fout, int *numOpfamilies)
Definition: pg_dump.c:5054
TSTemplateInfo * getTSTemplates(Archive *fout, int *numTSTemplates)
Definition: pg_dump.c:8502
static int numCollations
Definition: common.c:61
ExtensionInfo * getExtensions(Archive *fout, int *numExtensions)
Definition: pg_dump.c:4314
static int numextmembers
Definition: common.c:67
TypeInfo * getTypes(Archive *fout, int *numTypes)
Definition: pg_dump.c:4401
void addObjectDependency(DumpableObject *dobj, DumpId refId)
Definition: common.c:712
static DumpableObject ** extinfoindex
Definition: common.c:56
void getPublications(Archive *fout)
Definition: pg_dump.c:3451
ForeignServerInfo * getForeignServers(Archive *fout, int *numForeignServers)
Definition: pg_dump.c:8830
static DumpableObject ** funinfoindex
Definition: common.c:52
CatalogId catId
Definition: pg_dump.h:131
#define DUMP_COMPONENT_ALL
Definition: pg_dump.h:99
CatalogId catId
Definition: pg_dump.h:620
#define RELKIND_VIEW
Definition: pg_class.h:164
int i
static DumpableObject ** nspinfoindex
Definition: common.c:55
ProcLangInfo * getProcLangs(Archive *fout, int *numProcLangs)
Definition: pg_dump.c:7436
TypeInfo * findTypeByOid(Oid oid)
Definition: common.c:770
void getExtensionMembership(Archive *fout, ExtensionInfo extinfo[], int numExtensions)
Definition: pg_dump.c:17188
int numParents
Definition: pg_dump.h:329
#define qsort(a, b, c, d)
Definition: port.h:443
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
DumpableObjectType objType
Definition: pg_dump.h:130
static void flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables)
Definition: common.c:370
bool g_verbose
Definition: pg_dump.c:91
int load_via_partition_root
Definition: pg_backup.h:160
DumpId createDumpId(void)
Definition: common.c:520
CastInfo * getCasts(Archive *fout, int *numCasts)
Definition: pg_dump.c:7617
char * adef_expr
Definition: pg_dump.h:341
void getDumpableObjects(DumpableObject ***objs, int *numObjs)
Definition: common.c:690