Commit b2678efd authored by Stephen Frost's avatar Stephen Frost

psql: Add \gx command

It can often be useful to use expanded mode output (\x) for just a
single query.  Introduce a \gx which acts exactly like \g except that it
will force expanded output mode for that one \gx call.  This is simpler
than having to use \x as a toggle and also means that the user doesn't
have to worry about the current state of the expanded variable, or
resetting it later, to ensure a given query is always returned in
expanded mode.

Primairly Christoph's patch, though I did tweak the documentation and help
text a bit, and re-indented the tab completion section.

Author: Christoph Berg
Reviewed By: Daniel Verite
Discussion: https://postgr.es/m/20170127132737.6skslelaf4txs6iw%40msg.credativ.de
parent 9a83d56b
......@@ -1890,6 +1890,18 @@ Tue Oct 26 21:40:57 CEST 1999
</varlistentry>
<varlistentry>
<term><literal>\gx [ <replaceable class="parameter">filename</replaceable> ]</literal></term>
<term><literal>\gx [ |<replaceable class="parameter">command</replaceable> ]</literal></term>
<listitem>
<para>
<literal>\gx</literal> is equivalent to <literal>\g</literal>, but
forces expanded output mode for this query. See <literal>\x</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>\gexec</literal></term>
......
......@@ -906,8 +906,11 @@ exec_command(const char *cmd,
free(fname);
}
/* \g [filename] -- send query, optionally with output to file/pipe */
else if (strcmp(cmd, "g") == 0)
/*
* \g [filename] -- send query, optionally with output to file/pipe
* \gx [filename] -- same as \g, with expanded mode forced
*/
else if (strcmp(cmd, "g") == 0 || strcmp(cmd, "gx") == 0)
{
char *fname = psql_scan_slash_option(scan_state,
OT_FILEPIPE, NULL, false);
......@@ -920,6 +923,8 @@ exec_command(const char *cmd,
pset.gfname = pg_strdup(fname);
}
free(fname);
if (strcmp(cmd, "gx") == 0)
pset.g_expanded = true;
status = PSQL_CMD_SEND;
}
......
......@@ -770,6 +770,10 @@ PrintQueryTuples(const PGresult *results)
{
printQueryOpt my_popt = pset.popt;
/* one-shot expanded output requested via \gx */
if (pset.g_expanded)
my_popt.topt.expanded = 1;
/* write output to \g argument, if any */
if (pset.gfname)
{
......@@ -1410,6 +1414,9 @@ sendquery_cleanup:
pset.gfname = NULL;
}
/* reset \gx's expanded-mode flag */
pset.g_expanded = false;
/* reset \gset trigger */
if (pset.gset_prefix)
{
......
......@@ -173,6 +173,7 @@ slashUsage(unsigned short int pager)
fprintf(output, _(" \\copyright show PostgreSQL usage and distribution terms\n"));
fprintf(output, _(" \\errverbose show most recent error message at maximum verbosity\n"));
fprintf(output, _(" \\g [FILE] or ; execute query (and send results to file or |pipe)\n"));
fprintf(output, _(" \\gx [FILE] as \\g, but forces expanded output mode\n"));
fprintf(output, _(" \\gexec execute query, then execute each value in its result\n"));
fprintf(output, _(" \\gset [PREFIX] execute query and store results in psql variables\n"));
fprintf(output, _(" \\q quit psql\n"));
......
......@@ -91,6 +91,7 @@ typedef struct _psqlSettings
printQueryOpt popt;
char *gfname; /* one-shot file output argument for \g */
bool g_expanded; /* one-shot expanded output requested via \gx */
char *gset_prefix; /* one-shot prefix argument for \gset */
bool gexec_flag; /* one-shot flag to execute query's results */
bool crosstab_flag; /* one-shot request to crosstab results */
......
......@@ -1375,11 +1375,12 @@ psql_completion(const char *text, int start, int end)
"\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\drds", "\\ds", "\\dS",
"\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
"\\e", "\\echo", "\\ef", "\\encoding", "\\errverbose", "\\ev",
"\\f", "\\g", "\\gexec", "\\gset", "\\h", "\\help", "\\H", "\\i", "\\ir", "\\l",
"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
"\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
"\\s", "\\set", "\\setenv", "\\sf", "\\sv", "\\t", "\\T",
"\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!", NULL
"\\f", "\\g", "\\gexec", "\\gset", "\\gx", "\\h", "\\help", "\\H",
"\\i", "\\ir", "\\l", "\\lo_import", "\\lo_export", "\\lo_list",
"\\lo_unlink", "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q",
"\\qecho", "\\r", "\\s", "\\set", "\\setenv", "\\sf", "\\sv", "\\t",
"\\T", "\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!",
NULL
};
(void) end; /* "end" is not used */
......
......@@ -28,6 +28,29 @@ on
\unset ON_ERROR_ROLLBACK
\echo :ON_ERROR_ROLLBACK
off
-- \g and \gx
SELECT 1 as one, 2 as two \g
one | two
-----+-----
1 | 2
(1 row)
\gx
-[ RECORD 1 ]
one | 1
two | 2
SELECT 3 as three, 4 as four \gx
-[ RECORD 1 ]
three | 3
four | 4
\g
three | four
-------+------
3 | 4
(1 row)
-- \gset
select 10 as test01, 20 as test02, 'Hello' as test03 \gset pref01_
\echo :pref01_test01 :pref01_test02 :pref01_test03
......
......@@ -21,6 +21,13 @@
\unset ON_ERROR_ROLLBACK
\echo :ON_ERROR_ROLLBACK
-- \g and \gx
SELECT 1 as one, 2 as two \g
\gx
SELECT 3 as three, 4 as four \gx
\g
-- \gset
select 10 as test01, 20 as test02, 'Hello' as test03 \gset pref01_
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment