How to *really* quit psql?

Started by Fabien COELHOover 3 years ago10 messageshackers
Jump to latest
#1Fabien COELHO
coelho@cri.ensmp.fr

Hello devs,

I want to abort a psql script. How can I do that? The answer seems to be
\quit, but it is not so simple:

- when the current script is from a terminal, you exit psql, OK

- when the current script is from a file (-f, <), you exit psql, OK

- when the current script is included from something,
you quit the current script and proceed after the \i of next -f, BAD

Question: is there any way to really abort a psql script from an included
file?

I've found "\! kill $PPID" which works with bash, but I'm not sure of the
portability and I was hoping for something straightforward and cleaner.

If there is really no simple way, would it be okay to add a \exit which
does that?

--
Fabien.

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Fabien COELHO (#1)
Re: How to *really* quit psql?

Fabien COELHO <coelho@cri.ensmp.fr> writes:

- when the current script is included from something,
you quit the current script and proceed after the \i of next -f, BAD

Question: is there any way to really abort a psql script from an included
file?

Under what circumstances would it be appropriate for a script to take
it on itself to decide that? It has no way of knowing what the next -f
option is or what the user intended.

regards, tom lane

#3David G. Johnston
david.g.johnston@gmail.com
In reply to: Tom Lane (#2)
Re: How to *really* quit psql?

On Sat, Nov 19, 2022 at 12:10 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Fabien COELHO <coelho@cri.ensmp.fr> writes:

- when the current script is included from something,
you quit the current script and proceed after the \i of next -f, BAD

Question: is there any way to really abort a psql script from an

included

file?

Under what circumstances would it be appropriate for a script to take
it on itself to decide that? It has no way of knowing what the next -f
option is or what the user intended.

Can we add an exit code argument to the \quit meta-command that could be
set to non-zero and, combined with ON_ERROR_STOP, produces the desired
effect of aborting everything just like an error under ON_ERROR_STOP does
(which is the workaround here I suppose, but an ugly one that involves the
server).

David J.

#4Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#2)
Re: How to *really* quit psql?

On Sat, 19 Nov 2022 at 14:10, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Under what circumstances would it be appropriate for a script to take
it on itself to decide that? It has no way of knowing what the next -f
option is or what the user intended.

Presumably when they're written by the same person so the script does
effectively know what the "user" intended because it's written by the
same user.

Off the top of my head I could imagine someone writing something like
report-error-and-exit.sql and wanting to be able to use \i
report-error-and-exit.sql to ensure all scripts report their errors
using some common log file or something.

Not saying that's the only or best way to do that though. And there is
the risk that scripts would start using this functionality
inappropriately which would mean, for example, getting an install
script for something and then not being able to use it within another
script safely :(

--
greg

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Bruce Momjian (#4)
Re: How to *really* quit psql?

Greg Stark <stark@mit.edu> writes:

On Sat, 19 Nov 2022 at 14:10, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Under what circumstances would it be appropriate for a script to take
it on itself to decide that? It has no way of knowing what the next -f
option is or what the user intended.

Presumably when they're written by the same person so the script does
effectively know what the "user" intended because it's written by the
same user.

Even so, embedding that knowledge in the first script doesn't seem
like the sort of design we ought to encourage. It'd be better if
"don't run the next script if the first one fails" were directed
by a command-line switch or the like. I also wonder exactly how
this interacts with existing features like ON_ERROR_STOP.

regards, tom lane

#6David G. Johnston
david.g.johnston@gmail.com
In reply to: Tom Lane (#5)
Re: How to *really* quit psql?

On Sat, Nov 19, 2022 at 12:49 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Greg Stark <stark@mit.edu> writes:

On Sat, 19 Nov 2022 at 14:10, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Under what circumstances would it be appropriate for a script to take
it on itself to decide that? It has no way of knowing what the next -f
option is or what the user intended.

Presumably when they're written by the same person so the script does
effectively know what the "user" intended because it's written by the
same user.

Even so, embedding that knowledge in the first script doesn't seem
like the sort of design we ought to encourage. It'd be better if
"don't run the next script if the first one fails" were directed
by a command-line switch or the like. I also wonder exactly how
this interacts with existing features like ON_ERROR_STOP.

vagrant@vagrant:~$ /usr/local/pgsql/bin/psql -v ON_ERROR_STOP=1 -f two.psql
-f three.psql postgres
psql:two.psql:1: ERROR: division by zero
vagrant@vagrant:~$ /usr/local/pgsql/bin/psql -f two.psql -f three.psql
postgres
psql:two.psql:1: ERROR: division by zero
?column?
----------
2
(1 row)

?column?
----------
3
(1 row)

David J.

#7David G. Johnston
david.g.johnston@gmail.com
In reply to: David G. Johnston (#6)
Re: How to *really* quit psql?

On Sat, Nov 19, 2022 at 12:59 PM David G. Johnston <
david.g.johnston@gmail.com> wrote:

On Sat, Nov 19, 2022 at 12:49 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Greg Stark <stark@mit.edu> writes:

On Sat, 19 Nov 2022 at 14:10, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Under what circumstances would it be appropriate for a script to take
it on itself to decide that? It has no way of knowing what the next -f
option is or what the user intended.

Presumably when they're written by the same person so the script does
effectively know what the "user" intended because it's written by the
same user.

Even so, embedding that knowledge in the first script doesn't seem
like the sort of design we ought to encourage. It'd be better if
"don't run the next script if the first one fails" were directed
by a command-line switch or the like. I also wonder exactly how
this interacts with existing features like ON_ERROR_STOP.

vagrant@vagrant:~$ /usr/local/pgsql/bin/psql -v ON_ERROR_STOP=1 -f
two.psql -f three.psql postgres
psql:two.psql:1: ERROR: division by zero
vagrant@vagrant:~$ /usr/local/pgsql/bin/psql -f two.psql -f three.psql
postgres
psql:two.psql:1: ERROR: division by zero
?column?
----------
2
(1 row)

?column?
----------
3
(1 row)

Sorry, forgot the \quit test:

vagrant@vagrant:~$ /usr/local/pgsql/bin/psql -v ON_ERROR_STOP=1 -f two.psql
-f three.psql postgres
?column?
----------
2
(1 row)

?column?
----------
3
(1 row)

(there is a \quit at the end of two.psql)

David J.

#8Fabien COELHO
coelho@cri.ensmp.fr
In reply to: Tom Lane (#2)
Re: How to *really* quit psql?

Hello Tom,

- when the current script is included from something,
you quit the current script and proceed after the \i of next -f, BAD

Question: is there any way to really abort a psql script from an included
file?

Under what circumstances would it be appropriate for a script to take
it on itself to decide that?

The use case is psql scripts which update or cleanup an application
schema. For security, some of these scripts check for conditions (eg, we
are not in production, the application schema is in the expected version,
whatever…) and should abort if the conditions are not okay. As checking
for the conditions requires a few lines of code and is always the same, a
simple approach is to include another script which does the check and
aborts the run if necessary, eg:

```sql
-- this script should not run in "prod"!
\ir not_in_prod.sql
-- should have aborted if it is a "prod" version.
DROP TABLE AllMyUsers CASCADE;
DROP TABLE QuiteImportantData CASCADE;
```

It has no way of knowing what the next -f option is or what the user
intended.

The intention of the user who wrote the script is to abort in some cases,
to avoid damaging the database contents.

--
Fabien.

#9Fabien COELHO
coelho@cri.ensmp.fr
In reply to: David G. Johnston (#7)
Re: How to *really* quit psql?

Hello David,

vagrant@vagrant:~$ /usr/local/pgsql/bin/psql -v ON_ERROR_STOP=1 -f two.psql
-f three.psql postgres
?column?
----------
2
(1 row)

?column?
----------
3
(1 row)

(there is a \quit at the end of two.psql)

Yep, that summarizes my issues!

ON_ERROR_STOP is only of SQL errors, so a script can really stop by having
an intentional SQL error.

--
Fabien.

Attachments:

quit.sqlapplication/sql; name=quit.sqlDownload
error.sqlapplication/sql; name=error.sqlDownload
include.sqlapplication/sql; name=include.sqlDownload
exit.sqlapplication/sql; name=exit.sqlDownload
#10Fabien COELHO
coelho@cri.ensmp.fr
In reply to: David G. Johnston (#3)
Re: How to *really* quit psql?

Hello David,

Question: is there any way to really abort a psql script from an
included file?

Under what circumstances would it be appropriate for a script to take
it on itself to decide that? It has no way of knowing what the next -f
option is or what the user intended.

Can we add an exit code argument to the \quit meta-command that could be
set to non-zero and, combined with ON_ERROR_STOP, produces the desired
effect of aborting everything just like an error under ON_ERROR_STOP does
(which is the workaround here I suppose, but an ugly one that involves the
server).

I like the simple idea of adding an optional exit status argument to
\quit. I'm unsure whether "ON_ERROR_STOP" should or should not change the
behavior, or whether it should just exit(n) with \quit n.

Note that using quit to abort a psql script is already used when loading
extensions to prevent them to be run directly by psql:

-- from some sql files in "contrib/pg_stat_statements/":
\echo Use "ALTER EXTENSION pg_stat_statements UPDATE TO '1.10'" to load this file. \quit

But the same trick would fail if the guard is reach with an include.

--
Fabien.