Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 31ae2aa

Browse filesBrowse files
committed
psql: set SHELL_ERROR and SHELL_EXIT_CODE in more places.
Make the \g, \o, \w, and \copy commands set these variables when closing a pipe. We missed doing this in commit b0d8f2d, but it seems like a good idea. There are some remaining places in psql that intentionally don't update these variables after running a child program: * pager invocations * backtick evaluation within a prompt * \e (edit query buffer) Corey Huinker and Tom Lane Discussion: https://postgr.es/m/CADkLM=eSKwRGF-rnRqhtBORRtL49QsjcVUCa-kLxKTqxypsakw@mail.gmail.com
1 parent 029dea8 commit 31ae2aa
Copy full SHA for 31ae2aa

File tree

6 files changed

+44
-27
lines changed
Filter options

6 files changed

+44
-27
lines changed

‎doc/src/sgml/ref/psql-ref.sgml

Copy file name to clipboardExpand all lines: doc/src/sgml/ref/psql-ref.sgml
+12-4
Original file line numberDiff line numberDiff line change
@@ -4277,8 +4277,12 @@ bar
42774277
<para>
42784278
<literal>true</literal> if the last shell command
42794279
failed, <literal>false</literal> if it succeeded.
4280-
This applies to shell commands invoked via the <literal>\!</literal>
4281-
meta-command or backquote (<literal>`</literal>) expansion.
4280+
This applies to shell commands invoked via the <literal>\!</literal>,
4281+
<literal>\g</literal>, <literal>\o</literal>, <literal>\w</literal>,
4282+
and <literal>\copy</literal> meta-commands, as well as backquote
4283+
(<literal>`</literal>) expansion. Note that
4284+
for <literal>\o</literal>, this variable is updated when the output
4285+
pipe is closed by the next <literal>\o</literal> command.
42824286
See also <varname>SHELL_EXIT_CODE</varname>.
42834287
</para>
42844288
</listitem>
@@ -4292,8 +4296,12 @@ bar
42924296
0&ndash;127 represent program exit codes, 128&ndash;255
42934297
indicate termination by a signal, and -1 indicates failure
42944298
to launch a program or to collect its exit status.
4295-
This applies to shell commands invoked via the <literal>\!</literal>
4296-
meta-command or backquote (<literal>`</literal>) expansion.
4299+
This applies to shell commands invoked via the <literal>\!</literal>,
4300+
<literal>\g</literal>, <literal>\o</literal>, <literal>\w</literal>,
4301+
and <literal>\copy</literal> meta-commands, as well as backquote
4302+
(<literal>`</literal>) expansion. Note that
4303+
for <literal>\o</literal>, this variable is updated when the output
4304+
pipe is closed by the next <literal>\o</literal> command.
42974305
See also <varname>SHELL_ERROR</varname>.
42984306
</para>
42994307
</listitem>

‎src/bin/psql/command.c

Copy file name to clipboardExpand all lines: src/bin/psql/command.c
+2-14
Original file line numberDiff line numberDiff line change
@@ -2734,6 +2734,7 @@ exec_command_write(PsqlScanState scan_state, bool active_branch,
27342734
pg_log_error("%s: %s", fname, wait_result_to_str(result));
27352735
status = PSQL_CMD_ERROR;
27362736
}
2737+
SetShellResultVariables(result);
27372738
}
27382739
else
27392740
{
@@ -5119,20 +5120,7 @@ do_shell(const char *command)
51195120
else
51205121
result = system(command);
51215122

5122-
if (result == 0)
5123-
{
5124-
SetVariable(pset.vars, "SHELL_EXIT_CODE", "0");
5125-
SetVariable(pset.vars, "SHELL_ERROR", "false");
5126-
}
5127-
else
5128-
{
5129-
int exit_code = wait_result_to_exit_code(result);
5130-
char buf[32];
5131-
5132-
snprintf(buf, sizeof(buf), "%d", exit_code);
5133-
SetVariable(pset.vars, "SHELL_EXIT_CODE", buf);
5134-
SetVariable(pset.vars, "SHELL_ERROR", "true");
5135-
}
5123+
SetShellResultVariables(result);
51365124

51375125
if (result == 127 || result == -1)
51385126
{

‎src/bin/psql/common.c

Copy file name to clipboardExpand all lines: src/bin/psql/common.c
+23-3
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ setQFout(const char *fname)
103103
if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)
104104
{
105105
if (pset.queryFoutPipe)
106-
pclose(pset.queryFout);
106+
SetShellResultVariables(pclose(pset.queryFout));
107107
else
108108
fclose(pset.queryFout);
109109
}
@@ -449,6 +449,26 @@ SetResultVariables(PGresult *result, bool success)
449449
}
450450

451451

452+
/*
453+
* Set special variables from a shell command result
454+
* - SHELL_ERROR: true/false, whether command returned exit code 0
455+
* - SHELL_EXIT_CODE: exit code according to shell conventions
456+
*
457+
* The argument is a wait status as returned by wait(2) or waitpid(2),
458+
* which also applies to pclose(3) and system(3).
459+
*/
460+
void
461+
SetShellResultVariables(int wait_result)
462+
{
463+
char buf[32];
464+
465+
SetVariable(pset.vars, "SHELL_ERROR",
466+
(wait_result == 0) ? "false" : "true");
467+
snprintf(buf, sizeof(buf), "%d", wait_result_to_exit_code(wait_result));
468+
SetVariable(pset.vars, "SHELL_EXIT_CODE", buf);
469+
}
470+
471+
452472
/*
453473
* ClearOrSaveResult
454474
*
@@ -1652,7 +1672,7 @@ ExecQueryAndProcessResults(const char *query,
16521672
{
16531673
if (gfile_is_pipe)
16541674
{
1655-
pclose(gfile_fout);
1675+
SetShellResultVariables(pclose(gfile_fout));
16561676
restore_sigpipe_trap();
16571677
}
16581678
else
@@ -1870,7 +1890,7 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
18701890
/* close \g argument file/pipe */
18711891
if (is_pipe)
18721892
{
1873-
pclose(fout);
1893+
SetShellResultVariables(pclose(fout));
18741894
restore_sigpipe_trap();
18751895
}
18761896
else

‎src/bin/psql/common.h

Copy file name to clipboardExpand all lines: src/bin/psql/common.h
+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ extern sigjmp_buf sigint_interrupt_jmp;
2929

3030
extern void psql_setup_cancel_handler(void);
3131

32+
extern void SetShellResultVariables(int wait_result);
33+
3234
extern PGresult *PSQLexec(const char *query);
3335
extern int PSQLexecWatch(const char *query, const printQueryOpt *opt, FILE *printQueryFout);
3436

‎src/bin/psql/copy.c

Copy file name to clipboardExpand all lines: src/bin/psql/copy.c
+1
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ do_copy(const char *args)
391391
}
392392
success = false;
393393
}
394+
SetShellResultVariables(pclose_rc);
394395
restore_sigpipe_trap();
395396
}
396397
else

‎src/bin/psql/psqlscanslash.l

Copy file name to clipboardExpand all lines: src/bin/psql/psqlscanslash.l
+4-6
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
*/
1919
#include "postgres_fe.h"
2020

21+
#include "common.h"
2122
#include "psqlscanslash.h"
22-
#include "settings.h"
2323

2424
#include "common/logging.h"
2525
#include "fe_utils/conditional.h"
@@ -807,7 +807,7 @@ evaluate_backtick(PsqlScanState state)
807807
if (fd)
808808
{
809809
/*
810-
* Although pclose's result always sets SHELL_EXIT_CODE, we
810+
* Although pclose's result always sets the shell result variables, we
811811
* historically have abandoned the backtick substitution only if it
812812
* returns -1.
813813
*/
@@ -839,10 +839,8 @@ evaluate_backtick(PsqlScanState state)
839839
appendBinaryPQExpBuffer(output_buf, cmd_output.data, cmd_output.len);
840840
}
841841

842-
/* And finally, set the shell error variables */
843-
snprintf(buf, sizeof(buf), "%d", wait_result_to_exit_code(exit_code));
844-
SetVariable(pset.vars, "SHELL_EXIT_CODE", buf);
845-
SetVariable(pset.vars, "SHELL_ERROR", (exit_code == 0) ? "false" : "true");
842+
/* And finally, set the shell result variables */
843+
SetShellResultVariables(exit_code);
846844

847845
termPQExpBuffer(&cmd_output);
848846
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.