/rtmp/pg_dump
text/x-diff
Filename: /rtmp/pg_dump
Type: text/x-diff
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/bin/pg_dump/common.c | 0 | 0 |
| src/bin/pg_dump/common.h | 0 | 0 |
| src/bin/pg_dump/compress_io.c | 0 | 0 |
| src/bin/pg_dump/dumpcatalog.c | 0 | 0 |
| src/bin/pg_dump/dumpmem.c | 0 | 0 |
| src/bin/pg_dump/dumpmem.h | 0 | 0 |
| src/bin/pg_dump/dumputils.c | 0 | 0 |
| src/bin/pg_dump/Makefile | 0 | 0 |
| src/bin/pg_dump/pg_backup_archiver.c | 0 | 0 |
| src/bin/pg_dump/pg_backup_custom.c | 0 | 0 |
| src/bin/pg_dump/pg_backup_db.c | 0 | 0 |
| src/bin/pg_dump/pg_backup_directory.c | 0 | 0 |
| src/bin/pg_dump/pg_backup_files.c | 0 | 0 |
| src/bin/pg_dump/pg_backup_null.c | 0 | 0 |
| src/bin/pg_dump/pg_backup_tar.c | 0 | 0 |
| src/bin/pg_dump/pg_dump.c | 0 | 0 |
| src/bin/pg_dump/pg_dump_sort.c | 0 | 0 |
| src/bin/pg_dump/pg_restore.c | 0 | 0 |
diff --git a/src/bin/pg_dump/Makefile b/src/bin/pg_dump/Makefile
new file mode 100644
index 9d13bec..4e8e421
*** a/src/bin/pg_dump/Makefile
--- b/src/bin/pg_dump/Makefile
*************** override CPPFLAGS := -I$(libpq_srcdir) $
*** 20,26 ****
OBJS= pg_backup_archiver.o pg_backup_db.o pg_backup_custom.o \
pg_backup_files.o pg_backup_null.o pg_backup_tar.o \
! pg_backup_directory.o common.o dumputils.o compress_io.o $(WIN32RES)
KEYWRDOBJS = keywords.o kwlookup.o
--- 20,26 ----
OBJS= pg_backup_archiver.o pg_backup_db.o pg_backup_custom.o \
pg_backup_files.o pg_backup_null.o pg_backup_tar.o \
! pg_backup_directory.o dumpmem.o dumputils.o compress_io.o $(WIN32RES)
KEYWRDOBJS = keywords.o kwlookup.o
*************** kwlookup.c: % : $(top_srcdir)/src/backen
*** 29,36 ****
all: pg_dump pg_restore pg_dumpall
! pg_dump: pg_dump.o dumpcatalog.o pg_dump_sort.o $(OBJS) $(KEYWRDOBJS) | submake-libpq submake-libpgport
! $(CC) $(CFLAGS) pg_dump.o dumpcatalog.o pg_dump_sort.o $(KEYWRDOBJS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
pg_restore: pg_restore.o $(OBJS) $(KEYWRDOBJS) | submake-libpq submake-libpgport
$(CC) $(CFLAGS) pg_restore.o $(KEYWRDOBJS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
--- 29,36 ----
all: pg_dump pg_restore pg_dumpall
! pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) $(KEYWRDOBJS) | submake-libpq submake-libpgport
! $(CC) $(CFLAGS) pg_dump.o common.o pg_dump_sort.o $(KEYWRDOBJS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
pg_restore: pg_restore.o $(OBJS) $(KEYWRDOBJS) | submake-libpq submake-libpgport
$(CC) $(CFLAGS) pg_restore.o $(KEYWRDOBJS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
new file mode 100644
index 1a3f4cb..6f921f7
*** a/src/bin/pg_dump/common.c
--- b/src/bin/pg_dump/common.c
***************
*** 1,8 ****
/*-------------------------------------------------------------------------
*
* common.c
! * common routines between pg_dump and pg_restore (but not pg_dumpall
! * because there is no failure location to report).
*
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
--- 1,8 ----
/*-------------------------------------------------------------------------
*
* common.c
! * catalog routines used by pg_dump; long ago these were shared
! * by another dump tool, but not anymore.
*
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
***************
*** 14,73 ****
*-------------------------------------------------------------------------
*/
#include "postgres_fe.h"
- #include "pg_backup.h"
- #include "common.h"
#include <ctype.h>
/*
! * Safer versions of some standard C library functions. If an
! * out-of-memory condition occurs, these functions will bail out
! * safely; therefore, their return value is guaranteed to be non-NULL.
! * We also report the program name and close the database connection.
*/
! char *
! pg_strdup(const char *string)
{
! char *tmp;
! if (!string)
! exit_horribly(NULL, NULL, "cannot duplicate null pointer\n");
! tmp = strdup(string);
! if (!tmp)
! exit_horribly(NULL, NULL, "out of memory\n");
! return tmp;
}
! void *
! pg_malloc(size_t size)
{
! void *tmp;
! tmp = malloc(size);
! if (!tmp)
! exit_horribly(NULL, NULL, "out of memory\n");
! return tmp;
}
! void *
! pg_calloc(size_t nmemb, size_t size)
{
! void *tmp;
! tmp = calloc(nmemb, size);
! if (!tmp)
! exit_horribly(NULL, NULL, _("out of memory\n"));
! return tmp;
}
! void *
! pg_realloc(void *ptr, size_t size)
{
! void *tmp;
! tmp = realloc(ptr, size);
! if (!tmp)
! exit_horribly(NULL, NULL, _("out of memory\n"));
! return tmp;
}
--- 14,979 ----
*-------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include <ctype.h>
+ #include "catalog/pg_class.h"
+
+ #include "pg_backup_archiver.h"
+ #include "dumpmem.h"
+
+
/*
! * Variables for mapping DumpId to DumpableObject
*/
+ static DumpableObject **dumpIdMap = NULL;
+ static int allocedDumpIds = 0;
+ static DumpId lastDumpId = 0;
! /*
! * Variables for mapping CatalogId to DumpableObject
! */
! static bool catalogIdMapValid = false;
! static DumpableObject **catalogIdMap = NULL;
! static int numCatalogIds = 0;
!
! /*
! * These variables are static to avoid the notational cruft of having to pass
! * them into findTableByOid() and friends. For each of these arrays, we
! * build a sorted-by-OID index array immediately after it's built, and then
! * we use binary search in findTableByOid() and friends. (qsort'ing the base
! * arrays themselves would be simpler, but it doesn't work because pg_dump.c
! * may have already established pointers between items.)
! */
! static TableInfo *tblinfo;
! static TypeInfo *typinfo;
! static FuncInfo *funinfo;
! static OprInfo *oprinfo;
! static int numTables;
! static int numTypes;
! static int numFuncs;
! static int numOperators;
! static int numCollations;
! static DumpableObject **tblinfoindex;
! static DumpableObject **typinfoindex;
! static DumpableObject **funinfoindex;
! static DumpableObject **oprinfoindex;
! static DumpableObject **collinfoindex;
!
!
! static void flagInhTables(TableInfo *tbinfo, int numTables,
! InhInfo *inhinfo, int numInherits);
! static void flagInhAttrs(TableInfo *tblinfo, int numTables);
! static DumpableObject **buildIndexArray(void *objArray, int numObjs,
! Size objSize);
! static int DOCatalogIdCompare(const void *p1, const void *p2);
! static void findParentsByOid(TableInfo *self,
! InhInfo *inhinfo, int numInherits);
! static int strInArray(const char *pattern, char **arr, int arr_size);
!
!
! /*
! * getSchemaData
! * Collect information about all potentially dumpable objects
! */
! TableInfo *
! getSchemaData(int *numTablesPtr)
{
! ExtensionInfo *extinfo;
! InhInfo *inhinfo;
! CollInfo *collinfo;
! int numNamespaces;
! int numExtensions;
! int numAggregates;
! int numInherits;
! int numRules;
! int numProcLangs;
! int numCasts;
! int numOpclasses;
! int numOpfamilies;
! int numConversions;
! int numTSParsers;
! int numTSTemplates;
! int numTSDicts;
! int numTSConfigs;
! int numForeignDataWrappers;
! int numForeignServers;
! int numDefaultACLs;
! if (g_verbose)
! write_msg(NULL, "reading schemas\n");
! getNamespaces(&numNamespaces);
!
! /*
! * getTables should be done as soon as possible, so as to minimize the
! * window between starting our transaction and acquiring per-table locks.
! * However, we have to do getNamespaces first because the tables get
! * linked to their containing namespaces during getTables.
! */
! if (g_verbose)
! write_msg(NULL, "reading user-defined tables\n");
! tblinfo = getTables(&numTables);
! tblinfoindex = buildIndexArray(tblinfo, numTables, sizeof(TableInfo));
!
! if (g_verbose)
! write_msg(NULL, "reading extensions\n");
! extinfo = getExtensions(&numExtensions);
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined functions\n");
! funinfo = getFuncs(&numFuncs);
! funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo));
!
! /* this must be after getTables and getFuncs */
! if (g_verbose)
! write_msg(NULL, "reading user-defined types\n");
! typinfo = getTypes(&numTypes);
! typinfoindex = buildIndexArray(typinfo, numTypes, sizeof(TypeInfo));
!
! /* this must be after getFuncs, too */
! if (g_verbose)
! write_msg(NULL, "reading procedural languages\n");
! getProcLangs(&numProcLangs);
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined aggregate functions\n");
! getAggregates(&numAggregates);
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined operators\n");
! oprinfo = getOperators(&numOperators);
! oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo));
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined operator classes\n");
! getOpclasses(&numOpclasses);
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined operator families\n");
! getOpfamilies(&numOpfamilies);
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined text search parsers\n");
! getTSParsers(&numTSParsers);
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined text search templates\n");
! getTSTemplates(&numTSTemplates);
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined text search dictionaries\n");
! getTSDictionaries(&numTSDicts);
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined text search configurations\n");
! getTSConfigurations(&numTSConfigs);
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined foreign-data wrappers\n");
! getForeignDataWrappers(&numForeignDataWrappers);
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined foreign servers\n");
! getForeignServers(&numForeignServers);
!
! if (g_verbose)
! write_msg(NULL, "reading default privileges\n");
! getDefaultACLs(&numDefaultACLs);
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined collations\n");
! collinfo = getCollations(&numCollations);
! collinfoindex = buildIndexArray(collinfo, numCollations, sizeof(CollInfo));
!
! if (g_verbose)
! write_msg(NULL, "reading user-defined conversions\n");
! getConversions(&numConversions);
!
! if (g_verbose)
! write_msg(NULL, "reading type casts\n");
! getCasts(&numCasts);
!
! if (g_verbose)
! write_msg(NULL, "reading table inheritance information\n");
! inhinfo = getInherits(&numInherits);
!
! if (g_verbose)
! write_msg(NULL, "reading rewrite rules\n");
! getRules(&numRules);
!
! /*
! * Identify extension member objects and mark them as not to be dumped.
! * This must happen after reading all objects that can be direct members
! * of extensions, but before we begin to process table subsidiary objects.
! */
! if (g_verbose)
! write_msg(NULL, "finding extension members\n");
! getExtensionMembership(extinfo, numExtensions);
!
! /* Link tables to parents, mark parents of target tables interesting */
! if (g_verbose)
! write_msg(NULL, "finding inheritance relationships\n");
! flagInhTables(tblinfo, numTables, inhinfo, numInherits);
!
! if (g_verbose)
! write_msg(NULL, "reading column info for interesting tables\n");
! getTableAttrs(tblinfo, numTables);
!
! if (g_verbose)
! write_msg(NULL, "flagging inherited columns in subtables\n");
! flagInhAttrs(tblinfo, numTables);
!
! if (g_verbose)
! write_msg(NULL, "reading indexes\n");
! getIndexes(tblinfo, numTables);
!
! if (g_verbose)
! write_msg(NULL, "reading constraints\n");
! getConstraints(tblinfo, numTables);
!
! if (g_verbose)
! write_msg(NULL, "reading triggers\n");
! getTriggers(tblinfo, numTables);
!
! *numTablesPtr = numTables;
! return tblinfo;
}
! /* flagInhTables -
! * Fill in parent link fields of every target table, and mark
! * parents of target tables as interesting
! *
! * Note that only direct ancestors of targets are marked interesting.
! * This is sufficient; we don't much care whether they inherited their
! * attributes or not.
! *
! * modifies tblinfo
! */
! static void
! flagInhTables(TableInfo *tblinfo, int numTables,
! InhInfo *inhinfo, int numInherits)
{
! int i,
! j;
! int numParents;
! TableInfo **parents;
! for (i = 0; i < numTables; i++)
! {
! /* Sequences and views never have parents */
! if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
! tblinfo[i].relkind == RELKIND_VIEW)
! continue;
!
! /* Don't bother computing anything for non-target tables, either */
! if (!tblinfo[i].dobj.dump)
! continue;
!
! /* Find all the immediate parent tables */
! findParentsByOid(&tblinfo[i], inhinfo, numInherits);
!
! /* Mark the parents as interesting for getTableAttrs */
! numParents = tblinfo[i].numParents;
! parents = tblinfo[i].parents;
! for (j = 0; j < numParents; j++)
! parents[j]->interesting = true;
! }
}
! /* flagInhAttrs -
! * for each dumpable table in tblinfo, flag its inherited attributes
! * so when we dump the table out, we don't dump out the inherited attributes
! *
! * modifies tblinfo
! */
! static void
! flagInhAttrs(TableInfo *tblinfo, int numTables)
{
! int i,
! j,
! k;
! for (i = 0; i < numTables; i++)
! {
! TableInfo *tbinfo = &(tblinfo[i]);
! int numParents;
! TableInfo **parents;
! TableInfo *parent;
!
! /* Sequences and views never have parents */
! if (tbinfo->relkind == RELKIND_SEQUENCE ||
! tbinfo->relkind == RELKIND_VIEW)
! continue;
!
! /* Don't bother computing anything for non-target tables, either */
! if (!tbinfo->dobj.dump)
! continue;
!
! numParents = tbinfo->numParents;
! parents = tbinfo->parents;
!
! if (numParents == 0)
! continue; /* nothing to see here, move along */
!
! /*----------------------------------------------------------------
! * For each attr, check the parent info: if no parent has an attr
! * with the same name, then it's not inherited. If there *is* an
! * attr with the same name, then only dump it if:
! *
! * - it is NOT NULL and zero parents are NOT NULL
! * OR
! * - it has a default value AND the default value does not match
! * all parent default values, or no parents specify a default.
! *
! * See discussion on -hackers around 2-Apr-2001.
! *----------------------------------------------------------------
! */
! for (j = 0; j < tbinfo->numatts; j++)
! {
! bool foundAttr; /* Attr was found in a parent */
! bool foundNotNull; /* Attr was NOT NULL in a parent */
! bool defaultsMatch; /* All non-empty defaults match */
! bool defaultsFound; /* Found a default in a parent */
! AttrDefInfo *attrDef;
!
! foundAttr = false;
! foundNotNull = false;
! defaultsMatch = true;
! defaultsFound = false;
!
! attrDef = tbinfo->attrdefs[j];
!
! for (k = 0; k < numParents; k++)
! {
! int inhAttrInd;
!
! parent = parents[k];
! inhAttrInd = strInArray(tbinfo->attnames[j],
! parent->attnames,
! parent->numatts);
!
! if (inhAttrInd != -1)
! {
! AttrDefInfo *inhDef = parent->attrdefs[inhAttrInd];
!
! foundAttr = true;
! foundNotNull |= parent->notnull[inhAttrInd];
! if (inhDef != NULL)
! {
! defaultsFound = true;
!
! /*
! * If any parent has a default and the child doesn't,
! * we have to emit an explicit DEFAULT NULL clause for
! * the child, else the parent's default will win.
! */
! if (attrDef == NULL)
! {
! attrDef = (AttrDefInfo *) pg_malloc(sizeof(AttrDefInfo));
! attrDef->dobj.objType = DO_ATTRDEF;
! attrDef->dobj.catId.tableoid = 0;
! attrDef->dobj.catId.oid = 0;
! AssignDumpId(&attrDef->dobj);
! attrDef->adtable = tbinfo;
! attrDef->adnum = j + 1;
! attrDef->adef_expr = pg_strdup("NULL");
!
! attrDef->dobj.name = pg_strdup(tbinfo->dobj.name);
! attrDef->dobj.namespace = tbinfo->dobj.namespace;
!
! attrDef->dobj.dump = tbinfo->dobj.dump;
!
! attrDef->separate = false;
! addObjectDependency(&tbinfo->dobj,
! attrDef->dobj.dumpId);
!
! tbinfo->attrdefs[j] = attrDef;
! }
! if (strcmp(attrDef->adef_expr, inhDef->adef_expr) != 0)
! {
! defaultsMatch = false;
!
! /*
! * Whenever there is a non-matching parent
! * default, add a dependency to force the parent
! * default to be dumped first, in case the
! * defaults end up being dumped as separate
! * commands. Otherwise the parent default will
! * override the child's when it is applied.
! */
! addObjectDependency(&attrDef->dobj,
! inhDef->dobj.dumpId);
! }
! }
! }
! }
!
! /*
! * Based on the scan of the parents, decide if we can rely on the
! * inherited attr
! */
! if (foundAttr) /* Attr was inherited */
! {
! /* Set inherited flag by default */
! tbinfo->inhAttrs[j] = true;
! tbinfo->inhAttrDef[j] = true;
! tbinfo->inhNotNull[j] = true;
!
! /*
! * Clear it if attr had a default, but parents did not, or
! * mismatch
! */
! if ((attrDef != NULL) && (!defaultsFound || !defaultsMatch))
! {
! tbinfo->inhAttrs[j] = false;
! tbinfo->inhAttrDef[j] = false;
! }
!
! /*
! * Clear it if NOT NULL and none of the parents were NOT NULL
! */
! if (tbinfo->notnull[j] && !foundNotNull)
! {
! tbinfo->inhAttrs[j] = false;
! tbinfo->inhNotNull[j] = false;
! }
!
! /* Clear it if attr has local definition */
! if (tbinfo->attislocal[j])
! tbinfo->inhAttrs[j] = false;
! }
! }
! }
}
! /*
! * AssignDumpId
! * Given a newly-created dumpable object, assign a dump ID,
! * and enter the object into the lookup table.
! *
! * The caller is expected to have filled in objType and catId,
! * but not any of the other standard fields of a DumpableObject.
! */
! void
! AssignDumpId(DumpableObject *dobj)
{
! dobj->dumpId = ++lastDumpId;
! dobj->name = NULL; /* must be set later */
! dobj->namespace = NULL; /* may be set later */
! dobj->dump = true; /* default assumption */
! dobj->ext_member = false; /* default assumption */
! dobj->dependencies = NULL;
! dobj->nDeps = 0;
! dobj->allocDeps = 0;
! while (dobj->dumpId >= allocedDumpIds)
! {
! int newAlloc;
!
! if (allocedDumpIds <= 0)
! {
! newAlloc = 256;
! dumpIdMap = (DumpableObject **)
! pg_malloc(newAlloc * sizeof(DumpableObject *));
! }
! else
! {
! newAlloc = allocedDumpIds * 2;
! dumpIdMap = (DumpableObject **)
! pg_realloc(dumpIdMap, newAlloc * sizeof(DumpableObject *));
! }
! memset(dumpIdMap + allocedDumpIds, 0,
! (newAlloc - allocedDumpIds) * sizeof(DumpableObject *));
! allocedDumpIds = newAlloc;
! }
! dumpIdMap[dobj->dumpId] = dobj;
!
! /* mark catalogIdMap invalid, but don't rebuild it yet */
! catalogIdMapValid = false;
! }
!
! /*
! * Assign a DumpId that's not tied to a DumpableObject.
! *
! * This is used when creating a "fixed" ArchiveEntry that doesn't need to
! * participate in the sorting logic.
! */
! DumpId
! createDumpId(void)
! {
! return ++lastDumpId;
! }
!
! /*
! * Return the largest DumpId so far assigned
! */
! DumpId
! getMaxDumpId(void)
! {
! return lastDumpId;
! }
!
! /*
! * Find a DumpableObject by dump ID
! *
! * Returns NULL for invalid ID
! */
! DumpableObject *
! findObjectByDumpId(DumpId dumpId)
! {
! if (dumpId <= 0 || dumpId >= allocedDumpIds)
! return NULL; /* out of range? */
! return dumpIdMap[dumpId];
! }
!
! /*
! * Find a DumpableObject by catalog ID
! *
! * Returns NULL for unknown ID
! *
! * We use binary search in a sorted list that is built on first call.
! * If AssignDumpId() and findObjectByCatalogId() calls were freely intermixed,
! * the code would work, but possibly be very slow. In the current usage
! * pattern that does not happen, indeed we build the list at most twice.
! */
! DumpableObject *
! findObjectByCatalogId(CatalogId catalogId)
! {
! DumpableObject **low;
! DumpableObject **high;
!
! if (!catalogIdMapValid)
! {
! if (catalogIdMap)
! free(catalogIdMap);
! getDumpableObjects(&catalogIdMap, &numCatalogIds);
! if (numCatalogIds > 1)
! qsort((void *) catalogIdMap, numCatalogIds,
! sizeof(DumpableObject *), DOCatalogIdCompare);
! catalogIdMapValid = true;
! }
!
! /*
! * We could use bsearch() here, but the notational cruft of calling
! * bsearch is nearly as bad as doing it ourselves; and the generalized
! * bsearch function is noticeably slower as well.
! */
! if (numCatalogIds <= 0)
! return NULL;
! low = catalogIdMap;
! high = catalogIdMap + (numCatalogIds - 1);
! while (low <= high)
! {
! DumpableObject **middle;
! int difference;
!
! middle = low + (high - low) / 2;
! /* comparison must match DOCatalogIdCompare, below */
! difference = oidcmp((*middle)->catId.oid, catalogId.oid);
! if (difference == 0)
! difference = oidcmp((*middle)->catId.tableoid, catalogId.tableoid);
! if (difference == 0)
! return *middle;
! else if (difference < 0)
! low = middle + 1;
! else
! high = middle - 1;
! }
! return NULL;
! }
!
! /*
! * Find a DumpableObject by OID, in a pre-sorted array of one type of object
! *
! * Returns NULL for unknown OID
! */
! static DumpableObject *
! findObjectByOid(Oid oid, DumpableObject **indexArray, int numObjs)
! {
! DumpableObject **low;
! DumpableObject **high;
!
! /*
! * This is the same as findObjectByCatalogId except we assume we need not
! * look at table OID because the objects are all the same type.
! *
! * We could use bsearch() here, but the notational cruft of calling
! * bsearch is nearly as bad as doing it ourselves; and the generalized
! * bsearch function is noticeably slower as well.
! */
! if (numObjs <= 0)
! return NULL;
! low = indexArray;
! high = indexArray + (numObjs - 1);
! while (low <= high)
! {
! DumpableObject **middle;
! int difference;
!
! middle = low + (high - low) / 2;
! difference = oidcmp((*middle)->catId.oid, oid);
! if (difference == 0)
! return *middle;
! else if (difference < 0)
! low = middle + 1;
! else
! high = middle - 1;
! }
! return NULL;
! }
!
! /*
! * Build an index array of DumpableObject pointers, sorted by OID
! */
! static DumpableObject **
! buildIndexArray(void *objArray, int numObjs, Size objSize)
! {
! DumpableObject **ptrs;
! int i;
!
! ptrs = (DumpableObject **) pg_malloc(numObjs * sizeof(DumpableObject *));
! for (i = 0; i < numObjs; i++)
! ptrs[i] = (DumpableObject *) ((char *) objArray + i * objSize);
!
! /* We can use DOCatalogIdCompare to sort since its first key is OID */
! if (numObjs > 1)
! qsort((void *) ptrs, numObjs, sizeof(DumpableObject *),
! DOCatalogIdCompare);
!
! return ptrs;
! }
!
! /*
! * qsort comparator for pointers to DumpableObjects
! */
! static int
! DOCatalogIdCompare(const void *p1, const void *p2)
! {
! const DumpableObject *obj1 = *(DumpableObject * const *) p1;
! const DumpableObject *obj2 = *(DumpableObject * const *) p2;
! int cmpval;
!
! /*
! * Compare OID first since it's usually unique, whereas there will only be
! * a few distinct values of tableoid.
! */
! cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid);
! if (cmpval == 0)
! cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid);
! return cmpval;
! }
!
! /*
! * Build an array of pointers to all known dumpable objects
! *
! * This simply creates a modifiable copy of the internal map.
! */
! void
! getDumpableObjects(DumpableObject ***objs, int *numObjs)
! {
! int i,
! j;
!
! *objs = (DumpableObject **)
! pg_malloc(allocedDumpIds * sizeof(DumpableObject *));
! j = 0;
! for (i = 1; i < allocedDumpIds; i++)
! {
! if (dumpIdMap[i])
! (*objs)[j++] = dumpIdMap[i];
! }
! *numObjs = j;
! }
!
! /*
! * Add a dependency link to a DumpableObject
! *
! * Note: duplicate dependencies are currently not eliminated
! */
! void
! addObjectDependency(DumpableObject *dobj, DumpId refId)
! {
! if (dobj->nDeps >= dobj->allocDeps)
! {
! if (dobj->allocDeps <= 0)
! {
! dobj->allocDeps = 16;
! dobj->dependencies = (DumpId *)
! pg_malloc(dobj->allocDeps * sizeof(DumpId));
! }
! else
! {
! dobj->allocDeps *= 2;
! dobj->dependencies = (DumpId *)
! pg_realloc(dobj->dependencies,
! dobj->allocDeps * sizeof(DumpId));
! }
! }
! dobj->dependencies[dobj->nDeps++] = refId;
! }
!
! /*
! * Remove a dependency link from a DumpableObject
! *
! * If there are multiple links, all are removed
! */
! void
! removeObjectDependency(DumpableObject *dobj, DumpId refId)
! {
! int i;
! int j = 0;
!
! for (i = 0; i < dobj->nDeps; i++)
! {
! if (dobj->dependencies[i] != refId)
! dobj->dependencies[j++] = dobj->dependencies[i];
! }
! dobj->nDeps = j;
! }
!
!
! /*
! * findTableByOid
! * finds the entry (in tblinfo) of the table with the given oid
! * returns NULL if not found
! */
! TableInfo *
! findTableByOid(Oid oid)
! {
! return (TableInfo *) findObjectByOid(oid, tblinfoindex, numTables);
! }
!
! /*
! * findTypeByOid
! * finds the entry (in typinfo) of the type with the given oid
! * returns NULL if not found
! */
! TypeInfo *
! findTypeByOid(Oid oid)
! {
! return (TypeInfo *) findObjectByOid(oid, typinfoindex, numTypes);
! }
!
! /*
! * findFuncByOid
! * finds the entry (in funinfo) of the function with the given oid
! * returns NULL if not found
! */
! FuncInfo *
! findFuncByOid(Oid oid)
! {
! return (FuncInfo *) findObjectByOid(oid, funinfoindex, numFuncs);
! }
!
! /*
! * findOprByOid
! * finds the entry (in oprinfo) of the operator with the given oid
! * returns NULL if not found
! */
! OprInfo *
! findOprByOid(Oid oid)
! {
! return (OprInfo *) findObjectByOid(oid, oprinfoindex, numOperators);
! }
!
! /*
! * findCollationByOid
! * finds the entry (in collinfo) of the collation with the given oid
! * returns NULL if not found
! */
! CollInfo *
! findCollationByOid(Oid oid)
! {
! return (CollInfo *) findObjectByOid(oid, collinfoindex, numCollations);
! }
!
!
! /*
! * findParentsByOid
! * find a table's parents in tblinfo[]
! */
! static void
! findParentsByOid(TableInfo *self,
! InhInfo *inhinfo, int numInherits)
! {
! Oid oid = self->dobj.catId.oid;
! int i,
! j;
! int numParents;
!
! numParents = 0;
! for (i = 0; i < numInherits; i++)
! {
! if (inhinfo[i].inhrelid == oid)
! numParents++;
! }
!
! self->numParents = numParents;
!
! if (numParents > 0)
! {
! self->parents = (TableInfo **)
! pg_malloc(sizeof(TableInfo *) * numParents);
! j = 0;
! for (i = 0; i < numInherits; i++)
! {
! if (inhinfo[i].inhrelid == oid)
! {
! TableInfo *parent;
!
! parent = findTableByOid(inhinfo[i].inhparent);
! if (parent == NULL)
! {
! write_msg(NULL, "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found\n",
! inhinfo[i].inhparent,
! self->dobj.name,
! oid);
! exit_nicely();
! }
! self->parents[j++] = parent;
! }
! }
! }
! else
! self->parents = NULL;
! }
!
! /*
! * parseOidArray
! * parse a string of numbers delimited by spaces into a character array
! *
! * Note: actually this is used for both Oids and potentially-signed
! * attribute numbers. This should cause no trouble, but we could split
! * the function into two functions with different argument types if it does.
! */
!
! void
! parseOidArray(const char *str, Oid *array, int arraysize)
! {
! int j,
! argNum;
! char temp[100];
! char s;
!
! argNum = 0;
! j = 0;
! for (;;)
! {
! s = *str++;
! if (s == ' ' || s == '\0')
! {
! if (j > 0)
! {
! if (argNum >= arraysize)
! {
! write_msg(NULL, "could not parse numeric array \"%s\": too many numbers\n", str);
! exit_nicely();
! }
! temp[j] = '\0';
! array[argNum++] = atooid(temp);
! j = 0;
! }
! if (s == '\0')
! break;
! }
! else
! {
! if (!(isdigit((unsigned char) s) || s == '-') ||
! j >= sizeof(temp) - 1)
! {
! write_msg(NULL, "could not parse numeric array \"%s\": invalid character in number\n", str);
! exit_nicely();
! }
! temp[j++] = s;
! }
! }
!
! while (argNum < arraysize)
! array[argNum++] = InvalidOid;
! }
!
!
! /*
! * strInArray:
! * takes in a string and a string array and the number of elements in the
! * string array.
! * returns the index if the string is somewhere in the array, -1 otherwise
! */
!
! static int
! strInArray(const char *pattern, char **arr, int arr_size)
! {
! int i;
!
! for (i = 0; i < arr_size; i++)
! {
! if (strcmp(pattern, arr[i]) == 0)
! return i;
! }
! return -1;
! }
!
!
! /*
! * Support for simple list operations
! */
!
! void
! simple_oid_list_append(SimpleOidList *list, Oid val)
! {
! SimpleOidListCell *cell;
!
! cell = (SimpleOidListCell *) pg_malloc(sizeof(SimpleOidListCell));
! cell->next = NULL;
! cell->val = val;
!
! if (list->tail)
! list->tail->next = cell;
! else
! list->head = cell;
! list->tail = cell;
! }
!
! void
! simple_string_list_append(SimpleStringList *list, const char *val)
! {
! SimpleStringListCell *cell;
!
! /* this calculation correctly accounts for the null trailing byte */
! cell = (SimpleStringListCell *)
! pg_malloc(sizeof(SimpleStringListCell) + strlen(val));
! cell->next = NULL;
! strcpy(cell->val, val);
!
! if (list->tail)
! list->tail->next = cell;
! else
! list->head = cell;
! list->tail = cell;
! }
!
! bool
! simple_oid_list_member(SimpleOidList *list, Oid val)
! {
! SimpleOidListCell *cell;
!
! for (cell = list->head; cell; cell = cell->next)
! {
! if (cell->val == val)
! return true;
! }
! return false;
! }
!
! bool
! simple_string_list_member(SimpleStringList *list, const char *val)
! {
! SimpleStringListCell *cell;
!
! for (cell = list->head; cell; cell = cell->next)
! {
! if (strcmp(cell->val, val) == 0)
! return true;
! }
! return false;
}
diff --git a/src/bin/pg_dump/common.h b/src/bin/pg_dump/common.h
new file mode .
index 742d9f6..e69de29
*** a/src/bin/pg_dump/common.h
--- b/src/bin/pg_dump/common.h
***************
*** 1,24 ****
- /*-------------------------------------------------------------------------
- *
- * common.h
- * Common header file for the pg_dump, pg_dumpall, and pg_restore
- *
- * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/bin/pg_dump/common.h
- *
- *-------------------------------------------------------------------------
- */
-
- #ifndef COMMON_H
- #define COMMON_H
-
- #include "postgres_fe.h"
-
- extern char *pg_strdup(const char *string);
- extern void *pg_malloc(size_t size);
- extern void *pg_calloc(size_t nmemb, size_t size);
- extern void *pg_realloc(void *ptr, size_t size);
-
- #endif /* COMMON_H */
--- 0 ----
diff --git a/src/bin/pg_dump/compress_io.c b/src/bin/pg_dump/compress_io.c
new file mode 100644
index 8375762..8c1e2b8
*** a/src/bin/pg_dump/compress_io.c
--- b/src/bin/pg_dump/compress_io.c
***************
*** 53,59 ****
*/
#include "compress_io.h"
! #include "common.h"
/*----------------------
* Compressor API
--- 53,59 ----
*/
#include "compress_io.h"
! #include "dumpmem.h"
/*----------------------
* Compressor API
diff --git a/src/bin/pg_dump/dumpcatalog.c b/src/bin/pg_dump/dumpcatalog.c
new file mode .
index 9747d47..e69de29
*** a/src/bin/pg_dump/dumpcatalog.c
--- b/src/bin/pg_dump/dumpcatalog.c
***************
*** 1,978 ****
- /*-------------------------------------------------------------------------
- *
- * common.c
- * catalog routines used by pg_dump
- *
- * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/bin/pg_dump/dumpcatalog.c
- *
- *-------------------------------------------------------------------------
- */
- #include "postgres_fe.h"
-
- #include <ctype.h>
-
- #include "catalog/pg_class.h"
-
- #include "pg_backup_archiver.h"
- #include "common.h"
-
-
- /*
- * Variables for mapping DumpId to DumpableObject
- */
- static DumpableObject **dumpIdMap = NULL;
- static int allocedDumpIds = 0;
- static DumpId lastDumpId = 0;
-
- /*
- * Variables for mapping CatalogId to DumpableObject
- */
- static bool catalogIdMapValid = false;
- static DumpableObject **catalogIdMap = NULL;
- static int numCatalogIds = 0;
-
- /*
- * These variables are static to avoid the notational cruft of having to pass
- * them into findTableByOid() and friends. For each of these arrays, we
- * build a sorted-by-OID index array immediately after it's built, and then
- * we use binary search in findTableByOid() and friends. (qsort'ing the base
- * arrays themselves would be simpler, but it doesn't work because pg_dump.c
- * may have already established pointers between items.)
- */
- static TableInfo *tblinfo;
- static TypeInfo *typinfo;
- static FuncInfo *funinfo;
- static OprInfo *oprinfo;
- static int numTables;
- static int numTypes;
- static int numFuncs;
- static int numOperators;
- static int numCollations;
- static DumpableObject **tblinfoindex;
- static DumpableObject **typinfoindex;
- static DumpableObject **funinfoindex;
- static DumpableObject **oprinfoindex;
- static DumpableObject **collinfoindex;
-
-
- static void flagInhTables(TableInfo *tbinfo, int numTables,
- InhInfo *inhinfo, int numInherits);
- static void flagInhAttrs(TableInfo *tblinfo, int numTables);
- static DumpableObject **buildIndexArray(void *objArray, int numObjs,
- Size objSize);
- static int DOCatalogIdCompare(const void *p1, const void *p2);
- static void findParentsByOid(TableInfo *self,
- InhInfo *inhinfo, int numInherits);
- static int strInArray(const char *pattern, char **arr, int arr_size);
-
-
- /*
- * getSchemaData
- * Collect information about all potentially dumpable objects
- */
- TableInfo *
- getSchemaData(int *numTablesPtr)
- {
- ExtensionInfo *extinfo;
- InhInfo *inhinfo;
- CollInfo *collinfo;
- int numNamespaces;
- int numExtensions;
- int numAggregates;
- int numInherits;
- int numRules;
- int numProcLangs;
- int numCasts;
- int numOpclasses;
- int numOpfamilies;
- int numConversions;
- int numTSParsers;
- int numTSTemplates;
- int numTSDicts;
- int numTSConfigs;
- int numForeignDataWrappers;
- int numForeignServers;
- int numDefaultACLs;
-
- if (g_verbose)
- write_msg(NULL, "reading schemas\n");
- getNamespaces(&numNamespaces);
-
- /*
- * getTables should be done as soon as possible, so as to minimize the
- * window between starting our transaction and acquiring per-table locks.
- * However, we have to do getNamespaces first because the tables get
- * linked to their containing namespaces during getTables.
- */
- if (g_verbose)
- write_msg(NULL, "reading user-defined tables\n");
- tblinfo = getTables(&numTables);
- tblinfoindex = buildIndexArray(tblinfo, numTables, sizeof(TableInfo));
-
- if (g_verbose)
- write_msg(NULL, "reading extensions\n");
- extinfo = getExtensions(&numExtensions);
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined functions\n");
- funinfo = getFuncs(&numFuncs);
- funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo));
-
- /* this must be after getTables and getFuncs */
- if (g_verbose)
- write_msg(NULL, "reading user-defined types\n");
- typinfo = getTypes(&numTypes);
- typinfoindex = buildIndexArray(typinfo, numTypes, sizeof(TypeInfo));
-
- /* this must be after getFuncs, too */
- if (g_verbose)
- write_msg(NULL, "reading procedural languages\n");
- getProcLangs(&numProcLangs);
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined aggregate functions\n");
- getAggregates(&numAggregates);
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined operators\n");
- oprinfo = getOperators(&numOperators);
- oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo));
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined operator classes\n");
- getOpclasses(&numOpclasses);
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined operator families\n");
- getOpfamilies(&numOpfamilies);
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined text search parsers\n");
- getTSParsers(&numTSParsers);
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined text search templates\n");
- getTSTemplates(&numTSTemplates);
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined text search dictionaries\n");
- getTSDictionaries(&numTSDicts);
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined text search configurations\n");
- getTSConfigurations(&numTSConfigs);
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined foreign-data wrappers\n");
- getForeignDataWrappers(&numForeignDataWrappers);
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined foreign servers\n");
- getForeignServers(&numForeignServers);
-
- if (g_verbose)
- write_msg(NULL, "reading default privileges\n");
- getDefaultACLs(&numDefaultACLs);
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined collations\n");
- collinfo = getCollations(&numCollations);
- collinfoindex = buildIndexArray(collinfo, numCollations, sizeof(CollInfo));
-
- if (g_verbose)
- write_msg(NULL, "reading user-defined conversions\n");
- getConversions(&numConversions);
-
- if (g_verbose)
- write_msg(NULL, "reading type casts\n");
- getCasts(&numCasts);
-
- if (g_verbose)
- write_msg(NULL, "reading table inheritance information\n");
- inhinfo = getInherits(&numInherits);
-
- if (g_verbose)
- write_msg(NULL, "reading rewrite rules\n");
- getRules(&numRules);
-
- /*
- * Identify extension member objects and mark them as not to be dumped.
- * This must happen after reading all objects that can be direct members
- * of extensions, but before we begin to process table subsidiary objects.
- */
- if (g_verbose)
- write_msg(NULL, "finding extension members\n");
- getExtensionMembership(extinfo, numExtensions);
-
- /* Link tables to parents, mark parents of target tables interesting */
- if (g_verbose)
- write_msg(NULL, "finding inheritance relationships\n");
- flagInhTables(tblinfo, numTables, inhinfo, numInherits);
-
- if (g_verbose)
- write_msg(NULL, "reading column info for interesting tables\n");
- getTableAttrs(tblinfo, numTables);
-
- if (g_verbose)
- write_msg(NULL, "flagging inherited columns in subtables\n");
- flagInhAttrs(tblinfo, numTables);
-
- if (g_verbose)
- write_msg(NULL, "reading indexes\n");
- getIndexes(tblinfo, numTables);
-
- if (g_verbose)
- write_msg(NULL, "reading constraints\n");
- getConstraints(tblinfo, numTables);
-
- if (g_verbose)
- write_msg(NULL, "reading triggers\n");
- getTriggers(tblinfo, numTables);
-
- *numTablesPtr = numTables;
- return tblinfo;
- }
-
- /* flagInhTables -
- * Fill in parent link fields of every target table, and mark
- * parents of target tables as interesting
- *
- * Note that only direct ancestors of targets are marked interesting.
- * This is sufficient; we don't much care whether they inherited their
- * attributes or not.
- *
- * modifies tblinfo
- */
- static void
- flagInhTables(TableInfo *tblinfo, int numTables,
- InhInfo *inhinfo, int numInherits)
- {
- int i,
- j;
- int numParents;
- TableInfo **parents;
-
- for (i = 0; i < numTables; i++)
- {
- /* Sequences and views never have parents */
- if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
- tblinfo[i].relkind == RELKIND_VIEW)
- continue;
-
- /* Don't bother computing anything for non-target tables, either */
- if (!tblinfo[i].dobj.dump)
- continue;
-
- /* Find all the immediate parent tables */
- findParentsByOid(&tblinfo[i], inhinfo, numInherits);
-
- /* Mark the parents as interesting for getTableAttrs */
- numParents = tblinfo[i].numParents;
- parents = tblinfo[i].parents;
- for (j = 0; j < numParents; j++)
- parents[j]->interesting = true;
- }
- }
-
- /* flagInhAttrs -
- * for each dumpable table in tblinfo, flag its inherited attributes
- * so when we dump the table out, we don't dump out the inherited attributes
- *
- * modifies tblinfo
- */
- static void
- flagInhAttrs(TableInfo *tblinfo, int numTables)
- {
- int i,
- j,
- k;
-
- for (i = 0; i < numTables; i++)
- {
- TableInfo *tbinfo = &(tblinfo[i]);
- int numParents;
- TableInfo **parents;
- TableInfo *parent;
-
- /* Sequences and views never have parents */
- if (tbinfo->relkind == RELKIND_SEQUENCE ||
- tbinfo->relkind == RELKIND_VIEW)
- continue;
-
- /* Don't bother computing anything for non-target tables, either */
- if (!tbinfo->dobj.dump)
- continue;
-
- numParents = tbinfo->numParents;
- parents = tbinfo->parents;
-
- if (numParents == 0)
- continue; /* nothing to see here, move along */
-
- /*----------------------------------------------------------------
- * For each attr, check the parent info: if no parent has an attr
- * with the same name, then it's not inherited. If there *is* an
- * attr with the same name, then only dump it if:
- *
- * - it is NOT NULL and zero parents are NOT NULL
- * OR
- * - it has a default value AND the default value does not match
- * all parent default values, or no parents specify a default.
- *
- * See discussion on -hackers around 2-Apr-2001.
- *----------------------------------------------------------------
- */
- for (j = 0; j < tbinfo->numatts; j++)
- {
- bool foundAttr; /* Attr was found in a parent */
- bool foundNotNull; /* Attr was NOT NULL in a parent */
- bool defaultsMatch; /* All non-empty defaults match */
- bool defaultsFound; /* Found a default in a parent */
- AttrDefInfo *attrDef;
-
- foundAttr = false;
- foundNotNull = false;
- defaultsMatch = true;
- defaultsFound = false;
-
- attrDef = tbinfo->attrdefs[j];
-
- for (k = 0; k < numParents; k++)
- {
- int inhAttrInd;
-
- parent = parents[k];
- inhAttrInd = strInArray(tbinfo->attnames[j],
- parent->attnames,
- parent->numatts);
-
- if (inhAttrInd != -1)
- {
- AttrDefInfo *inhDef = parent->attrdefs[inhAttrInd];
-
- foundAttr = true;
- foundNotNull |= parent->notnull[inhAttrInd];
- if (inhDef != NULL)
- {
- defaultsFound = true;
-
- /*
- * If any parent has a default and the child doesn't,
- * we have to emit an explicit DEFAULT NULL clause for
- * the child, else the parent's default will win.
- */
- if (attrDef == NULL)
- {
- attrDef = (AttrDefInfo *) pg_malloc(sizeof(AttrDefInfo));
- attrDef->dobj.objType = DO_ATTRDEF;
- attrDef->dobj.catId.tableoid = 0;
- attrDef->dobj.catId.oid = 0;
- AssignDumpId(&attrDef->dobj);
- attrDef->adtable = tbinfo;
- attrDef->adnum = j + 1;
- attrDef->adef_expr = pg_strdup("NULL");
-
- attrDef->dobj.name = pg_strdup(tbinfo->dobj.name);
- attrDef->dobj.namespace = tbinfo->dobj.namespace;
-
- attrDef->dobj.dump = tbinfo->dobj.dump;
-
- attrDef->separate = false;
- addObjectDependency(&tbinfo->dobj,
- attrDef->dobj.dumpId);
-
- tbinfo->attrdefs[j] = attrDef;
- }
- if (strcmp(attrDef->adef_expr, inhDef->adef_expr) != 0)
- {
- defaultsMatch = false;
-
- /*
- * Whenever there is a non-matching parent
- * default, add a dependency to force the parent
- * default to be dumped first, in case the
- * defaults end up being dumped as separate
- * commands. Otherwise the parent default will
- * override the child's when it is applied.
- */
- addObjectDependency(&attrDef->dobj,
- inhDef->dobj.dumpId);
- }
- }
- }
- }
-
- /*
- * Based on the scan of the parents, decide if we can rely on the
- * inherited attr
- */
- if (foundAttr) /* Attr was inherited */
- {
- /* Set inherited flag by default */
- tbinfo->inhAttrs[j] = true;
- tbinfo->inhAttrDef[j] = true;
- tbinfo->inhNotNull[j] = true;
-
- /*
- * Clear it if attr had a default, but parents did not, or
- * mismatch
- */
- if ((attrDef != NULL) && (!defaultsFound || !defaultsMatch))
- {
- tbinfo->inhAttrs[j] = false;
- tbinfo->inhAttrDef[j] = false;
- }
-
- /*
- * Clear it if NOT NULL and none of the parents were NOT NULL
- */
- if (tbinfo->notnull[j] && !foundNotNull)
- {
- tbinfo->inhAttrs[j] = false;
- tbinfo->inhNotNull[j] = false;
- }
-
- /* Clear it if attr has local definition */
- if (tbinfo->attislocal[j])
- tbinfo->inhAttrs[j] = false;
- }
- }
- }
- }
-
- /*
- * AssignDumpId
- * Given a newly-created dumpable object, assign a dump ID,
- * and enter the object into the lookup table.
- *
- * The caller is expected to have filled in objType and catId,
- * but not any of the other standard fields of a DumpableObject.
- */
- void
- AssignDumpId(DumpableObject *dobj)
- {
- dobj->dumpId = ++lastDumpId;
- dobj->name = NULL; /* must be set later */
- dobj->namespace = NULL; /* may be set later */
- dobj->dump = true; /* default assumption */
- dobj->ext_member = false; /* default assumption */
- dobj->dependencies = NULL;
- dobj->nDeps = 0;
- dobj->allocDeps = 0;
-
- while (dobj->dumpId >= allocedDumpIds)
- {
- int newAlloc;
-
- if (allocedDumpIds <= 0)
- {
- newAlloc = 256;
- dumpIdMap = (DumpableObject **)
- pg_malloc(newAlloc * sizeof(DumpableObject *));
- }
- else
- {
- newAlloc = allocedDumpIds * 2;
- dumpIdMap = (DumpableObject **)
- pg_realloc(dumpIdMap, newAlloc * sizeof(DumpableObject *));
- }
- memset(dumpIdMap + allocedDumpIds, 0,
- (newAlloc - allocedDumpIds) * sizeof(DumpableObject *));
- allocedDumpIds = newAlloc;
- }
- dumpIdMap[dobj->dumpId] = dobj;
-
- /* mark catalogIdMap invalid, but don't rebuild it yet */
- catalogIdMapValid = false;
- }
-
- /*
- * Assign a DumpId that's not tied to a DumpableObject.
- *
- * This is used when creating a "fixed" ArchiveEntry that doesn't need to
- * participate in the sorting logic.
- */
- DumpId
- createDumpId(void)
- {
- return ++lastDumpId;
- }
-
- /*
- * Return the largest DumpId so far assigned
- */
- DumpId
- getMaxDumpId(void)
- {
- return lastDumpId;
- }
-
- /*
- * Find a DumpableObject by dump ID
- *
- * Returns NULL for invalid ID
- */
- DumpableObject *
- findObjectByDumpId(DumpId dumpId)
- {
- if (dumpId <= 0 || dumpId >= allocedDumpIds)
- return NULL; /* out of range? */
- return dumpIdMap[dumpId];
- }
-
- /*
- * Find a DumpableObject by catalog ID
- *
- * Returns NULL for unknown ID
- *
- * We use binary search in a sorted list that is built on first call.
- * If AssignDumpId() and findObjectByCatalogId() calls were freely intermixed,
- * the code would work, but possibly be very slow. In the current usage
- * pattern that does not happen, indeed we build the list at most twice.
- */
- DumpableObject *
- findObjectByCatalogId(CatalogId catalogId)
- {
- DumpableObject **low;
- DumpableObject **high;
-
- if (!catalogIdMapValid)
- {
- if (catalogIdMap)
- free(catalogIdMap);
- getDumpableObjects(&catalogIdMap, &numCatalogIds);
- if (numCatalogIds > 1)
- qsort((void *) catalogIdMap, numCatalogIds,
- sizeof(DumpableObject *), DOCatalogIdCompare);
- catalogIdMapValid = true;
- }
-
- /*
- * We could use bsearch() here, but the notational cruft of calling
- * bsearch is nearly as bad as doing it ourselves; and the generalized
- * bsearch function is noticeably slower as well.
- */
- if (numCatalogIds <= 0)
- return NULL;
- low = catalogIdMap;
- high = catalogIdMap + (numCatalogIds - 1);
- while (low <= high)
- {
- DumpableObject **middle;
- int difference;
-
- middle = low + (high - low) / 2;
- /* comparison must match DOCatalogIdCompare, below */
- difference = oidcmp((*middle)->catId.oid, catalogId.oid);
- if (difference == 0)
- difference = oidcmp((*middle)->catId.tableoid, catalogId.tableoid);
- if (difference == 0)
- return *middle;
- else if (difference < 0)
- low = middle + 1;
- else
- high = middle - 1;
- }
- return NULL;
- }
-
- /*
- * Find a DumpableObject by OID, in a pre-sorted array of one type of object
- *
- * Returns NULL for unknown OID
- */
- static DumpableObject *
- findObjectByOid(Oid oid, DumpableObject **indexArray, int numObjs)
- {
- DumpableObject **low;
- DumpableObject **high;
-
- /*
- * This is the same as findObjectByCatalogId except we assume we need not
- * look at table OID because the objects are all the same type.
- *
- * We could use bsearch() here, but the notational cruft of calling
- * bsearch is nearly as bad as doing it ourselves; and the generalized
- * bsearch function is noticeably slower as well.
- */
- if (numObjs <= 0)
- return NULL;
- low = indexArray;
- high = indexArray + (numObjs - 1);
- while (low <= high)
- {
- DumpableObject **middle;
- int difference;
-
- middle = low + (high - low) / 2;
- difference = oidcmp((*middle)->catId.oid, oid);
- if (difference == 0)
- return *middle;
- else if (difference < 0)
- low = middle + 1;
- else
- high = middle - 1;
- }
- return NULL;
- }
-
- /*
- * Build an index array of DumpableObject pointers, sorted by OID
- */
- static DumpableObject **
- buildIndexArray(void *objArray, int numObjs, Size objSize)
- {
- DumpableObject **ptrs;
- int i;
-
- ptrs = (DumpableObject **) pg_malloc(numObjs * sizeof(DumpableObject *));
- for (i = 0; i < numObjs; i++)
- ptrs[i] = (DumpableObject *) ((char *) objArray + i * objSize);
-
- /* We can use DOCatalogIdCompare to sort since its first key is OID */
- if (numObjs > 1)
- qsort((void *) ptrs, numObjs, sizeof(DumpableObject *),
- DOCatalogIdCompare);
-
- return ptrs;
- }
-
- /*
- * qsort comparator for pointers to DumpableObjects
- */
- static int
- DOCatalogIdCompare(const void *p1, const void *p2)
- {
- const DumpableObject *obj1 = *(DumpableObject * const *) p1;
- const DumpableObject *obj2 = *(DumpableObject * const *) p2;
- int cmpval;
-
- /*
- * Compare OID first since it's usually unique, whereas there will only be
- * a few distinct values of tableoid.
- */
- cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid);
- if (cmpval == 0)
- cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid);
- return cmpval;
- }
-
- /*
- * Build an array of pointers to all known dumpable objects
- *
- * This simply creates a modifiable copy of the internal map.
- */
- void
- getDumpableObjects(DumpableObject ***objs, int *numObjs)
- {
- int i,
- j;
-
- *objs = (DumpableObject **)
- pg_malloc(allocedDumpIds * sizeof(DumpableObject *));
- j = 0;
- for (i = 1; i < allocedDumpIds; i++)
- {
- if (dumpIdMap[i])
- (*objs)[j++] = dumpIdMap[i];
- }
- *numObjs = j;
- }
-
- /*
- * Add a dependency link to a DumpableObject
- *
- * Note: duplicate dependencies are currently not eliminated
- */
- void
- addObjectDependency(DumpableObject *dobj, DumpId refId)
- {
- if (dobj->nDeps >= dobj->allocDeps)
- {
- if (dobj->allocDeps <= 0)
- {
- dobj->allocDeps = 16;
- dobj->dependencies = (DumpId *)
- pg_malloc(dobj->allocDeps * sizeof(DumpId));
- }
- else
- {
- dobj->allocDeps *= 2;
- dobj->dependencies = (DumpId *)
- pg_realloc(dobj->dependencies,
- dobj->allocDeps * sizeof(DumpId));
- }
- }
- dobj->dependencies[dobj->nDeps++] = refId;
- }
-
- /*
- * Remove a dependency link from a DumpableObject
- *
- * If there are multiple links, all are removed
- */
- void
- removeObjectDependency(DumpableObject *dobj, DumpId refId)
- {
- int i;
- int j = 0;
-
- for (i = 0; i < dobj->nDeps; i++)
- {
- if (dobj->dependencies[i] != refId)
- dobj->dependencies[j++] = dobj->dependencies[i];
- }
- dobj->nDeps = j;
- }
-
-
- /*
- * findTableByOid
- * finds the entry (in tblinfo) of the table with the given oid
- * returns NULL if not found
- */
- TableInfo *
- findTableByOid(Oid oid)
- {
- return (TableInfo *) findObjectByOid(oid, tblinfoindex, numTables);
- }
-
- /*
- * findTypeByOid
- * finds the entry (in typinfo) of the type with the given oid
- * returns NULL if not found
- */
- TypeInfo *
- findTypeByOid(Oid oid)
- {
- return (TypeInfo *) findObjectByOid(oid, typinfoindex, numTypes);
- }
-
- /*
- * findFuncByOid
- * finds the entry (in funinfo) of the function with the given oid
- * returns NULL if not found
- */
- FuncInfo *
- findFuncByOid(Oid oid)
- {
- return (FuncInfo *) findObjectByOid(oid, funinfoindex, numFuncs);
- }
-
- /*
- * findOprByOid
- * finds the entry (in oprinfo) of the operator with the given oid
- * returns NULL if not found
- */
- OprInfo *
- findOprByOid(Oid oid)
- {
- return (OprInfo *) findObjectByOid(oid, oprinfoindex, numOperators);
- }
-
- /*
- * findCollationByOid
- * finds the entry (in collinfo) of the collation with the given oid
- * returns NULL if not found
- */
- CollInfo *
- findCollationByOid(Oid oid)
- {
- return (CollInfo *) findObjectByOid(oid, collinfoindex, numCollations);
- }
-
-
- /*
- * findParentsByOid
- * find a table's parents in tblinfo[]
- */
- static void
- findParentsByOid(TableInfo *self,
- InhInfo *inhinfo, int numInherits)
- {
- Oid oid = self->dobj.catId.oid;
- int i,
- j;
- int numParents;
-
- numParents = 0;
- for (i = 0; i < numInherits; i++)
- {
- if (inhinfo[i].inhrelid == oid)
- numParents++;
- }
-
- self->numParents = numParents;
-
- if (numParents > 0)
- {
- self->parents = (TableInfo **)
- pg_malloc(sizeof(TableInfo *) * numParents);
- j = 0;
- for (i = 0; i < numInherits; i++)
- {
- if (inhinfo[i].inhrelid == oid)
- {
- TableInfo *parent;
-
- parent = findTableByOid(inhinfo[i].inhparent);
- if (parent == NULL)
- {
- write_msg(NULL, "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found\n",
- inhinfo[i].inhparent,
- self->dobj.name,
- oid);
- exit_nicely();
- }
- self->parents[j++] = parent;
- }
- }
- }
- else
- self->parents = NULL;
- }
-
- /*
- * parseOidArray
- * parse a string of numbers delimited by spaces into a character array
- *
- * Note: actually this is used for both Oids and potentially-signed
- * attribute numbers. This should cause no trouble, but we could split
- * the function into two functions with different argument types if it does.
- */
-
- void
- parseOidArray(const char *str, Oid *array, int arraysize)
- {
- int j,
- argNum;
- char temp[100];
- char s;
-
- argNum = 0;
- j = 0;
- for (;;)
- {
- s = *str++;
- if (s == ' ' || s == '\0')
- {
- if (j > 0)
- {
- if (argNum >= arraysize)
- {
- write_msg(NULL, "could not parse numeric array \"%s\": too many numbers\n", str);
- exit_nicely();
- }
- temp[j] = '\0';
- array[argNum++] = atooid(temp);
- j = 0;
- }
- if (s == '\0')
- break;
- }
- else
- {
- if (!(isdigit((unsigned char) s) || s == '-') ||
- j >= sizeof(temp) - 1)
- {
- write_msg(NULL, "could not parse numeric array \"%s\": invalid character in number\n", str);
- exit_nicely();
- }
- temp[j++] = s;
- }
- }
-
- while (argNum < arraysize)
- array[argNum++] = InvalidOid;
- }
-
-
- /*
- * strInArray:
- * takes in a string and a string array and the number of elements in the
- * string array.
- * returns the index if the string is somewhere in the array, -1 otherwise
- */
-
- static int
- strInArray(const char *pattern, char **arr, int arr_size)
- {
- int i;
-
- for (i = 0; i < arr_size; i++)
- {
- if (strcmp(pattern, arr[i]) == 0)
- return i;
- }
- return -1;
- }
-
-
- /*
- * Support for simple list operations
- */
-
- void
- simple_oid_list_append(SimpleOidList *list, Oid val)
- {
- SimpleOidListCell *cell;
-
- cell = (SimpleOidListCell *) pg_malloc(sizeof(SimpleOidListCell));
- cell->next = NULL;
- cell->val = val;
-
- if (list->tail)
- list->tail->next = cell;
- else
- list->head = cell;
- list->tail = cell;
- }
-
- void
- simple_string_list_append(SimpleStringList *list, const char *val)
- {
- SimpleStringListCell *cell;
-
- /* this calculation correctly accounts for the null trailing byte */
- cell = (SimpleStringListCell *)
- pg_malloc(sizeof(SimpleStringListCell) + strlen(val));
- cell->next = NULL;
- strcpy(cell->val, val);
-
- if (list->tail)
- list->tail->next = cell;
- else
- list->head = cell;
- list->tail = cell;
- }
-
- bool
- simple_oid_list_member(SimpleOidList *list, Oid val)
- {
- SimpleOidListCell *cell;
-
- for (cell = list->head; cell; cell = cell->next)
- {
- if (cell->val == val)
- return true;
- }
- return false;
- }
-
- bool
- simple_string_list_member(SimpleStringList *list, const char *val)
- {
- SimpleStringListCell *cell;
-
- for (cell = list->head; cell; cell = cell->next)
- {
- if (strcmp(cell->val, val) == 0)
- return true;
- }
- return false;
- }
--- 0 ----
diff --git a/src/bin/pg_dump/dumpmem.c b/src/bin/pg_dump/dumpmem.c
new file mode 100644
index ...a50f4f5
*** a/src/bin/pg_dump/dumpmem.c
--- b/src/bin/pg_dump/dumpmem.c
***************
*** 0 ****
--- 1,73 ----
+ /*-------------------------------------------------------------------------
+ *
+ * dumpmem.c
+ * memory routines used by pg_dump and pg_restore (but not pg_dumpall
+ * because there is no failure location to report).
+ *
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/bin/pg_dump/dumpmem.c
+ *
+ *-------------------------------------------------------------------------
+ */
+ #include "postgres_fe.h"
+ #include "pg_backup.h"
+ #include "dumpmem.h"
+
+ #include <ctype.h>
+
+ /*
+ * Safer versions of some standard C library functions. If an
+ * out-of-memory condition occurs, these functions will bail out
+ * safely; therefore, their return value is guaranteed to be non-NULL.
+ * We also report the program name and close the database connection.
+ */
+
+ char *
+ pg_strdup(const char *string)
+ {
+ char *tmp;
+
+ if (!string)
+ exit_horribly(NULL, NULL, "cannot duplicate null pointer\n");
+ tmp = strdup(string);
+ if (!tmp)
+ exit_horribly(NULL, NULL, "out of memory\n");
+ return tmp;
+ }
+
+ void *
+ pg_malloc(size_t size)
+ {
+ void *tmp;
+
+ tmp = malloc(size);
+ if (!tmp)
+ exit_horribly(NULL, NULL, "out of memory\n");
+ return tmp;
+ }
+
+ void *
+ pg_calloc(size_t nmemb, size_t size)
+ {
+ void *tmp;
+
+ tmp = calloc(nmemb, size);
+ if (!tmp)
+ exit_horribly(NULL, NULL, _("out of memory\n"));
+ return tmp;
+ }
+
+ void *
+ pg_realloc(void *ptr, size_t size)
+ {
+ void *tmp;
+
+ tmp = realloc(ptr, size);
+ if (!tmp)
+ exit_horribly(NULL, NULL, _("out of memory\n"));
+ return tmp;
+ }
diff --git a/src/bin/pg_dump/dumpmem.h b/src/bin/pg_dump/dumpmem.h
new file mode 100644
index ...f70b320
*** a/src/bin/pg_dump/dumpmem.h
--- b/src/bin/pg_dump/dumpmem.h
***************
*** 0 ****
--- 1,24 ----
+ /*-------------------------------------------------------------------------
+ *
+ * dumpmem.h
+ * Common header file for the pg_dump and pg_restore
+ *
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/bin/pg_dump/dumpmem.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+ #ifndef DUMPMEM_H
+ #define DUMPMEM_H
+
+ #include "postgres_fe.h"
+
+ extern char *pg_strdup(const char *string);
+ extern void *pg_malloc(size_t size);
+ extern void *pg_calloc(size_t nmemb, size_t size);
+ extern void *pg_realloc(void *ptr, size_t size);
+
+ #endif /* DUMPMEM_H */
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
new file mode 100644
index 5cc012d..92b9d28
*** a/src/bin/pg_dump/dumputils.c
--- b/src/bin/pg_dump/dumputils.c
***************
*** 16,22 ****
#include <ctype.h>
! #include "common.h"
#include "dumputils.h"
#include "parser/keywords.h"
--- 16,22 ----
#include <ctype.h>
! #include "dumpmem.h"
#include "dumputils.h"
#include "parser/keywords.h"
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
new file mode 100644
index 8fb8382..164d593
*** a/src/bin/pg_dump/pg_backup_archiver.c
--- b/src/bin/pg_dump/pg_backup_archiver.c
***************
*** 21,27 ****
*/
#include "pg_backup_db.h"
! #include "common.h"
#include "dumputils.h"
#include <ctype.h>
--- 21,27 ----
*/
#include "pg_backup_db.h"
! #include "dumpmem.h"
#include "dumputils.h"
#include <ctype.h>
diff --git a/src/bin/pg_dump/pg_backup_custom.c b/src/bin/pg_dump/pg_backup_custom.c
new file mode 100644
index bfdf482..b2f3196
*** a/src/bin/pg_dump/pg_backup_custom.c
--- b/src/bin/pg_dump/pg_backup_custom.c
***************
*** 25,31 ****
*/
#include "compress_io.h"
! #include "common.h"
/*--------
* Routines in the format interface
--- 25,31 ----
*/
#include "compress_io.h"
! #include "dumpmem.h"
/*--------
* Routines in the format interface
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
new file mode 100644
index a58eb2d..bd1b8ef
*** a/src/bin/pg_dump/pg_backup_db.c
--- b/src/bin/pg_dump/pg_backup_db.c
***************
*** 11,17 ****
*/
#include "pg_backup_db.h"
! #include "common.h"
#include "dumputils.h"
#include <unistd.h>
--- 11,17 ----
*/
#include "pg_backup_db.h"
! #include "dumpmem.h"
#include "dumputils.h"
#include <unistd.h>
diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c
new file mode 100644
index 4f9fcc2..bd18ec5
*** a/src/bin/pg_dump/pg_backup_directory.c
--- b/src/bin/pg_dump/pg_backup_directory.c
***************
*** 34,40 ****
*/
#include "compress_io.h"
! #include "common.h"
#include <dirent.h>
#include <sys/stat.h>
--- 34,40 ----
*/
#include "compress_io.h"
! #include "dumpmem.h"
#include <dirent.h>
#include <sys/stat.h>
diff --git a/src/bin/pg_dump/pg_backup_files.c b/src/bin/pg_dump/pg_backup_files.c
new file mode 100644
index 76366e1..85373b5
*** a/src/bin/pg_dump/pg_backup_files.c
--- b/src/bin/pg_dump/pg_backup_files.c
***************
*** 26,32 ****
*/
#include "pg_backup_archiver.h"
! #include "common.h"
static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te);
static void _StartData(ArchiveHandle *AH, TocEntry *te);
--- 26,32 ----
*/
#include "pg_backup_archiver.h"
! #include "dumpmem.h"
static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te);
static void _StartData(ArchiveHandle *AH, TocEntry *te);
diff --git a/src/bin/pg_dump/pg_backup_null.c b/src/bin/pg_dump/pg_backup_null.c
new file mode 100644
index 252e7a4..201f0d9
*** a/src/bin/pg_dump/pg_backup_null.c
--- b/src/bin/pg_dump/pg_backup_null.c
***************
*** 23,29 ****
*/
#include "pg_backup_archiver.h"
! #include "common.h"
#include "dumputils.h"
#include <unistd.h> /* for dup */
--- 23,29 ----
*/
#include "pg_backup_archiver.h"
! #include "dumpmem.h"
#include "dumputils.h"
#include <unistd.h> /* for dup */
diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c
new file mode 100644
index 94133cf..39ce417
*** a/src/bin/pg_dump/pg_backup_tar.c
--- b/src/bin/pg_dump/pg_backup_tar.c
***************
*** 28,34 ****
#include "pg_backup.h"
#include "pg_backup_archiver.h"
#include "pg_backup_tar.h"
! #include "common.h"
#include <sys/stat.h>
#include <ctype.h>
--- 28,34 ----
#include "pg_backup.h"
#include "pg_backup_archiver.h"
#include "pg_backup_tar.h"
! #include "dumpmem.h"
#include <sys/stat.h>
#include <ctype.h>
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
new file mode 100644
index e11ba4d..ec932e4
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
***************
*** 57,63 ****
#include "libpq/libpq-fs.h"
#include "pg_backup_archiver.h"
! #include "common.h"
#include "dumputils.h"
extern char *optarg;
--- 57,63 ----
#include "libpq/libpq-fs.h"
#include "pg_backup_archiver.h"
! #include "dumpmem.h"
#include "dumputils.h"
extern char *optarg;
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
new file mode 100644
index 3bb220d..8023450
*** a/src/bin/pg_dump/pg_dump_sort.c
--- b/src/bin/pg_dump/pg_dump_sort.c
***************
*** 14,20 ****
*-------------------------------------------------------------------------
*/
#include "pg_backup_archiver.h"
! #include "common.h"
static const char *modulename = gettext_noop("sorter");
--- 14,20 ----
*-------------------------------------------------------------------------
*/
#include "pg_backup_archiver.h"
! #include "dumpmem.h"
static const char *modulename = gettext_noop("sorter");
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
new file mode 100644
index a810ed6..ea68f51
*** a/src/bin/pg_dump/pg_restore.c
--- b/src/bin/pg_dump/pg_restore.c
***************
*** 39,45 ****
*-------------------------------------------------------------------------
*/
! #include "common.h"
#include "pg_backup_archiver.h"
#include "dumputils.h"
--- 39,45 ----
*-------------------------------------------------------------------------
*/
! #include "dumpmem.h"
#include "pg_backup_archiver.h"
#include "dumputils.h"