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