-- -- Test inheritance features -- CREATETABLE a (aa TEXT); CREATETABLE b (bb TEXT) INHERITS (a); CREATETABLE c (cc TEXT) INHERITS (a); CREATETABLE d (dd TEXT) INHERITS (b,c,a);
SELECT relname, a.* FROM a, pg_class where a.tableoid = pg_class.oid; SELECT relname, b.* FROM b, pg_class where b.tableoid = pg_class.oid; SELECT relname, c.* FROM c, pg_class where c.tableoid = pg_class.oid; SELECT relname, d.* FROM d, pg_class where d.tableoid = pg_class.oid; SELECT relname, a.* FROM ONLY a, pg_class where a.tableoid = pg_class.oid; SELECT relname, b.* FROM ONLY b, pg_class where b.tableoid = pg_class.oid; SELECT relname, c.* FROM ONLY c, pg_class where c.tableoid = pg_class.oid; SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
UPDATE a SET aa='zzzz'WHERE aa='aaaa'; UPDATE ONLY a SET aa='zzzzz'WHERE aa='aaaaa'; UPDATE b SET aa='zzz'WHERE aa='aaa'; UPDATE ONLY b SET aa='zzz'WHERE aa='aaa'; UPDATE a SET aa='zzzzzz'WHERE aa LIKE'aaa%';
SELECT relname, a.* FROM a, pg_class where a.tableoid = pg_class.oid; SELECT relname, b.* FROM b, pg_class where b.tableoid = pg_class.oid; SELECT relname, c.* FROM c, pg_class where c.tableoid = pg_class.oid; SELECT relname, d.* FROM d, pg_class where d.tableoid = pg_class.oid; SELECT relname, a.* FROM ONLY a, pg_class where a.tableoid = pg_class.oid; SELECT relname, b.* FROM ONLY b, pg_class where b.tableoid = pg_class.oid; SELECT relname, c.* FROM ONLY c, pg_class where c.tableoid = pg_class.oid; SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
UPDATE b SET aa='new';
SELECT relname, a.* FROM a, pg_class where a.tableoid = pg_class.oid; SELECT relname, b.* FROM b, pg_class where b.tableoid = pg_class.oid; SELECT relname, c.* FROM c, pg_class where c.tableoid = pg_class.oid; SELECT relname, d.* FROM d, pg_class where d.tableoid = pg_class.oid; SELECT relname, a.* FROM ONLY a, pg_class where a.tableoid = pg_class.oid; SELECT relname, b.* FROM ONLY b, pg_class where b.tableoid = pg_class.oid; SELECT relname, c.* FROM ONLY c, pg_class where c.tableoid = pg_class.oid; SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
UPDATE a SET aa='new';
DELETEFROM ONLY c WHERE aa='new';
SELECT relname, a.* FROM a, pg_class where a.tableoid = pg_class.oid; SELECT relname, b.* FROM b, pg_class where b.tableoid = pg_class.oid; SELECT relname, c.* FROM c, pg_class where c.tableoid = pg_class.oid; SELECT relname, d.* FROM d, pg_class where d.tableoid = pg_class.oid; SELECT relname, a.* FROM ONLY a, pg_class where a.tableoid = pg_class.oid; SELECT relname, b.* FROM ONLY b, pg_class where b.tableoid = pg_class.oid; SELECT relname, c.* FROM ONLY c, pg_class where c.tableoid = pg_class.oid; SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
DELETEFROM a;
SELECT relname, a.* FROM a, pg_class where a.tableoid = pg_class.oid; SELECT relname, b.* FROM b, pg_class where b.tableoid = pg_class.oid; SELECT relname, c.* FROM c, pg_class where c.tableoid = pg_class.oid; SELECT relname, d.* FROM d, pg_class where d.tableoid = pg_class.oid; SELECT relname, a.* FROM ONLY a, pg_class where a.tableoid = pg_class.oid; SELECT relname, b.* FROM ONLY b, pg_class where b.tableoid = pg_class.oid; SELECT relname, c.* FROM ONLY c, pg_class where c.tableoid = pg_class.oid; SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
-- Confirm PRIMARY KEY adds NOT NULL constraint to child table CREATE TEMP TABLE z (b TEXT, PRIMARYKEY(aa, b)) inherits (a); INSERTINTO z VALUES (NULL, 'text'); -- should fail -- ... but not UNIQUE. CREATE TEMP TABLE z2 (b TEXT, UNIQUE(aa, b)) inherits (a); INSERTINTO z2 VALUES (NULL, 'text'); -- should work
-- Check inherited UPDATE with first child excluded createtable some_tab (f1 int, f2 int, f3 int, check (f1 < 10) no inherit); createtable some_tab_child () inherits(some_tab); insertinto some_tab_child select i, i+1, 0from generate_series(1,1000) i; createindexon some_tab_child(f1, f2); -- while at it, also check that statement-level triggers fire create function some_tab_stmt_trig_func() returns triggeras
$$begin raise notice 'updating some_tab'; returnNULL; end;$$
language plpgsql; createtrigger some_tab_stmt_trig beforeupdateon some_tab execute function some_tab_stmt_trig_func();
explain (costs off) update some_tab set f3 = 11where f1 = 12and f2 = 13; update some_tab set f3 = 11where f1 = 12and f2 = 13;
droptable some_tab cascade; drop function some_tab_stmt_trig_func();
-- Check inherited UPDATE with all children excluded createtable some_tab (a int, b int); createtable some_tab_child () inherits (some_tab); insertinto some_tab_child values(1,2);
explain (verbose, costs off) update some_tab set a = a + 1wherefalse; update some_tab set a = a + 1wherefalse; explain (verbose, costs off) update some_tab set a = a + 1wherefalse returning b, a; update some_tab set a = a + 1wherefalse returning b, a; table some_tab;
insertinto foo values(1,1); insertinto foo values(3,3); insertinto foo2 values(2,2,2); insertinto foo2 values(3,3,3); insertinto bar values(1,1); insertinto bar values(2,2); insertinto bar values(3,3); insertinto bar values(4,4); insertinto bar2 values(1,1,1); insertinto bar2 values(2,2,2); insertinto bar2 values(3,3,3); insertinto bar2 values(4,4,4);
update bar set f2 = f2 + 100where f1 in (select f1 from foo);
select tableoid::regclass::text as relname, bar.* from bar orderby1,2;
-- Check UPDATE with inherited target and an appendrel subquery update bar set f2 = f2 + 100 from
( select f1 from foo unionallselect f1+3from foo ) ss where bar.f1 = ss.f1;
select tableoid::regclass::text as relname, bar.* from bar orderby1,2;
-- Check UPDATE with *partitioned* inherited target and an appendrel subquery createtable some_tab (a int); insertinto some_tab values (0); createtable some_tab_child () inherits (some_tab); insertinto some_tab_child values (1); createtable parted_tab (a int, b char) partition by list (a); createtable parted_tab_part1 partition of parted_tab forvaluesin (1); createtable parted_tab_part2 partition of parted_tab forvaluesin (2); createtable parted_tab_part3 partition of parted_tab forvaluesin (3); insertinto parted_tab values (1, 'a'), (2, 'a'), (3, 'a');
update parted_tab set b = 'b' from
(select a from some_tab unionallselect a+1from some_tab) ss (a) where parted_tab.a = ss.a; select tableoid::regclass::text as relname, parted_tab.* from parted_tab orderby1,2;
truncate parted_tab; insertinto parted_tab values (1, 'a'), (2, 'a'), (3, 'a'); update parted_tab set b = 'b' from
(select0from parted_tab unionallselect1from parted_tab) ss (a) where parted_tab.a = ss.a; select tableoid::regclass::text as relname, parted_tab.* from parted_tab orderby1,2;
-- modifies partition key, but no rows will actually be updated explainupdate parted_tab set a = 2wherefalse;
droptable parted_tab;
-- Check UPDATE with multi-level partitioned inherited target createtable mlparted_tab (a int, b char, c text) partition by list (a); createtable mlparted_tab_part1 partition of mlparted_tab forvaluesin (1); createtable mlparted_tab_part2 partition of mlparted_tab forvaluesin (2) partition by list (b); createtable mlparted_tab_part3 partition of mlparted_tab forvaluesin (3); createtable mlparted_tab_part2a partition of mlparted_tab_part2 forvaluesin ('a'); createtable mlparted_tab_part2b partition of mlparted_tab_part2 forvaluesin ('b'); insertinto mlparted_tab values (1, 'a'), (2, 'a'), (2, 'b'), (3, 'a');
update mlparted_tab mlp set c = 'xxx' from
(select a from some_tab unionallselect a+1from some_tab) ss (a) where (mlp.a = ss.a and mlp.b = 'b') or mlp.a = 3; select tableoid::regclass::text as relname, mlparted_tab.* from mlparted_tab orderby1,2;
-- Test changing the type of inherited columns insertinto d values('test','one','two','three'); altertable a altercolumn aa type integerusing bit_length(aa); select * from d;
-- The above verified that we can change the type of a multiply-inherited -- column; but we should reject that if any definition was inherited from -- an unrelated parent. create temp table parent1(f1 int, f2 int); create temp table parent2(f1 int, f3 bigint); create temp table childtab(f4 int) inherits(parent1, parent2); altertable parent1 altercolumn f1 type bigint; -- fail, conflict w/parent2 altertable parent1 altercolumn f2 type bigint; -- ok
-- Test non-inheritable parent constraints createtable p1(ff1 int); altertable p1 addconstraint p1chk check (ff1 > 0) no inherit; altertable p1 addconstraint p2chk check (ff1 > 10); -- connoinherit should be true for NO INHERIT constraint select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pgc.connoinherit from pg_class as pc innerjoin pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname = 'p1'orderby1,2;
-- Test that child does not inherit NO INHERIT constraints createtable c1 () inherits (p1);
\d p1
\d c1
-- Test that child does not override inheritable constraints of the parent createtable c2 (constraint p2chk check (ff1 > 10) no inherit) inherits (p1); --fails
droptable p1 cascade;
-- Tests for casting between the rowtypes of parent and child -- tables. See the pgsql-hackers thread beginning Dec. 4/04 createtable base (i integer); createtable derived () inherits (base); createtable more_derived (like derived, b int) inherits (derived); insertinto derived (i) values (0); select derived::base from derived; selectNULL::derived::base; -- remove redundant conversions. explain (verbose on, costs off) select row(i, b)::more_derived::derived::base from more_derived; explain (verbose on, costs off) select (1, 2)::more_derived::derived::base; droptable more_derived; droptable derived; droptable base;
createtable p1(ff1 int); createtable p2(f1 text); create function p2text(p2) returns text as'select $1.f1' language sql; createtable c1(f3 int) inherits(p1,p2); insertinto c1 values(123456789, 'hi', 42); select p2text(c1.*) from c1; drop function p2text(p2); droptable c1; droptable p2; droptable p1;
CREATETABLE ac (aa TEXT); altertable ac addconstraint ac_check check (aa isnotnull); CREATETABLE bc (bb TEXT) INHERITS (ac); select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pg_get_expr(pgc.conbin, pc.oid) as consrc from pg_class as pc innerjoin pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') orderby1,2;
insertinto ac (aa) values (NULL); insertinto bc (aa) values (NULL);
altertable bc dropconstraint ac_check; -- fail, disallowed altertable ac dropconstraint ac_check; select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pg_get_expr(pgc.conbin, pc.oid) as consrc from pg_class as pc innerjoin pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') orderby1,2;
-- try the unnamed-constraint case altertable ac addcheck (aa isnotnull); select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pg_get_expr(pgc.conbin, pc.oid) as consrc from pg_class as pc innerjoin pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') orderby1,2;
insertinto ac (aa) values (NULL); insertinto bc (aa) values (NULL);
altertable bc dropconstraint ac_aa_check; -- fail, disallowed altertable ac dropconstraint ac_aa_check; select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pg_get_expr(pgc.conbin, pc.oid) as consrc from pg_class as pc innerjoin pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') orderby1,2;
altertable ac addconstraint ac_check check (aa isnotnull); altertable bc no inherit ac; select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pg_get_expr(pgc.conbin, pc.oid) as consrc from pg_class as pc innerjoin pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') orderby1,2; altertable bc dropconstraint ac_check; select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pg_get_expr(pgc.conbin, pc.oid) as consrc from pg_class as pc innerjoin pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') orderby1,2; altertable ac dropconstraint ac_check; select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pg_get_expr(pgc.conbin, pc.oid) as consrc from pg_class as pc innerjoin pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') orderby1,2;
droptable bc; droptable ac;
createtable ac (a intconstraint check_a check (a <> 0)); createtable bc (a intconstraint check_a check (a <> 0), b intconstraint check_b check (b <> 0)) inherits (ac); select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pg_get_expr(pgc.conbin, pc.oid) as consrc from pg_class as pc innerjoin pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') orderby1,2;
droptable bc; droptable ac;
createtable ac (a intconstraint check_a check (a <> 0)); createtable bc (b intconstraint check_b check (b <> 0)); createtable cc (c intconstraint check_c check (c <> 0)) inherits (ac, bc); select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pg_get_expr(pgc.conbin, pc.oid) as consrc from pg_class as pc innerjoin pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc', 'cc') orderby1,2;
altertable cc no inherit bc; select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pg_get_expr(pgc.conbin, pc.oid) as consrc from pg_class as pc innerjoin pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc', 'cc') orderby1,2;
-- Test for renaming in simple multiple inheritance CREATETABLE inht1 (a int, b int); CREATETABLE inhs1 (b int, c int); CREATETABLE inhts (d int) INHERITS (inht1, inhs1);
ALTERTABLE inht1 RENAME a TO aa; ALTERTABLE inht1 RENAME b TO bb; -- to be failed ALTERTABLE inhts RENAME aa TO aaa; -- to be failed ALTERTABLE inhts RENAME d TO dd;
\d+ inhts
DROPTABLE inhts;
-- Test for adding a column to a parent table with complex inheritance CREATETABLE inhta (); CREATETABLE inhtb () INHERITS (inhta); CREATETABLE inhtc () INHERITS (inhtb); CREATETABLE inhtd () INHERITS (inhta, inhtb, inhtc); ALTERTABLE inhta ADDCOLUMN i int, ADDCOLUMN j bigintDEFAULT1;
\d+ inhta
\d+ inhtd DROPTABLE inhta, inhtb, inhtc, inhtd;
-- Test for renaming in diamond inheritance CREATETABLE inht2 (x int) INHERITS (inht1); CREATETABLE inht3 (y int) INHERITS (inht1); CREATETABLE inht4 (z int) INHERITS (inht2, inht3);
ALTERTABLE inht1 RENAME aa TO aaa;
\d+ inht4
CREATETABLE inhts (d int) INHERITS (inht2, inhs1); ALTERTABLE inht1 RENAME aaa TO aaaa; ALTERTABLE inht1 RENAME b TO bb; -- to be failed
\d+ inhts
WITH RECURSIVE r AS ( SELECT'inht1'::regclass AS inhrelid UNIONALL SELECT c.inhrelid FROM pg_inherits c, r WHERE r.inhrelid = c.inhparent
) SELECT a.attrelid::regclass, a.attname, a.attinhcount, e.expected FROM (SELECT inhrelid, count(*) AS expected FROM pg_inherits WHERE inhparent IN (SELECT inhrelid FROM r) GROUPBY inhrelid) e JOIN pg_attribute a ON e.inhrelid = a.attrelid WHERENOT attislocal ORDERBY a.attrelid::regclass::name, a.attnum;
DROPTABLE inht1, inhs1 CASCADE;
-- Test non-inheritable indices [UNIQUE, EXCLUDE] constraints CREATETABLE test_constraints (id int, val1 varchar, val2 int, UNIQUE(val1, val2)); CREATETABLE test_constraints_inh () INHERITS (test_constraints);
\d+ test_constraints ALTERTABLE ONLY test_constraints DROPCONSTRAINT test_constraints_val1_val2_key;
\d+ test_constraints
\d+ test_constraints_inh DROPTABLE test_constraints_inh; DROPTABLE test_constraints;
-- the not-valid state of the child constraint will be ignored here. altertable p1 addconstraint inh_check_constraint10 check (f1 < 10) not enforced; altertable p1_c1 addconstraint inh_check_constraint10 check (f1 < 10) not valid enforced;
-- constraints with different enforceability can be merged by marking them as ENFORCED createtable p1_c3() inherits(p1, p1_c1);
-- but not allowed if the child constraint is explicitly asked to be NOT ENFORCED createtable p1_fail(f1 intconstraint inh_check_constraint6 check (f1 < 10) not enforced) inherits(p1, p1_c1);
select conrelid::regclass::text as relname, conname, conislocal, coninhcount, conenforced, convalidated from pg_constraint where conname like'inh\_check\_constraint%' orderby1, 2;
droptable p1 cascade;
-- -- Similarly, check the merging of existing constraints; a parent constraint -- marked as NOT ENFORCED can merge with an ENFORCED child constraint, but the -- reverse is not allowed. -- createtable p1(f1 intconstraint p1_a_check check (f1 > 0) not enforced); createtable p1_c1(f1 intconstraint p1_a_check check (f1 > 0) enforced); altertable p1_c1 inherit p1; droptable p1 cascade;
-- Test that a valid child can have not-valid parent, but not vice versa createtable invalid_check_con(f1 int); createtable invalid_check_con_child() inherits(invalid_check_con);
select conrelid::regclass::text as relname, conname,
convalidated, conislocal, coninhcount, connoinherit from pg_constraint where conname like'inh\_check\_constraint%' orderby1, 2;
-- We don't drop the invalid_check_con* tables, to test dump/reload with
-- -- Test parameterized append plans for inheritance trees --
create temp table patest0 (id, x) as select x, x from generate_series(0,1000) x; create temp table patest1() inherits (patest0); insertinto patest1 select x, x from generate_series(0,1000) x; create temp table patest2() inherits (patest0); insertinto patest2 select x, x from generate_series(0,1000) x; createindex patest0i on patest0(id); createindex patest1i on patest1(id); createindex patest2i on patest2(id); analyze patest0; analyze patest1; analyze patest2;
explain (costs off) select * from patest0 join (select f1 from int4_tbl limit1) ss on id = f1; select * from patest0 join (select f1 from int4_tbl limit1) ss on id = f1;
dropindex patest2i;
explain (costs off) select * from patest0 join (select f1 from int4_tbl limit1) ss on id = f1; select * from patest0 join (select f1 from int4_tbl limit1) ss on id = f1;
droptable patest0 cascade;
-- -- Test merge-append plans for inheritance trees --
createtable matest0 (id serial primarykey, name text); createtable matest1 (id integerprimarykey) inherits (matest0); createtable matest2 (id integerprimarykey) inherits (matest0); createtable matest3 (id integerprimarykey) inherits (matest0);
createindex matest0i on matest0 ((1-id)); createindex matest1i on matest1 ((1-id)); -- create index matest2i on matest2 ((1-id)); -- intentionally missing createindex matest3i on matest3 ((1-id));
set enable_indexscan = off; -- force use of seqscan/sort, so no merge explain (verbose, costs off) select * from matest0 orderby1-id; select * from matest0 orderby1-id; explain (verbose, costs off) select min(1-id) from matest0; select min(1-id) from matest0;
reset enable_indexscan;
set enable_seqscan = off; -- plan with fewest seqscans should be merge set enable_parallel_append = off; -- Don't let parallel-append interfere explain (verbose, costs off) select * from matest0 orderby1-id; select * from matest0 orderby1-id; explain (verbose, costs off) select min(1-id) from matest0; select min(1-id) from matest0;
reset enable_seqscan;
reset enable_parallel_append;
explain (verbose, costs off) -- bug #18652 select1 - id as c from
(select id from matest3 t1 unionallselect id * 2from matest3 t2) ss orderby c; select1 - id as c from
(select id from matest3 t1 unionallselect id * 2from matest3 t2) ss orderby c;
droptable matest0 cascade;
-- -- Check that use of an index with an extraneous column doesn't produce -- a plan with extraneous sorting --
createtable matest0 (a int, b int, c int, d int); createtable matest1 () inherits(matest0); createindex matest0i on matest0 (b, c); createindex matest1i on matest1 (b, c);
set enable_nestloop = off; -- we want a plan with two MergeAppends
explain (costs off) select t1.* from matest0 t1, matest0 t2 where t1.b = t2.b and t2.c = t2.d orderby t1.b limit10;
reset enable_nestloop;
droptable matest0 cascade;
-- Test a MergeAppend plan where one child requires a sort createtable matest0(a intprimarykey); createtable matest1() inherits (matest0); insertinto matest0 select generate_series(1, 400); insertinto matest1 select generate_series(1, 200); analyze matest0; analyze matest1;
explain (costs off) select * from matest0 where a < 100orderby a;
droptable matest0 cascade;
-- -- Test merge-append for UNION ALL append relations --
set enable_seqscan = off; set enable_indexscan = on; set enable_bitmapscan = off;
-- Check handling of duplicated, constant, or volatile targetlist items explain (costs off) SELECT thousand, tenthous FROM tenk1 UNIONALL SELECT thousand, thousand FROM tenk1 ORDERBY thousand, tenthous;
explain (costs off) SELECT thousand, tenthous, thousand+tenthous AS x FROM tenk1 UNIONALL SELECT42, 42, hundred FROM tenk1 ORDERBY thousand, tenthous;
-- Check min/max aggregate optimization explain (costs off) SELECT min(x) FROM
(SELECT unique1 AS x FROM tenk1 a UNIONALL SELECT unique2 AS x FROM tenk1 b) s;
explain (costs off) SELECT min(y) FROM
(SELECT unique1 AS x, unique1 AS y FROM tenk1 a UNIONALL SELECT unique2 AS x, unique2 AS y FROM tenk1 b) s;
-- XXX planner doesn't recognize that index on unique2 is sufficiently sorted explain (costs off) SELECT x, y FROM
(SELECT thousand AS x, tenthous AS y FROM tenk1 a UNIONALL SELECT unique2 AS x, unique2 AS y FROM tenk1 b) s ORDERBY x, y;
-- exercise rescan code path via a repeatedly-evaluated subquery explain (costs off) SELECT
ARRAY(SELECT f.i FROM (
(SELECT d + g.i FROM generate_series(4, 30, 3) d ORDERBY1) UNIONALL
(SELECT d + g.i FROM generate_series(0, 30, 5) d ORDERBY1)
) f(i) ORDERBY f.i LIMIT10) FROM generate_series(1, 3) g(i);
SELECT
ARRAY(SELECT f.i FROM (
(SELECT d + g.i FROM generate_series(4, 30, 3) d ORDERBY1) UNIONALL
(SELECT d + g.i FROM generate_series(0, 30, 5) d ORDERBY1)
) f(i) ORDERBY f.i LIMIT10) FROM generate_series(1, 3) g(i);
-- -- Check handling of MULTIEXPR SubPlans in inherited updates -- createtable inhpar(f1 int, f2 name); createtable inhcld(f2 name, f1 int); altertable inhcld inherit inhpar; insertinto inhpar select x, x::text from generate_series(1,5) x; insertinto inhcld select x::text, x from generate_series(6,10) x;
explain (verbose, costs off) update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-'from int4_tbl limit1); update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-'from int4_tbl limit1); select * from inhpar;
droptable inhpar cascade;
-- -- And the same for partitioned cases -- createtable inhpar(f1 intprimarykey, f2 name) partition by range (f1); createtable inhcld1(f2 name, f1 intprimarykey); createtable inhcld2(f1 intprimarykey, f2 name); altertable inhpar attach partition inhcld1 forvaluesfrom (1) to (5); altertable inhpar attach partition inhcld2 forvaluesfrom (5) to (100); insertinto inhpar select x, x::text from generate_series(1,10) x;
explain (verbose, costs off) update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-'from int4_tbl limit1); update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-'from int4_tbl limit1); select * from inhpar;
-- Also check ON CONFLICT insertinto inhpar as i values (3), (7) on conflict (f1)
do updateset (f1, f2) = (select i.f1, i.f2 || '+'); select * from inhpar orderby f1; -- tuple order might be unstable here
droptable inhpar cascade;
-- -- Check handling of a constant-null CHECK constraint -- createtable cnullparent (f1 int); createtable cnullchild (check (f1 = 1or f1 = null)) inherits(cnullparent); insertinto cnullchild values(1); insertinto cnullchild values(2); insertinto cnullchild values(null); select * from cnullparent; select * from cnullparent where f1 = 2; droptable cnullparent cascade;
-- -- Test inheritance of NOT NULL constraints -- createtable pp1 (f1 int); createtable cc1 (f2 text, f3 int) inherits (pp1); createtable cc2 (f4 float) inherits (pp1,cc1); createtable cc3 () inherits (pp1,cc1,cc2); altertable pp1 alter f1 setnotnull;
\d+ cc3 altertable cc3 no inherit pp1; altertable cc3 no inherit cc1; altertable cc3 no inherit cc2;
\d+ cc3 droptable cc3;
-- named NOT NULL constraint altertable cc1 addcolumn a2 intconstraint nn notnull;
\d+ cc1
\d+ cc2 altertable pp1 altercolumn f1 setnotnull;
\d+ pp1
\d+ cc1
\d+ cc2
-- cannot create table with inconsistent NO INHERIT constraint createtable cc3 (a2 intnotnull no inherit) inherits (cc1);
-- change NO INHERIT status of inherited constraint: no dice, it's inherited altertable cc2 addnotnull a2 no inherit;
-- remove constraint from cc2: no dice, it's inherited altertable cc2 altercolumn a2 dropnotnull;
-- remove constraint from cc1, should succeed altertable cc1 altercolumn a2 dropnotnull;
\d+ cc1
-- same for cc2 altertable cc2 altercolumn f1 dropnotnull;
\d+ cc2
-- remove from cc1, should fail again altertable cc1 altercolumn f1 dropnotnull;
-- remove from pp1, should succeed altertable pp1 altercolumn f1 dropnotnull;
\d+ pp1
altertable pp1 addprimarykey (f1); -- Leave these tables around, for pg_upgrade testing
-- test that removing inheritance of NOT NULL NO INHERIT works correctly createtable inh_parent (f1 intnotnull no inherit, f2 intnotnull no inherit); createtable inh_child (f1 intnotnull no inherit, f2 int); altertable inh_child inherit inh_parent; altertable inh_child no inherit inh_parent;
\d+ inh_child droptable inh_parent, inh_child;
-- test that inhcount is updated correctly through multiple inheritance createtable inh_pp1 (f1 int); createtable inh_cc1 (f2 text, f3 int) inherits (inh_pp1); createtable inh_cc2(f4 float) inherits(inh_pp1,inh_cc1); altertable inh_pp1 altercolumn f1 setnotnull; altertable inh_cc2 no inherit inh_pp1; altertable inh_cc2 no inherit inh_cc1;
\d+ inh_cc2 droptable inh_pp1, inh_cc1, inh_cc2;
-- Test a not-null addition that must walk down the hierarchy CREATETABLE inh_parent (); CREATETABLE inh_child (i int) INHERITS (inh_parent); CREATETABLE inh_grandchild () INHERITS (inh_parent, inh_child); ALTERTABLE inh_parent ADDCOLUMN i intNOTNULL; droptable inh_parent, inh_child, inh_grandchild;
-- Test the same constraint name for different columns in different parents createtable inh_parent1(a intconstraint nn notnull); createtable inh_parent2(b intconstraint nn notnull); createtable inh_child1 () inherits (inh_parent1, inh_parent2);
\d+ inh_child1
createtable inh_child2 (constraint foo notnull a) inherits (inh_parent1, inh_parent2); altertable inh_child2 no inherit inh_parent2;
\d+ inh_child2
-- Test multiple parents with overlapping primary keys createtable inh_parent1(a int, b int, c int, primarykey (a, b)); createtable inh_parent2(d int, e int, b int, primarykey (d, b)); createtable inh_child() inherits (inh_parent1, inh_parent2); select conrelid::regclass, conname, contype, conkey,
coninhcount, conislocal, connoinherit from pg_constraint where contype in ('n','p') and
conrelid::regclass::text in ('inh_child', 'inh_parent1', 'inh_parent2') orderby1, 2;
\d+ inh_child droptable inh_parent1, inh_parent2, inh_child;
-- NOT NULL NO INHERIT createtable inh_nn_parent(a int); createtable inh_nn_child() inherits (inh_nn_parent); altertable inh_nn_parent addnotnull a no inherit; createtable inh_nn_child2() inherits (inh_nn_parent); select conrelid::regclass, conname, contype, conkey,
(select attname from pg_attribute where attrelid = conrelid and attnum = conkey[1]),
coninhcount, conislocal, connoinherit from pg_constraint where contype = 'n'and
conrelid::regclass::text like'inh\_nn\_%' orderby2, 1;
\d+ inh_nn* droptable inh_nn_parent, inh_nn_child, inh_nn_child2;
CREATETABLE inh_nn_parent (a int, NOTNULL a NO INHERIT); CREATETABLE inh_nn_child() INHERITS (inh_nn_parent); ALTERTABLE inh_nn_parent ADDCONSTRAINT nna NOTNULL a; ALTERTABLE inh_nn_parent ALTER a SETNOTNULL; DROPTABLE inh_nn_parent cascade;
-- Adding a PK at the top level of a hierarchy should cause all descendants -- to be checked for nulls, even past a no-inherit constraint CREATETABLE inh_nn_lvl1 (a int); CREATETABLE inh_nn_lvl2 () INHERITS (inh_nn_lvl1); CREATETABLE inh_nn_lvl3 (CONSTRAINT foo NOTNULL a NO INHERIT) INHERITS (inh_nn_lvl2); ALTERTABLE inh_nn_lvl1 ADDPRIMARYKEY (a); DROPTABLE inh_nn_lvl1, inh_nn_lvl2, inh_nn_lvl3;
-- Disallow specifying conflicting NO INHERIT flags for the same constraint CREATETABLE inh_nn1 (a intprimarykey, b int, notnull a no inherit); CREATETABLE inh_nn1 (a intnotnull); CREATETABLE inh_nn2 (a intnotnull no inherit) INHERITS (inh_nn1); CREATETABLE inh_nn3 (a intnotnull, b int, notnull a no inherit); CREATETABLE inh_nn4 (a intnotnull no inherit, b int, notnull a); DROPTABLEIFEXISTS inh_nn1, inh_nn2, inh_nn3, inh_nn4;
-- ALTER TABLE INHERIT ensures that the child has not-null constraints createtable inh_parent (a intnotnull); createtable inh_child (a int); altertable inh_child inherit inh_parent; -- nope droptable inh_parent, inh_child;
-- Can't merge a NO INHERIT constraint with a normal one createtable inh_parent (a intnotnull); createtable inh_child (a intnotnull no inherit); altertable inh_child inherit inh_parent; droptable inh_parent, inh_child;
-- don't interfere with other types of constraints createtable inh_parent (a intprimarykey); createtable inh_child (a intprimarykey) inherits (inh_parent); altertable inh_parent addconstraint inh_parent_excl exclude ((1) with =); altertable inh_parent addconstraint inh_parent_uq unique (a); altertable inh_parent addconstraint inh_parent_fk foreignkey (a) references inh_parent (a); createtable inh_child2 () inherits (inh_parent); createtable inh_child3 (like inh_parent); altertable inh_child3 inherit inh_parent; select conrelid::regclass, conname, contype, coninhcount, conislocal from pg_constraint where conrelid::regclass::text in ('inh_parent', 'inh_child', 'inh_child2', 'inh_child3') orderby2, 1;
-- -- test multi inheritance tree -- createtable inh_parent(f1 intnotnull); createtable inh_child1() inherits(inh_parent); createtable inh_child2() inherits(inh_parent); createtable inh_child3() inherits(inh_child1, inh_child2);
-- show constraint info select conrelid::regclass, conname, contype, coninhcount, conislocal from pg_constraint where contype = 'n'and
conrelid in ('inh_parent'::regclass, 'inh_child1'::regclass, 'inh_child2'::regclass, 'inh_child3'::regclass) orderby2, conrelid::regclass::text;
droptable inh_parent cascade;
-- test child table with inherited columns and -- with explicitly specified not null constraints createtable inh_parent_1(f1 int); createtable inh_parent_2(f2 text); createtable inh_child(f1 intnotnull, f2 text notnull) inherits(inh_parent_1, inh_parent_2);
-- show constraint info select conrelid::regclass, conname, contype, coninhcount, conislocal from pg_constraint where contype = 'n'and
conrelid in ('inh_parent_1'::regclass, 'inh_parent_2'::regclass, 'inh_child'::regclass) orderby2, conrelid::regclass::text;
-- also drops inh_child table droptable inh_parent_1 cascade; droptable inh_parent_2;
-- test multi layer inheritance tree createtable inh_p1(f1 intnotnull); createtable inh_p2(f1 intnotnull); createtable inh_p3(f2 int); createtable inh_p4(f1 intnotnull, f3 text notnull);
-- constraint on f1 should have three parents select conrelid::regclass, contype, conname,
(select attname from pg_attribute where attrelid = conrelid and attnum = conkey[1]),
coninhcount, conislocal from pg_constraint where contype = 'n'and
conrelid::regclass in ('inh_p1', 'inh_p2', 'inh_p3', 'inh_p4', 'inh_multiparent') orderby conrelid::regclass::text, conname;
createtable inh_multiparent2 (a intnotnull, f1 int) inherits(inh_p3, inh_multiparent); select conrelid::regclass, contype, conname,
(select attname from pg_attribute where attrelid = conrelid and attnum = conkey[1]),
coninhcount, conislocal from pg_constraint where contype = 'n'and
conrelid::regclass in ('inh_p3', 'inh_multiparent', 'inh_multiparent2') orderby conrelid::regclass::text, conname;
droptable inh_p1, inh_p2, inh_p3, inh_p4 cascade;
-- -- Test ALTER CONSTRAINT SET [NO] INHERIT -- createtable inh_nn1 (f1 intnotnull no inherit); createtable inh_nn2 (f2 text, f3 int, f1 int); altertable inh_nn2 inherit inh_nn1; createtable inh_nn3 (f4 float) inherits (inh_nn2); createtable inh_nn4 (f5 int, f4 float, f2 text, f3 int, f1 int); altertable inh_nn4 inherit inh_nn2, inherit inh_nn1, inherit inh_nn3; altertable inh_nn1 alterconstraint inh_nn1_f1_not_null inherit; select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit from pg_constraint where contype = 'n'and
conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4') orderby2, 1; -- ALTER CONSTRAINT NO INHERIT should work on top-level constraints altertable inh_nn1 alterconstraint inh_nn1_f1_not_null no inherit; select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit from pg_constraint where contype = 'n'and
conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4') orderby2, 1; -- A constraint that's NO INHERIT can be dropped without damaging children altertable inh_nn1 dropconstraint inh_nn1_f1_not_null; select conrelid::regclass, conname, coninhcount, conislocal, connoinherit from pg_constraint where contype = 'n'and
conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4') orderby2, 1; droptable inh_nn1, inh_nn2, inh_nn3, inh_nn4;
-- Test inherit constraint and make sure it validates. createtable inh_nn1 (f1 intnotnull no inherit); createtable inh_nn2 (f2 text, f3 int) inherits (inh_nn1); insertinto inh_nn2 values(NULL, 'sample', 1); altertable inh_nn1 alterconstraint inh_nn1_f1_not_null inherit; deletefrom inh_nn2; createtable inh_nn3 () inherits (inh_nn2); createtable inh_nn4 () inherits (inh_nn1, inh_nn2); altertable inh_nn1 -- test multicommand alter table while at it alterconstraint inh_nn1_f1_not_null inherit, alterconstraint inh_nn1_f1_not_null no inherit; select conrelid::regclass, conname, coninhcount, conislocal, connoinherit from pg_constraint where contype = 'n'and
conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4') orderby2, 1; droptable inh_nn1, inh_nn2, inh_nn3, inh_nn4;
-- Test not null inherit constraint which already exists on child table. createtable inh_nn1 (f1 intnotnull no inherit); createtable inh_nn2 (f2 text, f3 int) inherits (inh_nn1); createtable inh_nn3 (f4 float, constraint nn3_f1 notnull f1 no inherit) inherits (inh_nn1, inh_nn2); select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit from pg_constraint where contype = 'n'and
conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3') orderby2, 1; -- error: inh_nn3 has an incompatible NO INHERIT constraint altertable inh_nn1 alterconstraint inh_nn1_f1_not_null inherit; altertable inh_nn3 alterconstraint nn3_f1 inherit; altertable inh_nn1 alterconstraint inh_nn1_f1_not_null inherit; -- now it works select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit from pg_constraint where contype = 'n'and
conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3') orderby2, 1; droptable inh_nn1, inh_nn2, inh_nn3;
-- Negative scenarios for alter constraint .. inherit. createtable inh_nn1 (f1 intcheck(f1 > 5) primarykeyreferences inh_nn1, f2 intnotnull); -- constraints other than not-null are not supported altertable inh_nn1 alterconstraint inh_nn1_f1_check inherit; altertable inh_nn1 alterconstraint inh_nn1_pkey inherit; altertable inh_nn1 alterconstraint inh_nn1_f1_fkey inherit; -- try to drop a nonexistant constraint altertable inh_nn1 alterconstraint foo inherit; -- Can't modify inheritability of inherited constraints createtable inh_nn2 () inherits (inh_nn1); altertable inh_nn2 alterconstraint inh_nn1_f2_not_null no inherit;
droptable inh_nn1, inh_nn2;
-- -- Mixed ownership inheritance tree -- create role regress_alice; create role regress_bob; grantallonschema public to regress_alice, regress_bob; grant regress_alice to regress_bob; set session authorization regress_alice; createtable inh_parent (a intnotnull); set session authorization regress_bob; createtable inh_child () inherits (inh_parent); set session authorization regress_alice; -- alice can't do this: she doesn't own inh_child altertable inh_parent alter a dropnotnull; set session authorization regress_bob; altertable inh_parent alter a dropnotnull;
reset session authorization; droptable inh_parent, inh_child; revokeallonschema public from regress_alice, regress_bob; drop role regress_alice, regress_bob;
-- -- Check use of temporary tables with inheritance trees -- createtable inh_perm_parent (a1 int); create temp table inh_temp_parent (a1 int); create temp table inh_temp_child () inherits (inh_perm_parent); -- ok createtable inh_perm_child () inherits (inh_temp_parent); -- error create temp table inh_temp_child_2 () inherits (inh_temp_parent); -- ok insertinto inh_perm_parent values (1); insertinto inh_temp_parent values (2); insertinto inh_temp_child values (3); insertinto inh_temp_child_2 values (4); select tableoid::regclass, a1 from inh_perm_parent; select tableoid::regclass, a1 from inh_temp_parent; droptable inh_perm_parent cascade; droptable inh_temp_parent cascade;
-- -- Check that constraint exclusion works correctly with partitions using -- implicit constraints generated from the partition bound information. -- createtable list_parted (
a varchar
) partition by list (a); createtable part_ab_cd partition of list_parted forvaluesin ('ab', 'cd'); createtable part_ef_gh partition of list_parted forvaluesin ('ef', 'gh'); createtable part_null_xy partition of list_parted forvaluesin (null, 'xy');
explain (costs off) select * from list_parted; explain (costs off) select * from list_parted where a isnull; explain (costs off) select * from list_parted where a isnotnull; explain (costs off) select * from list_parted where a in ('ab', 'cd', 'ef'); explain (costs off) select * from list_parted where a = 'ab'or a in (null, 'cd'); explain (costs off) select * from list_parted where a = 'ab';
createtable range_list_parted (
a int,
b char(2)
) partition by range (a); createtable part_1_10 partition of range_list_parted forvaluesfrom (1) to (10) partition by list (b); createtable part_1_10_ab partition of part_1_10 forvaluesin ('ab'); createtable part_1_10_cd partition of part_1_10 forvaluesin ('cd'); createtable part_10_20 partition of range_list_parted forvaluesfrom (10) to (20) partition by list (b); createtable part_10_20_ab partition of part_10_20 forvaluesin ('ab'); createtable part_10_20_cd partition of part_10_20 forvaluesin ('cd'); createtable part_21_30 partition of range_list_parted forvaluesfrom (21) to (30) partition by list (b); createtable part_21_30_ab partition of part_21_30 forvaluesin ('ab'); createtable part_21_30_cd partition of part_21_30 forvaluesin ('cd'); createtable part_40_inf partition of range_list_parted forvaluesfrom (40) to (maxvalue) partition by list (b); createtable part_40_inf_ab partition of part_40_inf forvaluesin ('ab'); createtable part_40_inf_cd partition of part_40_inf forvaluesin ('cd'); createtable part_40_inf_null partition of part_40_inf forvaluesin (null);
explain (costs off) select * from range_list_parted; explain (costs off) select * from range_list_parted where a = 5; explain (costs off) select * from range_list_parted where b = 'ab'; explain (costs off) select * from range_list_parted where a between3and23and b in ('ab');
/* Should select no rows because range partition key cannot be null */ explain (costs off) select * from range_list_parted where a isnull;
/* Should only select rows from the null-accepting partition */ explain (costs off) select * from range_list_parted where b isnull; explain (costs off) select * from range_list_parted where a isnotnulland a < 67; explain (costs off) select * from range_list_parted where a >= 30;
-- check that constraint exclusion is able to cope with the partition -- constraint emitted for multi-column range partitioned tables createtable mcrparted (a int, b int, c int) partition by range (a, abs(b), c); createtable mcrparted_def partition of mcrparted default; createtable mcrparted0 partition of mcrparted forvaluesfrom (minvalue, minvalue, minvalue) to (1, 1, 1); createtable mcrparted1 partition of mcrparted forvaluesfrom (1, 1, 1) to (10, 5, 10); createtable mcrparted2 partition of mcrparted forvaluesfrom (10, 5, 10) to (10, 10, 10); createtable mcrparted3 partition of mcrparted forvaluesfrom (11, 1, 1) to (20, 10, 10); createtable mcrparted4 partition of mcrparted forvaluesfrom (20, 10, 10) to (20, 20, 20); createtable mcrparted5 partition of mcrparted forvaluesfrom (20, 20, 20) to (maxvalue, maxvalue, maxvalue); explain (costs off) select * from mcrparted where a = 0; -- scans mcrparted0, mcrparted_def explain (costs off) select * from mcrparted where a = 10and abs(b) < 5; -- scans mcrparted1, mcrparted_def explain (costs off) select * from mcrparted where a = 10and abs(b) = 5; -- scans mcrparted1, mcrparted2, mcrparted_def explain (costs off) select * from mcrparted where abs(b) = 5; -- scans all partitions explain (costs off) select * from mcrparted where a > -1; -- scans all partitions explain (costs off) select * from mcrparted where a = 20and abs(b) = 10and c > 10; -- scans mcrparted4 explain (costs off) select * from mcrparted where a = 20and c > 20; -- scans mcrparted3, mcrparte4, mcrparte5, mcrparted_def
-- check that partitioned table Appends cope with being referenced in -- subplans createtable parted_minmax (a int, b varchar(16)) partition by range (a); createtable parted_minmax1 partition of parted_minmax forvaluesfrom (1) to (10); createindex parted_minmax1i on parted_minmax1 (a, b); insertinto parted_minmax values (1,'12345'); explain (costs off) select min(a), max(a) from parted_minmax where b = '12345'; select min(a), max(a) from parted_minmax where b = '12345'; droptable parted_minmax;
-- Test code that uses Append nodes in place of MergeAppend when the -- partition ordering matches the desired ordering.
createindex mcrparted_a_abs_c_idx on mcrparted (a, abs(b), c);
-- MergeAppend must be used when a default partition exists explain (costs off) select * from mcrparted orderby a, abs(b), c;
droptable mcrparted_def;
-- Append is used for a RANGE partitioned table with no default -- and no subpartitions explain (costs off) select * from mcrparted orderby a, abs(b), c;
-- Append is used with subpaths in reverse order with backwards index scans explain (costs off) select * from mcrparted orderby a desc, abs(b) desc, c desc;
-- check that Append plan is used containing a MergeAppend for sub-partitions -- that are unordered. droptable mcrparted5; createtable mcrparted5 partition of mcrparted forvaluesfrom (20, 20, 20) to (maxvalue, maxvalue, maxvalue) partition by list (a); createtable mcrparted5a partition of mcrparted5 forvaluesin(20); createtable mcrparted5_def partition of mcrparted5 default;
explain (costs off) select * from mcrparted orderby a, abs(b), c;
droptable mcrparted5_def;
-- check that an Append plan is used and the sub-partitions are flattened -- into the main Append when the sub-partition is unordered but contains -- just a single sub-partition. explain (costs off) select a, abs(b) from mcrparted orderby a, abs(b), c;
-- check that Append is used when the sub-partitioned tables are pruned -- during planning. explain (costs off) select * from mcrparted where a < 20orderby a, abs(b), c;
set enable_bitmapscan to off; set enable_sort to off; createtable mclparted (a int) partition by list(a); createtable mclparted1 partition of mclparted forvaluesin(1); createtable mclparted2 partition of mclparted forvaluesin(2); createindexon mclparted (a);
-- Ensure an Append is used for a list partition with an order by. explain (costs off) select * from mclparted orderby a;
-- Ensure a MergeAppend is used when a partition exists with interleaved -- datums in the partition bound. createtable mclparted3_5 partition of mclparted forvaluesin(3,5); createtable mclparted4 partition of mclparted forvaluesin(4);
explain (costs off) select * from mclparted orderby a; explain (costs off) select * from mclparted where a in(3,4,5) orderby a;
-- Introduce a NULL and DEFAULT partition so we can test more complex cases createtable mclparted_null partition of mclparted forvaluesin(null); createtable mclparted_def partition of mclparted default;
-- Append can be used providing we don't scan the interleaved partition explain (costs off) select * from mclparted where a in(1,2,4) orderby a; explain (costs off) select * from mclparted where a in(1,2,4) or a isnullorderby a;
-- Test a more complex case where the NULL partition allows some other value droptable mclparted_null; createtable mclparted_0_null partition of mclparted forvaluesin(0,null);
-- Ensure MergeAppend is used since 0 and NULLs are in the same partition. explain (costs off) select * from mclparted where a in(1,2,4) or a isnullorderby a; explain (costs off) select * from mclparted where a in(0,1,2,4) orderby a;
-- Ensure Append is used when the null partition is pruned explain (costs off) select * from mclparted where a in(1,2,4) orderby a;
-- Ensure MergeAppend is used when the default partition is not pruned explain (costs off) select * from mclparted where a in(1,2,4,100) orderby a;
-- Ensure subplans which don't have a path with the correct pathkeys get -- sorted correctly. dropindex mcrparted_a_abs_c_idx; createindexon mcrparted1 (a, abs(b), c); createindexon mcrparted2 (a, abs(b), c); createindexon mcrparted3 (a, abs(b), c); createindexon mcrparted4 (a, abs(b), c);
explain (costs off) select * from mcrparted where a < 20orderby a, abs(b), c limit1;
set enable_bitmapscan = 0; -- Ensure Append node can be used when the partition is ordered by some -- pathkeys which were deemed redundant. explain (costs off) select * from mcrparted where a = 10orderby a, abs(b), c;
reset enable_bitmapscan;
droptable mcrparted;
-- Ensure LIST partitions allow an Append to be used instead of a MergeAppend createtable bool_lp (b bool) partition by list(b); createtable bool_lp_true partition of bool_lp forvaluesin(true); createtable bool_lp_false partition of bool_lp forvaluesin(false); createindexon bool_lp (b);
explain (costs off) select * from bool_lp orderby b;
droptable bool_lp;
-- Ensure const bool quals can be properly detected as redundant createtable bool_rp (b bool, a int) partition by range(b,a); createtable bool_rp_false_1k partition of bool_rp forvaluesfrom (false,0) to (false,1000); createtable bool_rp_true_1k partition of bool_rp forvaluesfrom (true,0) to (true,1000); createtable bool_rp_false_2k partition of bool_rp forvaluesfrom (false,1000) to (false,2000); createtable bool_rp_true_2k partition of bool_rp forvaluesfrom (true,1000) to (true,2000); createindexon bool_rp (b,a); explain (costs off) select * from bool_rp where b = trueorderby b,a; explain (costs off) select * from bool_rp where b = falseorderby b,a; explain (costs off) select * from bool_rp where b = trueorderby a; explain (costs off) select * from bool_rp where b = falseorderby a;
droptable bool_rp;
-- Ensure an Append scan is chosen when the partition order is a subset of -- the required order. createtable range_parted (a int, b int, c int) partition by range(a, b); createtable range_parted1 partition of range_parted forvaluesfrom (0,0) to (10,10); createtable range_parted2 partition of range_parted forvaluesfrom (10,10) to (20,20); createindexon range_parted (a,b,c);
explain (costs off) select * from range_parted orderby a,b,c; explain (costs off) select * from range_parted orderby a desc,b desc,c desc;
droptable range_parted;
-- Check that we allow access to a child table's statistics when the user -- has permissions only for the parent table. createtable permtest_parent (a int, b text, c text) partition by list (a); createtable permtest_child (b text, c text, a int) partition by list (b); createtable permtest_grandchild (c text, b text, a int); altertable permtest_child attach partition permtest_grandchild forvaluesin ('a'); altertable permtest_parent attach partition permtest_child forvaluesin (1); createindexon permtest_parent (left(c, 3)); insertinto permtest_parent select1, 'a', left(fipshash(i::text), 5) from generate_series(0, 100) i; analyze permtest_parent; create role regress_no_child_access; revokeallon permtest_grandchild from regress_no_child_access; grantselecton permtest_parent to regress_no_child_access; set session authorization regress_no_child_access; -- without stats access, these queries would produce hash join plans: explain (costs off) select * from permtest_parent p1 innerjoin permtest_parent p2 on p1.a = p2.a and p1.c ~ 'a1$'; explain (costs off) select * from permtest_parent p1 innerjoin permtest_parent p2 on p1.a = p2.a andleft(p1.c, 3) ~ 'a1$';
reset session authorization; revokeallon permtest_parent from regress_no_child_access; grantselect(a,c) on permtest_parent to regress_no_child_access; set session authorization regress_no_child_access; explain (costs off) select p2.a, p1.c from permtest_parent p1 innerjoin permtest_parent p2 on p1.a = p2.a and p1.c ~ 'a1$'; -- we will not have access to the expression index's stats here: explain (costs off) select p2.a, p1.c from permtest_parent p1 innerjoin permtest_parent p2 on p1.a = p2.a andleft(p1.c, 3) ~ 'a1$';
reset session authorization; revokeallon permtest_parent from regress_no_child_access; drop role regress_no_child_access; droptable permtest_parent;
-- Verify that constraint errors across partition root / child are -- handled correctly (Bug #16293) CREATETABLE errtst_parent (
partid intnotnull,
shdata intnotnull,
data intNOTNULLDEFAULT0, CONSTRAINT shdata_small CHECK(shdata < 3)
) PARTITION BY RANGE (partid);
-- fast defaults lead to attribute mapping being used in one -- direction, but not the other CREATETABLE errtst_child_fastdef (
partid intnotnull,
shdata intnotnull, CONSTRAINT shdata_small CHECK(shdata < 3)
);
-- no remapping in either direction necessary CREATETABLE errtst_child_plaindef (
partid intnotnull,
shdata intnotnull,
data intNOTNULLDEFAULT0, CONSTRAINT shdata_small CHECK(shdata < 3), CHECK(data < 10)
);
-- remapping in both direction CREATETABLE errtst_child_reorder (
data intNOTNULLDEFAULT0,
shdata intnotnull,
partid intnotnull, CONSTRAINT shdata_small CHECK(shdata < 3), CHECK(data < 10)
);
-- within partition update without child check constraint violation
BEGIN; UPDATE errtst_parent SET data = data + 1WHERE partid = 0; UPDATE errtst_parent SET data = data + 1WHERE partid = 10; UPDATE errtst_parent SET data = data + 1WHERE partid = 20;
ROLLBACK;
-- within partition update with child check constraint violation UPDATE errtst_parent SET data = data + 10WHERE partid = 0; UPDATE errtst_parent SET data = data + 10WHERE partid = 10; UPDATE errtst_parent SET data = data + 10WHERE partid = 20;
-- direct leaf partition update, without partition id violation
BEGIN; UPDATE errtst_child_fastdef SET partid = 1WHERE partid = 0; UPDATE errtst_child_plaindef SET partid = 11WHERE partid = 10; UPDATE errtst_child_reorder SET partid = 21WHERE partid = 20;
ROLLBACK;
-- direct leaf partition update, with partition id violation UPDATE errtst_child_fastdef SET partid = partid + 10WHERE partid = 0; UPDATE errtst_child_plaindef SET partid = partid + 10WHERE partid = 10; UPDATE errtst_child_reorder SET partid = partid + 10WHERE partid = 20;
-- partition move, without child check constraint violation
BEGIN; UPDATE errtst_parent SET partid = 10, data = data + 1WHERE partid = 0; UPDATE errtst_parent SET partid = 20, data = data + 1WHERE partid = 10; UPDATE errtst_parent SET partid = 0, data = data + 1WHERE partid = 20;
ROLLBACK;
-- partition move, with child check constraint violation UPDATE errtst_parent SET partid = 10, data = data + 10WHERE partid = 0; UPDATE errtst_parent SET partid = 20, data = data + 10WHERE partid = 10; UPDATE errtst_parent SET partid = 0, data = data + 10WHERE partid = 20;
-- partition move, without target partition UPDATE errtst_parent SET partid = 30, data = data + 10WHERE partid = 20;
DROPTABLE errtst_parent;
-- Check that we have the correct tuples estimate for an appendrel createtable tuplesest_parted (a int, b int, c float) partition by range(a); createtable tuplesest_parted1 partition of tuplesest_parted forvaluesfrom (0) to (100); createtable tuplesest_parted2 partition of tuplesest_parted forvaluesfrom (100) to (200);
createtable tuplesest_tab (a int, b int);
insertinto tuplesest_parted select i%200, i%300, i%400from generate_series(1, 1000)i; insertinto tuplesest_tab select i, i from generate_series(1, 100)i;
analyze tuplesest_parted; analyze tuplesest_tab;
explain (costs off) select * from tuplesest_tab join
(select b from tuplesest_parted where c < 100groupby b) sub on tuplesest_tab.a = sub.b;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.