*** a/src/bin/psql/common.c --- b/src/bin/psql/common.c *************** *** 672,677 **** ProcessResult(PGresult **results) --- 672,685 ---- case PGRES_COPY_OUT: case PGRES_COPY_IN: + /* + * If this is second copy; then it will be definately not \copy, + * and also it can not be from any user given file. + * So reset the value of copystream to NULL, so that read/wrie + * happens from stdin/stdout. + */ + if (!first_cycle) + pset.copyStream = NULL; is_copy = true; break; *************** *** 691,709 **** ProcessResult(PGresult **results) */ SetCancelConn(); if (result_status == PGRES_COPY_OUT) ! success = handleCopyOut(pset.db, pset.queryFout) && success; else ! success = handleCopyIn(pset.db, pset.cur_cmd_source, ! PQbinaryTuples(*results)) && success; ResetCancelConn(); /* * Call PQgetResult() once more. In the typical case of a * single-command string, it will return NULL. Otherwise, we'll * have other results to process that may include other COPYs. */ ! PQclear(*results); ! *results = next_result = PQgetResult(pset.db); } else if (first_cycle) /* fast path: no COPY commands; PQexec visited all results */ --- 699,721 ---- */ SetCancelConn(); if (result_status == PGRES_COPY_OUT) ! success = handleCopyOut(pset.db, pset.copyStream, results) && success; else ! success = handleCopyIn(pset.db, pset.copyStream, ! PQbinaryTuples(*results), results) && success; ResetCancelConn(); /* * Call PQgetResult() once more. In the typical case of a * single-command string, it will return NULL. Otherwise, we'll * have other results to process that may include other COPYs. + * If it is NULL, then the last result will be returned back. */ ! if ((next_result = PQgetResult(pset.db))) ! { ! PQclear(*results); ! *results = next_result; ! } } else if (first_cycle) /* fast path: no COPY commands; PQexec visited all results */ *** a/src/bin/psql/copy.c --- b/src/bin/psql/copy.c *************** *** 269,276 **** do_copy(const char *args) { PQExpBufferData query; FILE *copystream; - FILE *save_file; - FILE **override_file; struct copy_options *options; bool success; struct stat st; --- 269,274 ---- *************** *** 287,294 **** do_copy(const char *args) if (options->from) { - override_file = &pset.cur_cmd_source; - if (options->file) { if (options->program) --- 285,290 ---- *************** *** 308,315 **** do_copy(const char *args) } else { - override_file = &pset.queryFout; - if (options->file) { if (options->program) --- 304,309 ---- *************** *** 369,378 **** do_copy(const char *args) appendPQExpBufferStr(&query, options->after_tofrom); /* Run it like a user command, interposing the data source or sink. */ ! save_file = *override_file; ! *override_file = copystream; success = SendQuery(query.data); ! *override_file = save_file; termPQExpBuffer(&query); if (options->file != NULL) --- 363,371 ---- appendPQExpBufferStr(&query, options->after_tofrom); /* Run it like a user command, interposing the data source or sink. */ ! pset.copyStream = copystream; success = SendQuery(query.data); ! pset.copyStream = NULL; termPQExpBuffer(&query); if (options->file != NULL) *************** *** 433,444 **** do_copy(const char *args) * result is true if successful, false if not. */ bool ! handleCopyOut(PGconn *conn, FILE *copystream) { bool OK = true; char *buf; int ret; ! PGresult *res; for (;;) { --- 426,439 ---- * result is true if successful, false if not. */ bool ! handleCopyOut(PGconn *conn, FILE *copystream, PGresult **res) { bool OK = true; char *buf; int ret; ! ! if (!copystream) ! copystream = stdout; for (;;) { *************** *** 490,508 **** handleCopyOut(PGconn *conn, FILE *copystream) * TO STDOUT commands. We trust that no condition can make PQexec() fail * indefinitely while retaining status PGRES_COPY_OUT. */ ! while (res = PQgetResult(conn), PQresultStatus(res) == PGRES_COPY_OUT) { OK = false; ! PQclear(res); PQexec(conn, "-- clear PGRES_COPY_OUT state"); } ! if (PQresultStatus(res) != PGRES_COMMAND_OK) { psql_error("%s", PQerrorMessage(conn)); OK = false; } - PQclear(res); return OK; } --- 485,502 ---- * TO STDOUT commands. We trust that no condition can make PQexec() fail * indefinitely while retaining status PGRES_COPY_OUT. */ ! while (*res = PQgetResult(conn), PQresultStatus(*res) == PGRES_COPY_OUT) { OK = false; ! PQclear(*res); PQexec(conn, "-- clear PGRES_COPY_OUT state"); } ! if (PQresultStatus(*res) != PGRES_COMMAND_OK) { psql_error("%s", PQerrorMessage(conn)); OK = false; } return OK; } *************** *** 523,534 **** handleCopyOut(PGconn *conn, FILE *copystream) #define COPYBUFSIZ 8192 bool ! handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary) { bool OK; const char *prompt; char buf[COPYBUFSIZ]; ! PGresult *res; /* * Establish longjmp destination for exiting from wait-for-input. (This is --- 517,531 ---- #define COPYBUFSIZ 8192 bool ! handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res) { bool OK; const char *prompt; char buf[COPYBUFSIZ]; ! ! if (!copystream) ! copystream = stdin; ! /* * Establish longjmp destination for exiting from wait-for-input. (This is *************** *** 656,663 **** handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary) } } ! if (copystream == pset.cur_cmd_source) ! pset.lineno++; } } --- 653,659 ---- } } ! pset.lineno++; } } *************** *** 682,700 **** copyin_cleanup: * indefinitely while retaining status PGRES_COPY_IN, we get an infinite * loop. This is more realistic than handleCopyOut()'s counterpart risk. */ ! while (res = PQgetResult(conn), PQresultStatus(res) == PGRES_COPY_IN) { OK = false; ! PQclear(res); PQputCopyEnd(pset.db, _("trying to exit copy mode")); } ! if (PQresultStatus(res) != PGRES_COMMAND_OK) { psql_error("%s", PQerrorMessage(conn)); OK = false; } - PQclear(res); return OK; } --- 678,695 ---- * indefinitely while retaining status PGRES_COPY_IN, we get an infinite * loop. This is more realistic than handleCopyOut()'s counterpart risk. */ ! while (*res = PQgetResult(conn), PQresultStatus(*res) == PGRES_COPY_IN) { OK = false; ! PQclear(*res); PQputCopyEnd(pset.db, _("trying to exit copy mode")); } ! if (PQresultStatus(*res) != PGRES_COMMAND_OK) { psql_error("%s", PQerrorMessage(conn)); OK = false; } return OK; } *** a/src/bin/psql/copy.h --- b/src/bin/psql/copy.h *************** *** 16,22 **** bool do_copy(const char *args); /* lower level processors for copy in/out streams */ ! bool handleCopyOut(PGconn *conn, FILE *copystream); ! bool handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary); #endif --- 16,22 ---- /* lower level processors for copy in/out streams */ ! bool handleCopyOut(PGconn *conn, FILE *copystream, PGresult **res); ! bool handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res); #endif *** a/src/bin/psql/settings.h --- b/src/bin/psql/settings.h *************** *** 70,75 **** typedef struct _psqlSettings --- 70,77 ---- FILE *queryFout; /* where to send the query results */ bool queryFoutPipe; /* queryFout is from a popen() */ + FILE *copyStream; /* Stream to read/write for copy command*/ + printQueryOpt popt; char *gfname; /* one-shot file output argument for \g */