📄 common.c
字号:
/*------------------------------------------------------------------------- * * common.c * common routines between pg_dump and pg4_dump * * Since pg4_dump is long-dead code, there is no longer any useful distinction * between this file and pg_dump.c. * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.87 2005/10/15 02:49:38 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres_fe.h"#include "pg_dump.h"#include "pg_backup_archiver.h"#include "postgres.h"#include "catalog/pg_class.h"#include <ctype.h>#include "libpq-fe.h"#ifndef HAVE_STRDUP#include "strdup.h"#endif/* * 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. */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 void flagInhTables(TableInfo *tbinfo, int numTables, InhInfo *inhinfo, int numInherits);static void flagInhAttrs(TableInfo *tbinfo, int numTables, InhInfo *inhinfo, int numInherits);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, const bool schemaOnly, const bool dataOnly){ NamespaceInfo *nsinfo; AggInfo *agginfo; InhInfo *inhinfo; RuleInfo *ruleinfo; ProcLangInfo *proclanginfo; CastInfo *castinfo; OpclassInfo *opcinfo; ConvInfo *convinfo; int numNamespaces; int numAggregates; int numInherits; int numRules; int numProcLangs; int numCasts; int numOpclasses; int numConversions; if (g_verbose) write_msg(NULL, "reading schemas\n"); nsinfo = getNamespaces(&numNamespaces); if (g_verbose) write_msg(NULL, "reading user-defined functions\n"); funinfo = getFuncs(&numFuncs); /* this must be after getFuncs */ if (g_verbose) write_msg(NULL, "reading user-defined types\n"); typinfo = getTypes(&numTypes); /* this must be after getFuncs, too */ if (g_verbose) write_msg(NULL, "reading procedural languages\n"); proclanginfo = getProcLangs(&numProcLangs); if (g_verbose) write_msg(NULL, "reading user-defined aggregate functions\n"); agginfo = getAggregates(&numAggregates); if (g_verbose) write_msg(NULL, "reading user-defined operators\n"); oprinfo = getOperators(&numOperators); if (g_verbose) write_msg(NULL, "reading user-defined operator classes\n"); opcinfo = getOpclasses(&numOpclasses); if (g_verbose) write_msg(NULL, "reading user-defined conversions\n"); convinfo = getConversions(&numConversions); if (g_verbose) write_msg(NULL, "reading user-defined tables\n"); tblinfo = getTables(&numTables); if (g_verbose) write_msg(NULL, "reading table inheritance information\n"); inhinfo = getInherits(&numInherits); if (g_verbose) write_msg(NULL, "reading rewrite rules\n"); ruleinfo = getRules(&numRules); if (g_verbose) write_msg(NULL, "reading type casts\n"); castinfo = getCasts(&numCasts); /* 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, inhinfo, numInherits); 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 voidflagInhTables(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].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 voidflagInhAttrs(TableInfo *tblinfo, int numTables, InhInfo *inhinfo, int numInherits){ 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->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) { foundAttr = true; foundNotNull |= parent->notnull[inhAttrInd]; if (attrDef != NULL) /* If we have a default, check * parent */ { AttrDefInfo *inhDef; inhDef = parent->attrdefs[inhAttrInd]; if (inhDef != NULL) { defaultsFound = true; defaultsMatch &= (strcmp(attrDef->adef_expr, inhDef->adef_expr) == 0); } } } } /* * 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; } } /* * Check for inherited CHECK constraints. We assume a constraint is * inherited if its name matches the name of any constraint in the * parent. Originally this code tried to compare the expression * texts, but that can fail if the parent and child tables are in * different schemas, because reverse-listing of function calls may * produce different text (schema-qualified or not) depending on * search path. We really need a more bulletproof way of detecting * inherited constraints --- pg_constraint should record this * explicitly! */ for (j = 0; j < tbinfo->ncheck; j++) { ConstraintInfo *constr; constr = &(tbinfo->checkexprs[j]); for (k = 0; k < numParents; k++) { int l; parent = parents[k]; for (l = 0; l < parent->ncheck; l++) { ConstraintInfo *pconstr = &(parent->checkexprs[l]); if (strcmp(pconstr->dobj.name, constr->dobj.name) == 0) { constr->coninherited = true; break; } } if (constr->coninherited) break; } } }}/* * 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 catalogId, * but not any of the other standard fields of a DumpableObject. */voidAssignDumpId(DumpableObject *dobj){ dobj->dumpId = ++lastDumpId; dobj->name = NULL; /* must be set later */ dobj->namespace = NULL; /* may be set later */ dobj->dependencies = NULL; dobj->nDeps = 0; dobj->allocDeps = 0; while (dobj->dumpId >= allocedDumpIds) { int newAlloc; if (allocedDumpIds <= 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -