In pg_restore's dump_lo_buf(), work a little harder on error handling.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 18 Oct 2020 16:26:02 +0000 (12:26 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 18 Oct 2020 16:26:02 +0000 (12:26 -0400)
Failure to write data to a large object during restore led to an ugly
and uninformative error message.  To add insult to injury, it then
fatal'd out, where other SQL-level errors usually result in pressing on.

Report the underlying error condition, rather than just giving not-very-
useful byte counts, and use warn_or_exit_horribly() so as to adhere to
pg_restore's general policy about whether to continue or not.

Also recognize that lo_write() returns int not size_t.

Per report from Justin Pryzby, though I didn't use his patch.
Given the lack of comparable complaints, I'm not sure this is
worth back-patching.

Discussion: https://postgr.es/m/20201018010232.GF9241@telsasoft.com

src/bin/pg_dump/pg_backup_archiver.c

index d61b290d2a62e119b4d5432af13d3130298a2d51..b961a24b36dd1ae76e9234a88339a23f5d52620d 100644 (file)
@@ -1637,16 +1637,17 @@ dump_lo_buf(ArchiveHandle *AH)
 {
        if (AH->connection)
        {
-               size_t          res;
+               int                     res;
 
                res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
-               pg_log_debug(ngettext("wrote %lu byte of large object data (result = %lu)",
-                                                         "wrote %lu bytes of large object data (result = %lu)",
+               pg_log_debug(ngettext("wrote %zu byte of large object data (result = %d)",
+                                                         "wrote %zu bytes of large object data (result = %d)",
                                                          AH->lo_buf_used),
-                                        (unsigned long) AH->lo_buf_used, (unsigned long) res);
+                                        AH->lo_buf_used, res);
+               /* We assume there are no short writes, only errors */
                if (res != AH->lo_buf_used)
-                       fatal("could not write to large object (result: %lu, expected: %lu)",
-                                 (unsigned long) res, (unsigned long) AH->lo_buf_used);
+                       warn_or_exit_horribly(AH, "could not write to large object: %s",
+                                                                 PQerrorMessage(AH->connection));
        }
        else
        {