aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Eisentraut <peter@eisentraut.org>2022-04-01 13:00:43 +0200
committerPeter Eisentraut <peter@eisentraut.org>2022-04-01 13:03:33 +0200
commit5519d5affdfae4f5ea4b5faca65348cc14c5d279 (patch)
treec6a78996f4211dc7edbeb593499b8947068fde80 /src
parentd16773cdc86210493a2874cb0cf93f3883fcda73 (diff)
downloadpostgresql-5519d5affdfae4f5ea4b5faca65348cc14c5d279.tar.gz
postgresql-5519d5affdfae4f5ea4b5faca65348cc14c5d279.zip
psql: Refactor ProcessResult()
Separate HandleCopyResult() from ProcessResult() in preparation for a subsequent patch. Author: Fabien COELHO <coelho@cri.ensmp.fr> Discussion: https://www.postgresql.org/message-id/flat/alpine.DEB.2.21.1904132231510.8961@lancre
Diffstat (limited to 'src')
-rw-r--r--src/bin/psql/common.c204
1 files changed, 111 insertions, 93 deletions
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index c9847c8f9a0..f6777bbfc44 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -893,6 +893,116 @@ loop_exit:
/*
+ * Marshal the COPY data. Either subroutine will get the
+ * connection out of its COPY state, then call PQresultStatus()
+ * once and report any error. Return whether all was ok.
+ *
+ * For COPY OUT, direct the output to pset.copyStream if it's set,
+ * otherwise to pset.gfname if it's set, otherwise to queryFout.
+ * For COPY IN, use pset.copyStream as data source if it's set,
+ * otherwise cur_cmd_source.
+ *
+ * Update result if further processing is necessary, or NULL otherwise.
+ * Return a result when queryFout can safely output a result status: on COPY
+ * IN, or on COPY OUT if written to something other than pset.queryFout.
+ * Returning NULL prevents the command status from being printed, which we
+ * want if the status line doesn't get taken as part of the COPY data.
+ */
+static bool
+HandleCopyResult(PGresult **resultp)
+{
+ bool success;
+ FILE *copystream;
+ PGresult *copy_result;
+ ExecStatusType result_status = PQresultStatus(*resultp);
+
+ Assert(result_status == PGRES_COPY_OUT ||
+ result_status == PGRES_COPY_IN);
+
+ SetCancelConn(pset.db);
+
+ if (result_status == PGRES_COPY_OUT)
+ {
+ bool need_close = false;
+ bool is_pipe = false;
+
+ if (pset.copyStream)
+ {
+ /* invoked by \copy */
+ copystream = pset.copyStream;
+ }
+ else if (pset.gfname)
+ {
+ /* invoked by \g */
+ if (openQueryOutputFile(pset.gfname,
+ &copystream, &is_pipe))
+ {
+ need_close = true;
+ if (is_pipe)
+ disable_sigpipe_trap();
+ }
+ else
+ copystream = NULL; /* discard COPY data entirely */
+ }
+ else
+ {
+ /* fall back to the generic query output stream */
+ copystream = pset.queryFout;
+ }
+
+ success = handleCopyOut(pset.db,
+ copystream,
+ &copy_result)
+ && (copystream != NULL);
+
+ /*
+ * 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;
+ }
+
+ if (need_close)
+ {
+ /* close \g argument file/pipe */
+ if (is_pipe)
+ {
+ pclose(copystream);
+ restore_sigpipe_trap();
+ }
+ else
+ {
+ fclose(copystream);
+ }
+ }
+ }
+ else
+ {
+ /* COPY IN */
+ copystream = pset.copyStream ? pset.copyStream : pset.cur_cmd_source;
+ success = handleCopyIn(pset.db,
+ copystream,
+ PQbinaryTuples(*resultp),
+ &copy_result);
+ }
+ ResetCancelConn();
+
+ /*
+ * Replace the PGRES_COPY_OUT/IN result with COPY command's exit
+ * status, or with NULL if we want to suppress printing anything.
+ */
+ PQclear(*resultp);
+ *resultp = copy_result;
+
+ return success;
+}
+
+
+/*
* ProcessResult: utility function for use by SendQuery() only
*
* When our command string contained a COPY FROM STDIN or COPY TO STDOUT,
@@ -957,99 +1067,7 @@ ProcessResult(PGresult **resultp)
}
if (is_copy)
- {
- /*
- * Marshal the COPY data. Either subroutine will get the
- * connection out of its COPY state, then call PQresultStatus()
- * once and report any error.
- *
- * For COPY OUT, direct the output to pset.copyStream if it's set,
- * otherwise to pset.gfname if it's set, otherwise to queryFout.
- * For COPY IN, use pset.copyStream as data source if it's set,
- * otherwise cur_cmd_source.
- */
- FILE *copystream;
- PGresult *copy_result;
-
- SetCancelConn(pset.db);
- if (result_status == PGRES_COPY_OUT)
- {
- bool need_close = false;
- bool is_pipe = false;
-
- if (pset.copyStream)
- {
- /* invoked by \copy */
- copystream = pset.copyStream;
- }
- else if (pset.gfname)
- {
- /* invoked by \g */
- if (openQueryOutputFile(pset.gfname,
- &copystream, &is_pipe))
- {
- need_close = true;
- if (is_pipe)
- disable_sigpipe_trap();
- }
- else
- copystream = NULL; /* discard COPY data entirely */
- }
- else
- {
- /* fall back to the generic query output stream */
- copystream = pset.queryFout;
- }
-
- success = handleCopyOut(pset.db,
- copystream,
- &copy_result)
- && success
- && (copystream != NULL);
-
- /*
- * 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;
- }
-
- if (need_close)
- {
- /* close \g argument file/pipe */
- if (is_pipe)
- {
- pclose(copystream);
- restore_sigpipe_trap();
- }
- else
- {
- fclose(copystream);
- }
- }
- }
- else
- {
- /* COPY IN */
- copystream = pset.copyStream ? pset.copyStream : pset.cur_cmd_source;
- success = handleCopyIn(pset.db,
- copystream,
- PQbinaryTuples(*resultp),
- &copy_result) && success;
- }
- ResetCancelConn();
-
- /*
- * Replace the PGRES_COPY_OUT/IN result with COPY command's exit
- * status, or with NULL if we want to suppress printing anything.
- */
- PQclear(*resultp);
- *resultp = copy_result;
- }
+ success = HandleCopyResult(resultp);
else if (first_cycle)
{
/* fast path: no COPY commands; PQexec visited all results */