On 09/18/2014 05:58 PM, Andres Freund wrote:
> I don't think we need to make any discinction between psql -f mydb.dump,
> psql < mydb.dump, and whatever | psql. Just check, when noninteractively
> reading the first line in mainloop.c:MainLoop(), whether it starts with
> the magic header. That'd also trigger the warning on \i pg_restore_file,
> but that's hardly a problem.

Done, patch attached.

If psql sees that the first line begins with PGDMP it'll emit:

  The input is a PostgreSQL custom-format dump. Use the pg_restore
  command-line client to restore this dump to a database.

then discard the rest of the current input source.

>> pg_restore already knows to tell you to use psql if it sees an SQL file
>> as input. Having something similar for pg_dump would be really useful.
> 
> Agreed.
> 
> We could additionally write out a hint whenever a directory is fed to
> psql -f that psql can't be used to read directory type dumps.

Unlike the confusion between pg_restore and psql for custom file format
dumps I haven't seen people getting this one muddled. Perhaps directory
format dumps are just a bit more niche, or perhaps it's just more
obvious that:

psql:sometump:0: could not read from input file: Is a directory

... means psql is the wrong tool.

Still, separate patch attached. psql will now emit:

psql:blah:0: Input path is a directory. Use pg_restore to restore
directory-format database dumps.

I'm less sure that this is a worthwhile improvement than the check for
PGDMP and custom format dumps though.

-- 
 Craig Ringer                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
>From e3a6633ec2782264f3a87fbe3be079f94d89b911 Mon Sep 17 00:00:00 2001
From: Craig Ringer <cr...@2ndquadrant.com>
Date: Fri, 17 Oct 2014 12:07:37 +0800
Subject: [PATCH 2/2] If the input path to psql is a directory, mention
 pg_restore in the error

This should help users who try to use psql to restore a directory-format
dump from pg_dump.
---
 src/bin/psql/input.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/bin/psql/input.c b/src/bin/psql/input.c
index 6416ab9..e332318 100644
--- a/src/bin/psql/input.c
+++ b/src/bin/psql/input.c
@@ -191,8 +191,15 @@ gets_fromFile(FILE *source)
 		{
 			if (ferror(source))
 			{
-				psql_error("could not read from input file: %s\n",
-						   strerror(errno));
+				/*
+				 * Could the user be trying to restore a directory
+				 * format dump?
+				 */
+				if (errno == EISDIR)
+					psql_error("Input path is a directory. Use pg_restore to restore directory-format database dumps.\n");
+				else
+					psql_error("could not read from input file: %s\n",
+							   strerror(errno));
 				return NULL;
 			}
 			break;
-- 
1.9.3

>From 5330eea78029f9cb689fd3c53722cb02217f47df Mon Sep 17 00:00:00 2001
From: Craig Ringer <cr...@2ndquadrant.com>
Date: Fri, 17 Oct 2014 11:54:29 +0800
Subject: [PATCH 1/2] Emit an error when psql is used to load a custom-format
 dump file

Users tend to get confused between psql and pg_restore, and will
use psql to try to restore a dump from pg_dump -Fc, or use pg_restore
to try to restore an SQL format dump.

pg_restore complains if it sees an SQL format dump, but psql doesn't
complain if it sees a custom-format dump.

Fix that by emitting an error if you try to run a custom format dump:

  The input is a PostgreSQL custom-format dump. Use the pg_restore
  command-line client to restore this dump to a database.
---
 src/bin/psql/mainloop.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c
index 98211dc..1e057a6 100644
--- a/src/bin/psql/mainloop.c
+++ b/src/bin/psql/mainloop.c
@@ -175,6 +175,17 @@ MainLoop(FILE *source)
 		if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
 			memmove(line, line + 3, strlen(line + 3) + 1);
 
+		/* Detect attempts to run custom-format dumps as SQL scripts */
+		if (pset.lineno == 1 && !pset.cur_cmd_interactive && strncmp(line, "PGDMP", 5) == 0)
+		{
+			free(line);
+			puts(_("The input is a PostgreSQL custom-format dump. Use the pg_restore \n"
+				   "command-line client to restore this dump to a database.\n"));
+			fflush(stdout);
+			successResult = EXIT_FAILURE;
+			break;
+		}
+
 		/* nothing left on line? then ignore */
 		if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
 		{
-- 
1.9.3

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to