Re: Alternative to \copy in psql modelled after \g

From: "Daniel Verite" <daniel(at)manitou-mail(dot)org>
To: "Fabien COELHO" <coelho(at)cri(dot)ensmp(dot)fr>
Cc: "Tom Lane" <tgl(at)sss(dot)pgh(dot)pa(dot)us>,"Alvaro Herrera" <alvherre(at)2ndquadrant(dot)com>,"PostgreSQL Hackers" <pgsql-hackers(at)lists(dot)postgresql(dot)org>,"David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
Subject: Re: Alternative to \copy in psql modelled after \g
Date: 2019-01-19 14:50:20
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Fabien COELHO wrote:

> > I've also changed handleCopyOut() to return success if it
> > could pump the data without writing it out locally for lack of
> > an output stream. It seems to make more sense like that.
> I'm hesitating on this one.
> On the one hand the SQL query is executed, on the other hand the \g
> command partially failed. There is a debatable side effect: If there is an
> error, eg:

The change mentioned above is not supposed to have any user-visible
effect, compared to the previous version. The success of the command
as a whole, that is reflected by :ERROR, is the result of AND'ing the
successes of different steps of the command. Having handleCopyOut()
succeed does not change the falseness of the aggregated result,
which is still false when it fails to open the output stream.

> But previously we had:
> sql> \echo :ROW_COUNT # 0

Previously "COPY... \g file" behaved as "COPY... \g", the argument being
ignored. In this case, and the patch doesn't change that, the code does:

* 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)
copy_result = NULL;

One effect of clearing that result is that :ROW_COUNT is going to
be set to zero by SetResultVariables(), which explains the above

:ROW_COUNT is incorrect after COPY TO STDOUT but this is a PG11-only
bug, :ROW_COUNT being a recent addition, so maybe we should deal with
this separately, since the current patch is supposed to address all versions?

> I understand from the code that the COPY is really executed, so the ERROR
> and so ROW_COUNT about the SQL should reflect that. Basically the change
> makes the client believe that there is an SQL error whereas the error is
> on the client.

Right, but wether COPY fails because psql can't write the output,
possibly half-way because of a disk full condition, or because the
query was cancelled or the server went down, are these distinctions
meaningful for a script?
If we say yes, how can the user know that the data fetched is
empty or incomplete? We don't have a CLIENT_SIDE_ERROR variable.
Also, the fact that psql retrieves the results when it doesn't have
a valid destination for them is an implementation detail.
I think we could also cancel the query in a way that would be
technically an SQL error, as Ctrl+C would do.
Hiding these details under a generic ERROR=true seems reasonable,
especially since we expose SQLSTATE for fine-grained error checking,
should that be needed.
ERROR=true and SQLSTATE empty is already mentioned as plausible
in SetResultVariables():

SetVariable(pset.vars, "ERROR", "true");

* If there is no SQLSTATE code, use an empty string. This can
* for libpq-detected errors (e.g., lost connection, ENOMEM).
if (code == NULL)
code = "";
SetVariable(pset.vars, "SQLSTATE", code);

> The later part of the comment is already stated in the documentation, I'm
> not sure it is worth repeating it here. I'd suggest a simpler /* handle
> "COPY TO STDOUT \g ..." */

The bug we're fixing here is due to missing the point the comment is
making, so being thick seems fair.

Best regards,
Daniel Vérité
PostgreSQL-powered mailer:
Twitter: @DanielVerite

In response to


Browse pgsql-hackers by date

  From Date Subject
Next Message Vik Fearing 2019-01-19 15:12:52 Re: pg_stat_statements vs. SELECT FOR UPDATE
Previous Message Andrew Gierth 2019-01-19 14:43:10 pg_stat_statements vs. SELECT FOR UPDATE