Fix pg_dump assertion failure when dumping pg_catalog.
authorJeff Davis <jdavis@postgresql.org>
Tue, 22 Aug 2023 18:21:36 +0000 (11:21 -0700)
committerJeff Davis <jdavis@postgresql.org>
Tue, 22 Aug 2023 19:50:01 +0000 (12:50 -0700)
Commit 396d348b04 did not account for the default collation.

Also, use pg_log_warning() instead of Assert().

Discussion: https://postgr.es/m/ce071503fee88334aa70f360e6e4ea14d48305ee.camel%40j-davis.com
Reviewed-by: Michael Paquier
Backpatch-through: 15

src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/t/002_pg_dump.pl

index 5dab1ba9eae6e055ddcdcd26504920d8ded06c0f..c73e9a11da934c5b204fd9b1155f0dea03f2f108 100644 (file)
@@ -13415,6 +13415,18 @@ dumpCollation(Archive *fout, const CollInfo *collinfo)
    else
        collctype = NULL;
 
+   /*
+    * Before version 15, collcollate and collctype were of type NAME and
+    * non-nullable. Treat empty strings as NULL for consistency.
+    */
+   if (fout->remoteVersion < 150000)
+   {
+       if (collcollate[0] == '\0')
+           collcollate = NULL;
+       if (collctype[0] == '\0')
+           collctype = NULL;
+   }
+
    if (!PQgetisnull(res, 0, i_colliculocale))
        colliculocale = PQgetvalue(res, 0, i_colliculocale);
    else
@@ -13446,35 +13458,60 @@ dumpCollation(Archive *fout, const CollInfo *collinfo)
    if (strcmp(PQgetvalue(res, 0, i_collisdeterministic), "f") == 0)
        appendPQExpBufferStr(q, ", deterministic = false");
 
-   if (colliculocale != NULL)
+   if (collprovider[0] == 'd')
    {
-       appendPQExpBufferStr(q, ", locale = ");
-       appendStringLiteralAH(q, colliculocale, fout);
+       if (collcollate || collctype || colliculocale || collicurules)
+           pg_log_warning("invalid collation \"%s\"", qcollname);
+
+       /* no locale -- the default collation cannot be reloaded anyway */
    }
-   else
+   else if (collprovider[0] == 'i')
    {
-       Assert(collcollate != NULL);
-       Assert(collctype != NULL);
+       if (fout->remoteVersion >= 150000)
+       {
+           if (collcollate || collctype || !colliculocale)
+               pg_log_warning("invalid collation \"%s\"", qcollname);
 
-       if (strcmp(collcollate, collctype) == 0)
+           appendPQExpBufferStr(q, ", locale = ");
+           appendStringLiteralAH(q, colliculocale ? colliculocale : "",
+                                 fout);
+       }
+       else
        {
+           if (!collcollate || !collctype || colliculocale ||
+               strcmp(collcollate, collctype) != 0)
+               pg_log_warning("invalid collation \"%s\"", qcollname);
+
            appendPQExpBufferStr(q, ", locale = ");
-           appendStringLiteralAH(q, collcollate, fout);
+           appendStringLiteralAH(q, collcollate ? collcollate : "", fout);
+       }
+
+       if (collicurules)
+       {
+           appendPQExpBufferStr(q, ", rules = ");
+           appendStringLiteralAH(q, collicurules ? collicurules : "", fout);
+       }
+   }
+   else if (collprovider[0] == 'c')
+   {
+       if (colliculocale || collicurules || !collcollate || !collctype)
+           pg_log_warning("invalid collation \"%s\"", qcollname);
+
+       if (collcollate && collctype && strcmp(collcollate, collctype) == 0)
+       {
+           appendPQExpBufferStr(q, ", locale = ");
+           appendStringLiteralAH(q, collcollate ? collcollate : "", fout);
        }
        else
        {
            appendPQExpBufferStr(q, ", lc_collate = ");
-           appendStringLiteralAH(q, collcollate, fout);
+           appendStringLiteralAH(q, collcollate ? collcollate : "", fout);
            appendPQExpBufferStr(q, ", lc_ctype = ");
-           appendStringLiteralAH(q, collctype, fout);
+           appendStringLiteralAH(q, collctype ? collctype : "", fout);
        }
    }
-
-   if (collicurules)
-   {
-       appendPQExpBufferStr(q, ", rules = ");
-       appendStringLiteralAH(q, collicurules, fout);
-   }
+   else
+       pg_fatal("unrecognized collation provider '%c'", collprovider[0]);
 
    /*
     * For binary upgrade, carry over the collation version.  For normal
index 6ad83102874ca56a59379ed5b06397f75a26fb84..23b78454a364abeb57b464d4800c932a383d7117 100644 (file)
@@ -4769,6 +4769,14 @@ $node->command_fails_like(
    qr/pg_dumpall: error: improper qualified name \(too many dotted names\): myhost\.mydb/,
    'pg_dumpall: option --exclude-database rejects multipart database names');
 
+##############################################################
+# Test dumping pg_catalog (for research -- cannot be reloaded)
+
+$node->command_ok(
+   [ 'pg_dump', '-p', "$port", '-n', 'pg_catalog' ],
+   'pg_dump: option -n pg_catalog'
+);
+
 #########################################
 # Test valid database exclusion patterns