Fix pg_dump's handling of extension-member casts and languages.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 16 May 2011 20:41:52 +0000 (16:41 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 16 May 2011 20:41:52 +0000 (16:41 -0400)
pg_dump has some heuristic rules for whether to dump casts and procedural
languages, since it's not all that easy to distinguish built-in ones from
user-defined ones.  However, we should not apply those rules to objects
that belong to an extension, but just use the perfectly well-defined rules
for what to do with extension member objects.  Otherwise we might
mistakenly lose extension member objects during a binary upgrade (which is
the only time that we'd want to dump extension members).

src/bin/pg_dump/pg_dump.c

index e474a6980d0c1f2ac1fc027270f15b50f8a1cb05..616c8855a06e43112f5e7d77eb70ac2752e816bd 100644 (file)
@@ -8252,6 +8252,9 @@ dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
  * For some backwards compatibility with the older behavior, we forcibly
  * dump a PL if its handler function (and validator if any) are in a
  * dumpable namespace. That case is not checked here.
+ *
+ * Also, if the PL belongs to an extension, we do not use this heuristic.
+ * That case isn't checked here either.
  */
 static bool
 shouldDumpProcLangs(void)
@@ -8316,13 +8319,22 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
     * If the functions are dumpable then emit a traditional CREATE LANGUAGE
     * with parameters.  Otherwise, dump only if shouldDumpProcLangs() says to
     * dump it.
+    *
+    * However, for a language that belongs to an extension, we must not use
+    * the shouldDumpProcLangs heuristic, but just dump the language iff we're
+    * told to (via dobj.dump).  Generally the support functions will belong
+    * to the same extension and so have the same dump flags ... if they don't,
+    * this might not work terribly nicely.
     */
    useParams = (funcInfo != NULL &&
                 (inlineInfo != NULL || !OidIsValid(plang->laninline)) &&
                 (validatorInfo != NULL || !OidIsValid(plang->lanvalidator)));
 
-   if (!useParams && !shouldDumpProcLangs())
-       return;
+   if (!plang->dobj.ext_member)
+   {
+       if (!useParams && !shouldDumpProcLangs())
+           return;
+   }
 
    defqry = createPQExpBuffer();
    delqry = createPQExpBuffer();
@@ -9013,13 +9025,12 @@ dumpCast(Archive *fout, CastInfo *cast)
    PQExpBuffer delqry;
    PQExpBuffer labelq;
    FuncInfo   *funcInfo = NULL;
-   TypeInfo   *sourceInfo;
-   TypeInfo   *targetInfo;
 
    /* Skip if not to be dumped */
    if (!cast->dobj.dump || dataOnly)
        return;
 
+   /* Cannot dump if we don't have the cast function's info */
    if (OidIsValid(cast->castfunc))
    {
        funcInfo = findFuncByOid(cast->castfunc);
@@ -9032,43 +9043,49 @@ dumpCast(Archive *fout, CastInfo *cast)
     * 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).
     */
-   sourceInfo = findTypeByOid(cast->castsource);
-   targetInfo = findTypeByOid(cast->casttarget);
+   if (!cast->dobj.ext_member)
+   {
+       TypeInfo   *sourceInfo = findTypeByOid(cast->castsource);
+       TypeInfo   *targetInfo = findTypeByOid(cast->casttarget);
 
-   if (sourceInfo == NULL || targetInfo == NULL)
-       return;
+       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 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;
+       /*
+        * 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;
+       /*
+        * 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;
+       /*
+        * 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("pg_catalog");