aboutsummaryrefslogtreecommitdiff
path: root/src/bin/psql/common.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2014-03-13 13:49:03 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2014-03-13 13:49:03 -0400
commitf70a78bc1f5556546d809a8164b9ba6a907f266f (patch)
treec1c76fbe6024efd57cdca5a9ee98043dea31cfd9 /src/bin/psql/common.c
parent7bae0284eeb0863220260e0d5ac80f0b37053690 (diff)
downloadpostgresql-f70a78bc1f5556546d809a8164b9ba6a907f266f.tar.gz
postgresql-f70a78bc1f5556546d809a8164b9ba6a907f266f.zip
Allow psql to print COPY command status in more cases.
Previously, psql would print the "COPY nnn" command status only for COPY commands executed server-side. Now it will print that for frontend copies too (including \copy). However, we continue to suppress the command status for COPY TO STDOUT, since in that case the copy data has been routed to the same place that the command status would go, and there is a risk of the status line being mistaken for another line of COPY data. Doing that would break existing scripts, and it doesn't seem worth the benefit --- this case seems fairly analogous to SELECT, for which we also suppress the command status. Kumar Rajeev Rastogi, with substantial review by Amit Khandekar
Diffstat (limited to 'src/bin/psql/common.c')
-rw-r--r--src/bin/psql/common.c52
1 files changed, 37 insertions, 15 deletions
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 6ca9bbc9d86..6968adfd42c 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -632,7 +632,9 @@ StoreQueryTuple(const PGresult *result)
* degenerates to an AcceptResult() call.
*
* Changes its argument to point to the last PGresult of the command string,
- * or NULL if that result was for a COPY FROM STDIN or COPY TO STDOUT.
+ * or NULL if that result was for a COPY TO STDOUT. (Returning NULL prevents
+ * the command status from being printed, which we want in that case so that
+ * the status line doesn't get taken as part of the COPY data.)
*
* Returns true on complete success, false otherwise. Possible failure modes
* include purely client-side problems; check the transaction status for the
@@ -641,14 +643,14 @@ StoreQueryTuple(const PGresult *result)
static bool
ProcessResult(PGresult **results)
{
- PGresult *next_result;
bool success = true;
bool first_cycle = true;
- do
+ for (;;)
{
ExecStatusType result_status;
bool is_copy;
+ PGresult *next_result;
if (!AcceptResult(*results))
{
@@ -693,6 +695,7 @@ ProcessResult(PGresult **results)
* otherwise use queryFout or cur_cmd_source as appropriate.
*/
FILE *copystream = pset.copyStream;
+ PGresult *copy_result;
SetCancelConn();
if (result_status == PGRES_COPY_OUT)
@@ -700,7 +703,19 @@ ProcessResult(PGresult **results)
if (!copystream)
copystream = pset.queryFout;
success = handleCopyOut(pset.db,
- copystream) && success;
+ copystream,
+ &copy_result) && success;
+
+ /*
+ * Suppress status printing if the report would go to the same
+ * place as the COPY data just went. Note this doesn't
+ * prevent error reporting, since handleCopyOut did that.
+ */
+ if (copystream == pset.queryFout)
+ {
+ PQclear(copy_result);
+ copy_result = NULL;
+ }
}
else
{
@@ -708,30 +723,37 @@ ProcessResult(PGresult **results)
copystream = pset.cur_cmd_source;
success = handleCopyIn(pset.db,
copystream,
- PQbinaryTuples(*results)) && success;
+ PQbinaryTuples(*results),
+ &copy_result) && 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.
+ * Replace the PGRES_COPY_OUT/IN result with COPY command's exit
+ * status, or with NULL if we want to suppress printing anything.
*/
PQclear(*results);
- *results = next_result = PQgetResult(pset.db);
+ *results = copy_result;
}
else if (first_cycle)
+ {
/* fast path: no COPY commands; PQexec visited all results */
break;
- else if ((next_result = PQgetResult(pset.db)))
- {
- /* non-COPY command(s) after a COPY: keep the last one */
- PQclear(*results);
- *results = next_result;
}
+ /*
+ * Check PQgetResult() again. 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. We keep the last result.
+ */
+ next_result = PQgetResult(pset.db);
+ if (!next_result)
+ break;
+
+ PQclear(*results);
+ *results = next_result;
first_cycle = false;
- } while (next_result);
+ }
/* may need this to recover from conn loss during COPY */
if (!first_cycle && !CheckConnection())