- This operation is not as efficient as the
SQL
- COPY command because all data must pass
- through the client/server connection. For large
- amounts of data the
SQL command might be preferable.
+ Another way to obtain the same result as \copy
+ ... to is to use the
SQL COPY
+ ... TO STDOUT command and terminate it
+ with \g filename
+ or \g |program.
+ Unlike \copy, this method allows the command to
+ span multiple lines; also, variable interpolation and backquote
+ expansion can be used.
+
+
+
+
+ These operations are not as efficient as the
SQL
+ COPY command with a file or program data source or
+ destination, because all data must pass through the client/server
+ connection. For large amounts of data the
SQL
+ command might be preferable.
* connection out of its COPY state, then call PQresultStatus()
* once and report any error.
*
- * If pset.copyStream is set, use that as data source/sink,
- * otherwise use queryFout or cur_cmd_source as appropriate.
+ * 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 = pset.copyStream;
+ FILE *copystream;
PGresult *copy_result;
SetCancelConn();
if (result_status == PGRES_COPY_OUT)
{
- if (!copystream)
+ 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,
+ ©stream, &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,
- ©_result) && success;
+ ©_result)
+ && success
+ && (copystream != NULL);
/*
* Suppress status printing if the report would go to the same
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
{
- if (!copystream)
- copystream = pset.cur_cmd_source;
+ /* COPY IN */
+ copystream = pset.copyStream ? pset.copyStream : pset.cur_cmd_source;
success = handleCopyIn(pset.db,
copystream,
PQbinaryTuples(*results),
*
* conn should be a database connection that you just issued COPY TO on
* and got back a PGRES_COPY_OUT result.
+ *
* copystream is the file stream for the data to go to.
+ * copystream can be NULL to eat the data without writing it anywhere.
+ *
* The final status for the COPY is returned into *res (but note
* we already reported the error, if it's not a success result).
*
if (buf)
{
- if (OK && fwrite(buf, 1, ret, copystream) != ret)
+ if (OK && copystream && fwrite(buf, 1, ret, copystream) != ret)
{
psql_error("could not write COPY data: %s\n",
strerror(errno));
}
}
- if (OK && fflush(copystream))
+ if (OK && copystream && fflush(copystream))
{
psql_error("could not write COPY data: %s\n",
strerror(errno));