Fix old pg_dump oversight: default values for domains really need to be dumped
authorTom Lane
Tue, 21 Feb 2006 18:01:32 +0000 (18:01 +0000)
committerTom Lane
Tue, 21 Feb 2006 18:01:32 +0000 (18:01 +0000)
by decompiling the typdefaultbin expression, not just printing the typdefault
text which may be out-of-date or assume the wrong schema search path.  (It's
the same hazard as for adbin vs adsrc in column defaults.)  The catalogs.sgml
spec for pg_type implies that the correct procedure is to look to
typdefaultbin first and consider typdefault only if typdefaultbin is NULL.
I made dumping of both domains and base types do that, even though in the
current backend code typdefaultbin is always correct for domains and
typdefault for base types --- might as well try to future-proof it a little.
Per bug report from Alexander Galler.

src/bin/pg_dump/pg_dump.c

index c88f383bf0b3368329e6e4a29c3c894d5e6859b5..3c5cd5d4d8b32f12181a2a32472bb4208fcfa4a0 100644 (file)
@@ -12,7 +12,7 @@
  * by PostgreSQL
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.429 2006/02/12 06:11:51 momjian Exp $
+ *   $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.430 2006/02/21 18:01:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -4690,10 +4690,11 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
    Oid         typsendoid;
    Oid         typanalyzeoid;
    char       *typdelim;
-   char       *typdefault;
    char       *typbyval;
    char       *typalign;
    char       *typstorage;
+   char       *typdefault;
+   bool        typdefault_is_literal = false;
 
    /* Set proper schema search path so regproc references list correctly */
    selectSourceSchema(tinfo->dobj.namespace->dobj.name);
@@ -4709,8 +4710,8 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                          "typreceive::pg_catalog.oid as typreceiveoid, "
                          "typsend::pg_catalog.oid as typsendoid, "
                          "typanalyze::pg_catalog.oid as typanalyzeoid, "
-                         "typdelim, typdefault, typbyval, typalign, "
-                         "typstorage "
+                         "typdelim, typbyval, typalign, typstorage, "
+                         "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
                          "FROM pg_catalog.pg_type "
                          "WHERE oid = '%u'::pg_catalog.oid",
                          tinfo->dobj.catId.oid);
@@ -4725,8 +4726,8 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                          "typreceive::pg_catalog.oid as typreceiveoid, "
                          "typsend::pg_catalog.oid as typsendoid, "
                          "0 as typanalyzeoid, "
-                         "typdelim, typdefault, typbyval, typalign, "
-                         "typstorage "
+                         "typdelim, typbyval, typalign, typstorage, "
+                         "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
                          "FROM pg_catalog.pg_type "
                          "WHERE oid = '%u'::pg_catalog.oid",
                          tinfo->dobj.catId.oid);
@@ -4741,13 +4742,13 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                          "typoutput::pg_catalog.oid as typoutputoid, "
                          "0 as typreceiveoid, 0 as typsendoid, "
                          "0 as typanalyzeoid, "
-                         "typdelim, typdefault, typbyval, typalign, "
-                         "typstorage "
+                         "typdelim, typbyval, typalign, typstorage, "
+                         "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
                          "FROM pg_catalog.pg_type "
                          "WHERE oid = '%u'::pg_catalog.oid",
                          tinfo->dobj.catId.oid);
    }
-   else if (fout->remoteVersion >= 70100)
+   else if (fout->remoteVersion >= 70200)
    {
        /*
         * Note: although pre-7.3 catalogs contain typreceive and typsend,
@@ -4761,8 +4762,28 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                          "typoutput::oid as typoutputoid, "
                          "0 as typreceiveoid, 0 as typsendoid, "
                          "0 as typanalyzeoid, "
-                         "typdelim, typdefault, typbyval, typalign, "
-                         "typstorage "
+                         "typdelim, typbyval, typalign, typstorage, "
+                         "NULL as typdefaultbin, typdefault "
+                         "FROM pg_type "
+                         "WHERE oid = '%u'::oid",
+                         tinfo->dobj.catId.oid);
+   }
+   else if (fout->remoteVersion >= 70100)
+   {
+       /*
+        * Ignore pre-7.2 typdefault; the field exists but has an unusable
+        * representation.
+        */
+       appendPQExpBuffer(query, "SELECT typlen, "
+                         "typinput, typoutput, "
+                         "'-' as typreceive, '-' as typsend, "
+                         "'-' as typanalyze, "
+                         "typinput::oid as typinputoid, "
+                         "typoutput::oid as typoutputoid, "
+                         "0 as typreceiveoid, 0 as typsendoid, "
+                         "0 as typanalyzeoid, "
+                         "typdelim, typbyval, typalign, typstorage, "
+                         "NULL as typdefaultbin, NULL as typdefault "
                          "FROM pg_type "
                          "WHERE oid = '%u'::oid",
                          tinfo->dobj.catId.oid);
@@ -4777,8 +4798,9 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                          "typoutput::oid as typoutputoid, "
                          "0 as typreceiveoid, 0 as typsendoid, "
                          "0 as typanalyzeoid, "
-                         "typdelim, typdefault, typbyval, typalign, "
-                         "'p'::char as typstorage "
+                         "typdelim, typbyval, typalign, "
+                         "'p'::char as typstorage, "
+                         "NULL as typdefaultbin, NULL as typdefault "
                          "FROM pg_type "
                          "WHERE oid = '%u'::oid",
                          tinfo->dobj.catId.oid);
@@ -4808,13 +4830,18 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
    typsendoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typsendoid")));
    typanalyzeoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typanalyzeoid")));
    typdelim = PQgetvalue(res, 0, PQfnumber(res, "typdelim"));
-   if (PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
-       typdefault = NULL;
-   else
-       typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault"));
    typbyval = PQgetvalue(res, 0, PQfnumber(res, "typbyval"));
    typalign = PQgetvalue(res, 0, PQfnumber(res, "typalign"));
    typstorage = PQgetvalue(res, 0, PQfnumber(res, "typstorage"));
+   if (!PQgetisnull(res, 0, PQfnumber(res, "typdefaultbin")))
+       typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefaultbin"));
+   else if (!PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
+   {
+       typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault"));
+       typdefault_is_literal = true;       /* it needs quotes */
+   }
+   else
+       typdefault = NULL;
 
    /*
     * DROP must be fully qualified in case same name appears in pg_catalog
@@ -4854,7 +4881,10 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
    if (typdefault != NULL)
    {
        appendPQExpBuffer(q, ",\n    DEFAULT = ");
-       appendStringLiteral(q, typdefault, true);
+       if (typdefault_is_literal)
+           appendStringLiteral(q, typdefault, true);
+       else
+           appendPQExpBufferStr(q, typdefault);
    }
 
    if (tinfo->isArray)
@@ -4936,6 +4966,7 @@ dumpDomain(Archive *fout, TypeInfo *tinfo)
    char       *typnotnull;
    char       *typdefn;
    char       *typdefault;
+   bool        typdefault_is_literal = false;
 
    /* Set proper schema search path so type references list correctly */
    selectSourceSchema(tinfo->dobj.namespace->dobj.name);
@@ -4944,7 +4975,7 @@ dumpDomain(Archive *fout, TypeInfo *tinfo)
    /* We assume here that remoteVersion must be at least 70300 */
    appendPQExpBuffer(query, "SELECT typnotnull, "
                "pg_catalog.format_type(typbasetype, typtypmod) as typdefn, "
-                     "typdefault "
+                     "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
                      "FROM pg_catalog.pg_type "
                      "WHERE oid = '%u'::pg_catalog.oid",
                      tinfo->dobj.catId.oid);
@@ -4963,10 +4994,15 @@ dumpDomain(Archive *fout, TypeInfo *tinfo)
 
    typnotnull = PQgetvalue(res, 0, PQfnumber(res, "typnotnull"));
    typdefn = PQgetvalue(res, 0, PQfnumber(res, "typdefn"));
-   if (PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
-       typdefault = NULL;
-   else
+   if (!PQgetisnull(res, 0, PQfnumber(res, "typdefaultbin")))
+       typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefaultbin"));
+   else if (!PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
+   {
        typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault"));
+       typdefault_is_literal = true;       /* it needs quotes */
+   }
+   else
+       typdefault = NULL;
 
    appendPQExpBuffer(q,
                      "CREATE DOMAIN %s AS %s",
@@ -4976,8 +5012,14 @@ dumpDomain(Archive *fout, TypeInfo *tinfo)
    if (typnotnull[0] == 't')
        appendPQExpBuffer(q, " NOT NULL");
 
-   if (typdefault)
-       appendPQExpBuffer(q, " DEFAULT %s", typdefault);
+   if (typdefault != NULL)
+   {
+       appendPQExpBuffer(q, " DEFAULT ");
+       if (typdefault_is_literal)
+           appendStringLiteral(q, typdefault, true);
+       else
+           appendPQExpBufferStr(q, typdefault);
+   }
 
    PQclear(res);