psql: Refactor ProcessResult()
authorPeter Eisentraut <peter@eisentraut.org>
Fri, 1 Apr 2022 11:00:43 +0000 (13:00 +0200)
committerPeter Eisentraut <peter@eisentraut.org>
Fri, 1 Apr 2022 11:03:33 +0000 (13:03 +0200)
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

src/bin/psql/common.c

index c9847c8f9a02745d8d5553095d2814b973479f06..f6777bbfc44a9469a3338178a0175f40f2103508 100644 (file)
@@ -892,6 +892,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
  *
@@ -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 */