From 876338886ab5f23a5379e180f87ff7011fb3cd80 Mon Sep 17 00:00:00 2001
From: David Gilman <davidgilman1@gmail.com>
Date: Sat, 16 May 2020 16:27:17 -0400
Subject: [PATCH] Warn when parallel restoring a custom dump without data
 offsets

If pg_dump can't seek on its output stream when writing a dump in the
custom archive format (possibly because you piped its stdout to a file)
it can't update that file with data offsets. These files will often
break parallel restoration. Warn when the user is doing pg_restore on
such a file to give them a hint as to why their restore is about to
fail.

The documentation for pg_restore -j is also updated to suggest that you
dump custom archive formats with the -f option.
---
 doc/src/sgml/ref/pg_restore.sgml   | 9 +++++++++
 src/bin/pg_dump/pg_backup_custom.c | 8 ++++++++
 2 files changed, 17 insertions(+)

diff --git doc/src/sgml/ref/pg_restore.sgml doc/src/sgml/ref/pg_restore.sgml
index 232f88024f..3c0f56db51 100644
--- doc/src/sgml/ref/pg_restore.sgml
+++ doc/src/sgml/ref/pg_restore.sgml
@@ -279,6 +279,15 @@ PostgreSQL documentation
         jobs cannot be used together with the
         option <option>--single-transaction</option>.
        </para>
+
+       <para>
+        The custom archive format may not work with the <option>-j</option>
+        option if the archive was originally created by redirecting the
+        standard output stream of <application>pg_dump</application>.
+        For the best concurrent restoration performance with the custom
+        archive format use <application>pg_dump</application>'s
+        <option>--file</option> option to specify an output file.
+       </para>
       </listitem>
      </varlistentry>
 
diff --git src/bin/pg_dump/pg_backup_custom.c src/bin/pg_dump/pg_backup_custom.c
index 369dcea429..9473e43b1b 100644
--- src/bin/pg_dump/pg_backup_custom.c
+++ src/bin/pg_dump/pg_backup_custom.c
@@ -773,6 +773,7 @@ _PrepParallelRestore(ArchiveHandle *AH)
 	TocEntry   *prev_te = NULL;
 	lclTocEntry *prev_tctx = NULL;
 	TocEntry   *te;
+	int        hasPos = 0;
 
 	/*
 	 * Knowing that the data items were dumped out in TOC order, we can
@@ -800,6 +801,7 @@ _PrepParallelRestore(ArchiveHandle *AH)
 
 		prev_te = te;
 		prev_tctx = tctx;
+		hasPos = 1;
 	}
 
 	/* If OK to seek, we can determine the length of the last item */
@@ -811,8 +813,14 @@ _PrepParallelRestore(ArchiveHandle *AH)
 			fatal("error during file seek: %m");
 		endpos = ftello(AH->FH);
 		if (endpos > prev_tctx->dataPos)
+		{
 			prev_te->dataLength = endpos - prev_tctx->dataPos;
+			hasPos = 1;
+		}
 	}
+
+	if (!hasPos)
+		pg_log_warning("dump file lacks all data offsets possibly preventing parallel restoration");
 }
 
 /*
-- 
2.26.2

