aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-05-17 12:24:19 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2017-05-17 12:24:19 -0400
commit49dfbb53cb8cadd985d49da02fbb64165bf69988 (patch)
tree5f3c31c1eb991ef3110eafb5fbd277346eb6ebe3
parent14605156180a424ba519e7058e34af51d641bffd (diff)
downloadpostgresql-49dfbb53cb8cadd985d49da02fbb64165bf69988.tar.gz
postgresql-49dfbb53cb8cadd985d49da02fbb64165bf69988.zip
Make psql handle EOF during COPY FROM STDIN properly on all platforms.
When stdin is a terminal, it's possible to end a COPY FROM STDIN with a keyboard EOF signal (typically control-D), and then keep on issuing SQL commands. One would expect another COPY FROM STDIN to work as well, but on some platforms it did not. This turns out to be because we were not resetting the stream's feof() flag, and BSD-ish versions of fread() and fgets() won't attempt to read more data if that's set. The misbehavior is observed on BSDen (including macOS), but not Linux, Windows, or SysV-ish Unixen, which makes this a portability bug not just a missing feature. Add a clearerr() call to fix the behavior, and improve the prompt that's issued when copying from a TTY to mention that EOF signals work. It's been like this forever, so back-patch to all supported branches. Thomas Munro Discussion: https://postgr.es/m/CAEepm=0MCGfYf=JAMiYhO6JPtv9-3ZfBo8fcGeCZ8oMzaw+Z+Q@mail.gmail.com
-rw-r--r--src/bin/psql/copy.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/src/bin/psql/copy.c b/src/bin/psql/copy.c
index 82edf431783..eee628ccdf1 100644
--- a/src/bin/psql/copy.c
+++ b/src/bin/psql/copy.c
@@ -539,7 +539,7 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
showprompt = true;
if (!pset.quiet)
puts(_("Enter data to be copied followed by a newline.\n"
- "End with a backslash and a period on a line by itself."));
+ "End with a backslash and a period on a line by itself, or an EOF signal."));
}
else
showprompt = false;
@@ -673,6 +673,16 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
copyin_cleanup:
/*
+ * Clear the EOF flag on the stream, in case copying ended due to an EOF
+ * signal. This allows an interactive TTY session to perform another COPY
+ * FROM STDIN later. (In non-STDIN cases, we're about to close the file
+ * anyway, so it doesn't matter.) Although we don't ever test the flag
+ * with feof(), some fread() implementations won't read more data if it's
+ * set. This also clears the error flag, but we already checked that.
+ */
+ clearerr(copystream);
+
+ /*
* Check command status and return to normal libpq state.
*
* We do not want to return with the status still PGRES_COPY_IN: our