Commit 3a513067 authored by Peter Eisentraut's avatar Peter Eisentraut

psql: Show all query results by default

Previously, psql printed only the last result if a command string
returned multiple result sets.  Now it prints all of them.  The
previous behavior can be obtained by setting the psql variable
SHOW_ALL_RESULTS to off.

Author: Fabien COELHO <coelho@cri.ensmp.fr>
Reviewed-by: default avatar"Iwata, Aya" <iwata.aya@jp.fujitsu.com>
Reviewed-by: default avatarDaniel Verite <daniel@manitou-mail.org>
Reviewed-by: default avatarPeter Eisentraut <peter.eisentraut@2ndquadrant.com>
Reviewed-by: default avatarKyotaro Horiguchi <horikyota.ntt@gmail.com>
Reviewed-by: default avatarvignesh C <vignesh21@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/alpine.DEB.2.21.1904132231510.8961@lancre
parent 518442c7
......@@ -50,8 +50,28 @@ BEGIN \;
SELECT 2.0 AS "float" \;
SELECT 'world' AS "text" \;
COMMIT;
float
-------
2.0
(1 row)
text
-------
world
(1 row)
-- compound with empty statements and spurious leading spacing
\;\; SELECT 3 + 3 \;\;\; SELECT ' ' || ' !' \;\; SELECT 1 + 4 \;;
?column?
----------
6
(1 row)
?column?
----------
!
(1 row)
?column?
----------
5
......@@ -61,6 +81,11 @@ COMMIT;
SELECT 1 + 1 + 1 AS "add" \gset
SELECT :add + 1 + 1 AS "add" \;
SELECT :add + 1 + 1 AS "add" \gset
add
-----
5
(1 row)
-- set operator
SELECT 1 AS i UNION SELECT 2 ORDER BY i;
i
......
......@@ -127,18 +127,11 @@ echo '\x \\ SELECT * FROM foo;' | psql
commands included in the string to divide it into multiple
transactions. (See <xref linkend="protocol-flow-multi-statement"/>
for more details about how the server handles multi-query strings.)
Also, <application>psql</application> only prints the
result of the last <acronym>SQL</acronym> command in the string.
This is different from the behavior when the same string is read from
a file or fed to <application>psql</application>'s standard input,
because then <application>psql</application> sends
each <acronym>SQL</acronym> command separately.
</para>
<para>
Because of this behavior, putting more than one SQL command in a
single <option>-c</option> string often has unexpected results.
It's better to use repeated <option>-c</option> commands or feed
multiple commands to <application>psql</application>'s standard input,
</para>
<para>
If having several commands executed in one transaction is not desired,
use repeated <option>-c</option> commands or feed multiple commands to
<application>psql</application>'s standard input,
either using <application>echo</application> as illustrated above, or
via a shell here-document, for example:
<programlisting>
......@@ -3527,10 +3520,6 @@ select 1\; select 2\; select 3;
commands included in the string to divide it into multiple
transactions. (See <xref linkend="protocol-flow-multi-statement"/>
for more details about how the server handles multi-query strings.)
<application>psql</application> prints only the last query result
it receives for each request; in this example, although all
three <command>SELECT</command>s are indeed executed, <application>psql</application>
only prints the <literal>3</literal>.
</para>
</listitem>
</varlistentry>
......@@ -4116,6 +4105,18 @@ bar
</listitem>
</varlistentry>
<varlistentry>
<term><varname>SHOW_ALL_RESULTS</varname></term>
<listitem>
<para>
When this variable is set to <literal>off</literal>, only the last
result of a combined query (<literal>\;</literal>) is shown instead of
all of them. The default is <literal>on</literal>. The off behavior
is for compatibility with older versions of psql.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>SHOW_CONTEXT</varname></term>
<listitem>
......
This diff is collapsed.
......@@ -410,6 +410,8 @@ helpVariables(unsigned short int pager)
fprintf(output, _(" SERVER_VERSION_NAME\n"
" SERVER_VERSION_NUM\n"
" server's version (in short string or numeric format)\n"));
fprintf(output, _(" SHOW_ALL_RESULTS\n"
" show all results of a combined query (\\;) instead of only the last\n"));
fprintf(output, _(" SHOW_CONTEXT\n"
" controls display of message context fields [never, errors, always]\n"));
fprintf(output, _(" SINGLELINE\n"
......
......@@ -148,6 +148,7 @@ typedef struct _psqlSettings
const char *prompt2;
const char *prompt3;
PGVerbosity verbosity; /* current error verbosity level */
bool show_all_results;
PGContextVisibility show_context; /* current context display level */
} PsqlSettings;
......
......@@ -196,6 +196,7 @@ main(int argc, char *argv[])
SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
SetVariableBool(pset.vars, "SHOW_ALL_RESULTS");
parse_psql_options(argc, argv, &options);
......@@ -1130,6 +1131,12 @@ verbosity_hook(const char *newval)
return true;
}
static bool
show_all_results_hook(const char *newval)
{
return ParseVariableBool(newval, "SHOW_ALL_RESULTS", &pset.show_all_results);
}
static char *
show_context_substitute_hook(char *newval)
{
......@@ -1231,6 +1238,9 @@ EstablishVariableSpace(void)
SetVariableHooks(pset.vars, "VERBOSITY",
verbosity_substitute_hook,
verbosity_hook);
SetVariableHooks(pset.vars, "SHOW_ALL_RESULTS",
bool_substitute_hook,
show_all_results_hook);
SetVariableHooks(pset.vars, "SHOW_CONTEXT",
show_context_substitute_hook,
show_context_hook);
......
......@@ -4122,7 +4122,7 @@ psql_completion(const char *text, int start, int end)
matches = complete_from_variables(text, "", "", false);
else if (TailMatchesCS("\\set", MatchAny))
{
if (TailMatchesCS("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
if (TailMatchesCS("AUTOCOMMIT|ON_ERROR_STOP|QUIET|SHOW_ALL_RESULTS|"
"SINGLELINE|SINGLESTEP"))
COMPLETE_WITH_CS("on", "off");
else if (TailMatchesCS("COMP_KEYWORD_CASE"))
......
......@@ -126,7 +126,7 @@ copy (select 1) to stdout\; select 1/0; -- row, then error
ERROR: division by zero
select 1/0\; copy (select 1) to stdout; -- error only
ERROR: division by zero
copy (select 1) to stdout\; copy (select 2) to stdout\; select 0\; select 3; -- 1 2 3
copy (select 1) to stdout\; copy (select 2) to stdout\; select 3\; select 4; -- 1 2 3 4
1
2
?column?
......@@ -134,8 +134,18 @@ copy (select 1) to stdout\; copy (select 2) to stdout\; select 0\; select 3; --
3
(1 row)
?column?
----------
4
(1 row)
create table test3 (c int);
select 0\; copy test3 from stdin\; copy test3 from stdin\; select 1; -- 1
select 0\; copy test3 from stdin\; copy test3 from stdin\; select 1; -- 0 1
?column?
----------
0
(1 row)
?column?
----------
1
......
......@@ -5078,3 +5078,96 @@ List of access methods
hash | uuid_ops | uuid | uuid | 2 | uuid_hash_extended
(5 rows)
--
-- combined queries
--
CREATE FUNCTION warn(msg TEXT) RETURNS BOOLEAN LANGUAGE plpgsql
AS $$
BEGIN RAISE NOTICE 'warn %', msg ; RETURN TRUE ; END
$$;
-- show both
SELECT 1 AS one \; SELECT warn('1.5') \; SELECT 2 AS two ;
one
-----
1
(1 row)
NOTICE: warn 1.5
CONTEXT: PL/pgSQL function warn(text) line 2 at RAISE
warn
------
t
(1 row)
two
-----
2
(1 row)
-- \gset applies to last query only
SELECT 3 AS three \; SELECT warn('3.5') \; SELECT 4 AS four \gset
three
-------
3
(1 row)
NOTICE: warn 3.5
CONTEXT: PL/pgSQL function warn(text) line 2 at RAISE
warn
------
t
(1 row)
\echo :three :four
:three 4
-- syntax error stops all processing
SELECT 5 \; SELECT 6 + \; SELECT warn('6.5') \; SELECT 7 ;
ERROR: syntax error at or near ";"
LINE 1: SELECT 5 ; SELECT 6 + ; SELECT warn('6.5') ; SELECT 7 ;
^
-- with aborted transaction, stop on first error
BEGIN \; SELECT 8 AS eight \; SELECT 9/0 AS nine \; ROLLBACK \; SELECT 10 AS ten ;
eight
-------
8
(1 row)
ERROR: division by zero
-- close previously aborted transaction
ROLLBACK;
-- misc SQL commands
-- (non SELECT output is sent to stderr, thus is not shown in expected results)
SELECT 'ok' AS "begin" \;
CREATE TABLE psql_comics(s TEXT) \;
INSERT INTO psql_comics VALUES ('Calvin'), ('hobbes') \;
COPY psql_comics FROM STDIN \;
UPDATE psql_comics SET s = 'Hobbes' WHERE s = 'hobbes' \;
DELETE FROM psql_comics WHERE s = 'Moe' \;
COPY psql_comics TO STDOUT \;
TRUNCATE psql_comics \;
DROP TABLE psql_comics \;
SELECT 'ok' AS "done" ;
begin
-------
ok
(1 row)
Calvin
Susie
Hobbes
done
------
ok
(1 row)
\set SHOW_ALL_RESULTS off
SELECT 1 AS one \; SELECT warn('1.5') \; SELECT 2 AS two ;
NOTICE: warn 1.5
CONTEXT: PL/pgSQL function warn(text) line 2 at RAISE
two
-----
2
(1 row)
\set SHOW_ALL_RESULTS on
DROP FUNCTION warn(TEXT);
......@@ -900,8 +900,18 @@ DROP TABLE abc;
-- tests rely on the fact that psql will not break SQL commands apart at a
-- backslash-quoted semicolon, but will send them as one Query.
create temp table i_table (f1 int);
-- psql will show only the last result in a multi-statement Query
-- psql will show all results of a multi-statement Query
SELECT 1\; SELECT 2\; SELECT 3;
?column?
----------
1
(1 row)
?column?
----------
2
(1 row)
?column?
----------
3
......@@ -916,6 +926,12 @@ insert into i_table values(1)\; select * from i_table;
-- 1/0 error will cause rolling back the whole implicit transaction
insert into i_table values(2)\; select * from i_table\; select 1/0;
f1
----
1
2
(2 rows)
ERROR: division by zero
select * from i_table;
f1
......@@ -935,8 +951,18 @@ WARNING: there is no transaction in progress
-- begin converts implicit transaction into a regular one that
-- can extend past the end of the Query
select 1\; begin\; insert into i_table values(5);
?column?
----------
1
(1 row)
commit;
select 1\; begin\; insert into i_table values(6);
?column?
----------
1
(1 row)
rollback;
-- commit in implicit-transaction state commits but issues a warning.
insert into i_table values(7)\; commit\; insert into i_table values(8)\; select 1/0;
......@@ -963,22 +989,52 @@ rollback; -- we are not in a transaction at this point
WARNING: there is no transaction in progress
-- implicit transaction block is still a transaction block, for e.g. VACUUM
SELECT 1\; VACUUM;
?column?
----------
1
(1 row)
ERROR: VACUUM cannot run inside a transaction block
SELECT 1\; COMMIT\; VACUUM;
WARNING: there is no transaction in progress
?column?
----------
1
(1 row)
ERROR: VACUUM cannot run inside a transaction block
-- we disallow savepoint-related commands in implicit-transaction state
SELECT 1\; SAVEPOINT sp;
?column?
----------
1
(1 row)
ERROR: SAVEPOINT can only be used in transaction blocks
SELECT 1\; COMMIT\; SAVEPOINT sp;
WARNING: there is no transaction in progress
?column?
----------
1
(1 row)
ERROR: SAVEPOINT can only be used in transaction blocks
ROLLBACK TO SAVEPOINT sp\; SELECT 2;
ERROR: ROLLBACK TO SAVEPOINT can only be used in transaction blocks
SELECT 2\; RELEASE SAVEPOINT sp\; SELECT 3;
?column?
----------
2
(1 row)
ERROR: RELEASE SAVEPOINT can only be used in transaction blocks
-- but this is OK, because the BEGIN converts it to a regular xact
SELECT 1\; BEGIN\; SAVEPOINT sp\; ROLLBACK TO SAVEPOINT sp\; COMMIT;
?column?
----------
1
(1 row)
-- Tests for AND CHAIN in implicit transaction blocks
SET TRANSACTION READ ONLY\; COMMIT AND CHAIN; -- error
ERROR: COMMIT AND CHAIN can only be used in transaction blocks
......
......@@ -84,10 +84,10 @@ drop table test1;
-- psql handling of COPY in multi-command strings
copy (select 1) to stdout\; select 1/0; -- row, then error
select 1/0\; copy (select 1) to stdout; -- error only
copy (select 1) to stdout\; copy (select 2) to stdout\; select 0\; select 3; -- 1 2 3
copy (select 1) to stdout\; copy (select 2) to stdout\; select 3\; select 4; -- 1 2 3 4
create table test3 (c int);
select 0\; copy test3 from stdin\; copy test3 from stdin\; select 1; -- 1
select 0\; copy test3 from stdin\; copy test3 from stdin\; select 1; -- 0 1
1
\.
2
......
......@@ -1228,3 +1228,41 @@ drop role regress_partitioning_role;
\dAo * pg_catalog.jsonb_path_ops
\dAp+ btree float_ops
\dAp * pg_catalog.uuid_ops
--
-- combined queries
--
CREATE FUNCTION warn(msg TEXT) RETURNS BOOLEAN LANGUAGE plpgsql
AS $$
BEGIN RAISE NOTICE 'warn %', msg ; RETURN TRUE ; END
$$;
-- show both
SELECT 1 AS one \; SELECT warn('1.5') \; SELECT 2 AS two ;
-- \gset applies to last query only
SELECT 3 AS three \; SELECT warn('3.5') \; SELECT 4 AS four \gset
\echo :three :four
-- syntax error stops all processing
SELECT 5 \; SELECT 6 + \; SELECT warn('6.5') \; SELECT 7 ;
-- with aborted transaction, stop on first error
BEGIN \; SELECT 8 AS eight \; SELECT 9/0 AS nine \; ROLLBACK \; SELECT 10 AS ten ;
-- close previously aborted transaction
ROLLBACK;
-- misc SQL commands
-- (non SELECT output is sent to stderr, thus is not shown in expected results)
SELECT 'ok' AS "begin" \;
CREATE TABLE psql_comics(s TEXT) \;
INSERT INTO psql_comics VALUES ('Calvin'), ('hobbes') \;
COPY psql_comics FROM STDIN \;
UPDATE psql_comics SET s = 'Hobbes' WHERE s = 'hobbes' \;
DELETE FROM psql_comics WHERE s = 'Moe' \;
COPY psql_comics TO STDOUT \;
TRUNCATE psql_comics \;
DROP TABLE psql_comics \;
SELECT 'ok' AS "done" ;
Moe
Susie
\.
\set SHOW_ALL_RESULTS off
SELECT 1 AS one \; SELECT warn('1.5') \; SELECT 2 AS two ;
\set SHOW_ALL_RESULTS on
DROP FUNCTION warn(TEXT);
......@@ -504,7 +504,7 @@ DROP TABLE abc;
create temp table i_table (f1 int);
-- psql will show only the last result in a multi-statement Query
-- psql will show all results of a multi-statement Query
SELECT 1\; SELECT 2\; SELECT 3;
-- this implicitly commits:
......
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