* by PostgreSQL
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.430 2006/02/21 18:01:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.431 2006/03/02 01:18:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
static void dumpBaseType(Archive *fout, TypeInfo *tinfo);
static void dumpDomain(Archive *fout, TypeInfo *tinfo);
static void dumpCompositeType(Archive *fout, TypeInfo *tinfo);
+static void dumpShellType(Archive *fout, ShellTypeInfo *stinfo);
static void dumpProcLang(Archive *fout, ProcLangInfo *plang);
static void dumpFunc(Archive *fout, FuncInfo *finfo);
static void dumpCast(Archive *fout, CastInfo *cast);
* namespace. Otherwise, dump all non-system namespaces.
*/
if (selectTableName != NULL)
- nsinfo->dump = false;
+ nsinfo->dobj.dump = false;
else if (selectSchemaName != NULL)
{
if (strcmp(nsinfo->dobj.name, selectSchemaName) == 0)
- nsinfo->dump = true;
+ nsinfo->dobj.dump = true;
else
- nsinfo->dump = false;
+ nsinfo->dobj.dump = false;
}
else if (strncmp(nsinfo->dobj.name, "pg_", 3) == 0 ||
strcmp(nsinfo->dobj.name, "information_schema") == 0)
- nsinfo->dump = false;
+ nsinfo->dobj.dump = false;
else
- nsinfo->dump = true;
+ nsinfo->dobj.dump = true;
}
/*
* tablename has been specified, dump matching table name; else, do not
* dump.
*/
- tbinfo->dump = false;
- if (tbinfo->dobj.namespace->dump)
- tbinfo->dump = true;
+ tbinfo->dobj.dump = false;
+ if (tbinfo->dobj.namespace->dobj.dump)
+ tbinfo->dobj.dump = true;
else if (selectTableName != NULL &&
strcmp(tbinfo->dobj.name, selectTableName) == 0)
{
/* If both -s and -t specified, must match both to dump */
if (selectSchemaName == NULL)
- tbinfo->dump = true;
+ tbinfo->dobj.dump = true;
else if (strcmp(tbinfo->dobj.namespace->dobj.name, selectSchemaName) == 0)
- tbinfo->dump = true;
+ tbinfo->dobj.dump = true;
}
}
+/*
+ * selectDumpableType: policy-setting subroutine
+ * Mark a type as to be dumped or not
+ */
+static void
+selectDumpableType(TypeInfo *tinfo)
+{
+ /* Dump only types in dumpable namespaces */
+ if (!tinfo->dobj.namespace->dobj.dump)
+ tinfo->dobj.dump = false;
+
+ /* skip complex types, except for standalone composite types */
+ /* (note: this test should now be unnecessary) */
+ else if (OidIsValid(tinfo->typrelid) &&
+ tinfo->typrelkind != RELKIND_COMPOSITE_TYPE)
+ tinfo->dobj.dump = false;
+
+ /* skip undefined placeholder types */
+ else if (!tinfo->isDefined)
+ tinfo->dobj.dump = false;
+
+ /* skip all array types that start w/ underscore */
+ else if ((tinfo->dobj.name[0] == '_') &&
+ OidIsValid(tinfo->typelem))
+ tinfo->dobj.dump = false;
+
+ else
+ tinfo->dobj.dump = true;
+}
+
+/*
+ * selectDumpableObject: policy-setting subroutine
+ * Mark a generic dumpable object as to be dumped or not
+ *
+ * Use this only for object types without a special-case routine above.
+ */
+static void
+selectDumpableObject(DumpableObject *dobj)
+{
+ /*
+ * Default policy is to dump if parent namespace is dumpable,
+ * or always for non-namespace-associated items.
+ */
+ if (dobj->namespace)
+ dobj->dump = dobj->namespace->dobj.dump;
+ else
+ dobj->dump = true;
+}
+
/*
* Dump a table's contents for loading using the COPY command
* - this routine is called by the Archiver when it wants the table
if (tblinfo[i].relkind == RELKIND_SEQUENCE)
continue;
- if (tblinfo[i].dump)
+ if (tblinfo[i].dobj.dump)
{
TableDataInfo *tdinfo;
int i;
PQExpBuffer query = createPQExpBuffer();
TypeInfo *tinfo;
+ ShellTypeInfo *stinfo;
int i_tableoid;
int i_oid;
int i_typname;
for (i = 0; i < ntups; i++)
{
- Oid typoutput;
- FuncInfo *funcInfo;
-
tinfo[i].dobj.objType = DO_TYPE;
tinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
tinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
tinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_typnamespace)),
tinfo[i].dobj.catId.oid);
tinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
- tinfo[i].typinput = atooid(PQgetvalue(res, i, i_typinput));
- typoutput = atooid(PQgetvalue(res, i, i_typoutput));
tinfo[i].typelem = atooid(PQgetvalue(res, i, i_typelem));
tinfo[i].typrelid = atooid(PQgetvalue(res, i, i_typrelid));
tinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind);
tinfo[i].typtype = *PQgetvalue(res, i, i_typtype);
+ tinfo[i].shellType = NULL;
/*
* If it's a table's rowtype, use special type code to facilitate
else
tinfo[i].isDefined = false;
+ /* Decide whether we want to dump it */
+ selectDumpableType(&tinfo[i]);
+
/*
* If it's a domain, fetch info about its constraints, if any
*/
tinfo[i].nDomChecks = 0;
tinfo[i].domChecks = NULL;
- if (tinfo[i].typtype == 'd')
+ if (tinfo[i].dobj.dump && tinfo[i].typtype == 'd')
getDomainConstraints(&(tinfo[i]));
/*
- * Make sure there are dependencies from the type to its input and
- * output functions. (We don't worry about typsend, typreceive, or
- * typanalyze since those are only valid in 7.4 and later, wherein the
- * standard dependency mechanism will pick them up.)
+ * If it's a base type, make a DumpableObject representing a shell
+ * definition of the type. We will need to dump that ahead of the
+ * I/O functions for the type.
+ *
+ * Note: the shell type doesn't have a catId. You might think it
+ * should copy the base type's catId, but then it might capture
+ * the pg_depend entries for the type, which we don't want.
*/
- funcInfo = findFuncByOid(tinfo[i].typinput);
- if (funcInfo)
- addObjectDependency(&tinfo[i].dobj,
- funcInfo->dobj.dumpId);
- funcInfo = findFuncByOid(typoutput);
- if (funcInfo)
- addObjectDependency(&tinfo[i].dobj,
- funcInfo->dobj.dumpId);
+ if (tinfo[i].dobj.dump && tinfo[i].typtype == 'b')
+ {
+ stinfo = (ShellTypeInfo *) malloc(sizeof(ShellTypeInfo));
+ stinfo->dobj.objType = DO_SHELL_TYPE;
+ stinfo->dobj.catId = nilCatalogId;
+ AssignDumpId(&stinfo->dobj);
+ stinfo->dobj.name = strdup(tinfo[i].dobj.name);
+ stinfo->dobj.namespace = tinfo[i].dobj.namespace;
+ stinfo->baseType = &(tinfo[i]);
+ tinfo[i].shellType = stinfo;
+
+ /*
+ * Initially mark the shell type as not to be dumped. We'll
+ * only dump it if the I/O functions need to be dumped; this
+ * is taken care of while sorting dependencies.
+ */
+ stinfo->dobj.dump = false;
+
+ /*
+ * However, if dumping from pre-7.3, there will be no dependency
+ * info so we have to fake it here. We only need to worry about
+ * typinput and typoutput since the other functions only exist
+ * post-7.3.
+ */
+ if (g_fout->remoteVersion < 70300)
+ {
+ Oid typinput;
+ Oid typoutput;
+ FuncInfo *funcInfo;
+
+ typinput = atooid(PQgetvalue(res, i, i_typinput));
+ typoutput = atooid(PQgetvalue(res, i, i_typoutput));
+
+ funcInfo = findFuncByOid(typinput);
+ if (funcInfo && funcInfo->dobj.dump)
+ {
+ /* base type depends on function */
+ addObjectDependency(&tinfo[i].dobj,
+ funcInfo->dobj.dumpId);
+ /* function depends on shell type */
+ addObjectDependency(&funcInfo->dobj,
+ stinfo->dobj.dumpId);
+ /* mark shell type as to be dumped */
+ stinfo->dobj.dump = true;
+ }
+
+ funcInfo = findFuncByOid(typoutput);
+ if (funcInfo && funcInfo->dobj.dump)
+ {
+ /* base type depends on function */
+ addObjectDependency(&tinfo[i].dobj,
+ funcInfo->dobj.dumpId);
+ /* function depends on shell type */
+ addObjectDependency(&funcInfo->dobj,
+ stinfo->dobj.dumpId);
+ /* mark shell type as to be dumped */
+ stinfo->dobj.dump = true;
+ }
+ }
+ }
if (strlen(tinfo[i].rolname) == 0 && tinfo[i].isDefined)
write_msg(NULL, "WARNING: owner of data type \"%s\" appears to be invalid\n",
oprinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));
+ /* Decide whether we want to dump it */
+ selectDumpableObject(&(oprinfo[i].dobj));
+
if (strlen(oprinfo[i].rolname) == 0)
write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
oprinfo[i].dobj.name);
convinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_connamespace)),
convinfo[i].dobj.catId.oid);
convinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+
+ /* Decide whether we want to dump it */
+ selectDumpableObject(&(convinfo[i].dobj));
}
PQclear(res);
opcinfo[i].dobj.catId.oid);
opcinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+ /* Decide whether we want to dump it */
+ selectDumpableObject(&(opcinfo[i].dobj));
+
if (g_fout->remoteVersion >= 70300)
{
if (strlen(opcinfo[i].rolname) == 0)
agginfo[i].aggfn.proacl = strdup(PQgetvalue(res, i, i_aggacl));
agginfo[i].anybasetype = false; /* computed when it's dumped */
agginfo[i].fmtbasetype = NULL; /* computed when it's dumped */
+
+ /* Decide whether we want to dump it */
+ selectDumpableObject(&(agginfo[i].aggfn.dobj));
}
PQclear(res);
finfo[i].argtypes, finfo[i].nargs);
}
+ /* Decide whether we want to dump it */
+ selectDumpableObject(&(finfo[i].dobj));
+
if (strlen(finfo[i].rolname) == 0)
write_msg(NULL,
"WARNING: owner of function \"%s\" appears to be invalid\n",
* their owning table's dump flag to them below.
*/
if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
- tblinfo[i].dump = false;
+ tblinfo[i].dobj.dump = false;
else if (OidIsValid(tblinfo[i].owning_tab))
- tblinfo[i].dump = false;
+ tblinfo[i].dobj.dump = false;
else
selectDumpableTable(&tblinfo[i]);
- tblinfo[i].interesting = tblinfo[i].dump;
+ tblinfo[i].interesting = tblinfo[i].dobj.dump;
/*
* Read-lock target tables to make sure they aren't DROPPED or altered
* NOTE: it'd be kinda nice to lock views and sequences too, not only
* plain tables, but the backend doesn't presently allow that.
*/
- if (tblinfo[i].dump && tblinfo[i].relkind == RELKIND_RELATION)
+ if (tblinfo[i].dobj.dump && tblinfo[i].relkind == RELKIND_RELATION)
{
resetPQExpBuffer(lockquery);
appendPQExpBuffer(lockquery,
if (tbinfo->relkind != RELKIND_RELATION || !tbinfo->hasindex)
continue;
- if (!tbinfo->dump)
+ /* Ignore indexes of tables not to be dumped */
+ if (!tbinfo->dobj.dump)
continue;
if (g_verbose)
{
TableInfo *tbinfo = &tblinfo[i];
- if (tbinfo->ntrig == 0 || !tbinfo->dump)
+ if (tbinfo->ntrig == 0 || !tbinfo->dobj.dump)
continue;
if (g_verbose)
exit_nicely();
}
ruleinfo[i].dobj.namespace = ruleinfo[i].ruletable->dobj.namespace;
+ ruleinfo[i].dobj.dump = ruleinfo[i].ruletable->dobj.dump;
ruleinfo[i].ev_type = *(PQgetvalue(res, i, i_ev_type));
ruleinfo[i].is_instead = *(PQgetvalue(res, i, i_is_instead)) == 't';
if (ruleinfo[i].ruletable)
{
TableInfo *tbinfo = &tblinfo[i];
- if (tbinfo->ntrig == 0 || !tbinfo->dump)
+ if (tbinfo->ntrig == 0 || !tbinfo->dobj.dump)
continue;
if (g_verbose)
attrdefs[j].dobj.name = strdup(tbinfo->dobj.name);
attrdefs[j].dobj.namespace = tbinfo->dobj.namespace;
+ attrdefs[j].dobj.dump = tbinfo->dobj.dump;
+
/*
* Defaults on a VIEW must always be dumped as separate ALTER
* TABLE commands. Defaults on regular tables are dumped as
constrs[j].coninherited = false;
constrs[j].separate = false;
+ constrs[j].dobj.dump = tbinfo->dobj.dump;
+
/*
* Mark the constraint as needing to appear before the table
* --- this is so that any other dependencies of the
*/
tbinfo->attisserial[j] = true;
seqinfo->interesting = tbinfo->interesting;
- seqinfo->dump = tbinfo->dump;
+ seqinfo->dobj.dump = tbinfo->dobj.dump;
break;
}
}
case DO_TYPE:
dumpType(fout, (TypeInfo *) dobj);
break;
+ case DO_SHELL_TYPE:
+ dumpShellType(fout, (ShellTypeInfo *) dobj);
+ break;
case DO_FUNC:
dumpFunc(fout, (FuncInfo *) dobj);
break;
PQExpBuffer delq;
char *qnspname;
- /* skip if not to be dumped */
- if (!nspinfo->dump || dataOnly)
+ /* Skip if not to be dumped */
+ if (!nspinfo->dobj.dump || dataOnly)
return;
/* don't dump dummy namespace from pre-7.3 source */
static void
dumpType(Archive *fout, TypeInfo *tinfo)
{
- /* Dump only types in dumpable namespaces */
- if (!tinfo->dobj.namespace->dump || dataOnly)
- return;
-
- /* skip complex types, except for standalone composite types */
- /* (note: this test should now be unnecessary) */
- if (OidIsValid(tinfo->typrelid) &&
- tinfo->typrelkind != RELKIND_COMPOSITE_TYPE)
- return;
-
- /* skip undefined placeholder types */
- if (!tinfo->isDefined)
- return;
-
- /* skip all array types that start w/ underscore */
- if ((tinfo->dobj.name[0] == '_') &&
- OidIsValid(tinfo->typelem))
+ /* Skip if not to be dumped */
+ if (!tinfo->dobj.dump || dataOnly)
return;
/* Dump out in proper style */
typdefault = NULL;
/*
- * DROP must be fully qualified in case same name appears in pg_catalog
+ * DROP must be fully qualified in case same name appears in pg_catalog.
+ * The reason we include CASCADE is that the circular dependency between
+ * the type and its I/O functions makes it impossible to drop the type
+ * any other way.
*/
appendPQExpBuffer(delq, "DROP TYPE %s.",
fmtId(tinfo->dobj.namespace->dobj.name));
destroyPQExpBuffer(query);
}
+/*
+ * dumpShellType
+ * writes out to fout the queries to create a shell type
+ *
+ * We dump a shell definition in advance of the I/O functions for the type.
+ */
+static void
+dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
+{
+ PQExpBuffer q;
+
+ /* Skip if not to be dumped */
+ if (!stinfo->dobj.dump || dataOnly)
+ return;
+
+ q = createPQExpBuffer();
+
+ /*
+ * Note the lack of a DROP command for the shell type; any required DROP
+ * is driven off the base type entry, instead. This interacts with
+ * _printTocEntry()'s use of the presence of a DROP command to decide
+ * whether an entry needs an ALTER OWNER command. We don't want to
+ * alter the shell type's owner immediately on creation; that should
+ * happen only after it's filled in, otherwise the backend complains.
+ */
+
+ appendPQExpBuffer(q, "CREATE TYPE %s;\n",
+ fmtId(stinfo->dobj.name));
+
+ ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId,
+ stinfo->dobj.name,
+ stinfo->dobj.namespace->dobj.name,
+ NULL,
+ stinfo->baseType->rolname, false,
+ "SHELL TYPE", q->data, "", NULL,
+ stinfo->dobj.dependencies, stinfo->dobj.nDeps,
+ NULL, NULL);
+
+ destroyPQExpBuffer(q);
+}
+
/*
* Determine whether we want to dump definitions for procedural languages.
* Since the languages themselves don't have schemas, we can't rely on
*/
funcInfo = findFuncByOid(plang->lanplcallfoid);
- if (funcInfo != NULL && !funcInfo->dobj.namespace->dump)
+ if (funcInfo != NULL && !funcInfo->dobj.dump)
funcInfo = NULL; /* treat not-dumped same as not-found */
if (OidIsValid(plang->lanvalidator))
{
validatorInfo = findFuncByOid(plang->lanvalidator);
- if (validatorInfo != NULL && !validatorInfo->dobj.namespace->dump)
+ if (validatorInfo != NULL && !validatorInfo->dobj.dump)
validatorInfo = NULL;
}
char **argmodes = NULL;
char **argnames = NULL;
- /* Dump only funcs in dumpable namespaces */
- if (!finfo->dobj.namespace->dump || dataOnly)
+ /* Skip if not to be dumped */
+ if (!finfo->dobj.dump || dataOnly)
return;
query = createPQExpBuffer();
/*
* As per discussion we dump casts if one or more of the underlying
* objects (the conversion function and the two data types) are not
- * builtin AND if all of the non-builtin objects namespaces are included
- * in the dump. Builtin meaning, the namespace name does not start with
- * "pg_".
+ * builtin AND if all of the non-builtin objects are included in the dump.
+ * Builtin meaning, the namespace name does not start with "pg_".
*/
sourceInfo = findTypeByOid(cast->castsource);
targetInfo = findTypeByOid(cast->casttarget);
return;
/*
- * Skip cast if function isn't from pg_ and that namespace is not dumped.
+ * Skip cast if function isn't from pg_ and is not to be dumped.
*/
if (funcInfo &&
strncmp(funcInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
- !funcInfo->dobj.namespace->dump)
+ !funcInfo->dobj.dump)
return;
/*
- * Same for the Source type
+ * Same for the source type
*/
if (strncmp(sourceInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
- !sourceInfo->dobj.namespace->dump)
+ !sourceInfo->dobj.dump)
return;
/*
* and the target type.
*/
if (strncmp(targetInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
- !targetInfo->dobj.namespace->dump)
+ !targetInfo->dobj.dump)
return;
/* Make sure we are in proper schema (needed for getFormattedTypeName) */
char *oprltcmpop;
char *oprgtcmpop;
- /* Dump only operators in dumpable namespaces */
- if (!oprinfo->dobj.namespace->dump || dataOnly)
+ /* Skip if not to be dumped */
+ if (!oprinfo->dobj.dump || dataOnly)
return;
/*
bool needComma;
int i;
- /* Dump only opclasses in dumpable namespaces */
- if (!opcinfo->dobj.namespace->dump || dataOnly)
+ /* Skip if not to be dumped */
+ if (!opcinfo->dobj.dump || dataOnly)
return;
/*
const char *conproc;
bool condefault;
- /* Dump only conversions in dumpable namespaces */
- if (!convinfo->dobj.namespace->dump || dataOnly)
+ /* Skip if not to be dumped */
+ if (!convinfo->dobj.dump || dataOnly)
return;
query = createPQExpBuffer();
const char *agginitval;
bool convertok;
- /* Dump only aggs in dumpable namespaces */
- if (!agginfo->aggfn.dobj.namespace->dump || dataOnly)
+ /* Skip if not to be dumped */
+ if (!agginfo->aggfn.dobj.dump || dataOnly)
return;
query = createPQExpBuffer();
{
char *namecopy;
- if (tbinfo->dump)
+ if (tbinfo->dobj.dump)
{
if (tbinfo->relkind == RELKIND_SEQUENCE)
dumpSequence(fout, tbinfo);
PQExpBuffer delq;
/* Only print it if "separate" mode is selected */
- if (!tbinfo->dump || !adinfo->separate || dataOnly)
+ if (!tbinfo->dobj.dump || !adinfo->separate || dataOnly)
return;
/* Don't print inherited or serial defaults, either */
PQExpBuffer q;
PQExpBuffer delq;
- if (dataOnly)
- return;
- if (tbinfo && !tbinfo->dump)
+ /* Skip if not to be dumped */
+ if (!coninfo->dobj.dump || dataOnly)
return;
q = createPQExpBuffer();
/* CHECK constraint on a domain */
TypeInfo *tinfo = coninfo->condomain;
- /* Ignore if not to be dumped separately, or if not dumping domain */
- if (coninfo->separate && tinfo->dobj.namespace->dump)
+ /* Ignore if not to be dumped separately */
+ if (coninfo->separate)
{
appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
fmtId(tinfo->dobj.name));
PQExpBuffer delcmd;
PGresult *res;
- /*
- * Ignore rules for not-to-be-dumped tables
- */
- if (tbinfo == NULL || !tbinfo->dump || dataOnly)
+ /* Skip if not to be dumped */
+ if (!rinfo->dobj.dump || dataOnly)
return;
/*