mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
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
This commit is contained in:
@ -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,
|
||||||
|
©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)
|
||||||
|
&& (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),
|
||||||
|
©_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
|
* ProcessResult: utility function for use by SendQuery() only
|
||||||
*
|
*
|
||||||
@ -957,99 +1067,7 @@ ProcessResult(PGresult **resultp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_copy)
|
if (is_copy)
|
||||||
{
|
success = HandleCopyResult(resultp);
|
||||||
/*
|
|
||||||
* 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,
|
|
||||||
©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
|
|
||||||
&& (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),
|
|
||||||
©_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;
|
|
||||||
}
|
|
||||||
else if (first_cycle)
|
else if (first_cycle)
|
||||||
{
|
{
|
||||||
/* fast path: no COPY commands; PQexec visited all results */
|
/* fast path: no COPY commands; PQexec visited all results */
|
||||||
|
Reference in New Issue
Block a user