@@ -892,6 +892,116 @@ ExecQueryTuples(const PGresult *result)
892892}
893893
894894
895+ /*
896+ * Marshal the COPY data. Either subroutine will get the
897+ * connection out of its COPY state, then call PQresultStatus()
898+ * once and report any error. Return whether all was ok.
899+ *
900+ * For COPY OUT, direct the output to pset.copyStream if it's set,
901+ * otherwise to pset.gfname if it's set, otherwise to queryFout.
902+ * For COPY IN, use pset.copyStream as data source if it's set,
903+ * otherwise cur_cmd_source.
904+ *
905+ * Update result if further processing is necessary, or NULL otherwise.
906+ * Return a result when queryFout can safely output a result status: on COPY
907+ * IN, or on COPY OUT if written to something other than pset.queryFout.
908+ * Returning NULL prevents the command status from being printed, which we
909+ * want if the status line doesn't get taken as part of the COPY data.
910+ */
911+ static bool
912+ HandleCopyResult (PGresult * * resultp )
913+ {
914+ bool success ;
915+ FILE * copystream ;
916+ PGresult * copy_result ;
917+ ExecStatusType result_status = PQresultStatus (* resultp );
918+
919+ Assert (result_status == PGRES_COPY_OUT ||
920+ result_status == PGRES_COPY_IN );
921+
922+ SetCancelConn (pset .db );
923+
924+ if (result_status == PGRES_COPY_OUT )
925+ {
926+ bool need_close = false;
927+ bool is_pipe = false;
928+
929+ if (pset .copyStream )
930+ {
931+ /* invoked by \copy */
932+ copystream = pset .copyStream ;
933+ }
934+ else if (pset .gfname )
935+ {
936+ /* invoked by \g */
937+ if (openQueryOutputFile (pset .gfname ,
938+ & copystream , & is_pipe ))
939+ {
940+ need_close = true;
941+ if (is_pipe )
942+ disable_sigpipe_trap ();
943+ }
944+ else
945+ copystream = NULL ; /* discard COPY data entirely */
946+ }
947+ else
948+ {
949+ /* fall back to the generic query output stream */
950+ copystream = pset .queryFout ;
951+ }
952+
953+ success = handleCopyOut (pset .db ,
954+ copystream ,
955+ & copy_result )
956+ && (copystream != NULL );
957+
958+ /*
959+ * Suppress status printing if the report would go to the same
960+ * place as the COPY data just went. Note this doesn't
961+ * prevent error reporting, since handleCopyOut did that.
962+ */
963+ if (copystream == pset .queryFout )
964+ {
965+ PQclear (copy_result );
966+ copy_result = NULL ;
967+ }
968+
969+ if (need_close )
970+ {
971+ /* close \g argument file/pipe */
972+ if (is_pipe )
973+ {
974+ pclose (copystream );
975+ restore_sigpipe_trap ();
976+ }
977+ else
978+ {
979+ fclose (copystream );
980+ }
981+ }
982+ }
983+ else
984+ {
985+ /* COPY IN */
986+ copystream = pset .copyStream ? pset .copyStream : pset .cur_cmd_source ;
987+ success = handleCopyIn (pset .db ,
988+ copystream ,
989+ PQbinaryTuples (* resultp ),
990+ & copy_result );
991+ }
992+ ResetCancelConn ();
993+
994+ /*
995+ * Replace the PGRES_COPY_OUT/IN result with COPY command's exit
996+ * status, or with NULL if we want to suppress printing anything.
997+ */
998+ PQclear (* resultp );
999+ * resultp = copy_result ;
1000+
1001+ return success ;
1002+ }
1003+
1004+
8951005/*
8961006 * ProcessResult: utility function for use by SendQuery() only
8971007 *
@@ -957,99 +1067,7 @@ ProcessResult(PGresult **resultp)
9571067 }
9581068
9591069 if (is_copy )
960- {
961- /*
962- * Marshal the COPY data. Either subroutine will get the
963- * connection out of its COPY state, then call PQresultStatus()
964- * once and report any error.
965- *
966- * For COPY OUT, direct the output to pset.copyStream if it's set,
967- * otherwise to pset.gfname if it's set, otherwise to queryFout.
968- * For COPY IN, use pset.copyStream as data source if it's set,
969- * otherwise cur_cmd_source.
970- */
971- FILE * copystream ;
972- PGresult * copy_result ;
973-
974- SetCancelConn (pset .db );
975- if (result_status == PGRES_COPY_OUT )
976- {
977- bool need_close = false;
978- bool is_pipe = false;
979-
980- if (pset .copyStream )
981- {
982- /* invoked by \copy */
983- copystream = pset .copyStream ;
984- }
985- else if (pset .gfname )
986- {
987- /* invoked by \g */
988- if (openQueryOutputFile (pset .gfname ,
989- & copystream , & is_pipe ))
990- {
991- need_close = true;
992- if (is_pipe )
993- disable_sigpipe_trap ();
994- }
995- else
996- copystream = NULL ; /* discard COPY data entirely */
997- }
998- else
999- {
1000- /* fall back to the generic query output stream */
1001- copystream = pset .queryFout ;
1002- }
1003-
1004- success = handleCopyOut (pset .db ,
1005- copystream ,
1006- & copy_result )
1007- && success
1008- && (copystream != NULL );
1009-
1010- /*
1011- * Suppress status printing if the report would go to the same
1012- * place as the COPY data just went. Note this doesn't
1013- * prevent error reporting, since handleCopyOut did that.
1014- */
1015- if (copystream == pset .queryFout )
1016- {
1017- PQclear (copy_result );
1018- copy_result = NULL ;
1019- }
1020-
1021- if (need_close )
1022- {
1023- /* close \g argument file/pipe */
1024- if (is_pipe )
1025- {
1026- pclose (copystream );
1027- restore_sigpipe_trap ();
1028- }
1029- else
1030- {
1031- fclose (copystream );
1032- }
1033- }
1034- }
1035- else
1036- {
1037- /* COPY IN */
1038- copystream = pset .copyStream ? pset .copyStream : pset .cur_cmd_source ;
1039- success = handleCopyIn (pset .db ,
1040- copystream ,
1041- PQbinaryTuples (* resultp ),
1042- & copy_result ) && success ;
1043- }
1044- ResetCancelConn ();
1045-
1046- /*
1047- * Replace the PGRES_COPY_OUT/IN result with COPY command's exit
1048- * status, or with NULL if we want to suppress printing anything.
1049- */
1050- PQclear (* resultp );
1051- * resultp = copy_result ;
1052- }
1070+ success = HandleCopyResult (resultp );
10531071 else if (first_cycle )
10541072 {
10551073 /* fast path: no COPY commands; PQexec visited all results */
0 commit comments