Skip to content

Commit 218dd20

Browse files
committed
Clean up error cases in psql's COPY TO STDOUT/FROM STDIN code.
Adjust handleCopyOut() to stop trying to write data once it's failed one time. For typical cases such as out-of-disk-space or broken-pipe, additional attempts aren't going to do anything but waste time, and in any case clean truncation of the output seems like a better behavior than randomly dropping blocks in the middle. Also remove dubious (and misleadingly documented) attempt to force our way out of COPY_OUT state if libpq didn't do that. If we did have a situation like that, it'd be a bug in libpq and would be better fixed there, IMO. We can hope that commit fa4440f took care of any such problems, anyway. Also fix longstanding bug in handleCopyIn(): PQputCopyEnd() only supports a non-null errormsg parameter in protocol version 3, and will actively fail if one is passed in version 2. This would've made our attempts to get out of COPY_IN state after a failure into infinite loops when talking to pre-7.4 servers. Back-patch the COPY_OUT state change business back to 9.2 where it was introduced, and the other two fixes into all supported branches.
1 parent 148052d commit 218dd20

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

src/bin/psql/copy.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,9 @@ do_copy(const char *args)
350350
PQresultStatus(result));
351351
/* if still in COPY IN state, try to get out of it */
352352
if (PQresultStatus(result) == PGRES_COPY_IN)
353-
PQputCopyEnd(pset.db, _("trying to exit copy mode"));
353+
PQputCopyEnd(pset.db,
354+
(PQprotocolVersion(pset.db) < 3) ? NULL :
355+
_("trying to exit copy mode"));
354356
PQclear(result);
355357
}
356358

@@ -397,15 +399,15 @@ handleCopyOut(PGconn *conn, FILE *copystream)
397399
ret = PQgetCopyData(conn, &buf, 0);
398400

399401
if (ret < 0)
400-
break; /* done or error */
402+
break; /* done or server/connection error */
401403

402404
if (buf)
403405
{
404-
if (fwrite(buf, 1, ret, copystream) != ret)
406+
if (OK && fwrite(buf, 1, ret, copystream) != ret)
405407
{
406-
if (OK) /* complain only once, keep reading data */
407-
psql_error("could not write COPY data: %s\n",
408-
strerror(errno));
408+
psql_error("could not write COPY data: %s\n",
409+
strerror(errno));
410+
/* complain only once, keep reading data from server */
409411
OK = false;
410412
}
411413
PQfreemem(buf);
@@ -469,7 +471,9 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary)
469471
/* got here with longjmp */
470472

471473
/* Terminate data transfer */
472-
PQputCopyEnd(conn, _("canceled by user"));
474+
PQputCopyEnd(conn,
475+
(PQprotocolVersion(conn) < 3) ? NULL :
476+
_("canceled by user"));
473477

474478
/* Check command status and return to normal libpq state */
475479
res = PQgetResult(conn);
@@ -597,7 +601,8 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary)
597601

598602
/* Terminate data transfer */
599603
if (PQputCopyEnd(conn,
600-
OK ? NULL : _("aborted because of read failure")) <= 0)
604+
(OK || PQprotocolVersion(conn) < 3) ? NULL :
605+
_("aborted because of read failure")) <= 0)
601606
OK = false;
602607

603608
/* Check command status and return to normal libpq state */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy