PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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-2025, 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 "catalog/pg_collation_d.h"
22#include "catalog/pg_extension_d.h"
23#include "catalog/pg_namespace_d.h"
24#include "catalog/pg_operator_d.h"
25#include "catalog/pg_proc_d.h"
26#include "catalog/pg_publication_d.h"
27#include "catalog/pg_subscription_d.h"
28#include "catalog/pg_type_d.h"
29#include "common/hashfn.h"
30#include "pg_backup_utils.h"
31#include "pg_dump.h"
32
33/*
34 * Variables for mapping DumpId to DumpableObject
35 */
36static DumpableObject **dumpIdMap = NULL;
37static int allocedDumpIds = 0;
38static DumpId lastDumpId = 0; /* Note: 0 is InvalidDumpId */
39
40/*
41 * Infrastructure for mapping CatalogId to DumpableObject
42 *
43 * We use a hash table generated by simplehash.h. That infrastructure
44 * requires all the hash table entries to be the same size, and it also
45 * expects that it can move them around when resizing the table. So we
46 * cannot make the DumpableObjects be elements of the hash table directly;
47 * instead, the hash table elements contain pointers to DumpableObjects.
48 * This does have the advantage of letting us map multiple CatalogIds
49 * to one DumpableObject, which is useful for blobs.
50 *
51 * It turns out to be convenient to also use this data structure to map
52 * CatalogIds to owning extensions, if any. Since extension membership
53 * data is read before creating most DumpableObjects, either one of dobj
54 * and ext could be NULL.
55 */
56typedef struct _catalogIdMapEntry
57{
58 CatalogId catId; /* the indexed CatalogId */
59 uint32 status; /* hash status */
60 uint32 hashval; /* hash code for the CatalogId */
61 DumpableObject *dobj; /* the associated DumpableObject, if any */
62 ExtensionInfo *ext; /* owning extension, if any */
64
65#define SH_PREFIX catalogid
66#define SH_ELEMENT_TYPE CatalogIdMapEntry
67#define SH_KEY_TYPE CatalogId
68#define SH_KEY catId
69#define SH_HASH_KEY(tb, key) hash_bytes((const unsigned char *) &(key), sizeof(CatalogId))
70#define SH_EQUAL(tb, a, b) ((a).oid == (b).oid && (a).tableoid == (b).tableoid)
71#define SH_STORE_HASH
72#define SH_GET_HASH(tb, a) (a)->hashval
73#define SH_SCOPE static inline
74#define SH_RAW_ALLOCATOR pg_malloc0
75#define SH_DECLARE
76#define SH_DEFINE
77#include "lib/simplehash.h"
78
79#define CATALOGIDHASH_INITIAL_SIZE 10000
80
81static catalogid_hash *catalogIdHash = NULL;
82
83static void flagInhTables(Archive *fout, TableInfo *tblinfo, int numTables,
84 InhInfo *inhinfo, int numInherits);
85static void flagInhIndexes(Archive *fout, TableInfo *tblinfo, int numTables);
86static void flagInhAttrs(Archive *fout, DumpOptions *dopt, TableInfo *tblinfo,
87 int numTables);
88static int strInArray(const char *pattern, char **arr, int arr_size);
89static IndxInfo *findIndexByOid(Oid oid);
90
91
92/*
93 * getSchemaData
94 * Collect information about all potentially dumpable objects
95 */
97getSchemaData(Archive *fout, int *numTablesPtr)
98{
99 TableInfo *tblinfo;
100 ExtensionInfo *extinfo;
101 InhInfo *inhinfo;
102 int numTables;
103 int numExtensions;
104 int numInherits;
105
106 /*
107 * We must read extensions and extension membership info first, because
108 * extension membership needs to be consultable during decisions about
109 * whether other objects are to be dumped.
110 */
111 pg_log_info("reading extensions");
112 extinfo = getExtensions(fout, &numExtensions);
113
114 pg_log_info("identifying extension members");
115 getExtensionMembership(fout, extinfo, numExtensions);
116
117 pg_log_info("reading schemas");
118 getNamespaces(fout);
119
120 /*
121 * getTables should be done as soon as possible, so as to minimize the
122 * window between starting our transaction and acquiring per-table locks.
123 * However, we have to do getNamespaces first because the tables get
124 * linked to their containing namespaces during getTables.
125 */
126 pg_log_info("reading user-defined tables");
127 tblinfo = getTables(fout, &numTables);
128
129 getOwnedSeqs(fout, tblinfo, numTables);
130
131 pg_log_info("reading user-defined functions");
132 getFuncs(fout);
133
134 /* this must be after getTables and getFuncs */
135 pg_log_info("reading user-defined types");
136 getTypes(fout);
137
138 /* this must be after getFuncs, too */
139 pg_log_info("reading procedural languages");
140 getProcLangs(fout);
141
142 pg_log_info("reading user-defined aggregate functions");
143 getAggregates(fout);
144
145 pg_log_info("reading user-defined operators");
146 getOperators(fout);
147
148 pg_log_info("reading user-defined access methods");
149 getAccessMethods(fout);
150
151 pg_log_info("reading user-defined operator classes");
152 getOpclasses(fout);
153
154 pg_log_info("reading user-defined operator families");
155 getOpfamilies(fout);
156
157 pg_log_info("reading user-defined text search parsers");
158 getTSParsers(fout);
159
160 pg_log_info("reading user-defined text search templates");
161 getTSTemplates(fout);
162
163 pg_log_info("reading user-defined text search dictionaries");
164 getTSDictionaries(fout);
165
166 pg_log_info("reading user-defined text search configurations");
168
169 pg_log_info("reading user-defined foreign-data wrappers");
171
172 pg_log_info("reading user-defined foreign servers");
173 getForeignServers(fout);
174
175 pg_log_info("reading default privileges");
176 getDefaultACLs(fout);
177
178 pg_log_info("reading user-defined collations");
179 getCollations(fout);
180
181 pg_log_info("reading user-defined conversions");
182 getConversions(fout);
183
184 pg_log_info("reading type casts");
185 getCasts(fout);
186
187 pg_log_info("reading transforms");
188 getTransforms(fout);
189
190 pg_log_info("reading table inheritance information");
191 inhinfo = getInherits(fout, &numInherits);
192
193 pg_log_info("reading event triggers");
194 getEventTriggers(fout);
195
196 /* Identify extension configuration tables that should be dumped */
197 pg_log_info("finding extension tables");
198 processExtensionTables(fout, extinfo, numExtensions);
199
200 /* Link tables to parents, mark parents of target tables interesting */
201 pg_log_info("finding inheritance relationships");
202 flagInhTables(fout, tblinfo, numTables, inhinfo, numInherits);
203
204 pg_log_info("reading column info for interesting tables");
205 getTableAttrs(fout, tblinfo, numTables);
206
207 pg_log_info("flagging inherited columns in subtables");
208 flagInhAttrs(fout, fout->dopt, tblinfo, numTables);
209
210 pg_log_info("reading partitioning data");
212
213 pg_log_info("reading indexes");
214 getIndexes(fout, tblinfo, numTables);
215
216 pg_log_info("flagging indexes in partitioned tables");
217 flagInhIndexes(fout, tblinfo, numTables);
218
219 pg_log_info("reading extended statistics");
221
222 pg_log_info("reading constraints");
223 getConstraints(fout, tblinfo, numTables);
224
225 pg_log_info("reading triggers");
226 getTriggers(fout, tblinfo, numTables);
227
228 pg_log_info("reading rewrite rules");
229 getRules(fout);
230
231 pg_log_info("reading policies");
232 getPolicies(fout, tblinfo, numTables);
233
234 pg_log_info("reading publications");
235 getPublications(fout);
236
237 pg_log_info("reading publication membership of tables");
238 getPublicationTables(fout, tblinfo, numTables);
239
240 pg_log_info("reading publication membership of schemas");
242
243 pg_log_info("reading subscriptions");
244 getSubscriptions(fout);
245
246 pg_log_info("reading subscription membership of tables");
248
249 free(inhinfo); /* not needed any longer */
250
251 *numTablesPtr = numTables;
252 return tblinfo;
253}
254
255/* flagInhTables -
256 * Fill in parent link fields of tables for which we need that information,
257 * mark parents of target tables as interesting, and create
258 * TableAttachInfo objects for partitioned tables with appropriate
259 * dependency links.
260 *
261 * Note that only direct ancestors of targets are marked interesting.
262 * This is sufficient; we don't much care whether they inherited their
263 * attributes or not.
264 *
265 * modifies tblinfo
266 */
267static void
268flagInhTables(Archive *fout, TableInfo *tblinfo, int numTables,
269 InhInfo *inhinfo, int numInherits)
270{
271 TableInfo *child = NULL;
272 TableInfo *parent = NULL;
273 int i,
274 j;
275
276 /*
277 * Set up links from child tables to their parents.
278 *
279 * We used to attempt to skip this work for tables that are not to be
280 * dumped; but the optimizable cases are rare in practice, and setting up
281 * these links in bulk is cheaper than the old way. (Note in particular
282 * that it's very rare for a child to have more than one parent.)
283 */
284 for (i = 0; i < numInherits; i++)
285 {
286 /*
287 * Skip a hashtable lookup if it's same table as last time. This is
288 * unlikely for the child, but less so for the parent. (Maybe we
289 * should ask the backend for a sorted array to make it more likely?
290 * Not clear the sorting effort would be repaid, though.)
291 */
292 if (child == NULL ||
293 child->dobj.catId.oid != inhinfo[i].inhrelid)
294 {
295 child = findTableByOid(inhinfo[i].inhrelid);
296
297 /*
298 * If we find no TableInfo, assume the pg_inherits entry is for a
299 * partitioned index, which we don't need to track.
300 */
301 if (child == NULL)
302 continue;
303 }
304 if (parent == NULL ||
305 parent->dobj.catId.oid != inhinfo[i].inhparent)
306 {
307 parent = findTableByOid(inhinfo[i].inhparent);
308 if (parent == NULL)
309 pg_fatal("failed sanity check, parent OID %u of table \"%s\" (OID %u) not found",
310 inhinfo[i].inhparent,
311 child->dobj.name,
312 child->dobj.catId.oid);
313 }
314 /* Add this parent to the child's list of parents. */
315 if (child->numParents > 0)
316 child->parents = pg_realloc_array(child->parents,
317 TableInfo *,
318 child->numParents + 1);
319 else
320 child->parents = pg_malloc_array(TableInfo *, 1);
321 child->parents[child->numParents++] = parent;
322 }
323
324 /*
325 * Now consider all child tables and mark parents interesting as needed.
326 */
327 for (i = 0; i < numTables; i++)
328 {
329 /*
330 * If needed, mark the parents as interesting for getTableAttrs and
331 * getIndexes. We only need this for direct parents of dumpable
332 * tables.
333 */
334 if (tblinfo[i].dobj.dump)
335 {
336 int numParents = tblinfo[i].numParents;
337 TableInfo **parents = tblinfo[i].parents;
338
339 for (j = 0; j < numParents; j++)
340 parents[j]->interesting = true;
341 }
342
343 /* Create TableAttachInfo object if needed */
344 if ((tblinfo[i].dobj.dump & DUMP_COMPONENT_DEFINITION) &&
345 tblinfo[i].ispartition)
346 {
347 TableAttachInfo *attachinfo;
348
349 /* With partitions there can only be one parent */
350 if (tblinfo[i].numParents != 1)
351 pg_fatal("invalid number of parents %d for table \"%s\"",
352 tblinfo[i].numParents,
353 tblinfo[i].dobj.name);
354
355 attachinfo = (TableAttachInfo *) palloc(sizeof(TableAttachInfo));
356 attachinfo->dobj.objType = DO_TABLE_ATTACH;
357 attachinfo->dobj.catId.tableoid = 0;
358 attachinfo->dobj.catId.oid = 0;
359 AssignDumpId(&attachinfo->dobj);
360 attachinfo->dobj.name = pg_strdup(tblinfo[i].dobj.name);
361 attachinfo->dobj.namespace = tblinfo[i].dobj.namespace;
362 attachinfo->parentTbl = tblinfo[i].parents[0];
363 attachinfo->partitionTbl = &tblinfo[i];
364
365 /*
366 * We must state the DO_TABLE_ATTACH object's dependencies
367 * explicitly, since it will not match anything in pg_depend.
368 *
369 * Give it dependencies on both the partition table and the parent
370 * table, so that it will not be executed till both of those
371 * exist. (There's no need to care what order those are created
372 * in.)
373 */
374 addObjectDependency(&attachinfo->dobj, tblinfo[i].dobj.dumpId);
375 addObjectDependency(&attachinfo->dobj, tblinfo[i].parents[0]->dobj.dumpId);
376 }
377 }
378}
379
380/*
381 * flagInhIndexes -
382 * Create IndexAttachInfo objects for partitioned indexes, and add
383 * appropriate dependency links.
384 */
385static void
386flagInhIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
387{
388 int i,
389 j;
390
391 for (i = 0; i < numTables; i++)
392 {
393 if (!tblinfo[i].ispartition || tblinfo[i].numParents == 0)
394 continue;
395
396 Assert(tblinfo[i].numParents == 1);
397
398 for (j = 0; j < tblinfo[i].numIndexes; j++)
399 {
400 IndxInfo *index = &(tblinfo[i].indexes[j]);
401 IndxInfo *parentidx;
402 IndexAttachInfo *attachinfo;
403
404 if (index->parentidx == 0)
405 continue;
406
407 parentidx = findIndexByOid(index->parentidx);
408 if (parentidx == NULL)
409 continue;
410
411 attachinfo = pg_malloc_object(IndexAttachInfo);
412
413 attachinfo->dobj.objType = DO_INDEX_ATTACH;
414 attachinfo->dobj.catId.tableoid = 0;
415 attachinfo->dobj.catId.oid = 0;
416 AssignDumpId(&attachinfo->dobj);
417 attachinfo->dobj.name = pg_strdup(index->dobj.name);
418 attachinfo->dobj.namespace = index->indextable->dobj.namespace;
419 attachinfo->parentIdx = parentidx;
420 attachinfo->partitionIdx = index;
421
422 /*
423 * We must state the DO_INDEX_ATTACH object's dependencies
424 * explicitly, since it will not match anything in pg_depend.
425 *
426 * Give it dependencies on both the partition index and the parent
427 * index, so that it will not be executed till both of those
428 * exist. (There's no need to care what order those are created
429 * in.)
430 *
431 * In addition, give it dependencies on the indexes' underlying
432 * tables. This does nothing of great value so far as serial
433 * restore ordering goes, but it ensures that a parallel restore
434 * will not try to run the ATTACH concurrently with other
435 * operations on those tables.
436 */
437 addObjectDependency(&attachinfo->dobj, index->dobj.dumpId);
438 addObjectDependency(&attachinfo->dobj, parentidx->dobj.dumpId);
439 addObjectDependency(&attachinfo->dobj,
440 index->indextable->dobj.dumpId);
441 addObjectDependency(&attachinfo->dobj,
442 parentidx->indextable->dobj.dumpId);
443
444 /* keep track of the list of partitions in the parent index */
445 simple_ptr_list_append(&parentidx->partattaches, &attachinfo->dobj);
446 }
447 }
448}
449
450/* flagInhAttrs -
451 * for each dumpable table in tblinfo, flag its inherited attributes
452 *
453 * What we need to do here is:
454 *
455 * - Detect child columns that inherit NOT NULL bits from their parents, so
456 * that we needn't specify that again for the child. (Versions >= 18 no
457 * longer need this.)
458 *
459 * - Detect child columns that have DEFAULT NULL when their parents had some
460 * non-null default. In this case, we make up a dummy AttrDefInfo object so
461 * that we'll correctly emit the necessary DEFAULT NULL clause; otherwise
462 * the backend will apply an inherited default to the column.
463 *
464 * - Detect child columns that have a generation expression and all their
465 * parents also have the same generation expression, and if so suppress the
466 * child's expression. The child will inherit the generation expression
467 * automatically, so there's no need to dump it. This improves the dump's
468 * compatibility with pre-v16 servers, which didn't allow the child's
469 * expression to be given explicitly. Exceptions: If it's a partition or
470 * we are in binary upgrade mode, we dump such expressions anyway because
471 * in those cases inherited tables are recreated standalone first and then
472 * reattached to the parent. (See also the logic in dumpTableSchema().)
473 *
474 * modifies tblinfo
475 */
476static void
477flagInhAttrs(Archive *fout, DumpOptions *dopt, TableInfo *tblinfo, int numTables)
478{
479 int i,
480 j,
481 k;
482
483 /*
484 * We scan the tables in OID order, since that's how tblinfo[] is sorted.
485 * Hence we will typically visit parents before their children --- but
486 * that is *not* guaranteed. Thus this loop must be careful that it does
487 * not alter table properties in a way that could change decisions made at
488 * child tables during other iterations.
489 */
490 for (i = 0; i < numTables; i++)
491 {
492 TableInfo *tbinfo = &(tblinfo[i]);
493 int numParents;
494 TableInfo **parents;
495
496 /* Some kinds never have parents */
497 if (tbinfo->relkind == RELKIND_SEQUENCE ||
498 tbinfo->relkind == RELKIND_VIEW ||
499 tbinfo->relkind == RELKIND_MATVIEW)
500 continue;
501
502 /* Don't bother computing anything for non-target tables, either */
503 if (!tbinfo->dobj.dump)
504 continue;
505
506 numParents = tbinfo->numParents;
507 parents = tbinfo->parents;
508
509 if (numParents == 0)
510 continue; /* nothing to see here, move along */
511
512 /* For each column, search for matching column names in parent(s) */
513 for (j = 0; j < tbinfo->numatts; j++)
514 {
515 bool foundNotNull; /* Attr was NOT NULL in a parent */
516 bool foundDefault; /* Found a default in a parent */
517 bool foundSameGenerated; /* Found matching GENERATED */
518 bool foundDiffGenerated; /* Found non-matching GENERATED */
519
520 /* no point in examining dropped columns */
521 if (tbinfo->attisdropped[j])
522 continue;
523
524 foundNotNull = false;
525 foundDefault = false;
526 foundSameGenerated = false;
527 foundDiffGenerated = false;
528 for (k = 0; k < numParents; k++)
529 {
530 TableInfo *parent = parents[k];
531 int inhAttrInd;
532
533 inhAttrInd = strInArray(tbinfo->attnames[j],
534 parent->attnames,
535 parent->numatts);
536 if (inhAttrInd >= 0)
537 {
538 AttrDefInfo *parentDef = parent->attrdefs[inhAttrInd];
539
540 /*
541 * Account for each parent having a not-null constraint.
542 * In versions 18 and later, we don't need this (and those
543 * didn't have NO INHERIT.)
544 */
545 if (fout->remoteVersion < 180000 &&
546 parent->notnull_constrs[inhAttrInd] != NULL)
547 foundNotNull = true;
548
549 foundDefault |= (parentDef != NULL &&
550 strcmp(parentDef->adef_expr, "NULL") != 0 &&
551 !parent->attgenerated[inhAttrInd]);
552 if (parent->attgenerated[inhAttrInd])
553 {
554 /* these pointer nullness checks are just paranoia */
555 if (parentDef != NULL &&
556 tbinfo->attrdefs[j] != NULL &&
557 strcmp(parentDef->adef_expr,
558 tbinfo->attrdefs[j]->adef_expr) == 0)
559 foundSameGenerated = true;
560 else
561 foundDiffGenerated = true;
562 }
563 }
564 }
565
566 /*
567 * In versions < 18, for lack of a better system, we arbitrarily
568 * decide that a not-null constraint is not locally defined if at
569 * least one of the parents has it.
570 */
571 if (fout->remoteVersion < 180000 && foundNotNull)
572 tbinfo->notnull_islocal[j] = false;
573
574 /*
575 * Manufacture a DEFAULT NULL clause if necessary. This breaks
576 * the advice given above to avoid changing state that might get
577 * inspected in other loop iterations. We prevent trouble by
578 * having the foundDefault test above check whether adef_expr is
579 * "NULL", so that it will reach the same conclusion before or
580 * after this is done.
581 */
582 if (foundDefault && tbinfo->attrdefs[j] == NULL)
583 {
584 AttrDefInfo *attrDef;
585
586 attrDef = pg_malloc_object(AttrDefInfo);
587 attrDef->dobj.objType = DO_ATTRDEF;
588 attrDef->dobj.catId.tableoid = 0;
589 attrDef->dobj.catId.oid = 0;
590 AssignDumpId(&attrDef->dobj);
591 attrDef->dobj.name = pg_strdup(tbinfo->dobj.name);
592 attrDef->dobj.namespace = tbinfo->dobj.namespace;
593 attrDef->dobj.dump = tbinfo->dobj.dump;
594
595 attrDef->adtable = tbinfo;
596 attrDef->adnum = j + 1;
597 attrDef->adef_expr = pg_strdup("NULL");
598
599 /* Will column be dumped explicitly? */
600 if (shouldPrintColumn(dopt, tbinfo, j))
601 {
602 attrDef->separate = false;
603 /* No dependency needed: NULL cannot have dependencies */
604 }
605 else
606 {
607 /* column will be suppressed, print default separately */
608 attrDef->separate = true;
609 /* ensure it comes out after the table */
610 addObjectDependency(&attrDef->dobj,
611 tbinfo->dobj.dumpId);
612 }
613
614 tbinfo->attrdefs[j] = attrDef;
615 }
616
617 /* No need to dump generation expression if it's inheritable */
618 if (foundSameGenerated && !foundDiffGenerated &&
619 !tbinfo->ispartition && !dopt->binary_upgrade)
621 }
622 }
623}
624
625/*
626 * AssignDumpId
627 * Given a newly-created dumpable object, assign a dump ID,
628 * and enter the object into the lookup tables.
629 *
630 * The caller is expected to have filled in objType and catId,
631 * but not any of the other standard fields of a DumpableObject.
632 */
633void
635{
636 dobj->dumpId = ++lastDumpId;
637 dobj->name = NULL; /* must be set later */
638 dobj->namespace = NULL; /* may be set later */
639 dobj->dump = DUMP_COMPONENT_ALL; /* default assumption */
640 dobj->dump_contains = DUMP_COMPONENT_ALL; /* default assumption */
641 /* All objects have definitions; we may set more components bits later */
643 dobj->ext_member = false; /* default assumption */
644 dobj->depends_on_ext = false; /* default assumption */
645 dobj->dependencies = NULL;
646 dobj->nDeps = 0;
647 dobj->allocDeps = 0;
648
649 /* Add object to dumpIdMap[], enlarging that array if need be */
650 while (dobj->dumpId >= allocedDumpIds)
651 {
652 int newAlloc;
653
654 if (allocedDumpIds <= 0)
655 {
656 newAlloc = 256;
658 }
659 else
660 {
661 newAlloc = allocedDumpIds * 2;
663 }
664 memset(dumpIdMap + allocedDumpIds, 0,
665 (newAlloc - allocedDumpIds) * sizeof(DumpableObject *));
666 allocedDumpIds = newAlloc;
667 }
668 dumpIdMap[dobj->dumpId] = dobj;
669
670 /* If it has a valid CatalogId, enter it into the hash table */
671 if (OidIsValid(dobj->catId.tableoid))
672 {
673 CatalogIdMapEntry *entry;
674 bool found;
675
676 /* Initialize CatalogId hash table if not done yet */
677 if (catalogIdHash == NULL)
678 catalogIdHash = catalogid_create(CATALOGIDHASH_INITIAL_SIZE, NULL);
679
680 entry = catalogid_insert(catalogIdHash, dobj->catId, &found);
681 if (!found)
682 {
683 entry->dobj = NULL;
684 entry->ext = NULL;
685 }
686 Assert(entry->dobj == NULL);
687 entry->dobj = dobj;
688 }
689}
690
691/*
692 * recordAdditionalCatalogID
693 * Record an additional catalog ID for the given DumpableObject
694 */
695void
697{
698 CatalogIdMapEntry *entry;
699 bool found;
700
701 /* CatalogId hash table must exist, if we have a DumpableObject */
702 Assert(catalogIdHash != NULL);
703
704 /* Add reference to CatalogId hash */
705 entry = catalogid_insert(catalogIdHash, catId, &found);
706 if (!found)
707 {
708 entry->dobj = NULL;
709 entry->ext = NULL;
710 }
711 Assert(entry->dobj == NULL);
712 entry->dobj = dobj;
713}
714
715/*
716 * Assign a DumpId that's not tied to a DumpableObject.
717 *
718 * This is used when creating a "fixed" ArchiveEntry that doesn't need to
719 * participate in the sorting logic.
720 */
721DumpId
723{
724 return ++lastDumpId;
725}
726
727/*
728 * Return the largest DumpId so far assigned
729 */
730DumpId
732{
733 return lastDumpId;
734}
735
736/*
737 * Find a DumpableObject by dump ID
738 *
739 * Returns NULL for invalid ID
740 */
743{
744 if (dumpId <= 0 || dumpId >= allocedDumpIds)
745 return NULL; /* out of range? */
746 return dumpIdMap[dumpId];
747}
748
749/*
750 * Find a DumpableObject by catalog ID
751 *
752 * Returns NULL for unknown ID
753 */
756{
757 CatalogIdMapEntry *entry;
758
759 if (catalogIdHash == NULL)
760 return NULL; /* no objects exist yet */
761
762 entry = catalogid_lookup(catalogIdHash, catalogId);
763 if (entry == NULL)
764 return NULL;
765 return entry->dobj;
766}
767
768/*
769 * Build an array of pointers to all known dumpable objects
770 *
771 * This simply creates a modifiable copy of the internal map.
772 */
773void
774getDumpableObjects(DumpableObject ***objs, int *numObjs)
775{
776 int i,
777 j;
778
780 j = 0;
781 for (i = 1; i < allocedDumpIds; i++)
782 {
783 if (dumpIdMap[i])
784 (*objs)[j++] = dumpIdMap[i];
785 }
786 *numObjs = j;
787}
788
789/*
790 * Add a dependency link to a DumpableObject
791 *
792 * Note: duplicate dependencies are currently not eliminated
793 */
794void
796{
797 if (dobj->nDeps >= dobj->allocDeps)
798 {
799 if (dobj->allocDeps <= 0)
800 {
801 dobj->allocDeps = 16;
803 }
804 else
805 {
806 dobj->allocDeps *= 2;
808 DumpId, dobj->allocDeps);
809 }
810 }
811 dobj->dependencies[dobj->nDeps++] = refId;
812}
813
814/*
815 * Remove a dependency link from a DumpableObject
816 *
817 * If there are multiple links, all are removed
818 */
819void
821{
822 int i;
823 int j = 0;
824
825 for (i = 0; i < dobj->nDeps; i++)
826 {
827 if (dobj->dependencies[i] != refId)
828 dobj->dependencies[j++] = dobj->dependencies[i];
829 }
830 dobj->nDeps = j;
831}
832
833
834/*
835 * findTableByOid
836 * finds the DumpableObject for the table with the given oid
837 * returns NULL if not found
838 */
839TableInfo *
841{
842 CatalogId catId;
843 DumpableObject *dobj;
844
845 catId.tableoid = RelationRelationId;
846 catId.oid = oid;
847 dobj = findObjectByCatalogId(catId);
848 Assert(dobj == NULL || dobj->objType == DO_TABLE);
849 return (TableInfo *) dobj;
850}
851
852/*
853 * findIndexByOid
854 * finds the DumpableObject for the index with the given oid
855 * returns NULL if not found
856 */
857static IndxInfo *
859{
860 CatalogId catId;
861 DumpableObject *dobj;
862
863 catId.tableoid = RelationRelationId;
864 catId.oid = oid;
865 dobj = findObjectByCatalogId(catId);
866 Assert(dobj == NULL || dobj->objType == DO_INDEX);
867 return (IndxInfo *) dobj;
868}
869
870/*
871 * findTypeByOid
872 * finds the DumpableObject for the type with the given oid
873 * returns NULL if not found
874 */
875TypeInfo *
877{
878 CatalogId catId;
879 DumpableObject *dobj;
880
881 catId.tableoid = TypeRelationId;
882 catId.oid = oid;
883 dobj = findObjectByCatalogId(catId);
884 Assert(dobj == NULL ||
885 dobj->objType == DO_TYPE || dobj->objType == DO_DUMMY_TYPE);
886 return (TypeInfo *) dobj;
887}
888
889/*
890 * findFuncByOid
891 * finds the DumpableObject for the function with the given oid
892 * returns NULL if not found
893 */
894FuncInfo *
896{
897 CatalogId catId;
898 DumpableObject *dobj;
899
900 catId.tableoid = ProcedureRelationId;
901 catId.oid = oid;
902 dobj = findObjectByCatalogId(catId);
903 Assert(dobj == NULL || dobj->objType == DO_FUNC);
904 return (FuncInfo *) dobj;
905}
906
907/*
908 * findOprByOid
909 * finds the DumpableObject for the operator with the given oid
910 * returns NULL if not found
911 */
912OprInfo *
914{
915 CatalogId catId;
916 DumpableObject *dobj;
917
918 catId.tableoid = OperatorRelationId;
919 catId.oid = oid;
920 dobj = findObjectByCatalogId(catId);
921 Assert(dobj == NULL || dobj->objType == DO_OPERATOR);
922 return (OprInfo *) dobj;
923}
924
925/*
926 * findCollationByOid
927 * finds the DumpableObject for the collation with the given oid
928 * returns NULL if not found
929 */
930CollInfo *
932{
933 CatalogId catId;
934 DumpableObject *dobj;
935
936 catId.tableoid = CollationRelationId;
937 catId.oid = oid;
938 dobj = findObjectByCatalogId(catId);
939 Assert(dobj == NULL || dobj->objType == DO_COLLATION);
940 return (CollInfo *) dobj;
941}
942
943/*
944 * findNamespaceByOid
945 * finds the DumpableObject for the namespace with the given oid
946 * returns NULL if not found
947 */
950{
951 CatalogId catId;
952 DumpableObject *dobj;
953
954 catId.tableoid = NamespaceRelationId;
955 catId.oid = oid;
956 dobj = findObjectByCatalogId(catId);
957 Assert(dobj == NULL || dobj->objType == DO_NAMESPACE);
958 return (NamespaceInfo *) dobj;
959}
960
961/*
962 * findExtensionByOid
963 * finds the DumpableObject for the extension with the given oid
964 * returns NULL if not found
965 */
968{
969 CatalogId catId;
970 DumpableObject *dobj;
971
972 catId.tableoid = ExtensionRelationId;
973 catId.oid = oid;
974 dobj = findObjectByCatalogId(catId);
975 Assert(dobj == NULL || dobj->objType == DO_EXTENSION);
976 return (ExtensionInfo *) dobj;
977}
978
979/*
980 * findPublicationByOid
981 * finds the DumpableObject for the publication with the given oid
982 * returns NULL if not found
983 */
986{
987 CatalogId catId;
988 DumpableObject *dobj;
989
990 catId.tableoid = PublicationRelationId;
991 catId.oid = oid;
992 dobj = findObjectByCatalogId(catId);
993 Assert(dobj == NULL || dobj->objType == DO_PUBLICATION);
994 return (PublicationInfo *) dobj;
995}
996
997/*
998 * findSubscriptionByOid
999 * finds the DumpableObject for the subscription with the given oid
1000 * returns NULL if not found
1001 */
1004{
1005 CatalogId catId;
1006 DumpableObject *dobj;
1007
1008 catId.tableoid = SubscriptionRelationId;
1009 catId.oid = oid;
1010 dobj = findObjectByCatalogId(catId);
1011 Assert(dobj == NULL || dobj->objType == DO_SUBSCRIPTION);
1012 return (SubscriptionInfo *) dobj;
1013}
1014
1015
1016/*
1017 * recordExtensionMembership
1018 * Record that the object identified by the given catalog ID
1019 * belongs to the given extension
1020 */
1021void
1023{
1024 CatalogIdMapEntry *entry;
1025 bool found;
1026
1027 /* CatalogId hash table must exist, if we have an ExtensionInfo */
1028 Assert(catalogIdHash != NULL);
1029
1030 /* Add reference to CatalogId hash */
1031 entry = catalogid_insert(catalogIdHash, catId, &found);
1032 if (!found)
1033 {
1034 entry->dobj = NULL;
1035 entry->ext = NULL;
1036 }
1037 Assert(entry->ext == NULL);
1038 entry->ext = ext;
1039}
1040
1041/*
1042 * findOwningExtension
1043 * return owning extension for specified catalog ID, or NULL if none
1044 */
1047{
1048 CatalogIdMapEntry *entry;
1049
1050 if (catalogIdHash == NULL)
1051 return NULL; /* no objects exist yet */
1052
1053 entry = catalogid_lookup(catalogIdHash, catalogId);
1054 if (entry == NULL)
1055 return NULL;
1056 return entry->ext;
1057}
1058
1059
1060/*
1061 * parseOidArray
1062 * parse a string of numbers delimited by spaces into a character array
1063 *
1064 * Note: actually this is used for both Oids and potentially-signed
1065 * attribute numbers. This should cause no trouble, but we could split
1066 * the function into two functions with different argument types if it does.
1067 */
1068
1069void
1070parseOidArray(const char *str, Oid *array, int arraysize)
1071{
1072 int j,
1073 argNum;
1074 char temp[100];
1075 char s;
1076
1077 argNum = 0;
1078 j = 0;
1079 for (;;)
1080 {
1081 s = *str++;
1082 if (s == ' ' || s == '\0')
1083 {
1084 if (j > 0)
1085 {
1086 if (argNum >= arraysize)
1087 pg_fatal("could not parse numeric array \"%s\": too many numbers", str);
1088 temp[j] = '\0';
1089 array[argNum++] = atooid(temp);
1090 j = 0;
1091 }
1092 if (s == '\0')
1093 break;
1094 }
1095 else
1096 {
1097 if (!(isdigit((unsigned char) s) || s == '-') ||
1098 j >= sizeof(temp) - 1)
1099 pg_fatal("could not parse numeric array \"%s\": invalid character in number", str);
1100 temp[j++] = s;
1101 }
1102 }
1103
1104 while (argNum < arraysize)
1105 array[argNum++] = InvalidOid;
1106}
1107
1108
1109/*
1110 * strInArray:
1111 * takes in a string and a string array and the number of elements in the
1112 * string array.
1113 * returns the index if the string is somewhere in the array, -1 otherwise
1114 */
1115
1116static int
1117strInArray(const char *pattern, char **arr, int arr_size)
1118{
1119 int i;
1120
1121 for (i = 0; i < arr_size; i++)
1122 {
1123 if (strcmp(pattern, arr[i]) == 0)
1124 return i;
1125 }
1126 return -1;
1127}
void recordAdditionalCatalogID(CatalogId catId, DumpableObject *dobj)
Definition: common.c:696
void recordExtensionMembership(CatalogId catId, ExtensionInfo *ext)
Definition: common.c:1022
static void flagInhAttrs(Archive *fout, DumpOptions *dopt, TableInfo *tblinfo, int numTables)
Definition: common.c:477
FuncInfo * findFuncByOid(Oid oid)
Definition: common.c:895
TableInfo * findTableByOid(Oid oid)
Definition: common.c:840
static void flagInhTables(Archive *fout, TableInfo *tblinfo, int numTables, InhInfo *inhinfo, int numInherits)
Definition: common.c:268
static void flagInhIndexes(Archive *fout, TableInfo *tblinfo, int numTables)
ExtensionInfo * findExtensionByOid(Oid oid)
Definition: common.c:967
CollInfo * findCollationByOid(Oid oid)
Definition: common.c:931
SubscriptionInfo * findSubscriptionByOid(Oid oid)
Definition: common.c:1003
OprInfo * findOprByOid(Oid oid)
Definition: common.c:913
NamespaceInfo * findNamespaceByOid(Oid oid)
Definition: common.c:949
void addObjectDependency(DumpableObject *dobj, DumpId refId)
Definition: common.c:795
DumpableObject * findObjectByDumpId(DumpId dumpId)
Definition: common.c:742
static int allocedDumpIds
Definition: common.c:37
void parseOidArray(const char *str, Oid *array, int arraysize)
Definition: common.c:1070
ExtensionInfo * findOwningExtension(CatalogId catalogId)
Definition: common.c:1046
TableInfo * getSchemaData(Archive *fout, int *numTablesPtr)
Definition: common.c:97
TypeInfo * findTypeByOid(Oid oid)
Definition: common.c:876
static IndxInfo * findIndexByOid(Oid oid)
Definition: common.c:858
DumpId createDumpId(void)
Definition: common.c:722
DumpableObject * findObjectByCatalogId(CatalogId catalogId)
Definition: common.c:755
void AssignDumpId(DumpableObject *dobj)
Definition: common.c:634
DumpId getMaxDumpId(void)
Definition: common.c:731
static DumpableObject ** dumpIdMap
Definition: common.c:36
#define CATALOGIDHASH_INITIAL_SIZE
Definition: common.c:79
static int strInArray(const char *pattern, char **arr, int arr_size)
Definition: common.c:1117
void getDumpableObjects(DumpableObject ***objs, int *numObjs)
Definition: common.c:774
static catalogid_hash * catalogIdHash
Definition: common.c:81
PublicationInfo * findPublicationByOid(Oid oid)
Definition: common.c:985
struct _catalogIdMapEntry CatalogIdMapEntry
void removeObjectDependency(DumpableObject *dobj, DumpId refId)
Definition: common.c:820
static DumpId lastDumpId
Definition: common.c:38
uint32_t uint32
Definition: c.h:502
#define OidIsValid(objectId)
Definition: c.h:746
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define pg_realloc_array(pointer, type, count)
Definition: fe_memutils.h:63
#define pg_malloc_array(type, count)
Definition: fe_memutils.h:56
#define pg_malloc_object(type)
Definition: fe_memutils.h:50
Assert(PointerIsAligned(start, uint64))
const char * str
#define free(a)
Definition: header.h:65
int j
Definition: isn.c:73
int i
Definition: isn.c:72
#define pg_log_info(...)
Definition: logging.h:124
void * palloc(Size size)
Definition: mcxt.c:1317
int DumpId
Definition: pg_backup.h:278
#define pg_fatal(...)
void getConstraints(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:7946
ExtensionInfo * getExtensions(Archive *fout, int *numExtensions)
Definition: pg_dump.c:5866
void getPublicationNamespaces(Archive *fout)
Definition: pg_dump.c:4527
void getPartitioningInfo(Archive *fout)
Definition: pg_dump.c:7448
InhInfo * getInherits(Archive *fout, int *numInherits)
Definition: pg_dump.c:7392
void getForeignDataWrappers(Archive *fout)
Definition: pg_dump.c:9854
void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:4036
void getExtensionMembership(Archive *fout, ExtensionInfo extinfo[], int numExtensions)
Definition: pg_dump.c:18846
void getTypes(Archive *fout)
Definition: pg_dump.c:5941
void getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:7327
void getOpclasses(Archive *fout)
Definition: pg_dump.c:6362
void getForeignServers(Archive *fout)
Definition: pg_dump.c:9938
void getFuncs(Archive *fout)
Definition: pg_dump.c:6625
void getTSDictionaries(Archive *fout)
Definition: pg_dump.c:9670
void getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:4607
void getCasts(Archive *fout)
Definition: pg_dump.c:8679
void getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:7508
void getTSConfigurations(Archive *fout)
Definition: pg_dump.c:9795
void getAccessMethods(Archive *fout)
Definition: pg_dump.c:6300
void getConversions(Archive *fout)
Definition: pg_dump.c:6238
void getRules(Archive *fout)
Definition: pg_dump.c:8224
void getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
Definition: pg_dump.c:8873
void getSubscriptionTables(Archive *fout)
Definition: pg_dump.c:5076
void getCollations(Archive *fout)
Definition: pg_dump.c:6176
void getAggregates(Archive *fout)
Definition: pg_dump.c:6484
void getNamespaces(Archive *fout)
Definition: pg_dump.c:5734
void getPublications(Archive *fout)
Definition: pg_dump.c:4321
void getTSParsers(Archive *fout)
Definition: pg_dump.c:9596
TableInfo * getTables(Archive *fout, int *numTables)
Definition: pg_dump.c:6868
void getExtendedStatistics(Archive *fout)
Definition: pg_dump.c:7867
void processExtensionTables(Archive *fout, ExtensionInfo extinfo[], int numExtensions)
Definition: pg_dump.c:18939
void getDefaultACLs(Archive *fout)
Definition: pg_dump.c:10026
void getSubscriptions(Archive *fout)
Definition: pg_dump.c:4878
void getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
Definition: pg_dump.c:8321
void getTransforms(Archive *fout)
Definition: pg_dump.c:8789
void getEventTriggers(Archive *fout)
Definition: pg_dump.c:8517
void getTSTemplates(Archive *fout)
Definition: pg_dump.c:9736
void getProcLangs(Archive *fout)
Definition: pg_dump.c:8595
bool shouldPrintColumn(const DumpOptions *dopt, const TableInfo *tbinfo, int colno)
Definition: pg_dump.c:9581
void getOperators(Archive *fout)
Definition: pg_dump.c:6108
void getOpfamilies(Archive *fout)
Definition: pg_dump.c:6422
#define DUMP_COMPONENT_ALL
Definition: pg_dump.h:117
#define DUMP_COMPONENT_NONE
Definition: pg_dump.h:108
#define DUMP_COMPONENT_DEFINITION
Definition: pg_dump.h:109
@ DO_TYPE
Definition: pg_dump.h:43
@ DO_INDEX
Definition: pg_dump.h:56
@ DO_COLLATION
Definition: pg_dump.h:51
@ DO_OPERATOR
Definition: pg_dump.h:47
@ DO_SUBSCRIPTION
Definition: pg_dump.h:87
@ DO_ATTRDEF
Definition: pg_dump.h:55
@ DO_TABLE_ATTACH
Definition: pg_dump.h:54
@ DO_INDEX_ATTACH
Definition: pg_dump.h:57
@ DO_FUNC
Definition: pg_dump.h:45
@ DO_DUMMY_TYPE
Definition: pg_dump.h:67
@ DO_EXTENSION
Definition: pg_dump.h:42
@ DO_PUBLICATION
Definition: pg_dump.h:83
@ DO_TABLE
Definition: pg_dump.h:53
@ DO_NAMESPACE
Definition: pg_dump.h:41
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
#define atooid(x)
Definition: postgres_ext.h:43
void simple_ptr_list_append(SimplePtrList *list, void *ptr)
Definition: simple_list.c:162
int remoteVersion
Definition: pg_backup.h:227
DumpOptions * dopt
Definition: pg_backup.h:222
Oid tableoid
Definition: pg_backup.h:274
DumpableObject dobj
Definition: pg_dump.h:394
char * adef_expr
Definition: pg_dump.h:397
TableInfo * adtable
Definition: pg_dump.h:395
bool separate
Definition: pg_dump.h:398
CatalogId catId
Definition: common.c:58
ExtensionInfo * ext
Definition: common.c:62
uint32 status
Definition: common.c:59
DumpableObject * dobj
Definition: common.c:61
uint32 hashval
Definition: common.c:60
int binary_upgrade
Definition: pg_backup.h:171
DumpComponents dump
Definition: pg_dump.h:153
char * name
Definition: pg_dump.h:152
DumpId * dependencies
Definition: pg_dump.h:159
DumpId dumpId
Definition: pg_dump.h:151
bool ext_member
Definition: pg_dump.h:157
DumpComponents components
Definition: pg_dump.h:156
DumpableObjectType objType
Definition: pg_dump.h:149
CatalogId catId
Definition: pg_dump.h:150
DumpComponents dump_contains
Definition: pg_dump.h:155
bool depends_on_ext
Definition: pg_dump.h:158
IndxInfo * partitionIdx
Definition: pg_dump.h:435
DumpableObject dobj
Definition: pg_dump.h:433
IndxInfo * parentIdx
Definition: pg_dump.h:434
TableInfo * indextable
Definition: pg_dump.h:411
SimplePtrList partattaches
Definition: pg_dump.h:425
DumpableObject dobj
Definition: pg_dump.h:410
Oid inhparent
Definition: pg_dump.h:552
Oid inhrelid
Definition: pg_dump.h:551
TableInfo * partitionTbl
Definition: pg_dump.h:389
DumpableObject dobj
Definition: pg_dump.h:387
TableInfo * parentTbl
Definition: pg_dump.h:388
char ** notnull_constrs
Definition: pg_dump.h:364
bool ispartition
Definition: pg_dump.h:337
struct _indxInfo * indexes
Definition: pg_dump.h:379
DumpableObject dobj
Definition: pg_dump.h:300
int numParents
Definition: pg_dump.h:340
struct _tableInfo ** parents
Definition: pg_dump.h:341
char * attgenerated
Definition: pg_dump.h:355
bool * attisdropped
Definition: pg_dump.h:353
bool * notnull_islocal
Definition: pg_dump.h:369
int numatts
Definition: pg_dump.h:347
struct _attrDefInfo ** attrdefs
Definition: pg_dump.h:370
char ** attnames
Definition: pg_dump.h:348
char relkind
Definition: pg_dump.h:303
int numIndexes
Definition: pg_dump.h:378
Definition: type.h:96