PostgreSQL Source Code  git master
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-2021, 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 <ctype.h>
19 
20 #include "catalog/pg_class_d.h"
21 #include "fe_utils/string_utils.h"
22 #include "pg_backup_archiver.h"
23 #include "pg_backup_utils.h"
24 #include "pg_dump.h"
25 
26 /*
27  * Variables for mapping DumpId to DumpableObject
28  */
29 static DumpableObject **dumpIdMap = NULL;
30 static int allocedDumpIds = 0;
31 static DumpId lastDumpId = 0; /* Note: 0 is InvalidDumpId */
32 
33 /*
34  * Variables for mapping CatalogId to DumpableObject
35  */
36 static bool catalogIdMapValid = false;
37 static DumpableObject **catalogIdMap = NULL;
38 static int numCatalogIds = 0;
39 
40 /*
41  * These variables are static to avoid the notational cruft of having to pass
42  * them into findTableByOid() and friends. For each of these arrays, we build
43  * a sorted-by-OID index array immediately after the objects are fetched,
44  * and then we use binary search in findTableByOid() and friends. (qsort'ing
45  * the object arrays themselves would be simpler, but it doesn't work because
46  * pg_dump.c may have already established pointers between items.)
47  */
56 static int numTables;
57 static int numTypes;
58 static int numFuncs;
59 static int numOperators;
60 static int numCollations;
61 static int numNamespaces;
62 static int numExtensions;
63 static int numPublications;
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 flagInhIndexes(Archive *fout, TableInfo *tblinfo, int numTables);
72 static void flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables);
73 static DumpableObject **buildIndexArray(void *objArray, int numObjs,
74  Size objSize);
75 static int DOCatalogIdCompare(const void *p1, const void *p2);
76 static int ExtensionMemberIdCompare(const void *p1, const void *p2);
77 static void findParentsByOid(TableInfo *self,
78  InhInfo *inhinfo, int numInherits);
79 static int strInArray(const char *pattern, char **arr, int arr_size);
80 static IndxInfo *findIndexByOid(Oid oid, DumpableObject **idxinfoindex,
81  int numIndexes);
82 
83 
84 /*
85  * getSchemaData
86  * Collect information about all potentially dumpable objects
87  */
88 TableInfo *
89 getSchemaData(Archive *fout, int *numTablesPtr)
90 {
91  TableInfo *tblinfo;
93  FuncInfo *funinfo;
94  OprInfo *oprinfo;
95  CollInfo *collinfo;
96  NamespaceInfo *nspinfo;
97  ExtensionInfo *extinfo;
98  PublicationInfo *pubinfo;
99  InhInfo *inhinfo;
100  int numAggregates;
101  int numInherits;
102  int numRules;
103  int numProcLangs;
104  int numCasts;
105  int numTransforms;
106  int numAccessMethods;
107  int numOpclasses;
108  int numOpfamilies;
109  int numConversions;
110  int numTSParsers;
111  int numTSTemplates;
112  int numTSDicts;
113  int numTSConfigs;
114  int numForeignDataWrappers;
115  int numForeignServers;
116  int numDefaultACLs;
117  int numEventTriggers;
118 
119  /*
120  * We must read extensions and extension membership info first, because
121  * extension membership needs to be consultable during decisions about
122  * whether other objects are to be dumped.
123  */
124  pg_log_info("reading extensions");
125  extinfo = getExtensions(fout, &numExtensions);
126  extinfoindex = buildIndexArray(extinfo, numExtensions, sizeof(ExtensionInfo));
127 
128  pg_log_info("identifying extension members");
129  getExtensionMembership(fout, extinfo, numExtensions);
130 
131  pg_log_info("reading schemas");
132  nspinfo = getNamespaces(fout, &numNamespaces);
133  nspinfoindex = buildIndexArray(nspinfo, numNamespaces, sizeof(NamespaceInfo));
134 
135  /*
136  * getTables should be done as soon as possible, so as to minimize the
137  * window between starting our transaction and acquiring per-table locks.
138  * However, we have to do getNamespaces first because the tables get
139  * linked to their containing namespaces during getTables.
140  */
141  pg_log_info("reading user-defined tables");
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  pg_log_info("reading user-defined functions");
149  funinfo = getFuncs(fout, &numFuncs);
150  funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo));
151 
152  /* this must be after getTables and getFuncs */
153  pg_log_info("reading user-defined types");
154  typinfo = getTypes(fout, &numTypes);
155  typinfoindex = buildIndexArray(typinfo, numTypes, sizeof(TypeInfo));
156 
157  /* this must be after getFuncs, too */
158  pg_log_info("reading procedural languages");
159  getProcLangs(fout, &numProcLangs);
160 
161  pg_log_info("reading user-defined aggregate functions");
162  getAggregates(fout, &numAggregates);
163 
164  pg_log_info("reading user-defined operators");
165  oprinfo = getOperators(fout, &numOperators);
166  oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo));
167 
168  pg_log_info("reading user-defined access methods");
169  getAccessMethods(fout, &numAccessMethods);
170 
171  pg_log_info("reading user-defined operator classes");
172  getOpclasses(fout, &numOpclasses);
173 
174  pg_log_info("reading user-defined operator families");
175  getOpfamilies(fout, &numOpfamilies);
176 
177  pg_log_info("reading user-defined text search parsers");
178  getTSParsers(fout, &numTSParsers);
179 
180  pg_log_info("reading user-defined text search templates");
181  getTSTemplates(fout, &numTSTemplates);
182 
183  pg_log_info("reading user-defined text search dictionaries");
184  getTSDictionaries(fout, &numTSDicts);
185 
186  pg_log_info("reading user-defined text search configurations");
187  getTSConfigurations(fout, &numTSConfigs);
188 
189  pg_log_info("reading user-defined foreign-data wrappers");
190  getForeignDataWrappers(fout, &numForeignDataWrappers);
191 
192  pg_log_info("reading user-defined foreign servers");
193  getForeignServers(fout, &numForeignServers);
194 
195  pg_log_info("reading default privileges");
196  getDefaultACLs(fout, &numDefaultACLs);
197 
198  pg_log_info("reading user-defined collations");
199  collinfo = getCollations(fout, &numCollations);
200  collinfoindex = buildIndexArray(collinfo, numCollations, sizeof(CollInfo));
201 
202  pg_log_info("reading user-defined conversions");
203  getConversions(fout, &numConversions);
204 
205  pg_log_info("reading type casts");
206  getCasts(fout, &numCasts);
207 
208  pg_log_info("reading transforms");
209  getTransforms(fout, &numTransforms);
210 
211  pg_log_info("reading table inheritance information");
212  inhinfo = getInherits(fout, &numInherits);
213 
214  pg_log_info("reading event triggers");
215  getEventTriggers(fout, &numEventTriggers);
216 
217  /* Identify extension configuration tables that should be dumped */
218  pg_log_info("finding extension tables");
219  processExtensionTables(fout, extinfo, numExtensions);
220 
221  /* Link tables to parents, mark parents of target tables interesting */
222  pg_log_info("finding inheritance relationships");
223  flagInhTables(fout, tblinfo, numTables, inhinfo, numInherits);
224 
225  pg_log_info("reading column info for interesting tables");
226  getTableAttrs(fout, tblinfo, numTables);
227 
228  pg_log_info("flagging inherited columns in subtables");
229  flagInhAttrs(fout->dopt, tblinfo, numTables);
230 
231  pg_log_info("reading indexes");
232  getIndexes(fout, tblinfo, numTables);
233 
234  pg_log_info("flagging indexes in partitioned tables");
235  flagInhIndexes(fout, tblinfo, numTables);
236 
237  pg_log_info("reading extended statistics");
238  getExtendedStatistics(fout);
239 
240  pg_log_info("reading constraints");
241  getConstraints(fout, tblinfo, numTables);
242 
243  pg_log_info("reading triggers");
244  getTriggers(fout, tblinfo, numTables);
245 
246  pg_log_info("reading rewrite rules");
247  getRules(fout, &numRules);
248 
249  pg_log_info("reading policies");
250  getPolicies(fout, tblinfo, numTables);
251 
252  pg_log_info("reading publications");
253  pubinfo = getPublications(fout, &numPublications);
254  pubinfoindex = buildIndexArray(pubinfo, numPublications,
255  sizeof(PublicationInfo));
256 
257  pg_log_info("reading publication membership");
258  getPublicationTables(fout, tblinfo, numTables);
259 
260  pg_log_info("reading subscriptions");
261  getSubscriptions(fout);
262 
263  *numTablesPtr = numTables;
264  return tblinfo;
265 }
266 
267 /* flagInhTables -
268  * Fill in parent link fields of tables for which we need that information,
269  * mark parents of target tables as interesting, and create
270  * TableAttachInfo objects for partitioned tables with appropriate
271  * dependency links.
272  *
273  * Note that only direct ancestors of targets are marked interesting.
274  * This is sufficient; we don't much care whether they inherited their
275  * attributes or not.
276  *
277  * modifies tblinfo
278  */
279 static void
281  InhInfo *inhinfo, int numInherits)
282 {
283  DumpOptions *dopt = fout->dopt;
284  int i,
285  j;
286 
287  for (i = 0; i < numTables; i++)
288  {
289  bool find_parents = true;
290  bool mark_parents = true;
291 
292  /* Some kinds never have parents */
293  if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
294  tblinfo[i].relkind == RELKIND_VIEW ||
295  tblinfo[i].relkind == RELKIND_MATVIEW)
296  continue;
297 
298  /*
299  * Normally, we don't bother computing anything for non-target tables,
300  * but if load-via-partition-root is specified, we gather information
301  * on every partition in the system so that getRootTableInfo can trace
302  * from any given to leaf partition all the way up to the root. (We
303  * don't need to mark them as interesting for getTableAttrs, though.)
304  */
305  if (!tblinfo[i].dobj.dump)
306  {
307  mark_parents = false;
308 
309  if (!dopt->load_via_partition_root ||
310  !tblinfo[i].ispartition)
311  find_parents = false;
312  }
313 
314  /* If needed, find all the immediate parent tables. */
315  if (find_parents)
316  findParentsByOid(&tblinfo[i], inhinfo, numInherits);
317 
318  /*
319  * If needed, mark the parents as interesting for getTableAttrs and
320  * getIndexes.
321  */
322  if (mark_parents)
323  {
324  int numParents = tblinfo[i].numParents;
325  TableInfo **parents = tblinfo[i].parents;
326 
327  for (j = 0; j < numParents; j++)
328  parents[j]->interesting = true;
329  }
330 
331  /* Create TableAttachInfo object if needed */
332  if (tblinfo[i].dobj.dump && tblinfo[i].ispartition)
333  {
334  TableAttachInfo *attachinfo;
335 
336  /* With partitions there can only be one parent */
337  if (tblinfo[i].numParents != 1)
338  fatal("invalid number of parents %d for table \"%s\"",
339  tblinfo[i].numParents,
340  tblinfo[i].dobj.name);
341 
342  attachinfo = (TableAttachInfo *) palloc(sizeof(TableAttachInfo));
343  attachinfo->dobj.objType = DO_TABLE_ATTACH;
344  attachinfo->dobj.catId.tableoid = 0;
345  attachinfo->dobj.catId.oid = 0;
346  AssignDumpId(&attachinfo->dobj);
347  attachinfo->dobj.name = pg_strdup(tblinfo[i].dobj.name);
348  attachinfo->dobj.namespace = tblinfo[i].dobj.namespace;
349  attachinfo->parentTbl = tblinfo[i].parents[0];
350  attachinfo->partitionTbl = &tblinfo[i];
351 
352  /*
353  * We must state the DO_TABLE_ATTACH object's dependencies
354  * explicitly, since it will not match anything in pg_depend.
355  *
356  * Give it dependencies on both the partition table and the parent
357  * table, so that it will not be executed till both of those
358  * exist. (There's no need to care what order those are created
359  * in.)
360  */
361  addObjectDependency(&attachinfo->dobj, tblinfo[i].dobj.dumpId);
362  addObjectDependency(&attachinfo->dobj, tblinfo[i].parents[0]->dobj.dumpId);
363  }
364  }
365 }
366 
367 /*
368  * flagInhIndexes -
369  * Create IndexAttachInfo objects for partitioned indexes, and add
370  * appropriate dependency links.
371  */
372 static void
374 {
375  int i,
376  j,
377  k;
378  DumpableObject ***parentIndexArray;
379 
380  parentIndexArray = (DumpableObject ***)
381  pg_malloc0(getMaxDumpId() * sizeof(DumpableObject **));
382 
383  for (i = 0; i < numTables; i++)
384  {
385  TableInfo *parenttbl;
386  IndexAttachInfo *attachinfo;
387 
388  if (!tblinfo[i].ispartition || tblinfo[i].numParents == 0)
389  continue;
390 
391  Assert(tblinfo[i].numParents == 1);
392  parenttbl = tblinfo[i].parents[0];
393 
394  /*
395  * We need access to each parent table's index list, but there is no
396  * index to cover them outside of this function. To avoid having to
397  * sort every parent table's indexes each time we come across each of
398  * its partitions, create an indexed array for each parent the first
399  * time it is required.
400  */
401  if (parentIndexArray[parenttbl->dobj.dumpId] == NULL)
402  parentIndexArray[parenttbl->dobj.dumpId] =
403  buildIndexArray(parenttbl->indexes,
404  parenttbl->numIndexes,
405  sizeof(IndxInfo));
406 
407  attachinfo = (IndexAttachInfo *)
408  pg_malloc0(tblinfo[i].numIndexes * sizeof(IndexAttachInfo));
409  for (j = 0, k = 0; j < tblinfo[i].numIndexes; j++)
410  {
411  IndxInfo *index = &(tblinfo[i].indexes[j]);
412  IndxInfo *parentidx;
413 
414  if (index->parentidx == 0)
415  continue;
416 
417  parentidx = findIndexByOid(index->parentidx,
418  parentIndexArray[parenttbl->dobj.dumpId],
419  parenttbl->numIndexes);
420  if (parentidx == NULL)
421  continue;
422 
423  attachinfo[k].dobj.objType = DO_INDEX_ATTACH;
424  attachinfo[k].dobj.catId.tableoid = 0;
425  attachinfo[k].dobj.catId.oid = 0;
426  AssignDumpId(&attachinfo[k].dobj);
427  attachinfo[k].dobj.name = pg_strdup(index->dobj.name);
428  attachinfo[k].dobj.namespace = index->indextable->dobj.namespace;
429  attachinfo[k].parentIdx = parentidx;
430  attachinfo[k].partitionIdx = index;
431 
432  /*
433  * We must state the DO_INDEX_ATTACH object's dependencies
434  * explicitly, since it will not match anything in pg_depend.
435  *
436  * Give it dependencies on both the partition index and the parent
437  * index, so that it will not be executed till both of those
438  * exist. (There's no need to care what order those are created
439  * in.)
440  *
441  * In addition, give it dependencies on the indexes' underlying
442  * tables. This does nothing of great value so far as serial
443  * restore ordering goes, but it ensures that a parallel restore
444  * will not try to run the ATTACH concurrently with other
445  * operations on those tables.
446  */
447  addObjectDependency(&attachinfo[k].dobj, index->dobj.dumpId);
448  addObjectDependency(&attachinfo[k].dobj, parentidx->dobj.dumpId);
449  addObjectDependency(&attachinfo[k].dobj,
450  index->indextable->dobj.dumpId);
451  addObjectDependency(&attachinfo[k].dobj,
452  parentidx->indextable->dobj.dumpId);
453 
454  /* keep track of the list of partitions in the parent index */
455  simple_ptr_list_append(&parentidx->partattaches, &attachinfo[k].dobj);
456 
457  k++;
458  }
459  }
460 
461  for (i = 0; i < numTables; i++)
462  if (parentIndexArray[i])
463  pg_free(parentIndexArray[i]);
464  pg_free(parentIndexArray);
465 }
466 
467 /* flagInhAttrs -
468  * for each dumpable table in tblinfo, flag its inherited attributes
469  *
470  * What we need to do here is:
471  *
472  * - Detect child columns that inherit NOT NULL bits from their parents, so
473  * that we needn't specify that again for the child.
474  *
475  * - Detect child columns that have DEFAULT NULL when their parents had some
476  * non-null default. In this case, we make up a dummy AttrDefInfo object so
477  * that we'll correctly emit the necessary DEFAULT NULL clause; otherwise
478  * the backend will apply an inherited default to the column.
479  *
480  * - Detect child columns that have a generation expression when their parents
481  * also have one. Generation expressions are always inherited, so there is
482  * no need to set them again in child tables, and there is no syntax for it
483  * either. Exceptions: If it's a partition or we are in binary upgrade
484  * mode, we dump them because in those cases inherited tables are recreated
485  * standalone first and then reattached to the parent. (See also the logic
486  * in dumpTableSchema().) In that situation, the generation expressions
487  * must match the parent, enforced by ALTER TABLE.
488  *
489  * modifies tblinfo
490  */
491 static void
493 {
494  int i,
495  j,
496  k;
497 
498  for (i = 0; i < numTables; i++)
499  {
500  TableInfo *tbinfo = &(tblinfo[i]);
501  int numParents;
502  TableInfo **parents;
503 
504  /* Some kinds never have parents */
505  if (tbinfo->relkind == RELKIND_SEQUENCE ||
506  tbinfo->relkind == RELKIND_VIEW ||
507  tbinfo->relkind == RELKIND_MATVIEW)
508  continue;
509 
510  /* Don't bother computing anything for non-target tables, either */
511  if (!tbinfo->dobj.dump)
512  continue;
513 
514  numParents = tbinfo->numParents;
515  parents = tbinfo->parents;
516 
517  if (numParents == 0)
518  continue; /* nothing to see here, move along */
519 
520  /* For each column, search for matching column names in parent(s) */
521  for (j = 0; j < tbinfo->numatts; j++)
522  {
523  bool foundNotNull; /* Attr was NOT NULL in a parent */
524  bool foundDefault; /* Found a default in a parent */
525  bool foundGenerated; /* Found a generated in a parent */
526 
527  /* no point in examining dropped columns */
528  if (tbinfo->attisdropped[j])
529  continue;
530 
531  foundNotNull = false;
532  foundDefault = false;
533  foundGenerated = false;
534  for (k = 0; k < numParents; k++)
535  {
536  TableInfo *parent = parents[k];
537  int inhAttrInd;
538 
539  inhAttrInd = strInArray(tbinfo->attnames[j],
540  parent->attnames,
541  parent->numatts);
542  if (inhAttrInd >= 0)
543  {
544  foundNotNull |= parent->notnull[inhAttrInd];
545  foundDefault |= (parent->attrdefs[inhAttrInd] != NULL && !parent->attgenerated[inhAttrInd]);
546  foundGenerated |= parent->attgenerated[inhAttrInd];
547  }
548  }
549 
550  /* Remember if we found inherited NOT NULL */
551  tbinfo->inhNotNull[j] = foundNotNull;
552 
553  /* Manufacture a DEFAULT NULL clause if necessary */
554  if (foundDefault && tbinfo->attrdefs[j] == NULL)
555  {
556  AttrDefInfo *attrDef;
557 
558  attrDef = (AttrDefInfo *) pg_malloc(sizeof(AttrDefInfo));
559  attrDef->dobj.objType = DO_ATTRDEF;
560  attrDef->dobj.catId.tableoid = 0;
561  attrDef->dobj.catId.oid = 0;
562  AssignDumpId(&attrDef->dobj);
563  attrDef->dobj.name = pg_strdup(tbinfo->dobj.name);
564  attrDef->dobj.namespace = tbinfo->dobj.namespace;
565  attrDef->dobj.dump = tbinfo->dobj.dump;
566 
567  attrDef->adtable = tbinfo;
568  attrDef->adnum = j + 1;
569  attrDef->adef_expr = pg_strdup("NULL");
570 
571  /* Will column be dumped explicitly? */
572  if (shouldPrintColumn(dopt, tbinfo, j))
573  {
574  attrDef->separate = false;
575  /* No dependency needed: NULL cannot have dependencies */
576  }
577  else
578  {
579  /* column will be suppressed, print default separately */
580  attrDef->separate = true;
581  /* ensure it comes out after the table */
582  addObjectDependency(&attrDef->dobj,
583  tbinfo->dobj.dumpId);
584  }
585 
586  tbinfo->attrdefs[j] = attrDef;
587  }
588 
589  /* Remove generation expression from child */
590  if (foundGenerated && !tbinfo->ispartition && !dopt->binary_upgrade)
591  tbinfo->attrdefs[j] = NULL;
592  }
593  }
594 }
595 
596 /*
597  * AssignDumpId
598  * Given a newly-created dumpable object, assign a dump ID,
599  * and enter the object into the lookup table.
600  *
601  * The caller is expected to have filled in objType and catId,
602  * but not any of the other standard fields of a DumpableObject.
603  */
604 void
606 {
607  dobj->dumpId = ++lastDumpId;
608  dobj->name = NULL; /* must be set later */
609  dobj->namespace = NULL; /* may be set later */
610  dobj->dump = DUMP_COMPONENT_ALL; /* default assumption */
611  dobj->dump_contains = DUMP_COMPONENT_ALL; /* default assumption */
612  dobj->ext_member = false; /* default assumption */
613  dobj->depends_on_ext = false; /* default assumption */
614  dobj->dependencies = NULL;
615  dobj->nDeps = 0;
616  dobj->allocDeps = 0;
617 
618  while (dobj->dumpId >= allocedDumpIds)
619  {
620  int newAlloc;
621 
622  if (allocedDumpIds <= 0)
623  {
624  newAlloc = 256;
625  dumpIdMap = (DumpableObject **)
626  pg_malloc(newAlloc * sizeof(DumpableObject *));
627  }
628  else
629  {
630  newAlloc = allocedDumpIds * 2;
631  dumpIdMap = (DumpableObject **)
632  pg_realloc(dumpIdMap, newAlloc * sizeof(DumpableObject *));
633  }
634  memset(dumpIdMap + allocedDumpIds, 0,
635  (newAlloc - allocedDumpIds) * sizeof(DumpableObject *));
636  allocedDumpIds = newAlloc;
637  }
638  dumpIdMap[dobj->dumpId] = dobj;
639 
640  /* mark catalogIdMap invalid, but don't rebuild it yet */
641  catalogIdMapValid = false;
642 }
643 
644 /*
645  * Assign a DumpId that's not tied to a DumpableObject.
646  *
647  * This is used when creating a "fixed" ArchiveEntry that doesn't need to
648  * participate in the sorting logic.
649  */
650 DumpId
652 {
653  return ++lastDumpId;
654 }
655 
656 /*
657  * Return the largest DumpId so far assigned
658  */
659 DumpId
661 {
662  return lastDumpId;
663 }
664 
665 /*
666  * Find a DumpableObject by dump ID
667  *
668  * Returns NULL for invalid ID
669  */
672 {
673  if (dumpId <= 0 || dumpId >= allocedDumpIds)
674  return NULL; /* out of range? */
675  return dumpIdMap[dumpId];
676 }
677 
678 /*
679  * Find a DumpableObject by catalog ID
680  *
681  * Returns NULL for unknown ID
682  *
683  * We use binary search in a sorted list that is built on first call.
684  * If AssignDumpId() and findObjectByCatalogId() calls were freely intermixed,
685  * the code would work, but possibly be very slow. In the current usage
686  * pattern that does not happen, indeed we build the list at most twice.
687  */
690 {
691  DumpableObject **low;
692  DumpableObject **high;
693 
694  if (!catalogIdMapValid)
695  {
696  if (catalogIdMap)
697  free(catalogIdMap);
698  getDumpableObjects(&catalogIdMap, &numCatalogIds);
699  if (numCatalogIds > 1)
700  qsort((void *) catalogIdMap, numCatalogIds,
702  catalogIdMapValid = true;
703  }
704 
705  /*
706  * We could use bsearch() here, but the notational cruft of calling
707  * bsearch is nearly as bad as doing it ourselves; and the generalized
708  * bsearch function is noticeably slower as well.
709  */
710  if (numCatalogIds <= 0)
711  return NULL;
712  low = catalogIdMap;
713  high = catalogIdMap + (numCatalogIds - 1);
714  while (low <= high)
715  {
716  DumpableObject **middle;
717  int difference;
718 
719  middle = low + (high - low) / 2;
720  /* comparison must match DOCatalogIdCompare, below */
721  difference = oidcmp((*middle)->catId.oid, catalogId.oid);
722  if (difference == 0)
723  difference = oidcmp((*middle)->catId.tableoid, catalogId.tableoid);
724  if (difference == 0)
725  return *middle;
726  else if (difference < 0)
727  low = middle + 1;
728  else
729  high = middle - 1;
730  }
731  return NULL;
732 }
733 
734 /*
735  * Find a DumpableObject by OID, in a pre-sorted array of one type of object
736  *
737  * Returns NULL for unknown OID
738  */
739 static DumpableObject *
740 findObjectByOid(Oid oid, DumpableObject **indexArray, int numObjs)
741 {
742  DumpableObject **low;
743  DumpableObject **high;
744 
745  /*
746  * This is the same as findObjectByCatalogId except we assume we need not
747  * look at table OID because the objects are all the same type.
748  *
749  * We could use bsearch() here, but the notational cruft of calling
750  * bsearch is nearly as bad as doing it ourselves; and the generalized
751  * bsearch function is noticeably slower as well.
752  */
753  if (numObjs <= 0)
754  return NULL;
755  low = indexArray;
756  high = indexArray + (numObjs - 1);
757  while (low <= high)
758  {
759  DumpableObject **middle;
760  int difference;
761 
762  middle = low + (high - low) / 2;
763  difference = oidcmp((*middle)->catId.oid, oid);
764  if (difference == 0)
765  return *middle;
766  else if (difference < 0)
767  low = middle + 1;
768  else
769  high = middle - 1;
770  }
771  return NULL;
772 }
773 
774 /*
775  * Build an index array of DumpableObject pointers, sorted by OID
776  */
777 static DumpableObject **
778 buildIndexArray(void *objArray, int numObjs, Size objSize)
779 {
780  DumpableObject **ptrs;
781  int i;
782 
783  if (numObjs <= 0)
784  return NULL;
785 
786  ptrs = (DumpableObject **) pg_malloc(numObjs * sizeof(DumpableObject *));
787  for (i = 0; i < numObjs; i++)
788  ptrs[i] = (DumpableObject *) ((char *) objArray + i * objSize);
789 
790  /* We can use DOCatalogIdCompare to sort since its first key is OID */
791  if (numObjs > 1)
792  qsort((void *) ptrs, numObjs, sizeof(DumpableObject *),
794 
795  return ptrs;
796 }
797 
798 /*
799  * qsort comparator for pointers to DumpableObjects
800  */
801 static int
802 DOCatalogIdCompare(const void *p1, const void *p2)
803 {
804  const DumpableObject *obj1 = *(DumpableObject *const *) p1;
805  const DumpableObject *obj2 = *(DumpableObject *const *) p2;
806  int cmpval;
807 
808  /*
809  * Compare OID first since it's usually unique, whereas there will only be
810  * a few distinct values of tableoid.
811  */
812  cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid);
813  if (cmpval == 0)
814  cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid);
815  return cmpval;
816 }
817 
818 /*
819  * Build an array of pointers to all known dumpable objects
820  *
821  * This simply creates a modifiable copy of the internal map.
822  */
823 void
824 getDumpableObjects(DumpableObject ***objs, int *numObjs)
825 {
826  int i,
827  j;
828 
829  *objs = (DumpableObject **)
831  j = 0;
832  for (i = 1; i < allocedDumpIds; i++)
833  {
834  if (dumpIdMap[i])
835  (*objs)[j++] = dumpIdMap[i];
836  }
837  *numObjs = j;
838 }
839 
840 /*
841  * Add a dependency link to a DumpableObject
842  *
843  * Note: duplicate dependencies are currently not eliminated
844  */
845 void
847 {
848  if (dobj->nDeps >= dobj->allocDeps)
849  {
850  if (dobj->allocDeps <= 0)
851  {
852  dobj->allocDeps = 16;
853  dobj->dependencies = (DumpId *)
854  pg_malloc(dobj->allocDeps * sizeof(DumpId));
855  }
856  else
857  {
858  dobj->allocDeps *= 2;
859  dobj->dependencies = (DumpId *)
860  pg_realloc(dobj->dependencies,
861  dobj->allocDeps * sizeof(DumpId));
862  }
863  }
864  dobj->dependencies[dobj->nDeps++] = refId;
865 }
866 
867 /*
868  * Remove a dependency link from a DumpableObject
869  *
870  * If there are multiple links, all are removed
871  */
872 void
874 {
875  int i;
876  int j = 0;
877 
878  for (i = 0; i < dobj->nDeps; i++)
879  {
880  if (dobj->dependencies[i] != refId)
881  dobj->dependencies[j++] = dobj->dependencies[i];
882  }
883  dobj->nDeps = j;
884 }
885 
886 
887 /*
888  * findTableByOid
889  * finds the entry (in tblinfo) of the table with the given oid
890  * returns NULL if not found
891  */
892 TableInfo *
894 {
895  return (TableInfo *) findObjectByOid(oid, tblinfoindex, numTables);
896 }
897 
898 /*
899  * findTypeByOid
900  * finds the entry (in typinfo) of the type with the given oid
901  * returns NULL if not found
902  */
903 TypeInfo *
905 {
906  return (TypeInfo *) findObjectByOid(oid, typinfoindex, numTypes);
907 }
908 
909 /*
910  * findFuncByOid
911  * finds the entry (in funinfo) of the function with the given oid
912  * returns NULL if not found
913  */
914 FuncInfo *
916 {
917  return (FuncInfo *) findObjectByOid(oid, funinfoindex, numFuncs);
918 }
919 
920 /*
921  * findOprByOid
922  * finds the entry (in oprinfo) of the operator with the given oid
923  * returns NULL if not found
924  */
925 OprInfo *
927 {
928  return (OprInfo *) findObjectByOid(oid, oprinfoindex, numOperators);
929 }
930 
931 /*
932  * findCollationByOid
933  * finds the entry (in collinfo) of the collation with the given oid
934  * returns NULL if not found
935  */
936 CollInfo *
938 {
939  return (CollInfo *) findObjectByOid(oid, collinfoindex, numCollations);
940 }
941 
942 /*
943  * findNamespaceByOid
944  * finds the entry (in nspinfo) of the namespace with the given oid
945  * returns NULL if not found
946  */
949 {
950  return (NamespaceInfo *) findObjectByOid(oid, nspinfoindex, numNamespaces);
951 }
952 
953 /*
954  * findExtensionByOid
955  * finds the entry (in extinfo) of the extension with the given oid
956  * returns NULL if not found
957  */
960 {
961  return (ExtensionInfo *) findObjectByOid(oid, extinfoindex, numExtensions);
962 }
963 
964 /*
965  * findPublicationByOid
966  * finds the entry (in pubinfo) of the publication with the given oid
967  * returns NULL if not found
968  */
971 {
972  return (PublicationInfo *) findObjectByOid(oid, pubinfoindex, numPublications);
973 }
974 
975 /*
976  * findIndexByOid
977  * find the entry of the index with the given oid
978  *
979  * This one's signature is different from the previous ones because we lack a
980  * global array of all indexes, so caller must pass their array as argument.
981  */
982 static IndxInfo *
983 findIndexByOid(Oid oid, DumpableObject **idxinfoindex, int numIndexes)
984 {
985  return (IndxInfo *) findObjectByOid(oid, idxinfoindex, numIndexes);
986 }
987 
988 /*
989  * setExtensionMembership
990  * accept and save data about which objects belong to extensions
991  */
992 void
994 {
995  /* Sort array in preparation for binary searches */
996  if (nextmems > 1)
997  qsort((void *) extmems, nextmems, sizeof(ExtensionMemberId),
999  /* And save */
1000  extmembers = extmems;
1001  numextmembers = nextmems;
1002 }
1003 
1004 /*
1005  * findOwningExtension
1006  * return owning extension for specified catalog ID, or NULL if none
1007  */
1008 ExtensionInfo *
1010 {
1011  ExtensionMemberId *low;
1012  ExtensionMemberId *high;
1013 
1014  /*
1015  * We could use bsearch() here, but the notational cruft of calling
1016  * bsearch is nearly as bad as doing it ourselves; and the generalized
1017  * bsearch function is noticeably slower as well.
1018  */
1019  if (numextmembers <= 0)
1020  return NULL;
1021  low = extmembers;
1022  high = extmembers + (numextmembers - 1);
1023  while (low <= high)
1024  {
1025  ExtensionMemberId *middle;
1026  int difference;
1027 
1028  middle = low + (high - low) / 2;
1029  /* comparison must match ExtensionMemberIdCompare, below */
1030  difference = oidcmp(middle->catId.oid, catalogId.oid);
1031  if (difference == 0)
1032  difference = oidcmp(middle->catId.tableoid, catalogId.tableoid);
1033  if (difference == 0)
1034  return middle->ext;
1035  else if (difference < 0)
1036  low = middle + 1;
1037  else
1038  high = middle - 1;
1039  }
1040  return NULL;
1041 }
1042 
1043 /*
1044  * qsort comparator for ExtensionMemberIds
1045  */
1046 static int
1047 ExtensionMemberIdCompare(const void *p1, const void *p2)
1048 {
1049  const ExtensionMemberId *obj1 = (const ExtensionMemberId *) p1;
1050  const ExtensionMemberId *obj2 = (const ExtensionMemberId *) p2;
1051  int cmpval;
1052 
1053  /*
1054  * Compare OID first since it's usually unique, whereas there will only be
1055  * a few distinct values of tableoid.
1056  */
1057  cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid);
1058  if (cmpval == 0)
1059  cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid);
1060  return cmpval;
1061 }
1062 
1063 
1064 /*
1065  * findParentsByOid
1066  * find a table's parents in tblinfo[]
1067  */
1068 static void
1070  InhInfo *inhinfo, int numInherits)
1071 {
1072  Oid oid = self->dobj.catId.oid;
1073  int i,
1074  j;
1075  int numParents;
1076 
1077  numParents = 0;
1078  for (i = 0; i < numInherits; i++)
1079  {
1080  if (inhinfo[i].inhrelid == oid)
1081  numParents++;
1082  }
1083 
1084  self->numParents = numParents;
1085 
1086  if (numParents > 0)
1087  {
1088  self->parents = (TableInfo **)
1089  pg_malloc(sizeof(TableInfo *) * numParents);
1090  j = 0;
1091  for (i = 0; i < numInherits; i++)
1092  {
1093  if (inhinfo[i].inhrelid == oid)
1094  {
1095  TableInfo *parent;
1096 
1097  parent = findTableByOid(inhinfo[i].inhparent);
1098  if (parent == NULL)
1099  {
1100  pg_log_error("failed sanity check, parent OID %u of table \"%s\" (OID %u) not found",
1101  inhinfo[i].inhparent,
1102  self->dobj.name,
1103  oid);
1104  exit_nicely(1);
1105  }
1106  self->parents[j++] = parent;
1107  }
1108  }
1109  }
1110  else
1111  self->parents = NULL;
1112 }
1113 
1114 /*
1115  * parseOidArray
1116  * parse a string of numbers delimited by spaces into a character array
1117  *
1118  * Note: actually this is used for both Oids and potentially-signed
1119  * attribute numbers. This should cause no trouble, but we could split
1120  * the function into two functions with different argument types if it does.
1121  */
1122 
1123 void
1124 parseOidArray(const char *str, Oid *array, int arraysize)
1125 {
1126  int j,
1127  argNum;
1128  char temp[100];
1129  char s;
1130 
1131  argNum = 0;
1132  j = 0;
1133  for (;;)
1134  {
1135  s = *str++;
1136  if (s == ' ' || s == '\0')
1137  {
1138  if (j > 0)
1139  {
1140  if (argNum >= arraysize)
1141  {
1142  pg_log_error("could not parse numeric array \"%s\": too many numbers", str);
1143  exit_nicely(1);
1144  }
1145  temp[j] = '\0';
1146  array[argNum++] = atooid(temp);
1147  j = 0;
1148  }
1149  if (s == '\0')
1150  break;
1151  }
1152  else
1153  {
1154  if (!(isdigit((unsigned char) s) || s == '-') ||
1155  j >= sizeof(temp) - 1)
1156  {
1157  pg_log_error("could not parse numeric array \"%s\": invalid character in number", str);
1158  exit_nicely(1);
1159  }
1160  temp[j++] = s;
1161  }
1162  }
1163 
1164  while (argNum < arraysize)
1165  array[argNum++] = InvalidOid;
1166 }
1167 
1168 
1169 /*
1170  * strInArray:
1171  * takes in a string and a string array and the number of elements in the
1172  * string array.
1173  * returns the index if the string is somewhere in the array, -1 otherwise
1174  */
1175 
1176 static int
1177 strInArray(const char *pattern, char **arr, int arr_size)
1178 {
1179  int i;
1180 
1181  for (i = 0; i < arr_size; i++)
1182  {
1183  if (strcmp(pattern, arr[i]) == 0)
1184  return i;
1185  }
1186  return -1;
1187 }
FuncInfo * getFuncs(Archive *fout, int *numFuncs)
Definition: pg_dump.c:5988
static DumpableObject ** collinfoindex
Definition: common.c:52
static int numTypes
Definition: common.c:57
char * name
Definition: pg_dump.h:131
TableInfo * findTableByOid(Oid oid)
Definition: common.c:893
ExtensionInfo * ext
Definition: pg_dump.h:657
int DumpId
Definition: pg_backup.h:243
AggInfo * getAggregates(Archive *fout, int *numAggs)
Definition: pg_dump.c:5795
struct _tableInfo ** parents
Definition: pg_dump.h:339
static int allocedDumpIds
Definition: common.c:30
void getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:4134
TableInfo * partitionTbl
Definition: pg_dump.h:351
CollInfo * getCollations(Archive *fout, int *numCollations)
Definition: pg_dump.c:5413
char relkind
Definition: pg_dump.h:271
DumpComponents dump
Definition: pg_dump.h:132
static DumpId lastDumpId
Definition: common.c:31
Oid tableoid
Definition: pg_backup.h:239
static DumpableObject ** dumpIdMap
Definition: common.c:29
#define oidcmp(x, y)
Definition: pg_dump.h:20
void AssignDumpId(DumpableObject *dobj)
Definition: common.c:605
OprInfo * getOperators(Archive *fout, int *numOprs)
Definition: pg_dump.c:5331
static DumpableObject ** oprinfoindex
Definition: common.c:51
DumpId * dependencies
Definition: pg_dump.h:137
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
static DumpableObject ** pubinfoindex
Definition: common.c:55
TransformInfo * getTransforms(Archive *fout, int *numTransforms)
Definition: pg_dump.c:8597
DefaultACLInfo * getDefaultACLs(Archive *fout, int *numDefaultACLs)
Definition: pg_dump.c:9830
#define pg_log_error(...)
Definition: logging.h:80
static void flagInhTables(Archive *fout, TableInfo *tbinfo, int numTables, InhInfo *inhinfo, int numInherits)
Definition: common.c:280
static int numFuncs
Definition: common.c:58
AccessMethodInfo * getAccessMethods(Archive *fout, int *numAccessMethods)
Definition: pg_dump.c:5564
static int DOCatalogIdCompare(const void *p1, const void *p2)
Definition: common.c:802
static int numCatalogIds
Definition: common.c:38
OpclassInfo * getOpclasses(Archive *fout, int *numOpclasses)
Definition: pg_dump.c:5638
bool * inhNotNull
Definition: pg_dump.h:327
TSConfigInfo * getTSConfigurations(Archive *fout, int *numTSConfigs)
Definition: pg_dump.c:9438
static void findParentsByOid(TableInfo *self, InhInfo *inhinfo, int numInherits)
Definition: common.c:1069
DumpId dumpId
Definition: pg_dump.h:130
static int numTables
Definition: common.c:56
unsigned int Oid
Definition: postgres_ext.h:31
char ** attnames
Definition: pg_dump.h:309
DumpableObject dobj
Definition: pg_dump.h:265
bool ext_member
Definition: pg_dump.h:135
Oid parentidx
Definition: pg_dump.h:385
static DumpableObject ** buildIndexArray(void *objArray, int numObjs, Size objSize)
Definition: common.c:778
TSParserInfo * getTSParsers(Archive *fout, int *numTSParsers)
Definition: pg_dump.c:9190
static DumpableObject * findObjectByOid(Oid oid, DumpableObject **indexArray, int numObjs)
Definition: common.c:740
Definition: type.h:89
static int strInArray(const char *pattern, char **arr, int arr_size)
Definition: common.c:1177
DumpableObject dobj
Definition: pg_dump.h:394
static DumpableObject ** typinfoindex
Definition: common.c:49
OprInfo * findOprByOid(Oid oid)
Definition: common.c:926
int binary_upgrade
Definition: pg_backup.h:143
bool separate
Definition: pg_dump.h:360
void getConstraints(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:7596
static void flagInhIndexes(Archive *fout, TableInfo *tblinfo, int numTables)
InhInfo * getInherits(Archive *fout, int *numInherits)
Definition: pg_dump.c:7118
DumpableObject dobj
Definition: pg_dump.h:349
ExtensionInfo * findOwningExtension(CatalogId catalogId)
Definition: common.c:1009
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
static int numOperators
Definition: common.c:59
DumpOptions * dopt
Definition: pg_backup.h:191
void setExtensionMembership(ExtensionMemberId *extmems, int nextmems)
Definition: common.c:993
DumpableObject * findObjectByDumpId(DumpId dumpId)
Definition: common.c:671
TableInfo * getTables(Archive *fout, int *numTables)
Definition: pg_dump.c:6222
TableInfo * indextable
Definition: pg_dump.h:373
void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:3663
DumpableObject * findObjectByCatalogId(CatalogId catalogId)
Definition: common.c:689
EventTriggerInfo * getEventTriggers(Archive *fout, int *numEventTriggers)
Definition: pg_dump.c:8199
static DumpableObject ** tblinfoindex
Definition: common.c:48
NamespaceInfo * findNamespaceByOid(Oid oid)
Definition: common.c:948
NamespaceInfo * getNamespaces(Archive *fout, int *numNamespaces)
Definition: pg_dump.c:4822
IndxInfo * partitionIdx
Definition: pg_dump.h:396
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
bool * attisdropped
Definition: pg_dump.h:315
static int numPublications
Definition: common.c:63
TableInfo * getSchemaData(Archive *fout, int *numTablesPtr)
Definition: common.c:89
static int numExtensions
Definition: common.c:62
DumpComponents dump_contains
Definition: pg_dump.h:134
TableInfo * adtable
Definition: pg_dump.h:357
static int numNamespaces
Definition: common.c:61
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:7843
TableInfo * parentTbl
Definition: pg_dump.h:350
FuncInfo * findFuncByOid(Oid oid)
Definition: common.c:915
FdwInfo * getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
Definition: pg_dump.c:9514
void processExtensionTables(Archive *fout, ExtensionInfo extinfo[], int numExtensions)
Definition: pg_dump.c:18301
static IndxInfo * findIndexByOid(Oid oid, DumpableObject **idxinfoindex, int numIndexes)
Definition: common.c:983
int numatts
Definition: pg_dump.h:308
void getSubscriptions(Archive *fout)
Definition: pg_dump.c:4281
void getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:7164
static int ExtensionMemberIdCompare(const void *p1, const void *p2)
Definition: common.c:1047
SimplePtrList partattaches
Definition: pg_dump.h:386
TSDictInfo * getTSDictionaries(Archive *fout, int *numTSDicts)
Definition: pg_dump.c:9280
#define exit_nicely(code)
Definition: pg_dumpall.c:97
void parseOidArray(const char *str, Oid *array, int arraysize)
Definition: common.c:1124
void getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:7956
Datum difference(PG_FUNCTION_ARGS)
int numIndexes
Definition: pg_dump.h:340
static ExtensionMemberId * extmembers
Definition: common.c:66
ExtensionInfo * findExtensionByOid(Oid oid)
Definition: common.c:959
void removeObjectDependency(DumpableObject *dobj, DumpId refId)
Definition: common.c:873
void getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
Definition: pg_dump.c:8694
PublicationInfo * getPublications(Archive *fout, int *numPublications)
Definition: pg_dump.c:3930
bool depends_on_ext
Definition: pg_dump.h:136
bool * notnull
Definition: pg_dump.h:326
DumpableObject dobj
Definition: pg_dump.h:356
#define InvalidOid
Definition: postgres_ext.h:36
DumpId getMaxDumpId(void)
Definition: common.c:660
#define free(a)
Definition: header.h:65
void getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:7055
bool ispartition
Definition: pg_dump.h:302
ConvInfo * getConversions(Archive *fout, int *numConversions)
Definition: pg_dump.c:5492
static DumpableObject ** catalogIdMap
Definition: common.c:37
#define Assert(condition)
Definition: c.h:804
IndxInfo * parentIdx
Definition: pg_dump.h:395
static bool catalogIdMapValid
Definition: common.c:36
CollInfo * findCollationByOid(Oid oid)
Definition: common.c:937
size_t Size
Definition: c.h:540
struct _attrDefInfo ** attrdefs
Definition: pg_dump.h:328
OpfamilyInfo * getOpfamilies(Archive *fout, int *numOpfamilies)
Definition: pg_dump.c:5712
TSTemplateInfo * getTSTemplates(Archive *fout, int *numTSTemplates)
Definition: pg_dump.c:9363
static int numCollations
Definition: common.c:60
#define fatal(...)
void pg_free(void *ptr)
Definition: fe_memutils.c:105
void getExtendedStatistics(Archive *fout)
Definition: pg_dump.c:7519
ExtensionInfo * getExtensions(Archive *fout, int *numExtensions)
Definition: pg_dump.c:4992
static int numextmembers
Definition: common.c:67
TypeInfo * getTypes(Archive *fout, int *numTypes)
Definition: pg_dump.c:5076
void addObjectDependency(DumpableObject *dobj, DumpId refId)
Definition: common.c:846
static DumpableObject ** extinfoindex
Definition: common.c:54
ForeignServerInfo * getForeignServers(Archive *fout, int *numForeignServers)
Definition: pg_dump.c:9680
static DumpableObject ** funinfoindex
Definition: common.c:50
struct _indxInfo * indexes
Definition: pg_dump.h:341
CatalogId catId
Definition: pg_dump.h:129
#define DUMP_COMPONENT_ALL
Definition: pg_dump.h:97
void * palloc(Size size)
Definition: mcxt.c:1062
DumpableObject dobj
Definition: pg_dump.h:372
CatalogId catId
Definition: pg_dump.h:656
void simple_ptr_list_append(SimplePtrList *list, void *ptr)
Definition: simple_list.c:162
int i
PublicationInfo * findPublicationByOid(Oid oid)
Definition: common.c:970
static DumpableObject ** nspinfoindex
Definition: common.c:53
ProcLangInfo * getProcLangs(Archive *fout, int *numProcLangs)
Definition: pg_dump.c:8290
TypeInfo * findTypeByOid(Oid oid)
Definition: common.c:904
void getExtensionMembership(Archive *fout, ExtensionInfo extinfo[], int numExtensions)
Definition: pg_dump.c:18196
int numParents
Definition: pg_dump.h:338
#define qsort(a, b, c, d)
Definition: port.h:504
char * attgenerated
Definition: pg_dump.h:317
DumpableObjectType objType
Definition: pg_dump.h:128
static void flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables)
Definition: common.c:492
bool shouldPrintColumn(const DumpOptions *dopt, const TableInfo *tbinfo, int colno)
Definition: pg_dump.c:9172
#define pg_log_info(...)
Definition: logging.h:88
int load_via_partition_root
Definition: pg_backup.h:169
DumpId createDumpId(void)
Definition: common.c:651
CastInfo * getCasts(Archive *fout, int *numCasts)
Definition: pg_dump.c:8471
char * adef_expr
Definition: pg_dump.h:359
void getDumpableObjects(DumpableObject ***objs, int *numObjs)
Definition: common.c:824