From 413ccaa74d9a126b042727c826e65e2844adadac Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Thu, 4 Apr 2019 16:34:58 -0300
Subject: [PATCH] pg_restore: Require "-f -" to mean stdout
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The previous convention that stdout was selected by default when nothing
is specified was just too error-prone.

After a suggestion from Andrew Gierth.
Author: Euler Taveira
Reviewed-by: Yoshikazu Imai, José Arthur Benetasso Villanova
Discussion: https://postgr.es/m/87sgwrmhdv.fsf@news-spur.riddles.org.uk
---
 doc/src/sgml/ref/pg_restore.sgml     |  4 ++--
 src/bin/pg_dump/pg_backup_archiver.c |  7 ++++++-
 src/bin/pg_dump/pg_restore.c         |  9 ++++++++-
 src/bin/pg_dump/t/001_basic.pl       | 22 ++++++++++++++--------
 4 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/doc/src/sgml/ref/pg_restore.sgml b/doc/src/sgml/ref/pg_restore.sgml
index cf369a0f3b9..c6013546a0e 100644
--- a/doc/src/sgml/ref/pg_restore.sgml
+++ b/doc/src/sgml/ref/pg_restore.sgml
@@ -176,8 +176,8 @@
       <listitem>
        <para>
         Specify output file for generated script, or for the listing
-        when used with <option>-l</option>. Default is the standard
-        output.
+        when used with <option>-l</option>. Use <literal>-</literal>
+        for <systemitem>stdout</systemitem>.
        </para>
       </listitem>
      </varlistentry>
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 1a75cd00cd9..fc1d8222446 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -1512,7 +1512,12 @@ SetOutput(ArchiveHandle *AH, const char *filename, int compression)
 	int			fn;
 
 	if (filename)
-		fn = -1;
+	{
+		if (strcmp(filename, "-") == 0)
+			fn = fileno(stdout);
+		else
+			fn = -1;
+	}
 	else if (AH->FH)
 		fn = fileno(AH->FH);
 	else if (AH->fSpec)
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
index 0a7eb46f5bd..8af6276e643 100644
--- a/src/bin/pg_dump/pg_restore.c
+++ b/src/bin/pg_dump/pg_restore.c
@@ -306,6 +306,13 @@ main(int argc, char **argv)
 		exit_nicely(1);
 	}
 
+	/* Complain if neither -f nor -d was specified (except if dumping TOC) */
+	if (!opts->dbname && !opts->filename && !opts->tocSummary)
+	{
+		pg_log_error("one of -d/--dbname and -f/--file must be specified");
+		exit_nicely(1);
+	}
+
 	/* Should get at most one of -d and -f, else user is confused */
 	if (opts->dbname)
 	{
@@ -461,7 +468,7 @@ usage(const char *progname)
 
 	printf(_("\nGeneral options:\n"));
 	printf(_("  -d, --dbname=NAME        connect to database name\n"));
-	printf(_("  -f, --file=FILENAME      output file name\n"));
+	printf(_("  -f, --file=FILENAME      output file name (- for stdout)\n"));
 	printf(_("  -F, --format=c|d|t       backup file format (should be automatic)\n"));
 	printf(_("  -l, --list               print summarized TOC of the archive\n"));
 	printf(_("  -v, --verbose            verbose mode\n"));
diff --git a/src/bin/pg_dump/t/001_basic.pl b/src/bin/pg_dump/t/001_basic.pl
index 3f8d4392cd7..5e3f0e58398 100644
--- a/src/bin/pg_dump/t/001_basic.pl
+++ b/src/bin/pg_dump/t/001_basic.pl
@@ -4,7 +4,7 @@ use warnings;
 use Config;
 use PostgresNode;
 use TestLib;
-use Test::More tests => 72;
+use Test::More tests => 74;
 
 my $tempdir       = TestLib::tempdir;
 my $tempdir_short = TestLib::tempdir_short;
@@ -50,7 +50,13 @@ command_fails_like(
 );
 
 command_fails_like(
-	[ 'pg_restore', '-s', '-a' ],
+	[ 'pg_restore' ],
+	qr{\Qpg_restore: error: one of -d/--dbname and -f/--file must be specified\E},
+	'pg_restore: error: one of -d/--dbname and -f/--file must be specified'
+);
+
+command_fails_like(
+	[ 'pg_restore', '-s', '-a', '-f -' ],
 	qr/\Qpg_restore: error: options -s\/--schema-only and -a\/--data-only cannot be used together\E/,
 	'pg_restore: options -s/--schema-only and -a/--data-only cannot be used together'
 );
@@ -66,7 +72,7 @@ command_fails_like(
 	'pg_dump: options -c/--clean and -a/--data-only cannot be used together');
 
 command_fails_like(
-	[ 'pg_restore', '-c', '-a' ],
+	[ 'pg_restore', '-c', '-a', '-f -' ],
 	qr/\Qpg_restore: error: options -c\/--clean and -a\/--data-only cannot be used together\E/,
 	'pg_restore: options -c/--clean and -a/--data-only cannot be used together'
 );
@@ -92,12 +98,12 @@ command_fails_like(
 	'pg_dump: invalid output format');
 
 command_fails_like(
-	[ 'pg_restore', '-j', '-1' ],
+	[ 'pg_restore', '-j', '-1', '-f -' ],
 	qr/\Qpg_restore: error: invalid number of parallel jobs\E/,
 	'pg_restore: invalid number of parallel jobs');
 
 command_fails_like(
-	[ 'pg_restore', '--single-transaction', '-j3' ],
+	[ 'pg_restore', '--single-transaction', '-j3', '-f -' ],
 	qr/\Qpg_restore: error: cannot specify both --single-transaction and multiple jobs\E/,
 	'pg_restore: cannot specify both --single-transaction and multiple jobs');
 
@@ -107,12 +113,12 @@ command_fails_like(
 	'pg_dump: compression level must be in range 0..9');
 
 command_fails_like(
-	[ 'pg_restore', '--if-exists' ],
+	[ 'pg_restore', '--if-exists', '-f -' ],
 	qr/\Qpg_restore: error: option --if-exists requires option -c\/--clean\E/,
 	'pg_restore: option --if-exists requires option -c/--clean');
 
 command_fails_like(
-	[ 'pg_restore', '-F', 'garbage' ],
+	[ 'pg_restore', '-f -', '-F', 'garbage' ],
 	qr/\Qpg_restore: error: unrecognized archive format "garbage";\E/,
 	'pg_dump: unrecognized archive format');
 
@@ -146,7 +152,7 @@ command_fails_like(
 	'pg_dumpall: option --if-exists requires option -c/--clean');
 
 command_fails_like(
-	[ 'pg_restore', '-C', '-1' ],
+	[ 'pg_restore', '-C', '-1', '-f -' ],
 	qr/\Qpg_restore: error: options -C\/--create and -1\/--single-transaction cannot be used together\E/,
 	'pg_restore: options -C\/--create and -1\/--single-transaction cannot be used together'
 );
-- 
GitLab