@@ -892,6 +892,116 @@ ExecQueryTuples(const PGresult *result)
892
892
}
893
893
894
894
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
+
895
1005
/*
896
1006
* ProcessResult: utility function for use by SendQuery() only
897
1007
*
@@ -957,99 +1067,7 @@ ProcessResult(PGresult **resultp)
957
1067
}
958
1068
959
1069
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 );
1053
1071
else if (first_cycle )
1054
1072
{
1055
1073
/* fast path: no COPY commands; PQexec visited all results */
0 commit comments