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