From 9feefedf9e92066fa6609d1e1e17b4892d81716f Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 10 Feb 2015 22:38:15 -0500 Subject: [PATCH] Fix pg_dump's heuristic for deciding which casts to dump. Back in 2003 we had a discussion about how to decide which casts to dump. At the time pg_dump really only considered an object's containing schema to decide what to dump (ie, dump whatever's not in pg_catalog), and so we chose a complicated idea involving whether the underlying types were to be dumped (cf commit a6790ce85752b67ad994f55fdf1a450262ccc32e). But users are allowed to create casts between built-in types, and we failed to dump such casts. Let's get rid of that heuristic, which has accreted even more ugliness since then, in favor of just looking at the cast's OID to decide if it's a built-in cast or not. In passing, also fix some really ancient code that supposed that it had to manufacture a dependency for the cast on its cast function; that's only true when dumping from a pre-7.3 server. This just resulted in some wasted cycles and duplicate dependency-list entries with newer servers, but we might as well improve it. Per gripes from a number of people, most recently Greg Sabino Mullane. Back-patch to all supported branches. --- src/bin/pg_dump/common.c | 2 +- src/bin/pg_dump/pg_dump.c | 78 ++++++++++++++------------------------- src/bin/pg_dump/pg_dump.h | 2 +- 3 files changed, 29 insertions(+), 53 deletions(-) diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c index d3d46d2438..1a0a587413 100644 --- a/src/bin/pg_dump/common.c +++ b/src/bin/pg_dump/common.c @@ -199,7 +199,7 @@ getSchemaData(Archive *fout, DumpOptions *dopt, int *numTablesPtr) if (g_verbose) write_msg(NULL, "reading type casts\n"); - getCasts(fout, &numCasts); + getCasts(fout, dopt, &numCasts); if (g_verbose) write_msg(NULL, "reading table inheritance information\n"); diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index abebdacfdc..7e92b74916 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -1350,6 +1350,24 @@ selectDumpableDefaultACL(DumpOptions *dopt, DefaultACLInfo *dinfo) dinfo->dobj.dump = dopt->include_everything; } +/* + * selectDumpableCast: policy-setting subroutine + * Mark a cast as to be dumped or not + * + * Casts do not belong to any particular namespace (since they haven't got + * names), nor do they have identifiable owners. To distinguish user-defined + * casts from built-in ones, we must resort to checking whether the cast's + * OID is in the range reserved for initdb. + */ +static void +selectDumpableCast(DumpOptions *dopt, CastInfo *cast) +{ + if (cast->dobj.catId.oid < (Oid) FirstNormalObjectId) + cast->dobj.dump = false; + else + cast->dobj.dump = dopt->include_everything; +} + /* * selectDumpableExtension: policy-setting subroutine * Mark an extension as to be dumped or not @@ -6471,7 +6489,7 @@ getProcLangs(Archive *fout, int *numProcLangs) * numCasts is set to the number of casts read in */ CastInfo * -getCasts(Archive *fout, int *numCasts) +getCasts(Archive *fout, DumpOptions *dopt, int *numCasts) { PGresult *res; int ntups; @@ -6561,12 +6579,13 @@ getCasts(Archive *fout, int *numCasts) sTypeInfo->dobj.name, tTypeInfo->dobj.name); castinfo[i].dobj.name = namebuf.data; - if (OidIsValid(castinfo[i].castfunc)) + if (fout->remoteVersion < 70300 && + OidIsValid(castinfo[i].castfunc)) { /* * We need to make a dependency to ensure the function will be * dumped first. (In 7.3 and later the regular dependency - * mechanism will handle this for us.) + * mechanism handles this for us.) */ FuncInfo *funcInfo; @@ -6575,6 +6594,9 @@ getCasts(Archive *fout, int *numCasts) addObjectDependency(&castinfo[i].dobj, funcInfo->dobj.dumpId); } + + /* Decide whether we want to dump it */ + selectDumpableCast(dopt, &(castinfo[i])); } PQclear(res); @@ -10480,55 +10502,9 @@ dumpCast(Archive *fout, DumpOptions *dopt, CastInfo *cast) } /* - * 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 are included in the dump. - * Builtin meaning, the namespace name does not start with "pg_". - * - * However, for a cast that belongs to an extension, we must not use this - * heuristic, but just dump the cast iff we're told to (via dobj.dump). + * Make sure we are in proper schema (needed for getFormattedTypeName). + * Casts don't have a schema of their own, so use pg_catalog. */ - if (!cast->dobj.ext_member) - { - TypeInfo *sourceInfo = findTypeByOid(cast->castsource); - TypeInfo *targetInfo = findTypeByOid(cast->casttarget); - - if (sourceInfo == NULL || targetInfo == NULL) - return; - - /* - * Skip this cast if all objects are from pg_ - */ - if ((funcInfo == NULL || - strncmp(funcInfo->dobj.namespace->dobj.name, "pg_", 3) == 0) && - strncmp(sourceInfo->dobj.namespace->dobj.name, "pg_", 3) == 0 && - strncmp(targetInfo->dobj.namespace->dobj.name, "pg_", 3) == 0) - return; - - /* - * 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.dump) - return; - - /* - * Same for the source type - */ - if (strncmp(sourceInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 && - !sourceInfo->dobj.dump) - return; - - /* - * and the target type. - */ - if (strncmp(targetInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 && - !targetInfo->dobj.dump) - return; - } - - /* Make sure we are in proper schema (needed for getFormattedTypeName) */ selectSourceSchema(fout, "pg_catalog"); defqry = createPQExpBuffer(); diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 51bf628d99..f42c42d5e6 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -534,7 +534,7 @@ extern void getConstraints(Archive *fout, TableInfo tblinfo[], int numTables); extern RuleInfo *getRules(Archive *fout, int *numRules); extern void getTriggers(Archive *fout, TableInfo tblinfo[], int numTables); extern ProcLangInfo *getProcLangs(Archive *fout, int *numProcLangs); -extern CastInfo *getCasts(Archive *fout, int *numCasts); +extern CastInfo *getCasts(Archive *fout, DumpOptions *dopt, int *numCasts); extern void getTableAttrs(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo, int numTables); extern bool shouldPrintColumn(DumpOptions *dopt, TableInfo *tbinfo, int colno); extern TSParserInfo *getTSParsers(Archive *fout, int *numTSParsers);