2013-02-02 23:06:38 +01:00
|
|
|
--
|
|
|
|
-- Tests for psql features that aren't closely connected to any
|
|
|
|
-- specific server features
|
|
|
|
--
|
|
|
|
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
-- \set
|
|
|
|
|
|
|
|
-- fail: invalid name
|
|
|
|
\set invalid/name foo
|
|
|
|
-- fail: invalid value for special variable
|
|
|
|
\set AUTOCOMMIT foo
|
|
|
|
\set FETCH_COUNT foo
|
Improve psql's behavior for \set and \unset of its control variables.
This commit improves on the results of commit 511ae628f in two ways:
1. It restores the historical behavior that "\set FOO" is interpreted
as setting FOO to "on", if FOO is a boolean control variable. We
already found one test script that was expecting that behavior, and
the psql documentation certainly does nothing to discourage people
from assuming that would work, since it often says just "if FOO is set"
when describing the effects of a boolean variable. However, now this
case will result in actually setting FOO to "on", not an empty string.
2. It arranges for an "\unset" of a control variable to set the value
back to its default value, rather than becoming apparently undefined.
The control variables are also initialized that way at psql startup.
In combination, these things guarantee that a control variable always
has a displayable value that reflects what psql is actually doing.
That is a pretty substantial usability improvement.
The implementation involves adding a second type of variable hook function
that is able to replace a proposed new value (including NULL) with another
one. We could alternatively have complicated the API of the assign hook,
but this way seems better since many variables can share the same
substitution hook function.
Also document the actual behavior of these variables more fully,
including covering assorted behaviors that were there before but
never documented.
This patch also includes some minor cleanup that should have been in
511ae628f but was missed.
Patch by me, but it owes a lot to discussions with Daniel Vérité.
Discussion: https://postgr.es/m/9572.1485821620@sss.pgh.pa.us
2017-02-01 17:02:40 +01:00
|
|
|
-- check handling of built-in boolean variable
|
|
|
|
\echo :ON_ERROR_ROLLBACK
|
|
|
|
\set ON_ERROR_ROLLBACK
|
|
|
|
\echo :ON_ERROR_ROLLBACK
|
|
|
|
\set ON_ERROR_ROLLBACK foo
|
|
|
|
\echo :ON_ERROR_ROLLBACK
|
|
|
|
\set ON_ERROR_ROLLBACK on
|
|
|
|
\echo :ON_ERROR_ROLLBACK
|
|
|
|
\unset ON_ERROR_ROLLBACK
|
|
|
|
\echo :ON_ERROR_ROLLBACK
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
|
2017-03-07 15:31:52 +01:00
|
|
|
-- \g and \gx
|
|
|
|
|
|
|
|
SELECT 1 as one, 2 as two \g
|
|
|
|
\gx
|
|
|
|
SELECT 3 as three, 4 as four \gx
|
|
|
|
\g
|
|
|
|
|
2017-08-24 22:20:50 +02:00
|
|
|
-- \gx should work in FETCH_COUNT mode too
|
|
|
|
\set FETCH_COUNT 1
|
|
|
|
|
|
|
|
SELECT 1 as one, 2 as two \g
|
|
|
|
\gx
|
|
|
|
SELECT 3 as three, 4 as four \gx
|
|
|
|
\g
|
|
|
|
|
|
|
|
\unset FETCH_COUNT
|
|
|
|
|
2013-02-02 23:06:38 +01:00
|
|
|
-- \gset
|
|
|
|
|
|
|
|
select 10 as test01, 20 as test02, 'Hello' as test03 \gset pref01_
|
|
|
|
|
|
|
|
\echo :pref01_test01 :pref01_test02 :pref01_test03
|
|
|
|
|
|
|
|
-- should fail: bad variable name
|
|
|
|
select 10 as "bad name"
|
|
|
|
\gset
|
|
|
|
|
|
|
|
-- multiple backslash commands in one line
|
|
|
|
select 1 as x, 2 as y \gset pref01_ \\ \echo :pref01_x
|
|
|
|
select 3 as x, 4 as y \gset pref01_ \echo :pref01_x \echo :pref01_y
|
|
|
|
select 5 as x, 6 as y \gset pref01_ \\ \g \echo :pref01_x :pref01_y
|
|
|
|
select 7 as x, 8 as y \g \gset pref01_ \echo :pref01_x :pref01_y
|
|
|
|
|
|
|
|
-- NULL should unset the variable
|
|
|
|
\set var2 xyz
|
|
|
|
select 1 as var1, NULL as var2, 3 as var3 \gset
|
|
|
|
\echo :var1 :var2 :var3
|
|
|
|
|
|
|
|
-- \gset requires just one tuple
|
|
|
|
select 10 as test01, 20 as test02 from generate_series(1,3) \gset
|
|
|
|
select 10 as test01, 20 as test02 from generate_series(1,0) \gset
|
|
|
|
|
|
|
|
-- \gset should work in FETCH_COUNT mode too
|
|
|
|
\set FETCH_COUNT 1
|
|
|
|
|
|
|
|
select 1 as x, 2 as y \gset pref01_ \\ \echo :pref01_x
|
|
|
|
select 3 as x, 4 as y \gset pref01_ \echo :pref01_x \echo :pref01_y
|
|
|
|
select 10 as test01, 20 as test02 from generate_series(1,3) \gset
|
|
|
|
select 10 as test01, 20 as test02 from generate_series(1,0) \gset
|
|
|
|
|
|
|
|
\unset FETCH_COUNT
|
2013-10-03 21:18:02 +02:00
|
|
|
|
2017-09-06 00:17:47 +02:00
|
|
|
-- \gdesc
|
|
|
|
|
|
|
|
SELECT
|
|
|
|
NULL AS zero,
|
|
|
|
1 AS one,
|
|
|
|
2.0 AS two,
|
|
|
|
'three' AS three,
|
|
|
|
$1 AS four,
|
|
|
|
sin($2) as five,
|
|
|
|
'foo'::varchar(4) as six,
|
|
|
|
CURRENT_DATE AS now
|
|
|
|
\gdesc
|
|
|
|
|
|
|
|
-- should work with tuple-returning utilities, such as EXECUTE
|
|
|
|
PREPARE test AS SELECT 1 AS first, 2 AS second;
|
|
|
|
EXECUTE test \gdesc
|
|
|
|
EXPLAIN EXECUTE test \gdesc
|
|
|
|
|
|
|
|
-- should fail cleanly - syntax error
|
|
|
|
SELECT 1 + \gdesc
|
|
|
|
|
|
|
|
-- check behavior with empty results
|
|
|
|
SELECT \gdesc
|
|
|
|
CREATE TABLE bububu(a int) \gdesc
|
|
|
|
|
|
|
|
-- subject command should not have executed
|
|
|
|
TABLE bububu; -- fail
|
|
|
|
|
|
|
|
-- query buffer should remain unchanged
|
|
|
|
SELECT 1 AS x, 'Hello', 2 AS y, true AS "dirty\name"
|
|
|
|
\gdesc
|
|
|
|
\g
|
|
|
|
|
|
|
|
-- all on one line
|
|
|
|
SELECT 3 AS x, 'Hello', 4 AS y, true AS "dirty\name" \gdesc \g
|
|
|
|
|
Add a \gexec command to psql for evaluation of computed queries.
\gexec executes the just-entered query, like \g, but instead of printing
the results it takes each field as a SQL command to send to the server.
Computing a series of queries to be executed is a fairly common thing,
but up to now you always had to resort to kluges like writing the queries
to a file and then inputting the file. Now it can be done with no
intermediate step.
The implementation is fairly straightforward except for its interaction
with FETCH_COUNT. ExecQueryUsingCursor isn't capable of being called
recursively, and even if it were, its need to create a transaction
block interferes unpleasantly with the desired behavior of \gexec after
a failure of a generated query (i.e., that it can continue). Therefore,
disable use of ExecQueryUsingCursor when doing the master \gexec query.
We can still apply it to individual generated queries, however, and there
might be some value in doing so.
While testing this feature's interaction with single-step mode, I (tgl) was
led to conclude that SendQuery needs to recognize SIGINT (cancel_pressed)
as a negative response to the single-step prompt. Perhaps that's a
back-patchable bug fix, but for now I just included it here.
Corey Huinker, reviewed by Jim Nasby, Daniel Vérité, and myself
2016-04-04 21:25:16 +02:00
|
|
|
-- \gexec
|
|
|
|
|
|
|
|
create temporary table gexec_test(a int, b text, c date, d float);
|
|
|
|
select format('create index on gexec_test(%I)', attname)
|
|
|
|
from pg_attribute
|
|
|
|
where attrelid = 'gexec_test'::regclass and attnum > 0
|
|
|
|
order by attnum
|
|
|
|
\gexec
|
|
|
|
|
|
|
|
-- \gexec should work in FETCH_COUNT mode too
|
|
|
|
-- (though the fetch limit applies to the executed queries not the meta query)
|
|
|
|
\set FETCH_COUNT 1
|
|
|
|
|
|
|
|
select 'select 1 as ones', 'select x.y, x.y*2 as double from generate_series(1,4) as x(y)'
|
|
|
|
union all
|
|
|
|
select 'drop table gexec_test', NULL
|
|
|
|
union all
|
|
|
|
select 'drop table gexec_test', 'select ''2000-01-01''::date as party_over'
|
|
|
|
\gexec
|
|
|
|
|
|
|
|
\unset FETCH_COUNT
|
|
|
|
|
2013-10-03 21:18:02 +02:00
|
|
|
-- show all pset options
|
|
|
|
\pset
|
2014-04-28 19:41:36 +02:00
|
|
|
|
|
|
|
-- test multi-line headers, wrapping, and newline indicators
|
2018-11-26 18:41:42 +01:00
|
|
|
-- in aligned, unaligned, and wrapped formats
|
2014-08-18 13:06:11 +02:00
|
|
|
prepare q as select array_to_string(array_agg(repeat('x',2*n)),E'\n') as "ab
|
2014-04-28 19:41:36 +02:00
|
|
|
|
2014-08-18 13:06:11 +02:00
|
|
|
c", array_to_string(array_agg(repeat('y',20-2*n)),E'\n') as "a
|
2016-10-10 22:41:57 +02:00
|
|
|
bc" from generate_series(1,10) as n(n) group by n>1 order by n>1;
|
2014-04-28 19:41:36 +02:00
|
|
|
|
|
|
|
\pset linestyle ascii
|
|
|
|
|
|
|
|
\pset expanded off
|
|
|
|
\pset columns 40
|
|
|
|
|
|
|
|
\pset border 0
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset expanded on
|
|
|
|
\pset columns 20
|
|
|
|
|
|
|
|
\pset border 0
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset linestyle old-ascii
|
|
|
|
|
|
|
|
\pset expanded off
|
|
|
|
\pset columns 40
|
|
|
|
|
|
|
|
\pset border 0
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset expanded on
|
|
|
|
\pset columns 20
|
|
|
|
|
|
|
|
\pset border 0
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
deallocate q;
|
2014-08-18 13:06:11 +02:00
|
|
|
|
|
|
|
-- test single-line header and data
|
|
|
|
prepare q as select repeat('x',2*n) as "0123456789abcdef", repeat('y',20-2*n) as "0123456789" from generate_series(1,10) as n;
|
|
|
|
|
|
|
|
\pset linestyle ascii
|
|
|
|
|
|
|
|
\pset expanded off
|
|
|
|
\pset columns 40
|
|
|
|
|
|
|
|
\pset border 0
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
2015-11-30 23:53:32 +01:00
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset expanded on
|
|
|
|
\pset columns 30
|
|
|
|
|
|
|
|
\pset border 0
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
2014-08-18 13:06:11 +02:00
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset expanded on
|
|
|
|
\pset columns 20
|
|
|
|
|
|
|
|
\pset border 0
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset linestyle old-ascii
|
|
|
|
|
|
|
|
\pset expanded off
|
|
|
|
\pset columns 40
|
|
|
|
|
|
|
|
\pset border 0
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset expanded on
|
|
|
|
|
|
|
|
\pset border 0
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
\pset format unaligned
|
|
|
|
execute q;
|
|
|
|
\pset format aligned
|
|
|
|
execute q;
|
|
|
|
\pset format wrapped
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
deallocate q;
|
2015-03-31 17:33:25 +02:00
|
|
|
|
2016-04-09 01:23:18 +02:00
|
|
|
\pset linestyle ascii
|
2018-11-26 18:41:42 +01:00
|
|
|
\pset border 1
|
|
|
|
|
|
|
|
-- support table for output-format tests (useful to create a footer)
|
|
|
|
|
|
|
|
create table psql_serial_tab (id serial);
|
2016-04-09 01:23:18 +02:00
|
|
|
|
2018-11-26 18:41:42 +01:00
|
|
|
-- test header/footer/tuples_only behavior in aligned/unaligned/wrapped cases
|
|
|
|
|
|
|
|
\pset format aligned
|
|
|
|
|
|
|
|
\pset expanded off
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
\pset expanded on
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
-- empty table is a special case for this format
|
|
|
|
select 1 where false;
|
|
|
|
|
|
|
|
\pset format unaligned
|
|
|
|
|
|
|
|
\pset expanded off
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
\pset expanded on
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
|
|
|
|
\pset format wrapped
|
|
|
|
|
|
|
|
\pset expanded off
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
\pset expanded on
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
|
tableam: introduce table AM infrastructure.
This introduces the concept of table access methods, i.e. CREATE
ACCESS METHOD ... TYPE TABLE and
CREATE TABLE ... USING (storage-engine).
No table access functionality is delegated to table AMs as of this
commit, that'll be done in following commits.
Subsequent commits will incrementally abstract table access
functionality to be routed through table access methods. That change
is too large to be reviewed & committed at once, so it'll be done
incrementally.
Docs will be updated at the end, as adding them incrementally would
likely make them less coherent, and definitely is a lot more work,
without a lot of benefit.
Table access methods are specified similar to index access methods,
i.e. pg_am.amhandler returns, as INTERNAL, a pointer to a struct with
callbacks. In contrast to index AMs that struct needs to live as long
as a backend, typically that's achieved by just returning a pointer to
a constant struct.
Psql's \d+ now displays a table's access method. That can be disabled
with HIDE_TABLEAM=true, which is mainly useful so regression tests can
be run against different AMs. It's quite possible that this behaviour
still needs to be fine tuned.
For now it's not allowed to set a table AM for a partitioned table, as
we've not resolved how partitions would inherit that. Disallowing
allows us to introduce, if we decide that's the way forward, such a
behaviour without a compatibility break.
Catversion bumped, to add the heap table AM and references to it.
Author: Haribabu Kommi, Andres Freund, Alvaro Herrera, Dimitri Golgov and others
Discussion:
https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
https://postgr.es/m/20160812231527.GA690404@alvherre.pgsql
https://postgr.es/m/20190107235616.6lur25ph22u5u5av@alap3.anarazel.de
https://postgr.es/m/20190304234700.w5tmhducs5wxgzls@alap3.anarazel.de
2019-03-06 18:54:38 +01:00
|
|
|
-- check conditional tableam display
|
|
|
|
|
|
|
|
-- Create a heap2 table am handler with heapam handler
|
|
|
|
CREATE ACCESS METHOD heap_psql TYPE TABLE HANDLER heap_tableam_handler;
|
|
|
|
CREATE TABLE tbl_heap_psql(f1 int, f2 char(100)) using heap_psql;
|
|
|
|
CREATE TABLE tbl_heap(f1 int, f2 char(100)) using heap;
|
|
|
|
\d+ tbl_heap_psql
|
|
|
|
\d+ tbl_heap
|
|
|
|
\set HIDE_TABLEAM off
|
|
|
|
\d+ tbl_heap_psql
|
|
|
|
\d+ tbl_heap
|
|
|
|
\set HIDE_TABLEAM on
|
|
|
|
DROP TABLE tbl_heap, tbl_heap_psql;
|
|
|
|
DROP ACCESS METHOD heap_psql;
|
|
|
|
|
2018-11-26 21:30:11 +01:00
|
|
|
-- test numericlocale (as best we can without control of psql's locale)
|
2018-11-26 18:41:42 +01:00
|
|
|
|
|
|
|
\pset format aligned
|
|
|
|
\pset expanded off
|
|
|
|
\pset numericlocale true
|
|
|
|
|
2018-11-26 21:30:11 +01:00
|
|
|
select n, -n as m, n * 111 as x, '1e90'::float8 as f
|
2018-11-26 18:41:42 +01:00
|
|
|
from generate_series(0,3) n;
|
|
|
|
|
|
|
|
\pset numericlocale false
|
|
|
|
|
|
|
|
-- test asciidoc output format
|
2015-03-31 17:33:25 +02:00
|
|
|
|
|
|
|
\pset format asciidoc
|
2018-11-26 18:41:42 +01:00
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset expanded off
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
\pset expanded on
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
|
|
|
|
prepare q as
|
|
|
|
select 'some|text' as "a|title", ' ' as "empty ", n as int
|
|
|
|
from generate_series(1,2) as n;
|
|
|
|
|
2015-03-31 17:33:25 +02:00
|
|
|
\pset expanded off
|
|
|
|
\pset border 0
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset expanded on
|
|
|
|
\pset border 0
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
deallocate q;
|
2015-09-05 17:58:20 +02:00
|
|
|
|
2018-11-26 21:18:55 +01:00
|
|
|
-- test csv output format
|
|
|
|
|
|
|
|
\pset format csv
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset expanded off
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
\pset expanded on
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
|
|
|
|
prepare q as
|
|
|
|
select 'some"text' as "a""title", E' <foo>\n<bar>' as "junk",
|
|
|
|
' ' as "empty", n as int
|
|
|
|
from generate_series(1,2) as n;
|
|
|
|
|
|
|
|
\pset expanded off
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset expanded on
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
deallocate q;
|
|
|
|
|
|
|
|
-- special cases
|
|
|
|
\pset expanded off
|
|
|
|
select 'comma,comma' as comma, 'semi;semi' as semi;
|
|
|
|
\pset csv_fieldsep ';'
|
|
|
|
select 'comma,comma' as comma, 'semi;semi' as semi;
|
|
|
|
select '\.' as data;
|
|
|
|
\pset csv_fieldsep '.'
|
|
|
|
select '\' as d1, '' as d2;
|
|
|
|
|
|
|
|
-- illegal csv separators
|
|
|
|
\pset csv_fieldsep ''
|
|
|
|
\pset csv_fieldsep '\0'
|
|
|
|
\pset csv_fieldsep '\n'
|
|
|
|
\pset csv_fieldsep '\r'
|
|
|
|
\pset csv_fieldsep '"'
|
|
|
|
\pset csv_fieldsep ',,'
|
|
|
|
|
|
|
|
\pset csv_fieldsep ','
|
|
|
|
|
2018-11-26 18:41:42 +01:00
|
|
|
-- test html output format
|
|
|
|
|
|
|
|
\pset format html
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset expanded off
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
\pset expanded on
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
|
|
|
|
prepare q as
|
|
|
|
select 'some"text' as "a&title", E' <foo>\n<bar>' as "junk",
|
|
|
|
' ' as "empty", n as int
|
|
|
|
from generate_series(1,2) as n;
|
|
|
|
|
|
|
|
\pset expanded off
|
|
|
|
\pset border 0
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset tableattr foobar
|
|
|
|
execute q;
|
|
|
|
\pset tableattr
|
|
|
|
|
|
|
|
\pset expanded on
|
|
|
|
\pset border 0
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset tableattr foobar
|
|
|
|
execute q;
|
|
|
|
\pset tableattr
|
|
|
|
|
|
|
|
deallocate q;
|
|
|
|
|
|
|
|
-- test latex output format
|
|
|
|
|
|
|
|
\pset format latex
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset expanded off
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
\pset expanded on
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
|
|
|
|
prepare q as
|
2018-11-26 23:32:51 +01:00
|
|
|
select 'some\more_text' as "a$title", E' #<foo>%&^~|\n{bar}' as "junk",
|
2018-11-26 18:41:42 +01:00
|
|
|
' ' as "empty", n as int
|
|
|
|
from generate_series(1,2) as n;
|
|
|
|
|
|
|
|
\pset expanded off
|
|
|
|
\pset border 0
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 3
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset expanded on
|
|
|
|
\pset border 0
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 3
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
deallocate q;
|
|
|
|
|
|
|
|
-- test latex-longtable output format
|
|
|
|
|
|
|
|
\pset format latex-longtable
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset expanded off
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
\pset expanded on
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
|
|
|
|
prepare q as
|
2018-11-26 23:32:51 +01:00
|
|
|
select 'some\more_text' as "a$title", E' #<foo>%&^~|\n{bar}' as "junk",
|
2018-11-26 18:41:42 +01:00
|
|
|
' ' as "empty", n as int
|
|
|
|
from generate_series(1,2) as n;
|
|
|
|
|
|
|
|
\pset expanded off
|
|
|
|
\pset border 0
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 3
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset tableattr lr
|
|
|
|
execute q;
|
|
|
|
\pset tableattr
|
|
|
|
|
|
|
|
\pset expanded on
|
|
|
|
\pset border 0
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 3
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset tableattr lr
|
|
|
|
execute q;
|
|
|
|
\pset tableattr
|
|
|
|
|
|
|
|
deallocate q;
|
|
|
|
|
|
|
|
-- test troff-ms output format
|
|
|
|
|
|
|
|
\pset format troff-ms
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
\pset expanded off
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
\pset expanded on
|
|
|
|
\d psql_serial_tab_id_seq
|
|
|
|
\pset tuples_only true
|
|
|
|
\df exp
|
|
|
|
\pset tuples_only false
|
|
|
|
|
|
|
|
prepare q as
|
|
|
|
select 'some\text' as "a\title", E' <foo>\n<bar>' as "junk",
|
|
|
|
' ' as "empty", n as int
|
|
|
|
from generate_series(1,2) as n;
|
|
|
|
|
|
|
|
\pset expanded off
|
|
|
|
\pset border 0
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset expanded on
|
|
|
|
\pset border 0
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 1
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
\pset border 2
|
|
|
|
execute q;
|
|
|
|
|
|
|
|
deallocate q;
|
|
|
|
|
|
|
|
-- check ambiguous format requests
|
|
|
|
|
|
|
|
\pset format a
|
|
|
|
\pset format l
|
|
|
|
|
|
|
|
-- clean up after output format tests
|
|
|
|
|
|
|
|
drop table psql_serial_tab;
|
|
|
|
|
2016-04-09 01:23:18 +02:00
|
|
|
\pset format aligned
|
|
|
|
\pset expanded off
|
|
|
|
\pset border 1
|
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
-- tests for \if ... \endif
|
|
|
|
|
|
|
|
\if true
|
|
|
|
select 'okay';
|
|
|
|
select 'still okay';
|
|
|
|
\else
|
|
|
|
not okay;
|
|
|
|
still not okay
|
|
|
|
\endif
|
|
|
|
|
|
|
|
-- at this point query buffer should still have last valid line
|
|
|
|
\g
|
|
|
|
|
|
|
|
-- \if should work okay on part of a query
|
|
|
|
select
|
|
|
|
\if true
|
|
|
|
42
|
|
|
|
\else
|
|
|
|
(bogus
|
|
|
|
\endif
|
|
|
|
forty_two;
|
|
|
|
|
|
|
|
select \if false \\ (bogus \else \\ 42 \endif \\ forty_two;
|
|
|
|
|
|
|
|
-- test a large nested if using a variety of true-equivalents
|
|
|
|
\if true
|
|
|
|
\if 1
|
|
|
|
\if yes
|
|
|
|
\if on
|
|
|
|
\echo 'all true'
|
|
|
|
\else
|
|
|
|
\echo 'should not print #1-1'
|
|
|
|
\endif
|
|
|
|
\else
|
|
|
|
\echo 'should not print #1-2'
|
|
|
|
\endif
|
|
|
|
\else
|
|
|
|
\echo 'should not print #1-3'
|
|
|
|
\endif
|
|
|
|
\else
|
|
|
|
\echo 'should not print #1-4'
|
|
|
|
\endif
|
|
|
|
|
|
|
|
-- test a variety of false-equivalents in an if/elif/else structure
|
|
|
|
\if false
|
|
|
|
\echo 'should not print #2-1'
|
|
|
|
\elif 0
|
|
|
|
\echo 'should not print #2-2'
|
|
|
|
\elif no
|
|
|
|
\echo 'should not print #2-3'
|
|
|
|
\elif off
|
|
|
|
\echo 'should not print #2-4'
|
|
|
|
\else
|
|
|
|
\echo 'all false'
|
|
|
|
\endif
|
|
|
|
|
|
|
|
-- test simple true-then-else
|
|
|
|
\if true
|
|
|
|
\echo 'first thing true'
|
|
|
|
\else
|
|
|
|
\echo 'should not print #3-1'
|
|
|
|
\endif
|
|
|
|
|
|
|
|
-- test simple false-true-else
|
|
|
|
\if false
|
|
|
|
\echo 'should not print #4-1'
|
|
|
|
\elif true
|
|
|
|
\echo 'second thing true'
|
|
|
|
\else
|
|
|
|
\echo 'should not print #5-1'
|
|
|
|
\endif
|
|
|
|
|
|
|
|
-- invalid boolean expressions are false
|
|
|
|
\if invalid boolean expression
|
|
|
|
\echo 'will not print #6-1'
|
|
|
|
\else
|
|
|
|
\echo 'will print anyway #6-2'
|
|
|
|
\endif
|
|
|
|
|
|
|
|
-- test un-matched endif
|
|
|
|
\endif
|
|
|
|
|
|
|
|
-- test un-matched else
|
|
|
|
\else
|
|
|
|
|
|
|
|
-- test un-matched elif
|
|
|
|
\elif
|
|
|
|
|
|
|
|
-- test double-else error
|
|
|
|
\if true
|
|
|
|
\else
|
|
|
|
\else
|
|
|
|
\endif
|
|
|
|
|
|
|
|
-- test elif out-of-order
|
|
|
|
\if false
|
|
|
|
\else
|
|
|
|
\elif
|
|
|
|
\endif
|
|
|
|
|
|
|
|
-- test if-endif matching in a false branch
|
|
|
|
\if false
|
|
|
|
\if false
|
|
|
|
\echo 'should not print #7-1'
|
|
|
|
\else
|
|
|
|
\echo 'should not print #7-2'
|
|
|
|
\endif
|
|
|
|
\echo 'should not print #7-3'
|
|
|
|
\else
|
|
|
|
\echo 'should print #7-4'
|
|
|
|
\endif
|
|
|
|
|
|
|
|
-- show that vars and backticks are not expanded when ignoring extra args
|
|
|
|
\set foo bar
|
|
|
|
\echo :foo :'foo' :"foo"
|
|
|
|
\pset fieldsep | `nosuchcommand` :foo :'foo' :"foo"
|
|
|
|
|
|
|
|
-- show that vars and backticks are not expanded and commands are ignored
|
|
|
|
-- when in a false if-branch
|
|
|
|
\set try_to_quit '\\q'
|
|
|
|
\if false
|
|
|
|
:try_to_quit
|
|
|
|
\echo `nosuchcommand` :foo :'foo' :"foo"
|
|
|
|
\pset fieldsep | `nosuchcommand` :foo :'foo' :"foo"
|
|
|
|
\a \C arg1 \c arg1 arg2 arg3 arg4 \cd arg1 \conninfo
|
|
|
|
\copy arg1 arg2 arg3 arg4 arg5 arg6
|
|
|
|
\copyright \dt arg1 \e arg1 arg2
|
|
|
|
\ef whole_line
|
|
|
|
\ev whole_line
|
|
|
|
\echo arg1 arg2 arg3 arg4 arg5 \echo arg1 \encoding arg1 \errverbose
|
|
|
|
\g arg1 \gx arg1 \gexec \h \html \i arg1 \ir arg1 \l arg1 \lo arg1 arg2
|
|
|
|
\o arg1 \p \password arg1 \prompt arg1 arg2 \pset arg1 arg2 \q
|
|
|
|
\reset \s arg1 \set arg1 arg2 arg3 arg4 arg5 arg6 arg7 \setenv arg1 arg2
|
|
|
|
\sf whole_line
|
|
|
|
\sv whole_line
|
|
|
|
\t arg1 \T arg1 \timing arg1 \unset arg1 \w arg1 \watch arg1 \x arg1
|
|
|
|
-- \else here is eaten as part of OT_FILEPIPE argument
|
|
|
|
\w |/no/such/file \else
|
|
|
|
-- \endif here is eaten as part of whole-line argument
|
|
|
|
\! whole_line \endif
|
|
|
|
\else
|
|
|
|
\echo 'should print #8-1'
|
|
|
|
\endif
|
|
|
|
|
2017-09-22 01:02:23 +02:00
|
|
|
-- :{?...} defined variable test
|
|
|
|
\set i 1
|
|
|
|
\if :{?i}
|
|
|
|
\echo '#9-1 ok, variable i is defined'
|
|
|
|
\else
|
|
|
|
\echo 'should not print #9-2'
|
|
|
|
\endif
|
|
|
|
|
|
|
|
\if :{?no_such_variable}
|
|
|
|
\echo 'should not print #10-1'
|
|
|
|
\else
|
|
|
|
\echo '#10-2 ok, variable no_such_variable is not defined'
|
|
|
|
\endif
|
|
|
|
|
|
|
|
SELECT :{?i} AS i_is_defined;
|
|
|
|
|
|
|
|
SELECT NOT :{?no_such_var} AS no_such_var_is_not_defined;
|
|
|
|
|
2015-09-05 17:58:20 +02:00
|
|
|
-- SHOW_CONTEXT
|
|
|
|
|
|
|
|
\set SHOW_CONTEXT never
|
|
|
|
do $$
|
|
|
|
begin
|
|
|
|
raise notice 'foo';
|
|
|
|
raise exception 'bar';
|
|
|
|
end $$;
|
|
|
|
|
|
|
|
\set SHOW_CONTEXT errors
|
|
|
|
do $$
|
|
|
|
begin
|
|
|
|
raise notice 'foo';
|
|
|
|
raise exception 'bar';
|
|
|
|
end $$;
|
|
|
|
|
|
|
|
\set SHOW_CONTEXT always
|
|
|
|
do $$
|
|
|
|
begin
|
|
|
|
raise notice 'foo';
|
|
|
|
raise exception 'bar';
|
|
|
|
end $$;
|
2017-04-02 22:50:25 +02:00
|
|
|
|
|
|
|
-- test printing and clearing the query buffer
|
|
|
|
SELECT 1;
|
|
|
|
\p
|
|
|
|
SELECT 2 \r
|
|
|
|
\p
|
|
|
|
SELECT 3 \p
|
|
|
|
UNION SELECT 4 \p
|
|
|
|
UNION SELECT 5
|
|
|
|
ORDER BY 1;
|
|
|
|
\r
|
|
|
|
\p
|
2017-09-13 01:27:48 +02:00
|
|
|
|
|
|
|
-- tests for special result variables
|
|
|
|
|
|
|
|
-- working query, 2 rows selected
|
|
|
|
SELECT 1 AS stuff UNION SELECT 2;
|
|
|
|
\echo 'error:' :ERROR
|
|
|
|
\echo 'error code:' :SQLSTATE
|
|
|
|
\echo 'number of rows:' :ROW_COUNT
|
|
|
|
|
|
|
|
-- syntax error
|
|
|
|
SELECT 1 UNION;
|
|
|
|
\echo 'error:' :ERROR
|
|
|
|
\echo 'error code:' :SQLSTATE
|
|
|
|
\echo 'number of rows:' :ROW_COUNT
|
|
|
|
\echo 'last error message:' :LAST_ERROR_MESSAGE
|
|
|
|
\echo 'last error code:' :LAST_ERROR_SQLSTATE
|
|
|
|
|
|
|
|
-- empty query
|
|
|
|
;
|
|
|
|
\echo 'error:' :ERROR
|
|
|
|
\echo 'error code:' :SQLSTATE
|
|
|
|
\echo 'number of rows:' :ROW_COUNT
|
|
|
|
-- must have kept previous values
|
|
|
|
\echo 'last error message:' :LAST_ERROR_MESSAGE
|
|
|
|
\echo 'last error code:' :LAST_ERROR_SQLSTATE
|
|
|
|
|
|
|
|
-- other query error
|
|
|
|
DROP TABLE this_table_does_not_exist;
|
|
|
|
\echo 'error:' :ERROR
|
|
|
|
\echo 'error code:' :SQLSTATE
|
|
|
|
\echo 'number of rows:' :ROW_COUNT
|
|
|
|
\echo 'last error message:' :LAST_ERROR_MESSAGE
|
|
|
|
\echo 'last error code:' :LAST_ERROR_SQLSTATE
|
|
|
|
|
2019-04-04 23:22:02 +02:00
|
|
|
-- nondefault verbosity error settings (except verbose, which is too unstable)
|
|
|
|
\set VERBOSITY terse
|
|
|
|
SELECT 1 UNION;
|
|
|
|
\echo 'error:' :ERROR
|
|
|
|
\echo 'error code:' :SQLSTATE
|
|
|
|
\echo 'last error message:' :LAST_ERROR_MESSAGE
|
|
|
|
|
|
|
|
\set VERBOSITY sqlstate
|
|
|
|
SELECT 1/0;
|
|
|
|
\echo 'error:' :ERROR
|
|
|
|
\echo 'error code:' :SQLSTATE
|
|
|
|
\echo 'last error message:' :LAST_ERROR_MESSAGE
|
|
|
|
|
|
|
|
\set VERBOSITY default
|
|
|
|
|
2017-09-13 01:27:48 +02:00
|
|
|
-- working \gdesc
|
|
|
|
SELECT 3 AS three, 4 AS four \gdesc
|
|
|
|
\echo 'error:' :ERROR
|
|
|
|
\echo 'error code:' :SQLSTATE
|
|
|
|
\echo 'number of rows:' :ROW_COUNT
|
|
|
|
|
|
|
|
-- \gdesc with an error
|
|
|
|
SELECT 4 AS \gdesc
|
|
|
|
\echo 'error:' :ERROR
|
|
|
|
\echo 'error code:' :SQLSTATE
|
|
|
|
\echo 'number of rows:' :ROW_COUNT
|
|
|
|
\echo 'last error message:' :LAST_ERROR_MESSAGE
|
|
|
|
\echo 'last error code:' :LAST_ERROR_SQLSTATE
|
|
|
|
|
|
|
|
-- check row count for a cursor-fetched query
|
|
|
|
\set FETCH_COUNT 10
|
2017-09-13 18:27:01 +02:00
|
|
|
select unique2 from tenk1 order by unique2 limit 19;
|
2017-09-13 01:27:48 +02:00
|
|
|
\echo 'error:' :ERROR
|
|
|
|
\echo 'error code:' :SQLSTATE
|
|
|
|
\echo 'number of rows:' :ROW_COUNT
|
|
|
|
|
2017-09-13 18:27:01 +02:00
|
|
|
-- cursor-fetched query with an error after the first group
|
|
|
|
select 1/(15-unique2) from tenk1 order by unique2 limit 19;
|
2017-09-13 01:27:48 +02:00
|
|
|
\echo 'error:' :ERROR
|
|
|
|
\echo 'error code:' :SQLSTATE
|
|
|
|
\echo 'number of rows:' :ROW_COUNT
|
|
|
|
\echo 'last error message:' :LAST_ERROR_MESSAGE
|
|
|
|
\echo 'last error code:' :LAST_ERROR_SQLSTATE
|
|
|
|
|
|
|
|
\unset FETCH_COUNT
|
2019-04-07 13:59:12 +02:00
|
|
|
|
|
|
|
create schema testpart;
|
2019-06-26 04:53:42 +02:00
|
|
|
create role regress_partitioning_role;
|
2019-04-07 13:59:12 +02:00
|
|
|
|
2019-06-26 04:53:42 +02:00
|
|
|
alter schema testpart owner to regress_partitioning_role;
|
2019-04-07 13:59:12 +02:00
|
|
|
|
2019-06-26 04:53:42 +02:00
|
|
|
set role to regress_partitioning_role;
|
2019-04-07 13:59:12 +02:00
|
|
|
|
|
|
|
-- run test inside own schema and hide other partitions
|
|
|
|
set search_path to testpart;
|
|
|
|
|
|
|
|
create table testtable_apple(logdate date);
|
|
|
|
create table testtable_orange(logdate date);
|
|
|
|
create index testtable_apple_index on testtable_apple(logdate);
|
|
|
|
create index testtable_orange_index on testtable_orange(logdate);
|
|
|
|
|
|
|
|
create table testpart_apple(logdate date) partition by range(logdate);
|
|
|
|
create table testpart_orange(logdate date) partition by range(logdate);
|
|
|
|
|
|
|
|
create index testpart_apple_index on testpart_apple(logdate);
|
|
|
|
create index testpart_orange_index on testpart_orange(logdate);
|
|
|
|
|
|
|
|
-- only partition related object should be displayed
|
|
|
|
\dP test*apple*
|
|
|
|
\dPt test*apple*
|
|
|
|
\dPi test*apple*
|
|
|
|
|
|
|
|
drop table testtable_apple;
|
|
|
|
drop table testtable_orange;
|
|
|
|
drop table testpart_apple;
|
|
|
|
drop table testpart_orange;
|
|
|
|
|
|
|
|
create table parent_tab (id int) partition by range (id);
|
|
|
|
create index parent_index on parent_tab (id);
|
|
|
|
create table child_0_10 partition of parent_tab
|
|
|
|
for values from (0) to (10);
|
|
|
|
create table child_10_20 partition of parent_tab
|
|
|
|
for values from (10) to (20);
|
|
|
|
create table child_20_30 partition of parent_tab
|
|
|
|
for values from (20) to (30);
|
|
|
|
insert into parent_tab values (generate_series(0,29));
|
|
|
|
create table child_30_40 partition of parent_tab
|
|
|
|
for values from (30) to (40)
|
|
|
|
partition by range(id);
|
|
|
|
create table child_30_35 partition of child_30_40
|
|
|
|
for values from (30) to (35);
|
|
|
|
create table child_35_40 partition of child_30_40
|
|
|
|
for values from (35) to (40);
|
|
|
|
insert into parent_tab values (generate_series(30,39));
|
|
|
|
|
|
|
|
\dPt
|
|
|
|
\dPi
|
|
|
|
|
|
|
|
\dP testpart.*
|
|
|
|
\dP
|
|
|
|
|
|
|
|
\dPtn
|
|
|
|
\dPin
|
|
|
|
\dPn
|
|
|
|
\dPn testpart.*
|
|
|
|
|
|
|
|
drop table parent_tab cascade;
|
|
|
|
|
|
|
|
drop schema testpart;
|
|
|
|
|
|
|
|
set search_path to default;
|
|
|
|
|
|
|
|
set role to default;
|
2019-06-26 04:53:42 +02:00
|
|
|
drop role regress_partitioning_role;
|