summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2015-08-04 19:34:12 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2015-08-04 19:34:12 -0400
commit3bdd7f90fc0a038ee8b5b3fd9f9507cf2f07a4b2 (patch)
treea91dececc4d6f193c8a3b721b9f935cf18e78e23
parent8ea3e7a75c0d22c41c57f59c8b367059b97d0b66 (diff)
downloadpostgresql-3bdd7f90fc0a038ee8b5b3fd9f9507cf2f07a4b2.tar.gz
Fix pg_dump to dump shell types.
Per discussion, it really ought to do this. The original choice to exclude shell types was probably made in the dark ages before we made it harder to accidentally create shell types; but that was in 7.3. Also, cause the standard regression tests to leave a shell type behind, for convenience in testing the case in pg_dump and pg_upgrade. Back-patch to all supported branches.
-rw-r--r--src/bin/pg_dump/pg_dump.c77
-rw-r--r--src/bin/pg_dump/pg_dump.h2
-rw-r--r--src/test/regress/expected/create_type.out2
-rw-r--r--src/test/regress/sql/create_type.sql3
4 files changed, 77 insertions, 7 deletions
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 00b8676633..51b6d3ae77 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -158,6 +158,7 @@ static void dumpType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
static void dumpBaseType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
static void dumpEnumType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
static void dumpRangeType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
+static void dumpUndefinedType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
static void dumpDomain(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
static void dumpCompositeType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
static void dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo);
@@ -1329,11 +1330,6 @@ selectDumpableType(TypeInfo *tyinfo)
/* dump only types in dumpable namespaces */
if (!tyinfo->dobj.namespace->dobj.dump)
tyinfo->dobj.dump = false;
-
- /* skip undefined placeholder types */
- else if (!tyinfo->isDefined)
- tyinfo->dobj.dump = false;
-
else
tyinfo->dobj.dump = true;
}
@@ -3707,7 +3703,7 @@ getTypes(Archive *fout, int *numTypes)
}
}
- if (strlen(tyinfo[i].rolname) == 0 && tyinfo[i].isDefined)
+ if (strlen(tyinfo[i].rolname) == 0)
write_msg(NULL, "WARNING: owner of data type \"%s\" appears to be invalid\n",
tyinfo[i].dobj.name);
}
@@ -8554,6 +8550,8 @@ dumpType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo)
dumpEnumType(fout, dopt, tyinfo);
else if (tyinfo->typtype == TYPTYPE_RANGE)
dumpRangeType(fout, dopt, tyinfo);
+ else if (tyinfo->typtype == TYPTYPE_PSEUDO && !tyinfo->isDefined)
+ dumpUndefinedType(fout, dopt, tyinfo);
else
write_msg(NULL, "WARNING: typtype of data type \"%s\" appears to be invalid\n",
tyinfo->dobj.name);
@@ -8821,6 +8819,73 @@ dumpRangeType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo)
}
/*
+ * dumpUndefinedType
+ * writes out to fout the queries to recreate a !typisdefined type
+ *
+ * This is a shell type, but we use different terminology to distinguish
+ * this case from where we have to emit a shell type definition to break
+ * circular dependencies. An undefined type shouldn't ever have anything
+ * depending on it.
+ */
+static void
+dumpUndefinedType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo)
+{
+ PQExpBuffer q = createPQExpBuffer();
+ PQExpBuffer delq = createPQExpBuffer();
+ PQExpBuffer labelq = createPQExpBuffer();
+ char *qtypname;
+
+ qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+
+ /*
+ * DROP must be fully qualified in case same name appears in pg_catalog.
+ */
+ appendPQExpBuffer(delq, "DROP TYPE %s.",
+ fmtId(tyinfo->dobj.namespace->dobj.name));
+ appendPQExpBuffer(delq, "%s;\n",
+ qtypname);
+
+ if (dopt->binary_upgrade)
+ binary_upgrade_set_type_oids_by_type_oid(fout,
+ q, tyinfo->dobj.catId.oid);
+
+ appendPQExpBuffer(q, "CREATE TYPE %s;\n",
+ qtypname);
+
+ appendPQExpBuffer(labelq, "TYPE %s", qtypname);
+
+ if (dopt->binary_upgrade)
+ binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+
+ ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
+ tyinfo->dobj.name,
+ tyinfo->dobj.namespace->dobj.name,
+ NULL,
+ tyinfo->rolname, false,
+ "TYPE", SECTION_PRE_DATA,
+ q->data, delq->data, NULL,
+ NULL, 0,
+ NULL, NULL);
+
+ /* Dump Type Comments and Security Labels */
+ dumpComment(fout, dopt, labelq->data,
+ tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
+ tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
+ dumpSecLabel(fout, dopt, labelq->data,
+ tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
+ tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
+
+ dumpACL(fout, dopt, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
+ qtypname, NULL, tyinfo->dobj.name,
+ tyinfo->dobj.namespace->dobj.name,
+ tyinfo->rolname, tyinfo->typacl);
+
+ destroyPQExpBuffer(q);
+ destroyPQExpBuffer(delq);
+ destroyPQExpBuffer(labelq);
+}
+
+/*
* dumpBaseType
* writes out to fout the queries to recreate a user-defined base type
*/
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 009dba5c9d..da7597ded1 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -127,7 +127,7 @@ typedef struct _typeInfo
char typtype; /* 'b', 'c', etc */
bool isArray; /* true if auto-generated array type */
bool isDefined; /* true if typisdefined */
- /* If it's a dumpable base type, we create a "shell type" entry for it */
+ /* If needed, we'll create a "shell type" entry for it; link that here: */
struct _shellTypeInfo *shellType; /* shell-type entry, or NULL */
/* If it's a domain, we store links to its constraints here: */
int nDomChecks;
diff --git a/src/test/regress/expected/create_type.out b/src/test/regress/expected/create_type.out
index b5af862ce5..7bdad4e9bb 100644
--- a/src/test/regress/expected/create_type.out
+++ b/src/test/regress/expected/create_type.out
@@ -29,6 +29,8 @@ ERROR: type "shell" already exists
DROP TYPE shell;
DROP TYPE shell; -- fail, type not exist
ERROR: type "shell" does not exist
+-- also, let's leave one around for purposes of pg_dump testing
+CREATE TYPE myshell;
--
-- Test type-related default values (broken in releases before PG 7.2)
--
diff --git a/src/test/regress/sql/create_type.sql b/src/test/regress/sql/create_type.sql
index 29ba625b46..a1839ef9e7 100644
--- a/src/test/regress/sql/create_type.sql
+++ b/src/test/regress/sql/create_type.sql
@@ -31,6 +31,9 @@ CREATE TYPE shell; -- fail, type already present
DROP TYPE shell;
DROP TYPE shell; -- fail, type not exist
+-- also, let's leave one around for purposes of pg_dump testing
+CREATE TYPE myshell;
+
--
-- Test type-related default values (broken in releases before PG 7.2)
--