Skip to content

Commit 5d175be

Browse files
committed
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.
1 parent bd32762 commit 5d175be

File tree

4 files changed

+68
-7
lines changed

4 files changed

+68
-7
lines changed

src/bin/pg_dump/pg_dump.c

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ static void dumpNamespace(Archive *fout, NamespaceInfo *nspinfo);
143143
static void dumpType(Archive *fout, TypeInfo *tyinfo);
144144
static void dumpBaseType(Archive *fout, TypeInfo *tyinfo);
145145
static void dumpEnumType(Archive *fout, TypeInfo *tyinfo);
146+
static void dumpUndefinedType(Archive *fout, TypeInfo *tyinfo);
146147
static void dumpDomain(Archive *fout, TypeInfo *tyinfo);
147148
static void dumpCompositeType(Archive *fout, TypeInfo *tyinfo);
148149
static void dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo);
@@ -1056,11 +1057,6 @@ selectDumpableType(TypeInfo *tyinfo)
10561057
/* dump only types in dumpable namespaces */
10571058
if (!tyinfo->dobj.namespace->dobj.dump)
10581059
tyinfo->dobj.dump = false;
1059-
1060-
/* skip undefined placeholder types */
1061-
else if (!tyinfo->isDefined)
1062-
tyinfo->dobj.dump = false;
1063-
10641060
else
10651061
tyinfo->dobj.dump = true;
10661062
}
@@ -2760,7 +2756,7 @@ getTypes(int *numTypes)
27602756
}
27612757
}
27622758

2763-
if (strlen(tyinfo[i].rolname) == 0 && tyinfo[i].isDefined)
2759+
if (strlen(tyinfo[i].rolname) == 0)
27642760
write_msg(NULL, "WARNING: owner of data type \"%s\" appears to be invalid\n",
27652761
tyinfo[i].dobj.name);
27662762
}
@@ -6711,6 +6707,11 @@ dumpType(Archive *fout, TypeInfo *tyinfo)
67116707
dumpCompositeType(fout, tyinfo);
67126708
else if (tyinfo->typtype == TYPTYPE_ENUM)
67136709
dumpEnumType(fout, tyinfo);
6710+
else if (tyinfo->typtype == TYPTYPE_PSEUDO && !tyinfo->isDefined)
6711+
dumpUndefinedType(fout, tyinfo);
6712+
else
6713+
write_msg(NULL, "WARNING: typtype of data type \"%s\" appears to be invalid\n",
6714+
tyinfo->dobj.name);
67146715
}
67156716

67166717
/*
@@ -6818,6 +6819,61 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
68186819
destroyPQExpBuffer(query);
68196820
}
68206821

6822+
/*
6823+
* dumpUndefinedType
6824+
* writes out to fout the queries to recreate a !typisdefined type
6825+
*
6826+
* This is a shell type, but we use different terminology to distinguish
6827+
* this case from where we have to emit a shell type definition to break
6828+
* circular dependencies. An undefined type shouldn't ever have anything
6829+
* depending on it.
6830+
*/
6831+
static void
6832+
dumpUndefinedType(Archive *fout, TypeInfo *tyinfo)
6833+
{
6834+
PQExpBuffer q = createPQExpBuffer();
6835+
PQExpBuffer delq = createPQExpBuffer();
6836+
PQExpBuffer labelq = createPQExpBuffer();
6837+
char *qtypname;
6838+
6839+
qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
6840+
6841+
/*
6842+
* DROP must be fully qualified in case same name appears in pg_catalog.
6843+
*/
6844+
appendPQExpBuffer(delq, "DROP TYPE %s.",
6845+
fmtId(tyinfo->dobj.namespace->dobj.name));
6846+
appendPQExpBuffer(delq, "%s;\n",
6847+
qtypname);
6848+
6849+
if (binary_upgrade)
6850+
binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
6851+
6852+
appendPQExpBuffer(q, "CREATE TYPE %s;\n",
6853+
qtypname);
6854+
6855+
appendPQExpBuffer(labelq, "TYPE %s", qtypname);
6856+
6857+
ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
6858+
tyinfo->dobj.name,
6859+
tyinfo->dobj.namespace->dobj.name,
6860+
NULL,
6861+
tyinfo->rolname, false,
6862+
"TYPE", SECTION_PRE_DATA,
6863+
q->data, delq->data, NULL,
6864+
NULL, 0,
6865+
NULL, NULL);
6866+
6867+
/* Dump Type Comments */
6868+
dumpComment(fout, labelq->data,
6869+
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
6870+
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
6871+
6872+
destroyPQExpBuffer(q);
6873+
destroyPQExpBuffer(delq);
6874+
destroyPQExpBuffer(labelq);
6875+
}
6876+
68216877
/*
68226878
* dumpBaseType
68236879
* writes out to fout the queries to recreate a user-defined base type

src/bin/pg_dump/pg_dump.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ typedef struct _typeInfo
154154
char typtype; /* 'b', 'c', etc */
155155
bool isArray; /* true if auto-generated array type */
156156
bool isDefined; /* true if typisdefined */
157-
/* If it's a dumpable base type, we create a "shell type" entry for it */
157+
/* If needed, we'll create a "shell type" entry for it; link that here: */
158158
struct _shellTypeInfo *shellType; /* shell-type entry, or NULL */
159159
/* If it's a domain, we store links to its constraints here: */
160160
int nDomChecks;

src/test/regress/expected/create_type.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ ERROR: type "shell" already exists
2929
DROP TYPE shell;
3030
DROP TYPE shell; -- fail, type not exist
3131
ERROR: type "shell" does not exist
32+
-- also, let's leave one around for purposes of pg_dump testing
33+
CREATE TYPE myshell;
3234
--
3335
-- Test type-related default values (broken in releases before PG 7.2)
3436
--

src/test/regress/sql/create_type.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ CREATE TYPE shell; -- fail, type already present
3131
DROP TYPE shell;
3232
DROP TYPE shell; -- fail, type not exist
3333

34+
-- also, let's leave one around for purposes of pg_dump testing
35+
CREATE TYPE myshell;
36+
3437
--
3538
-- Test type-related default values (broken in releases before PG 7.2)
3639
--

0 commit comments

Comments
 (0)