2 -- Test inheritance features
4 CREATE TABLE a (aa TEXT);
5 CREATE TABLE b (bb TEXT) INHERITS (a);
6 CREATE TABLE c (cc TEXT) INHERITS (a);
7 CREATE TABLE d (dd TEXT) INHERITS (b,c,a);
8 NOTICE: merging multiple inherited definitions of column "aa"
9 NOTICE: merging multiple inherited definitions of column "aa"
10 INSERT INTO a(aa) VALUES('aaa');
11 INSERT INTO a(aa) VALUES('aaaa');
12 INSERT INTO a(aa) VALUES('aaaaa');
13 INSERT INTO a(aa) VALUES('aaaaaa');
14 INSERT INTO a(aa) VALUES('aaaaaaa');
15 INSERT INTO a(aa) VALUES('aaaaaaaa');
16 INSERT INTO b(aa) VALUES('bbb');
17 INSERT INTO b(aa) VALUES('bbbb');
18 INSERT INTO b(aa) VALUES('bbbbb');
19 INSERT INTO b(aa) VALUES('bbbbbb');
20 INSERT INTO b(aa) VALUES('bbbbbbb');
21 INSERT INTO b(aa) VALUES('bbbbbbbb');
22 INSERT INTO c(aa) VALUES('ccc');
23 INSERT INTO c(aa) VALUES('cccc');
24 INSERT INTO c(aa) VALUES('ccccc');
25 INSERT INTO c(aa) VALUES('cccccc');
26 INSERT INTO c(aa) VALUES('ccccccc');
27 INSERT INTO c(aa) VALUES('cccccccc');
28 INSERT INTO d(aa) VALUES('ddd');
29 INSERT INTO d(aa) VALUES('dddd');
30 INSERT INTO d(aa) VALUES('ddddd');
31 INSERT INTO d(aa) VALUES('dddddd');
32 INSERT INTO d(aa) VALUES('ddddddd');
33 INSERT INTO d(aa) VALUES('dddddddd');
34 SELECT relname, a.* FROM a, pg_class where a.tableoid = pg_class.oid;
63 SELECT relname, b.* FROM b, pg_class where b.tableoid = pg_class.oid;
65 ---------+----------+----
80 SELECT relname, c.* FROM c, pg_class where c.tableoid = pg_class.oid;
82 ---------+----------+----
97 SELECT relname, d.* FROM d, pg_class where d.tableoid = pg_class.oid;
98 relname | aa | bb | cc | dd
99 ---------+----------+----+----+----
108 SELECT relname, a.* FROM ONLY a, pg_class where a.tableoid = pg_class.oid;
119 SELECT relname, b.* FROM ONLY b, pg_class where b.tableoid = pg_class.oid;
121 ---------+----------+----
130 SELECT relname, c.* FROM ONLY c, pg_class where c.tableoid = pg_class.oid;
132 ---------+----------+----
141 SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
142 relname | aa | bb | cc | dd
143 ---------+----------+----+----+----
152 UPDATE a SET aa='zzzz' WHERE aa='aaaa';
153 UPDATE ONLY a SET aa='zzzzz' WHERE aa='aaaaa';
154 UPDATE b SET aa='zzz' WHERE aa='aaa';
155 UPDATE ONLY b SET aa='zzz' WHERE aa='aaa';
156 UPDATE a SET aa='zzzzzz' WHERE aa LIKE 'aaa%';
157 SELECT relname, a.* FROM a, pg_class where a.tableoid = pg_class.oid;
186 SELECT relname, b.* FROM b, pg_class where b.tableoid = pg_class.oid;
188 ---------+----------+----
203 SELECT relname, c.* FROM c, pg_class where c.tableoid = pg_class.oid;
205 ---------+----------+----
220 SELECT relname, d.* FROM d, pg_class where d.tableoid = pg_class.oid;
221 relname | aa | bb | cc | dd
222 ---------+----------+----+----+----
231 SELECT relname, a.* FROM ONLY a, pg_class where a.tableoid = pg_class.oid;
242 SELECT relname, b.* FROM ONLY b, pg_class where b.tableoid = pg_class.oid;
244 ---------+----------+----
253 SELECT relname, c.* FROM ONLY c, pg_class where c.tableoid = pg_class.oid;
255 ---------+----------+----
264 SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
265 relname | aa | bb | cc | dd
266 ---------+----------+----+----+----
275 UPDATE b SET aa='new';
276 SELECT relname, a.* FROM a, pg_class where a.tableoid = pg_class.oid;
305 SELECT relname, b.* FROM b, pg_class where b.tableoid = pg_class.oid;
322 SELECT relname, c.* FROM c, pg_class where c.tableoid = pg_class.oid;
324 ---------+----------+----
339 SELECT relname, d.* FROM d, pg_class where d.tableoid = pg_class.oid;
340 relname | aa | bb | cc | dd
341 ---------+-----+----+----+----
350 SELECT relname, a.* FROM ONLY a, pg_class where a.tableoid = pg_class.oid;
361 SELECT relname, b.* FROM ONLY b, pg_class where b.tableoid = pg_class.oid;
372 SELECT relname, c.* FROM ONLY c, pg_class where c.tableoid = pg_class.oid;
374 ---------+----------+----
383 SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
384 relname | aa | bb | cc | dd
385 ---------+-----+----+----+----
394 UPDATE a SET aa='new';
395 DELETE FROM ONLY c WHERE aa='new';
396 SELECT relname, a.* FROM a, pg_class where a.tableoid = pg_class.oid;
419 SELECT relname, b.* FROM b, pg_class where b.tableoid = pg_class.oid;
436 SELECT relname, c.* FROM c, pg_class where c.tableoid = pg_class.oid;
447 SELECT relname, d.* FROM d, pg_class where d.tableoid = pg_class.oid;
448 relname | aa | bb | cc | dd
449 ---------+-----+----+----+----
458 SELECT relname, a.* FROM ONLY a, pg_class where a.tableoid = pg_class.oid;
469 SELECT relname, b.* FROM ONLY b, pg_class where b.tableoid = pg_class.oid;
480 SELECT relname, c.* FROM ONLY c, pg_class where c.tableoid = pg_class.oid;
485 SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
486 relname | aa | bb | cc | dd
487 ---------+-----+----+----+----
497 SELECT relname, a.* FROM a, pg_class where a.tableoid = pg_class.oid;
502 SELECT relname, b.* FROM b, pg_class where b.tableoid = pg_class.oid;
507 SELECT relname, c.* FROM c, pg_class where c.tableoid = pg_class.oid;
512 SELECT relname, d.* FROM d, pg_class where d.tableoid = pg_class.oid;
513 relname | aa | bb | cc | dd
514 ---------+----+----+----+----
517 SELECT relname, a.* FROM ONLY a, pg_class where a.tableoid = pg_class.oid;
522 SELECT relname, b.* FROM ONLY b, pg_class where b.tableoid = pg_class.oid;
527 SELECT relname, c.* FROM ONLY c, pg_class where c.tableoid = pg_class.oid;
532 SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
533 relname | aa | bb | cc | dd
534 ---------+----+----+----+----
537 -- Confirm PRIMARY KEY adds NOT NULL constraint to child table
538 CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a);
539 INSERT INTO z VALUES (NULL, 'text'); -- should fail
540 ERROR: null value in column "aa" of relation "z" violates not-null constraint
541 DETAIL: Failing row contains (null, text).
542 -- Check inherited UPDATE with first child excluded
543 create table some_tab (f1 int, f2 int, f3 int, check (f1 < 10) no inherit);
544 create table some_tab_child () inherits(some_tab);
545 insert into some_tab_child select i, i+1, 0 from generate_series(1,1000) i;
546 create index on some_tab_child(f1, f2);
547 -- while at it, also check that statement-level triggers fire
548 create function some_tab_stmt_trig_func() returns trigger as
549 $$begin raise notice 'updating some_tab'; return NULL; end;$$
551 create trigger some_tab_stmt_trig
552 before update on some_tab execute function some_tab_stmt_trig_func();
554 update some_tab set f3 = 11 where f1 = 12 and f2 = 13;
556 ------------------------------------------------------------------------------------
558 Update on some_tab_child some_tab_1
560 -> Index Scan using some_tab_child_f1_f2_idx on some_tab_child some_tab_1
561 Index Cond: ((f1 = 12) AND (f2 = 13))
564 update some_tab set f3 = 11 where f1 = 12 and f2 = 13;
565 NOTICE: updating some_tab
566 drop table some_tab cascade;
567 NOTICE: drop cascades to table some_tab_child
568 drop function some_tab_stmt_trig_func();
569 -- Check inherited UPDATE with all children excluded
570 create table some_tab (a int, b int);
571 create table some_tab_child () inherits (some_tab);
572 insert into some_tab_child values(1,2);
573 explain (verbose, costs off)
574 update some_tab set a = a + 1 where false;
576 --------------------------------------------------------
577 Update on public.some_tab
579 Output: (some_tab.a + 1), NULL::oid, NULL::tid
580 One-Time Filter: false
583 update some_tab set a = a + 1 where false;
584 explain (verbose, costs off)
585 update some_tab set a = a + 1 where false returning b, a;
587 --------------------------------------------------------
588 Update on public.some_tab
589 Output: some_tab.b, some_tab.a
591 Output: (some_tab.a + 1), NULL::oid, NULL::tid
592 One-Time Filter: false
595 update some_tab set a = a + 1 where false returning b, a;
606 drop table some_tab cascade;
607 NOTICE: drop cascades to table some_tab_child
608 -- Check UPDATE with inherited target and an inherited source table
609 create temp table foo(f1 int, f2 int);
610 create temp table foo2(f3 int) inherits (foo);
611 create temp table bar(f1 int, f2 int);
612 create temp table bar2(f3 int) inherits (bar);
613 insert into foo values(1,1);
614 insert into foo values(3,3);
615 insert into foo2 values(2,2,2);
616 insert into foo2 values(3,3,3);
617 insert into bar values(1,1);
618 insert into bar values(2,2);
619 insert into bar values(3,3);
620 insert into bar values(4,4);
621 insert into bar2 values(1,1,1);
622 insert into bar2 values(2,2,2);
623 insert into bar2 values(3,3,3);
624 insert into bar2 values(4,4,4);
625 update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
626 select tableoid::regclass::text as relname, bar.* from bar order by 1,2;
639 -- Check UPDATE with inherited target and an appendrel subquery
640 update bar set f2 = f2 + 100
642 ( select f1 from foo union all select f1+3 from foo ) ss
643 where bar.f1 = ss.f1;
644 select tableoid::regclass::text as relname, bar.* from bar order by 1,2;
657 -- Check UPDATE with *partitioned* inherited target and an appendrel subquery
658 create table some_tab (a int);
659 insert into some_tab values (0);
660 create table some_tab_child () inherits (some_tab);
661 insert into some_tab_child values (1);
662 create table parted_tab (a int, b char) partition by list (a);
663 create table parted_tab_part1 partition of parted_tab for values in (1);
664 create table parted_tab_part2 partition of parted_tab for values in (2);
665 create table parted_tab_part3 partition of parted_tab for values in (3);
666 insert into parted_tab values (1, 'a'), (2, 'a'), (3, 'a');
667 update parted_tab set b = 'b'
669 (select a from some_tab union all select a+1 from some_tab) ss (a)
670 where parted_tab.a = ss.a;
671 select tableoid::regclass::text as relname, parted_tab.* from parted_tab order by 1,2;
673 ------------------+---+---
674 parted_tab_part1 | 1 | b
675 parted_tab_part2 | 2 | b
676 parted_tab_part3 | 3 | a
680 insert into parted_tab values (1, 'a'), (2, 'a'), (3, 'a');
681 update parted_tab set b = 'b'
683 (select 0 from parted_tab union all select 1 from parted_tab) ss (a)
684 where parted_tab.a = ss.a;
685 select tableoid::regclass::text as relname, parted_tab.* from parted_tab order by 1,2;
687 ------------------+---+---
688 parted_tab_part1 | 1 | b
689 parted_tab_part2 | 2 | a
690 parted_tab_part3 | 3 | a
693 -- modifies partition key, but no rows will actually be updated
694 explain update parted_tab set a = 2 where false;
696 --------------------------------------------------------
697 Update on parted_tab (cost=0.00..0.00 rows=0 width=0)
698 -> Result (cost=0.00..0.00 rows=0 width=10)
699 One-Time Filter: false
702 drop table parted_tab;
703 -- Check UPDATE with multi-level partitioned inherited target
704 create table mlparted_tab (a int, b char, c text) partition by list (a);
705 create table mlparted_tab_part1 partition of mlparted_tab for values in (1);
706 create table mlparted_tab_part2 partition of mlparted_tab for values in (2) partition by list (b);
707 create table mlparted_tab_part3 partition of mlparted_tab for values in (3);
708 create table mlparted_tab_part2a partition of mlparted_tab_part2 for values in ('a');
709 create table mlparted_tab_part2b partition of mlparted_tab_part2 for values in ('b');
710 insert into mlparted_tab values (1, 'a'), (2, 'a'), (2, 'b'), (3, 'a');
711 update mlparted_tab mlp set c = 'xxx'
713 (select a from some_tab union all select a+1 from some_tab) ss (a)
714 where (mlp.a = ss.a and mlp.b = 'b') or mlp.a = 3;
715 select tableoid::regclass::text as relname, mlparted_tab.* from mlparted_tab order by 1,2;
717 ---------------------+---+---+-----
718 mlparted_tab_part1 | 1 | a |
719 mlparted_tab_part2a | 2 | a |
720 mlparted_tab_part2b | 2 | b | xxx
721 mlparted_tab_part3 | 3 | a | xxx
724 drop table mlparted_tab;
725 drop table some_tab cascade;
726 NOTICE: drop cascades to table some_tab_child
727 /* Test multiple inheritance of column defaults */
728 CREATE TABLE firstparent (tomorrow date default now()::date + 1);
729 CREATE TABLE secondparent (tomorrow date default now() :: date + 1);
730 CREATE TABLE jointchild () INHERITS (firstparent, secondparent); -- ok
731 NOTICE: merging multiple inherited definitions of column "tomorrow"
732 CREATE TABLE thirdparent (tomorrow date default now()::date - 1);
733 CREATE TABLE otherchild () INHERITS (firstparent, thirdparent); -- not ok
734 NOTICE: merging multiple inherited definitions of column "tomorrow"
735 ERROR: column "tomorrow" inherits conflicting default values
736 HINT: To resolve the conflict, specify a default explicitly.
737 CREATE TABLE otherchild (tomorrow date default now())
738 INHERITS (firstparent, thirdparent); -- ok, child resolves ambiguous default
739 NOTICE: merging multiple inherited definitions of column "tomorrow"
740 NOTICE: merging column "tomorrow" with inherited definition
741 DROP TABLE firstparent, secondparent, jointchild, thirdparent, otherchild;
742 -- Test changing the type of inherited columns
743 insert into d values('test','one','two','three');
744 alter table a alter column aa type integer using bit_length(aa);
747 ----+-----+-----+-------
748 32 | one | two | three
751 -- The above verified that we can change the type of a multiply-inherited
752 -- column; but we should reject that if any definition was inherited from
753 -- an unrelated parent.
754 create temp table parent1(f1 int, f2 int);
755 create temp table parent2(f1 int, f3 bigint);
756 create temp table childtab(f4 int) inherits(parent1, parent2);
757 NOTICE: merging multiple inherited definitions of column "f1"
758 alter table parent1 alter column f1 type bigint; -- fail, conflict w/parent2
759 ERROR: cannot alter inherited column "f1" of relation "childtab"
760 alter table parent1 alter column f2 type bigint; -- ok
761 -- Test non-inheritable parent constraints
762 create table p1(ff1 int);
763 alter table p1 add constraint p1chk check (ff1 > 0) no inherit;
764 alter table p1 add constraint p2chk check (ff1 > 10);
765 -- connoinherit should be true for NO INHERIT constraint
766 select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pgc.connoinherit from pg_class as pc inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname = 'p1' order by 1,2;
767 relname | conname | contype | conislocal | coninhcount | connoinherit
768 ---------+---------+---------+------------+-------------+--------------
769 p1 | p1chk | c | t | 0 | t
770 p1 | p2chk | c | t | 0 | f
773 -- Test that child does not inherit NO INHERIT constraints
774 create table c1 () inherits (p1);
777 Column | Type | Collation | Nullable | Default
778 --------+---------+-----------+----------+---------
781 "p1chk" CHECK (ff1 > 0) NO INHERIT
782 "p2chk" CHECK (ff1 > 10)
783 Number of child tables: 1 (Use \d+ to list them.)
787 Column | Type | Collation | Nullable | Default
788 --------+---------+-----------+----------+---------
791 "p2chk" CHECK (ff1 > 10)
794 -- Test that child does not override inheritable constraints of the parent
795 create table c2 (constraint p2chk check (ff1 > 10) no inherit) inherits (p1); --fails
796 ERROR: constraint "p2chk" conflicts with inherited constraint on relation "c2"
797 drop table p1 cascade;
798 NOTICE: drop cascades to table c1
799 -- Tests for casting between the rowtypes of parent and child
800 -- tables. See the pgsql-hackers thread beginning Dec. 4/04
801 create table base (i integer);
802 create table derived () inherits (base);
803 create table more_derived (like derived, b int) inherits (derived);
804 NOTICE: merging column "i" with inherited definition
805 insert into derived (i) values (0);
806 select derived::base from derived;
812 select NULL::derived::base;
818 -- remove redundant conversions.
819 explain (verbose on, costs off) select row(i, b)::more_derived::derived::base from more_derived;
821 -------------------------------------------
822 Seq Scan on public.more_derived
823 Output: (ROW(i, b)::more_derived)::base
826 explain (verbose on, costs off) select (1, 2)::more_derived::derived::base;
828 -----------------------
833 drop table more_derived;
836 create table p1(ff1 int);
837 create table p2(f1 text);
838 create function p2text(p2) returns text as 'select $1.f1' language sql;
839 create table c1(f3 int) inherits(p1,p2);
840 insert into c1 values(123456789, 'hi', 42);
841 select p2text(c1.*) from c1;
847 drop function p2text(p2);
851 CREATE TABLE ac (aa TEXT);
852 alter table ac add constraint ac_check check (aa is not null);
853 CREATE TABLE bc (bb TEXT) INHERITS (ac);
854 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 inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') order by 1,2;
855 relname | conname | contype | conislocal | coninhcount | consrc
856 ---------+----------+---------+------------+-------------+------------------
857 ac | ac_check | c | t | 0 | (aa IS NOT NULL)
858 bc | ac_check | c | f | 1 | (aa IS NOT NULL)
861 insert into ac (aa) values (NULL);
862 ERROR: new row for relation "ac" violates check constraint "ac_check"
863 DETAIL: Failing row contains (null).
864 insert into bc (aa) values (NULL);
865 ERROR: new row for relation "bc" violates check constraint "ac_check"
866 DETAIL: Failing row contains (null, null).
867 alter table bc drop constraint ac_check; -- fail, disallowed
868 ERROR: cannot drop inherited constraint "ac_check" of relation "bc"
869 alter table ac drop constraint ac_check;
870 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 inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') order by 1,2;
871 relname | conname | contype | conislocal | coninhcount | consrc
872 ---------+---------+---------+------------+-------------+--------
875 -- try the unnamed-constraint case
876 alter table ac add check (aa is not null);
877 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 inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') order by 1,2;
878 relname | conname | contype | conislocal | coninhcount | consrc
879 ---------+-------------+---------+------------+-------------+------------------
880 ac | ac_aa_check | c | t | 0 | (aa IS NOT NULL)
881 bc | ac_aa_check | c | f | 1 | (aa IS NOT NULL)
884 insert into ac (aa) values (NULL);
885 ERROR: new row for relation "ac" violates check constraint "ac_aa_check"
886 DETAIL: Failing row contains (null).
887 insert into bc (aa) values (NULL);
888 ERROR: new row for relation "bc" violates check constraint "ac_aa_check"
889 DETAIL: Failing row contains (null, null).
890 alter table bc drop constraint ac_aa_check; -- fail, disallowed
891 ERROR: cannot drop inherited constraint "ac_aa_check" of relation "bc"
892 alter table ac drop constraint ac_aa_check;
893 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 inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') order by 1,2;
894 relname | conname | contype | conislocal | coninhcount | consrc
895 ---------+---------+---------+------------+-------------+--------
898 alter table ac add constraint ac_check check (aa is not null);
899 alter table bc no inherit ac;
900 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 inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') order by 1,2;
901 relname | conname | contype | conislocal | coninhcount | consrc
902 ---------+----------+---------+------------+-------------+------------------
903 ac | ac_check | c | t | 0 | (aa IS NOT NULL)
904 bc | ac_check | c | t | 0 | (aa IS NOT NULL)
907 alter table bc drop constraint ac_check;
908 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 inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') order by 1,2;
909 relname | conname | contype | conislocal | coninhcount | consrc
910 ---------+----------+---------+------------+-------------+------------------
911 ac | ac_check | c | t | 0 | (aa IS NOT NULL)
914 alter table ac drop constraint ac_check;
915 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 inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') order by 1,2;
916 relname | conname | contype | conislocal | coninhcount | consrc
917 ---------+---------+---------+------------+-------------+--------
922 create table ac (a int constraint check_a check (a <> 0));
923 create table bc (a int constraint check_a check (a <> 0), b int constraint check_b check (b <> 0)) inherits (ac);
924 NOTICE: merging column "a" with inherited definition
925 NOTICE: merging constraint "check_a" with inherited definition
926 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 inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc') order by 1,2;
927 relname | conname | contype | conislocal | coninhcount | consrc
928 ---------+---------+---------+------------+-------------+----------
929 ac | check_a | c | t | 0 | (a <> 0)
930 bc | check_a | c | t | 1 | (a <> 0)
931 bc | check_b | c | t | 0 | (b <> 0)
936 create table ac (a int constraint check_a check (a <> 0));
937 create table bc (b int constraint check_b check (b <> 0));
938 create table cc (c int constraint check_c check (c <> 0)) inherits (ac, bc);
939 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 inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc', 'cc') order by 1,2;
940 relname | conname | contype | conislocal | coninhcount | consrc
941 ---------+---------+---------+------------+-------------+----------
942 ac | check_a | c | t | 0 | (a <> 0)
943 bc | check_b | c | t | 0 | (b <> 0)
944 cc | check_a | c | f | 1 | (a <> 0)
945 cc | check_b | c | f | 1 | (b <> 0)
946 cc | check_c | c | t | 0 | (c <> 0)
949 alter table cc no inherit bc;
950 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 inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname in ('ac', 'bc', 'cc') order by 1,2;
951 relname | conname | contype | conislocal | coninhcount | consrc
952 ---------+---------+---------+------------+-------------+----------
953 ac | check_a | c | t | 0 | (a <> 0)
954 bc | check_b | c | t | 0 | (b <> 0)
955 cc | check_a | c | f | 1 | (a <> 0)
956 cc | check_b | c | t | 0 | (b <> 0)
957 cc | check_c | c | t | 0 | (c <> 0)
963 create table p1(f1 int);
964 create table p2(f2 int);
965 create table c1(f3 int) inherits(p1,p2);
966 insert into c1 values(1,-1,2);
967 alter table p2 add constraint cc check (f2>0); -- fail
968 ERROR: check constraint "cc" of relation "c1" is violated by some row
969 alter table p2 add check (f2>0); -- check it without a name, too
970 ERROR: check constraint "p2_f2_check" of relation "c1" is violated by some row
972 insert into c1 values(1,1,2);
973 alter table p2 add check (f2>0);
974 insert into c1 values(1,-1,2); -- fail
975 ERROR: new row for relation "c1" violates check constraint "p2_f2_check"
976 DETAIL: Failing row contains (1, -1, 2).
977 create table c2(f3 int) inherits(p1,p2);
980 Column | Type | Collation | Nullable | Default
981 --------+---------+-----------+----------+---------
986 "p2_f2_check" CHECK (f2 > 0)
990 create table c3 (f4 int) inherits(c1,c2);
991 NOTICE: merging multiple inherited definitions of column "f1"
992 NOTICE: merging multiple inherited definitions of column "f2"
993 NOTICE: merging multiple inherited definitions of column "f3"
996 Column | Type | Collation | Nullable | Default
997 --------+---------+-----------+----------+---------
1003 "p2_f2_check" CHECK (f2 > 0)
1007 drop table p1 cascade;
1008 NOTICE: drop cascades to 3 other objects
1009 DETAIL: drop cascades to table c1
1010 drop cascades to table c2
1011 drop cascades to table c3
1012 drop table p2 cascade;
1013 create table pp1 (f1 int);
1014 create table cc1 (f2 text, f3 int) inherits (pp1);
1015 alter table pp1 add column a1 int check (a1 > 0);
1018 Column | Type | Collation | Nullable | Default
1019 --------+---------+-----------+----------+---------
1025 "pp1_a1_check" CHECK (a1 > 0)
1028 create table cc2(f4 float) inherits(pp1,cc1);
1029 NOTICE: merging multiple inherited definitions of column "f1"
1030 NOTICE: merging multiple inherited definitions of column "a1"
1033 Column | Type | Collation | Nullable | Default
1034 --------+------------------+-----------+----------+---------
1039 f4 | double precision | | |
1041 "pp1_a1_check" CHECK (a1 > 0)
1045 alter table pp1 add column a2 int check (a2 > 0);
1046 NOTICE: merging definition of column "a2" for child "cc2"
1047 NOTICE: merging constraint "pp1_a2_check" with inherited definition
1050 Column | Type | Collation | Nullable | Default
1051 --------+------------------+-----------+----------+---------
1056 f4 | double precision | | |
1059 "pp1_a1_check" CHECK (a1 > 0)
1060 "pp1_a2_check" CHECK (a2 > 0)
1064 drop table pp1 cascade;
1065 NOTICE: drop cascades to 2 other objects
1066 DETAIL: drop cascades to table cc1
1067 drop cascades to table cc2
1068 -- Test for renaming in simple multiple inheritance
1069 CREATE TABLE inht1 (a int, b int);
1070 CREATE TABLE inhs1 (b int, c int);
1071 CREATE TABLE inhts (d int) INHERITS (inht1, inhs1);
1072 NOTICE: merging multiple inherited definitions of column "b"
1073 ALTER TABLE inht1 RENAME a TO aa;
1074 ALTER TABLE inht1 RENAME b TO bb; -- to be failed
1075 ERROR: cannot rename inherited column "b"
1076 ALTER TABLE inhts RENAME aa TO aaa; -- to be failed
1077 ERROR: cannot rename inherited column "aa"
1078 ALTER TABLE inhts RENAME d TO dd;
1080 Table "public.inhts"
1081 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1082 --------+---------+-----------+----------+---------+---------+--------------+-------------
1083 aa | integer | | | | plain | |
1084 b | integer | | | | plain | |
1085 c | integer | | | | plain | |
1086 dd | integer | | | | plain | |
1091 -- Test for adding a column to a parent table with complex inheritance
1092 CREATE TABLE inhta ();
1093 CREATE TABLE inhtb () INHERITS (inhta);
1094 CREATE TABLE inhtc () INHERITS (inhtb);
1095 CREATE TABLE inhtd () INHERITS (inhta, inhtb, inhtc);
1096 ALTER TABLE inhta ADD COLUMN i int;
1097 NOTICE: merging definition of column "i" for child "inhtd"
1098 NOTICE: merging definition of column "i" for child "inhtd"
1100 Table "public.inhta"
1101 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1102 --------+---------+-----------+----------+---------+---------+--------------+-------------
1103 i | integer | | | | plain | |
1104 Child tables: inhtb,
1107 DROP TABLE inhta, inhtb, inhtc, inhtd;
1108 -- Test for renaming in diamond inheritance
1109 CREATE TABLE inht2 (x int) INHERITS (inht1);
1110 CREATE TABLE inht3 (y int) INHERITS (inht1);
1111 CREATE TABLE inht4 (z int) INHERITS (inht2, inht3);
1112 NOTICE: merging multiple inherited definitions of column "aa"
1113 NOTICE: merging multiple inherited definitions of column "b"
1114 ALTER TABLE inht1 RENAME aa TO aaa;
1116 Table "public.inht4"
1117 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1118 --------+---------+-----------+----------+---------+---------+--------------+-------------
1119 aaa | integer | | | | plain | |
1120 b | integer | | | | plain | |
1121 x | integer | | | | plain | |
1122 y | integer | | | | plain | |
1123 z | integer | | | | plain | |
1127 CREATE TABLE inhts (d int) INHERITS (inht2, inhs1);
1128 NOTICE: merging multiple inherited definitions of column "b"
1129 ALTER TABLE inht1 RENAME aaa TO aaaa;
1130 ALTER TABLE inht1 RENAME b TO bb; -- to be failed
1131 ERROR: cannot rename inherited column "b"
1133 Table "public.inhts"
1134 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1135 --------+---------+-----------+----------+---------+---------+--------------+-------------
1136 aaaa | integer | | | | plain | |
1137 b | integer | | | | plain | |
1138 x | integer | | | | plain | |
1139 c | integer | | | | plain | |
1140 d | integer | | | | plain | |
1144 WITH RECURSIVE r AS (
1145 SELECT 'inht1'::regclass AS inhrelid
1147 SELECT c.inhrelid FROM pg_inherits c, r WHERE r.inhrelid = c.inhparent
1149 SELECT a.attrelid::regclass, a.attname, a.attinhcount, e.expected
1150 FROM (SELECT inhrelid, count(*) AS expected FROM pg_inherits
1151 WHERE inhparent IN (SELECT inhrelid FROM r) GROUP BY inhrelid) e
1152 JOIN pg_attribute a ON e.inhrelid = a.attrelid WHERE NOT attislocal
1153 ORDER BY a.attrelid::regclass::name, a.attnum;
1154 attrelid | attname | attinhcount | expected
1155 ----------+---------+-------------+----------
1156 inht2 | aaaa | 1 | 1
1158 inht3 | aaaa | 1 | 1
1160 inht4 | aaaa | 2 | 2
1164 inhts | aaaa | 1 | 1
1170 DROP TABLE inht1, inhs1 CASCADE;
1171 NOTICE: drop cascades to 4 other objects
1172 DETAIL: drop cascades to table inht2
1173 drop cascades to table inhts
1174 drop cascades to table inht3
1175 drop cascades to table inht4
1176 -- Test non-inheritable indices [UNIQUE, EXCLUDE] constraints
1177 CREATE TABLE test_constraints (id int, val1 varchar, val2 int, UNIQUE(val1, val2));
1178 CREATE TABLE test_constraints_inh () INHERITS (test_constraints);
1179 \d+ test_constraints
1180 Table "public.test_constraints"
1181 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1182 --------+-------------------+-----------+----------+---------+----------+--------------+-------------
1183 id | integer | | | | plain | |
1184 val1 | character varying | | | | extended | |
1185 val2 | integer | | | | plain | |
1187 "test_constraints_val1_val2_key" UNIQUE CONSTRAINT, btree (val1, val2)
1188 Child tables: test_constraints_inh
1190 ALTER TABLE ONLY test_constraints DROP CONSTRAINT test_constraints_val1_val2_key;
1191 \d+ test_constraints
1192 Table "public.test_constraints"
1193 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1194 --------+-------------------+-----------+----------+---------+----------+--------------+-------------
1195 id | integer | | | | plain | |
1196 val1 | character varying | | | | extended | |
1197 val2 | integer | | | | plain | |
1198 Child tables: test_constraints_inh
1200 \d+ test_constraints_inh
1201 Table "public.test_constraints_inh"
1202 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1203 --------+-------------------+-----------+----------+---------+----------+--------------+-------------
1204 id | integer | | | | plain | |
1205 val1 | character varying | | | | extended | |
1206 val2 | integer | | | | plain | |
1207 Inherits: test_constraints
1209 DROP TABLE test_constraints_inh;
1210 DROP TABLE test_constraints;
1211 CREATE TABLE test_ex_constraints (
1213 EXCLUDE USING gist (c WITH &&)
1215 CREATE TABLE test_ex_constraints_inh () INHERITS (test_ex_constraints);
1216 \d+ test_ex_constraints
1217 Table "public.test_ex_constraints"
1218 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1219 --------+--------+-----------+----------+---------+---------+--------------+-------------
1220 c | circle | | | | plain | |
1222 "test_ex_constraints_c_excl" EXCLUDE USING gist (c WITH &&)
1223 Child tables: test_ex_constraints_inh
1225 ALTER TABLE test_ex_constraints DROP CONSTRAINT test_ex_constraints_c_excl;
1226 \d+ test_ex_constraints
1227 Table "public.test_ex_constraints"
1228 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1229 --------+--------+-----------+----------+---------+---------+--------------+-------------
1230 c | circle | | | | plain | |
1231 Child tables: test_ex_constraints_inh
1233 \d+ test_ex_constraints_inh
1234 Table "public.test_ex_constraints_inh"
1235 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1236 --------+--------+-----------+----------+---------+---------+--------------+-------------
1237 c | circle | | | | plain | |
1238 Inherits: test_ex_constraints
1240 DROP TABLE test_ex_constraints_inh;
1241 DROP TABLE test_ex_constraints;
1242 -- Test non-inheritable foreign key constraints
1243 CREATE TABLE test_primary_constraints(id int PRIMARY KEY);
1244 CREATE TABLE test_foreign_constraints(id1 int REFERENCES test_primary_constraints(id));
1245 CREATE TABLE test_foreign_constraints_inh () INHERITS (test_foreign_constraints);
1246 \d+ test_primary_constraints
1247 Table "public.test_primary_constraints"
1248 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1249 --------+---------+-----------+----------+---------+---------+--------------+-------------
1250 id | integer | | not null | | plain | |
1252 "test_primary_constraints_pkey" PRIMARY KEY, btree (id)
1254 TABLE "test_foreign_constraints" CONSTRAINT "test_foreign_constraints_id1_fkey" FOREIGN KEY (id1) REFERENCES test_primary_constraints(id)
1256 \d+ test_foreign_constraints
1257 Table "public.test_foreign_constraints"
1258 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1259 --------+---------+-----------+----------+---------+---------+--------------+-------------
1260 id1 | integer | | | | plain | |
1261 Foreign-key constraints:
1262 "test_foreign_constraints_id1_fkey" FOREIGN KEY (id1) REFERENCES test_primary_constraints(id)
1263 Child tables: test_foreign_constraints_inh
1265 ALTER TABLE test_foreign_constraints DROP CONSTRAINT test_foreign_constraints_id1_fkey;
1266 \d+ test_foreign_constraints
1267 Table "public.test_foreign_constraints"
1268 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1269 --------+---------+-----------+----------+---------+---------+--------------+-------------
1270 id1 | integer | | | | plain | |
1271 Child tables: test_foreign_constraints_inh
1273 \d+ test_foreign_constraints_inh
1274 Table "public.test_foreign_constraints_inh"
1275 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1276 --------+---------+-----------+----------+---------+---------+--------------+-------------
1277 id1 | integer | | | | plain | |
1278 Inherits: test_foreign_constraints
1280 DROP TABLE test_foreign_constraints_inh;
1281 DROP TABLE test_foreign_constraints;
1282 DROP TABLE test_primary_constraints;
1283 -- Test foreign key behavior
1284 create table inh_fk_1 (a int primary key);
1285 insert into inh_fk_1 values (1), (2), (3);
1286 create table inh_fk_2 (x int primary key, y int references inh_fk_1 on delete cascade);
1287 insert into inh_fk_2 values (11, 1), (22, 2), (33, 3);
1288 create table inh_fk_2_child () inherits (inh_fk_2);
1289 insert into inh_fk_2_child values (111, 1), (222, 2);
1290 delete from inh_fk_1 where a = 1;
1291 select * from inh_fk_1 order by 1;
1298 select * from inh_fk_2 order by 1, 2;
1307 drop table inh_fk_1, inh_fk_2, inh_fk_2_child;
1308 -- Test that parent and child CHECK constraints can be created in either order
1309 create table p1(f1 int);
1310 create table p1_c1() inherits(p1);
1311 alter table p1 add constraint inh_check_constraint1 check (f1 > 0);
1312 alter table p1_c1 add constraint inh_check_constraint1 check (f1 > 0);
1313 NOTICE: merging constraint "inh_check_constraint1" with inherited definition
1314 alter table p1_c1 add constraint inh_check_constraint2 check (f1 < 10);
1315 alter table p1 add constraint inh_check_constraint2 check (f1 < 10);
1316 NOTICE: merging constraint "inh_check_constraint2" with inherited definition
1317 select conrelid::regclass::text as relname, conname, conislocal, coninhcount
1318 from pg_constraint where conname like 'inh\_check\_constraint%'
1320 relname | conname | conislocal | coninhcount
1321 ---------+-----------------------+------------+-------------
1322 p1 | inh_check_constraint1 | t | 0
1323 p1 | inh_check_constraint2 | t | 0
1324 p1_c1 | inh_check_constraint1 | t | 1
1325 p1_c1 | inh_check_constraint2 | t | 1
1328 drop table p1 cascade;
1329 NOTICE: drop cascades to table p1_c1
1331 -- Test DROP behavior of multiply-defined CHECK constraints
1333 create table p1(f1 int constraint f1_pos CHECK (f1 > 0));
1334 create table p1_c1 (f1 int constraint f1_pos CHECK (f1 > 0)) inherits (p1);
1335 NOTICE: merging column "f1" with inherited definition
1336 NOTICE: merging constraint "f1_pos" with inherited definition
1337 alter table p1_c1 drop constraint f1_pos;
1338 ERROR: cannot drop inherited constraint "f1_pos" of relation "p1_c1"
1339 alter table p1 drop constraint f1_pos;
1341 Table "public.p1_c1"
1342 Column | Type | Collation | Nullable | Default
1343 --------+---------+-----------+----------+---------
1346 "f1_pos" CHECK (f1 > 0)
1349 drop table p1 cascade;
1350 NOTICE: drop cascades to table p1_c1
1351 create table p1(f1 int constraint f1_pos CHECK (f1 > 0));
1352 create table p2(f1 int constraint f1_pos CHECK (f1 > 0));
1353 create table p1p2_c1 (f1 int) inherits (p1, p2);
1354 NOTICE: merging multiple inherited definitions of column "f1"
1355 NOTICE: merging column "f1" with inherited definition
1356 create table p1p2_c2 (f1 int constraint f1_pos CHECK (f1 > 0)) inherits (p1, p2);
1357 NOTICE: merging multiple inherited definitions of column "f1"
1358 NOTICE: merging column "f1" with inherited definition
1359 NOTICE: merging constraint "f1_pos" with inherited definition
1360 alter table p2 drop constraint f1_pos;
1361 alter table p1 drop constraint f1_pos;
1363 Table "public.p1p2_c1"
1364 Column | Type | Collation | Nullable | Default
1365 --------+---------+-----------+----------+---------
1370 Table "public.p1p2_c2"
1371 Column | Type | Collation | Nullable | Default
1372 --------+---------+-----------+----------+---------
1375 "f1_pos" CHECK (f1 > 0)
1379 drop table p1, p2 cascade;
1380 NOTICE: drop cascades to 2 other objects
1381 DETAIL: drop cascades to table p1p2_c1
1382 drop cascades to table p1p2_c2
1383 create table p1(f1 int constraint f1_pos CHECK (f1 > 0));
1384 create table p1_c1() inherits (p1);
1385 create table p1_c2() inherits (p1);
1386 create table p1_c1c2() inherits (p1_c1, p1_c2);
1387 NOTICE: merging multiple inherited definitions of column "f1"
1389 Table "public.p1_c1c2"
1390 Column | Type | Collation | Nullable | Default
1391 --------+---------+-----------+----------+---------
1394 "f1_pos" CHECK (f1 > 0)
1398 alter table p1 drop constraint f1_pos;
1400 Table "public.p1_c1c2"
1401 Column | Type | Collation | Nullable | Default
1402 --------+---------+-----------+----------+---------
1407 drop table p1 cascade;
1408 NOTICE: drop cascades to 3 other objects
1409 DETAIL: drop cascades to table p1_c1
1410 drop cascades to table p1_c2
1411 drop cascades to table p1_c1c2
1412 create table p1(f1 int constraint f1_pos CHECK (f1 > 0));
1413 create table p1_c1() inherits (p1);
1414 create table p1_c2(constraint f1_pos CHECK (f1 > 0)) inherits (p1);
1415 NOTICE: merging constraint "f1_pos" with inherited definition
1416 create table p1_c1c2() inherits (p1_c1, p1_c2, p1);
1417 NOTICE: merging multiple inherited definitions of column "f1"
1418 NOTICE: merging multiple inherited definitions of column "f1"
1419 alter table p1_c2 drop constraint f1_pos;
1420 ERROR: cannot drop inherited constraint "f1_pos" of relation "p1_c2"
1421 alter table p1 drop constraint f1_pos;
1422 alter table p1_c1c2 drop constraint f1_pos;
1423 ERROR: cannot drop inherited constraint "f1_pos" of relation "p1_c1c2"
1424 alter table p1_c2 drop constraint f1_pos;
1426 Table "public.p1_c1c2"
1427 Column | Type | Collation | Nullable | Default
1428 --------+---------+-----------+----------+---------
1434 drop table p1 cascade;
1435 NOTICE: drop cascades to 3 other objects
1436 DETAIL: drop cascades to table p1_c1
1437 drop cascades to table p1_c2
1438 drop cascades to table p1_c1c2
1439 -- Test that a valid child can have not-valid parent, but not vice versa
1440 create table invalid_check_con(f1 int);
1441 create table invalid_check_con_child() inherits(invalid_check_con);
1442 alter table invalid_check_con_child add constraint inh_check_constraint check(f1 > 0) not valid;
1443 alter table invalid_check_con add constraint inh_check_constraint check(f1 > 0); -- fail
1444 ERROR: constraint "inh_check_constraint" conflicts with NOT VALID constraint on relation "invalid_check_con_child"
1445 alter table invalid_check_con_child drop constraint inh_check_constraint;
1446 insert into invalid_check_con values(0);
1447 alter table invalid_check_con_child add constraint inh_check_constraint check(f1 > 0);
1448 alter table invalid_check_con add constraint inh_check_constraint check(f1 > 0) not valid;
1449 NOTICE: merging constraint "inh_check_constraint" with inherited definition
1450 insert into invalid_check_con values(0); -- fail
1451 ERROR: new row for relation "invalid_check_con" violates check constraint "inh_check_constraint"
1452 DETAIL: Failing row contains (0).
1453 insert into invalid_check_con_child values(0); -- fail
1454 ERROR: new row for relation "invalid_check_con_child" violates check constraint "inh_check_constraint"
1455 DETAIL: Failing row contains (0).
1456 select conrelid::regclass::text as relname, conname,
1457 convalidated, conislocal, coninhcount, connoinherit
1458 from pg_constraint where conname like 'inh\_check\_constraint%'
1460 relname | conname | convalidated | conislocal | coninhcount | connoinherit
1461 -------------------------+----------------------+--------------+------------+-------------+--------------
1462 invalid_check_con | inh_check_constraint | f | t | 0 | f
1463 invalid_check_con_child | inh_check_constraint | t | t | 1 | f
1466 -- We don't drop the invalid_check_con* tables, to test dump/reload with
1468 -- Test parameterized append plans for inheritance trees
1470 create temp table patest0 (id, x) as
1471 select x, x from generate_series(0,1000) x;
1472 create temp table patest1() inherits (patest0);
1474 select x, x from generate_series(0,1000) x;
1475 create temp table patest2() inherits (patest0);
1477 select x, x from generate_series(0,1000) x;
1478 create index patest0i on patest0(id);
1479 create index patest1i on patest1(id);
1480 create index patest2i on patest2(id);
1485 select * from patest0 join (select f1 from int4_tbl limit 1) ss on id = f1;
1487 ------------------------------------------------------------
1490 -> Seq Scan on int4_tbl
1492 -> Index Scan using patest0i on patest0 patest0_1
1493 Index Cond: (id = int4_tbl.f1)
1494 -> Index Scan using patest1i on patest1 patest0_2
1495 Index Cond: (id = int4_tbl.f1)
1496 -> Index Scan using patest2i on patest2 patest0_3
1497 Index Cond: (id = int4_tbl.f1)
1500 select * from patest0 join (select f1 from int4_tbl limit 1) ss on id = f1;
1508 drop index patest2i;
1510 select * from patest0 join (select f1 from int4_tbl limit 1) ss on id = f1;
1512 ------------------------------------------------------------
1515 -> Seq Scan on int4_tbl
1517 -> Index Scan using patest0i on patest0 patest0_1
1518 Index Cond: (id = int4_tbl.f1)
1519 -> Index Scan using patest1i on patest1 patest0_2
1520 Index Cond: (id = int4_tbl.f1)
1521 -> Seq Scan on patest2 patest0_3
1522 Filter: (int4_tbl.f1 = id)
1525 select * from patest0 join (select f1 from int4_tbl limit 1) ss on id = f1;
1533 drop table patest0 cascade;
1534 NOTICE: drop cascades to 2 other objects
1535 DETAIL: drop cascades to table patest1
1536 drop cascades to table patest2
1538 -- Test merge-append plans for inheritance trees
1540 create table matest0 (id serial primary key, name text);
1541 create table matest1 (id integer primary key) inherits (matest0);
1542 NOTICE: merging column "id" with inherited definition
1543 create table matest2 (id integer primary key) inherits (matest0);
1544 NOTICE: merging column "id" with inherited definition
1545 create table matest3 (id integer primary key) inherits (matest0);
1546 NOTICE: merging column "id" with inherited definition
1547 create index matest0i on matest0 ((1-id));
1548 create index matest1i on matest1 ((1-id));
1549 -- create index matest2i on matest2 ((1-id)); -- intentionally missing
1550 create index matest3i on matest3 ((1-id));
1551 insert into matest1 (name) values ('Test 1');
1552 insert into matest1 (name) values ('Test 2');
1553 insert into matest2 (name) values ('Test 3');
1554 insert into matest2 (name) values ('Test 4');
1555 insert into matest3 (name) values ('Test 5');
1556 insert into matest3 (name) values ('Test 6');
1557 set enable_indexscan = off; -- force use of seqscan/sort, so no merge
1558 explain (verbose, costs off) select * from matest0 order by 1-id;
1560 ------------------------------------------------------------
1562 Output: matest0.id, matest0.name, ((1 - matest0.id))
1563 Sort Key: ((1 - matest0.id))
1565 Output: matest0.id, matest0.name, (1 - matest0.id)
1567 -> Seq Scan on public.matest0 matest0_1
1568 Output: matest0_1.id, matest0_1.name
1569 -> Seq Scan on public.matest1 matest0_2
1570 Output: matest0_2.id, matest0_2.name
1571 -> Seq Scan on public.matest2 matest0_3
1572 Output: matest0_3.id, matest0_3.name
1573 -> Seq Scan on public.matest3 matest0_4
1574 Output: matest0_4.id, matest0_4.name
1577 select * from matest0 order by 1-id;
1588 explain (verbose, costs off) select min(1-id) from matest0;
1590 --------------------------------------------------
1592 Output: min((1 - matest0.id))
1594 -> Seq Scan on public.matest0 matest0_1
1595 Output: matest0_1.id
1596 -> Seq Scan on public.matest1 matest0_2
1597 Output: matest0_2.id
1598 -> Seq Scan on public.matest2 matest0_3
1599 Output: matest0_3.id
1600 -> Seq Scan on public.matest3 matest0_4
1601 Output: matest0_4.id
1604 select min(1-id) from matest0;
1610 reset enable_indexscan;
1611 set enable_seqscan = off; -- plan with fewest seqscans should be merge
1612 set enable_parallel_append = off; -- Don't let parallel-append interfere
1613 explain (verbose, costs off) select * from matest0 order by 1-id;
1615 ------------------------------------------------------------------------
1618 Sort Key: ((1 - matest0.id))
1619 -> Index Scan using matest0i on public.matest0 matest0_1
1620 Output: matest0_1.id, matest0_1.name, (1 - matest0_1.id)
1621 -> Index Scan using matest1i on public.matest1 matest0_2
1622 Output: matest0_2.id, matest0_2.name, (1 - matest0_2.id)
1624 Output: matest0_3.id, matest0_3.name, ((1 - matest0_3.id))
1625 Sort Key: ((1 - matest0_3.id))
1626 -> Seq Scan on public.matest2 matest0_3
1628 Output: matest0_3.id, matest0_3.name, (1 - matest0_3.id)
1629 -> Index Scan using matest3i on public.matest3 matest0_4
1630 Output: matest0_4.id, matest0_4.name, (1 - matest0_4.id)
1633 select * from matest0 order by 1-id;
1644 explain (verbose, costs off) select min(1-id) from matest0;
1646 ---------------------------------------------------------------------------------
1648 Output: (InitPlan 1).col1
1651 Output: ((1 - matest0.id))
1653 Output: ((1 - matest0.id))
1655 Sort Key: ((1 - matest0.id))
1656 -> Index Scan using matest0i on public.matest0 matest0_1
1657 Output: matest0_1.id, (1 - matest0_1.id)
1658 Index Cond: ((1 - matest0_1.id) IS NOT NULL)
1659 -> Index Scan using matest1i on public.matest1 matest0_2
1660 Output: matest0_2.id, (1 - matest0_2.id)
1661 Index Cond: ((1 - matest0_2.id) IS NOT NULL)
1663 Output: matest0_3.id, ((1 - matest0_3.id))
1664 Sort Key: ((1 - matest0_3.id))
1665 -> Bitmap Heap Scan on public.matest2 matest0_3
1666 Output: matest0_3.id, (1 - matest0_3.id)
1667 Filter: ((1 - matest0_3.id) IS NOT NULL)
1668 -> Bitmap Index Scan on matest2_pkey
1669 -> Index Scan using matest3i on public.matest3 matest0_4
1670 Output: matest0_4.id, (1 - matest0_4.id)
1671 Index Cond: ((1 - matest0_4.id) IS NOT NULL)
1674 select min(1-id) from matest0;
1680 reset enable_seqscan;
1681 reset enable_parallel_append;
1682 drop table matest0 cascade;
1683 NOTICE: drop cascades to 3 other objects
1684 DETAIL: drop cascades to table matest1
1685 drop cascades to table matest2
1686 drop cascades to table matest3
1688 -- Check that use of an index with an extraneous column doesn't produce
1689 -- a plan with extraneous sorting
1691 create table matest0 (a int, b int, c int, d int);
1692 create table matest1 () inherits(matest0);
1693 create index matest0i on matest0 (b, c);
1694 create index matest1i on matest1 (b, c);
1695 set enable_nestloop = off; -- we want a plan with two MergeAppends
1697 select t1.* from matest0 t1, matest0 t2
1698 where t1.b = t2.b and t2.c = t2.d
1699 order by t1.b limit 10;
1701 -------------------------------------------------------------------
1704 Merge Cond: (t1.b = t2.b)
1707 -> Index Scan using matest0i on matest0 t1_1
1708 -> Index Scan using matest1i on matest1 t1_2
1712 -> Index Scan using matest0i on matest0 t2_1
1714 -> Index Scan using matest1i on matest1 t2_2
1718 reset enable_nestloop;
1719 drop table matest0 cascade;
1720 NOTICE: drop cascades to table matest1
1721 -- Test a MergeAppend plan where one child requires a sort
1722 create table matest0(a int primary key);
1723 create table matest1() inherits (matest0);
1724 insert into matest0 select generate_series(1, 400);
1725 insert into matest1 select generate_series(1, 200);
1729 select * from matest0 where a < 100 order by a;
1731 ---------------------------------------------------------------
1734 -> Index Only Scan using matest0_pkey on matest0 matest0_1
1735 Index Cond: (a < 100)
1737 Sort Key: matest0_2.a
1738 -> Seq Scan on matest1 matest0_2
1742 drop table matest0 cascade;
1743 NOTICE: drop cascades to table matest1
1745 -- Test merge-append for UNION ALL append relations
1747 set enable_seqscan = off;
1748 set enable_indexscan = on;
1749 set enable_bitmapscan = off;
1750 -- Check handling of duplicated, constant, or volatile targetlist items
1752 SELECT thousand, tenthous FROM tenk1
1754 SELECT thousand, thousand FROM tenk1
1755 ORDER BY thousand, tenthous;
1757 -------------------------------------------------------------------------
1759 Sort Key: tenk1.thousand, tenk1.tenthous
1760 -> Index Only Scan using tenk1_thous_tenthous on tenk1
1762 Sort Key: tenk1_1.thousand, tenk1_1.thousand
1763 -> Index Only Scan using tenk1_thous_tenthous on tenk1 tenk1_1
1767 SELECT thousand, tenthous, thousand+tenthous AS x FROM tenk1
1769 SELECT 42, 42, hundred FROM tenk1
1770 ORDER BY thousand, tenthous;
1772 ------------------------------------------------------------------
1774 Sort Key: tenk1.thousand, tenk1.tenthous
1775 -> Index Only Scan using tenk1_thous_tenthous on tenk1
1778 -> Index Only Scan using tenk1_hundred on tenk1 tenk1_1
1782 SELECT thousand, tenthous FROM tenk1
1784 SELECT thousand, random()::integer FROM tenk1
1785 ORDER BY thousand, tenthous;
1787 -------------------------------------------------------------------------
1789 Sort Key: tenk1.thousand, tenk1.tenthous
1790 -> Index Only Scan using tenk1_thous_tenthous on tenk1
1792 Sort Key: tenk1_1.thousand, ((random())::integer)
1793 -> Index Only Scan using tenk1_thous_tenthous on tenk1 tenk1_1
1796 -- Check min/max aggregate optimization
1799 (SELECT unique1 AS x FROM tenk1 a
1801 SELECT unique2 AS x FROM tenk1 b) s;
1803 --------------------------------------------------------------------
1809 -> Index Only Scan using tenk1_unique1 on tenk1 a
1810 Index Cond: (unique1 IS NOT NULL)
1811 -> Index Only Scan using tenk1_unique2 on tenk1 b
1812 Index Cond: (unique2 IS NOT NULL)
1817 (SELECT unique1 AS x, unique1 AS y FROM tenk1 a
1819 SELECT unique2 AS x, unique2 AS y FROM tenk1 b) s;
1821 --------------------------------------------------------------------
1827 -> Index Only Scan using tenk1_unique1 on tenk1 a
1828 Index Cond: (unique1 IS NOT NULL)
1829 -> Index Only Scan using tenk1_unique2 on tenk1 b
1830 Index Cond: (unique2 IS NOT NULL)
1833 -- XXX planner doesn't recognize that index on unique2 is sufficiently sorted
1836 (SELECT thousand AS x, tenthous AS y FROM tenk1 a
1838 SELECT unique2 AS x, unique2 AS y FROM tenk1 b) s
1841 -------------------------------------------------------------
1843 Sort Key: a.thousand, a.tenthous
1844 -> Index Only Scan using tenk1_thous_tenthous on tenk1 a
1846 Sort Key: b.unique2, b.unique2
1847 -> Index Only Scan using tenk1_unique2 on tenk1 b
1850 -- exercise rescan code path via a repeatedly-evaluated subquery
1853 ARRAY(SELECT f.i FROM (
1854 (SELECT d + g.i FROM generate_series(4, 30, 3) d ORDER BY 1)
1856 (SELECT d + g.i FROM generate_series(0, 30, 5) d ORDER BY 1)
1858 ORDER BY f.i LIMIT 10)
1859 FROM generate_series(1, 3) g(i);
1861 ----------------------------------------------------------------
1862 Function Scan on generate_series g
1866 Sort Key: ((d.d + g.i))
1868 Sort Key: ((d.d + g.i))
1869 -> Function Scan on generate_series d
1871 Sort Key: ((d_1.d + g.i))
1872 -> Function Scan on generate_series d_1
1876 ARRAY(SELECT f.i FROM (
1877 (SELECT d + g.i FROM generate_series(4, 30, 3) d ORDER BY 1)
1879 (SELECT d + g.i FROM generate_series(0, 30, 5) d ORDER BY 1)
1881 ORDER BY f.i LIMIT 10)
1882 FROM generate_series(1, 3) g(i);
1884 ------------------------------
1885 {1,5,6,8,11,11,14,16,17,20}
1886 {2,6,7,9,12,12,15,17,18,21}
1887 {3,7,8,10,13,13,16,18,19,22}
1890 reset enable_seqscan;
1891 reset enable_indexscan;
1892 reset enable_bitmapscan;
1894 -- Check handling of MULTIEXPR SubPlans in inherited updates
1896 create table inhpar(f1 int, f2 name);
1897 create table inhcld(f2 name, f1 int);
1898 alter table inhcld inherit inhpar;
1899 insert into inhpar select x, x::text from generate_series(1,5) x;
1900 insert into inhcld select x::text, x from generate_series(6,10) x;
1901 explain (verbose, costs off)
1902 update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1);
1904 --------------------------------------------------------------------------------------------
1905 Update on public.inhpar i
1906 Update on public.inhpar i_1
1907 Update on public.inhcld i_2
1909 Output: (SubPlan 1).col1, (SubPlan 1).col2, (rescan SubPlan 1), i.tableoid, i.ctid
1911 -> Seq Scan on public.inhpar i_1
1912 Output: i_1.f1, i_1.f2, i_1.tableoid, i_1.ctid
1913 -> Seq Scan on public.inhcld i_2
1914 Output: i_2.f1, i_2.f2, i_2.tableoid, i_2.ctid
1917 Output: (i.f1), (((i.f2)::text || '-'::text))
1918 -> Seq Scan on public.int4_tbl
1919 Output: i.f1, ((i.f2)::text || '-'::text)
1922 update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1);
1923 select * from inhpar;
1938 drop table inhpar cascade;
1939 NOTICE: drop cascades to table inhcld
1941 -- And the same for partitioned cases
1943 create table inhpar(f1 int primary key, f2 name) partition by range (f1);
1944 create table inhcld1(f2 name, f1 int primary key);
1945 create table inhcld2(f1 int primary key, f2 name);
1946 alter table inhpar attach partition inhcld1 for values from (1) to (5);
1947 alter table inhpar attach partition inhcld2 for values from (5) to (100);
1948 insert into inhpar select x, x::text from generate_series(1,10) x;
1949 explain (verbose, costs off)
1950 update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1);
1952 ------------------------------------------------------------------------------------------------------
1953 Update on public.inhpar i
1954 Update on public.inhcld1 i_1
1955 Update on public.inhcld2 i_2
1957 -> Seq Scan on public.inhcld1 i_1
1958 Output: (SubPlan 1).col1, (SubPlan 1).col2, (rescan SubPlan 1), i_1.tableoid, i_1.ctid
1961 Output: (i_1.f1), (((i_1.f2)::text || '-'::text))
1962 -> Seq Scan on public.int4_tbl
1963 Output: i_1.f1, ((i_1.f2)::text || '-'::text)
1964 -> Seq Scan on public.inhcld2 i_2
1965 Output: (SubPlan 1).col1, (SubPlan 1).col2, (rescan SubPlan 1), i_2.tableoid, i_2.ctid
1968 update inhpar i set (f1, f2) = (select i.f1, i.f2 || '-' from int4_tbl limit 1);
1969 select * from inhpar;
1984 -- Also check ON CONFLICT
1985 insert into inhpar as i values (3), (7) on conflict (f1)
1986 do update set (f1, f2) = (select i.f1, i.f2 || '+');
1987 select * from inhpar order by f1; -- tuple order might be unstable here
2002 drop table inhpar cascade;
2004 -- Check handling of a constant-null CHECK constraint
2006 create table cnullparent (f1 int);
2007 create table cnullchild (check (f1 = 1 or f1 = null)) inherits(cnullparent);
2008 insert into cnullchild values(1);
2009 insert into cnullchild values(2);
2010 insert into cnullchild values(null);
2011 select * from cnullparent;
2019 select * from cnullparent where f1 = 2;
2025 drop table cnullparent cascade;
2026 NOTICE: drop cascades to table cnullchild
2028 -- Mixed ownership inheritance tree
2030 create role regress_alice;
2031 create role regress_bob;
2032 grant all on schema public to regress_alice, regress_bob;
2033 grant regress_alice to regress_bob;
2034 set session authorization regress_alice;
2035 create table inh_parent (a int not null);
2036 set session authorization regress_bob;
2037 create table inh_child () inherits (inh_parent);
2038 set session authorization regress_alice;
2039 -- alice can't do this: she doesn't own inh_child
2040 alter table inh_parent alter a drop not null;
2041 ERROR: must be owner of table inh_child
2042 set session authorization regress_bob;
2043 alter table inh_parent alter a drop not null;
2044 reset session authorization;
2045 drop table inh_parent, inh_child;
2046 revoke all on schema public from regress_alice, regress_bob;
2047 drop role regress_alice, regress_bob;
2049 -- Check use of temporary tables with inheritance trees
2051 create table inh_perm_parent (a1 int);
2052 create temp table inh_temp_parent (a1 int);
2053 create temp table inh_temp_child () inherits (inh_perm_parent); -- ok
2054 create table inh_perm_child () inherits (inh_temp_parent); -- error
2055 ERROR: cannot inherit from temporary relation "inh_temp_parent"
2056 create temp table inh_temp_child_2 () inherits (inh_temp_parent); -- ok
2057 insert into inh_perm_parent values (1);
2058 insert into inh_temp_parent values (2);
2059 insert into inh_temp_child values (3);
2060 insert into inh_temp_child_2 values (4);
2061 select tableoid::regclass, a1 from inh_perm_parent;
2063 -----------------+----
2068 select tableoid::regclass, a1 from inh_temp_parent;
2070 ------------------+----
2072 inh_temp_child_2 | 4
2075 drop table inh_perm_parent cascade;
2076 NOTICE: drop cascades to table inh_temp_child
2077 drop table inh_temp_parent cascade;
2078 NOTICE: drop cascades to table inh_temp_child_2
2080 -- Check that constraint exclusion works correctly with partitions using
2081 -- implicit constraints generated from the partition bound information.
2083 create table list_parted (
2085 ) partition by list (a);
2086 create table part_ab_cd partition of list_parted for values in ('ab', 'cd');
2087 create table part_ef_gh partition of list_parted for values in ('ef', 'gh');
2088 create table part_null_xy partition of list_parted for values in (null, 'xy');
2089 explain (costs off) select * from list_parted;
2091 ----------------------------------------------
2093 -> Seq Scan on part_ab_cd list_parted_1
2094 -> Seq Scan on part_ef_gh list_parted_2
2095 -> Seq Scan on part_null_xy list_parted_3
2098 explain (costs off) select * from list_parted where a is null;
2100 --------------------------------------
2101 Seq Scan on part_null_xy list_parted
2105 explain (costs off) select * from list_parted where a is not null;
2107 ----------------------------------------------
2109 -> Seq Scan on part_ab_cd list_parted_1
2110 Filter: (a IS NOT NULL)
2111 -> Seq Scan on part_ef_gh list_parted_2
2112 Filter: (a IS NOT NULL)
2113 -> Seq Scan on part_null_xy list_parted_3
2114 Filter: (a IS NOT NULL)
2117 explain (costs off) select * from list_parted where a in ('ab', 'cd', 'ef');
2119 ----------------------------------------------------------
2121 -> Seq Scan on part_ab_cd list_parted_1
2122 Filter: ((a)::text = ANY ('{ab,cd,ef}'::text[]))
2123 -> Seq Scan on part_ef_gh list_parted_2
2124 Filter: ((a)::text = ANY ('{ab,cd,ef}'::text[]))
2127 explain (costs off) select * from list_parted where a = 'ab' or a in (null, 'cd');
2129 ---------------------------------------------------------------------------------
2130 Seq Scan on part_ab_cd list_parted
2131 Filter: (((a)::text = 'ab'::text) OR ((a)::text = ANY ('{NULL,cd}'::text[])))
2134 explain (costs off) select * from list_parted where a = 'ab';
2136 ------------------------------------
2137 Seq Scan on part_ab_cd list_parted
2138 Filter: ((a)::text = 'ab'::text)
2141 create table range_list_parted (
2144 ) partition by range (a);
2145 create table part_1_10 partition of range_list_parted for values from (1) to (10) partition by list (b);
2146 create table part_1_10_ab partition of part_1_10 for values in ('ab');
2147 create table part_1_10_cd partition of part_1_10 for values in ('cd');
2148 create table part_10_20 partition of range_list_parted for values from (10) to (20) partition by list (b);
2149 create table part_10_20_ab partition of part_10_20 for values in ('ab');
2150 create table part_10_20_cd partition of part_10_20 for values in ('cd');
2151 create table part_21_30 partition of range_list_parted for values from (21) to (30) partition by list (b);
2152 create table part_21_30_ab partition of part_21_30 for values in ('ab');
2153 create table part_21_30_cd partition of part_21_30 for values in ('cd');
2154 create table part_40_inf partition of range_list_parted for values from (40) to (maxvalue) partition by list (b);
2155 create table part_40_inf_ab partition of part_40_inf for values in ('ab');
2156 create table part_40_inf_cd partition of part_40_inf for values in ('cd');
2157 create table part_40_inf_null partition of part_40_inf for values in (null);
2158 explain (costs off) select * from range_list_parted;
2160 --------------------------------------------------------
2162 -> Seq Scan on part_1_10_ab range_list_parted_1
2163 -> Seq Scan on part_1_10_cd range_list_parted_2
2164 -> Seq Scan on part_10_20_ab range_list_parted_3
2165 -> Seq Scan on part_10_20_cd range_list_parted_4
2166 -> Seq Scan on part_21_30_ab range_list_parted_5
2167 -> Seq Scan on part_21_30_cd range_list_parted_6
2168 -> Seq Scan on part_40_inf_ab range_list_parted_7
2169 -> Seq Scan on part_40_inf_cd range_list_parted_8
2170 -> Seq Scan on part_40_inf_null range_list_parted_9
2173 explain (costs off) select * from range_list_parted where a = 5;
2175 ----------------------------------------------------
2177 -> Seq Scan on part_1_10_ab range_list_parted_1
2179 -> Seq Scan on part_1_10_cd range_list_parted_2
2183 explain (costs off) select * from range_list_parted where b = 'ab';
2185 ------------------------------------------------------
2187 -> Seq Scan on part_1_10_ab range_list_parted_1
2188 Filter: (b = 'ab'::bpchar)
2189 -> Seq Scan on part_10_20_ab range_list_parted_2
2190 Filter: (b = 'ab'::bpchar)
2191 -> Seq Scan on part_21_30_ab range_list_parted_3
2192 Filter: (b = 'ab'::bpchar)
2193 -> Seq Scan on part_40_inf_ab range_list_parted_4
2194 Filter: (b = 'ab'::bpchar)
2197 explain (costs off) select * from range_list_parted where a between 3 and 23 and b in ('ab');
2199 -----------------------------------------------------------------
2201 -> Seq Scan on part_1_10_ab range_list_parted_1
2202 Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
2203 -> Seq Scan on part_10_20_ab range_list_parted_2
2204 Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
2205 -> Seq Scan on part_21_30_ab range_list_parted_3
2206 Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
2209 /* Should select no rows because range partition key cannot be null */
2210 explain (costs off) select * from range_list_parted where a is null;
2212 --------------------------
2214 One-Time Filter: false
2217 /* Should only select rows from the null-accepting partition */
2218 explain (costs off) select * from range_list_parted where b is null;
2220 ------------------------------------------------
2221 Seq Scan on part_40_inf_null range_list_parted
2225 explain (costs off) select * from range_list_parted where a is not null and a < 67;
2227 --------------------------------------------------------
2229 -> Seq Scan on part_1_10_ab range_list_parted_1
2230 Filter: ((a IS NOT NULL) AND (a < 67))
2231 -> Seq Scan on part_1_10_cd range_list_parted_2
2232 Filter: ((a IS NOT NULL) AND (a < 67))
2233 -> Seq Scan on part_10_20_ab range_list_parted_3
2234 Filter: ((a IS NOT NULL) AND (a < 67))
2235 -> Seq Scan on part_10_20_cd range_list_parted_4
2236 Filter: ((a IS NOT NULL) AND (a < 67))
2237 -> Seq Scan on part_21_30_ab range_list_parted_5
2238 Filter: ((a IS NOT NULL) AND (a < 67))
2239 -> Seq Scan on part_21_30_cd range_list_parted_6
2240 Filter: ((a IS NOT NULL) AND (a < 67))
2241 -> Seq Scan on part_40_inf_ab range_list_parted_7
2242 Filter: ((a IS NOT NULL) AND (a < 67))
2243 -> Seq Scan on part_40_inf_cd range_list_parted_8
2244 Filter: ((a IS NOT NULL) AND (a < 67))
2245 -> Seq Scan on part_40_inf_null range_list_parted_9
2246 Filter: ((a IS NOT NULL) AND (a < 67))
2249 explain (costs off) select * from range_list_parted where a >= 30;
2251 --------------------------------------------------------
2253 -> Seq Scan on part_40_inf_ab range_list_parted_1
2255 -> Seq Scan on part_40_inf_cd range_list_parted_2
2257 -> Seq Scan on part_40_inf_null range_list_parted_3
2261 drop table list_parted;
2262 drop table range_list_parted;
2263 -- check that constraint exclusion is able to cope with the partition
2264 -- constraint emitted for multi-column range partitioned tables
2265 create table mcrparted (a int, b int, c int) partition by range (a, abs(b), c);
2266 create table mcrparted_def partition of mcrparted default;
2267 create table mcrparted0 partition of mcrparted for values from (minvalue, minvalue, minvalue) to (1, 1, 1);
2268 create table mcrparted1 partition of mcrparted for values from (1, 1, 1) to (10, 5, 10);
2269 create table mcrparted2 partition of mcrparted for values from (10, 5, 10) to (10, 10, 10);
2270 create table mcrparted3 partition of mcrparted for values from (11, 1, 1) to (20, 10, 10);
2271 create table mcrparted4 partition of mcrparted for values from (20, 10, 10) to (20, 20, 20);
2272 create table mcrparted5 partition of mcrparted for values from (20, 20, 20) to (maxvalue, maxvalue, maxvalue);
2273 explain (costs off) select * from mcrparted where a = 0; -- scans mcrparted0, mcrparted_def
2275 ---------------------------------------------
2277 -> Seq Scan on mcrparted0 mcrparted_1
2279 -> Seq Scan on mcrparted_def mcrparted_2
2283 explain (costs off) select * from mcrparted where a = 10 and abs(b) < 5; -- scans mcrparted1, mcrparted_def
2285 ---------------------------------------------
2287 -> Seq Scan on mcrparted1 mcrparted_1
2288 Filter: ((a = 10) AND (abs(b) < 5))
2289 -> Seq Scan on mcrparted_def mcrparted_2
2290 Filter: ((a = 10) AND (abs(b) < 5))
2293 explain (costs off) select * from mcrparted where a = 10 and abs(b) = 5; -- scans mcrparted1, mcrparted2, mcrparted_def
2295 ---------------------------------------------
2297 -> Seq Scan on mcrparted1 mcrparted_1
2298 Filter: ((a = 10) AND (abs(b) = 5))
2299 -> Seq Scan on mcrparted2 mcrparted_2
2300 Filter: ((a = 10) AND (abs(b) = 5))
2301 -> Seq Scan on mcrparted_def mcrparted_3
2302 Filter: ((a = 10) AND (abs(b) = 5))
2305 explain (costs off) select * from mcrparted where abs(b) = 5; -- scans all partitions
2307 ---------------------------------------------
2309 -> Seq Scan on mcrparted0 mcrparted_1
2310 Filter: (abs(b) = 5)
2311 -> Seq Scan on mcrparted1 mcrparted_2
2312 Filter: (abs(b) = 5)
2313 -> Seq Scan on mcrparted2 mcrparted_3
2314 Filter: (abs(b) = 5)
2315 -> Seq Scan on mcrparted3 mcrparted_4
2316 Filter: (abs(b) = 5)
2317 -> Seq Scan on mcrparted4 mcrparted_5
2318 Filter: (abs(b) = 5)
2319 -> Seq Scan on mcrparted5 mcrparted_6
2320 Filter: (abs(b) = 5)
2321 -> Seq Scan on mcrparted_def mcrparted_7
2322 Filter: (abs(b) = 5)
2325 explain (costs off) select * from mcrparted where a > -1; -- scans all partitions
2327 ---------------------------------------------
2329 -> Seq Scan on mcrparted0 mcrparted_1
2330 Filter: (a > '-1'::integer)
2331 -> Seq Scan on mcrparted1 mcrparted_2
2332 Filter: (a > '-1'::integer)
2333 -> Seq Scan on mcrparted2 mcrparted_3
2334 Filter: (a > '-1'::integer)
2335 -> Seq Scan on mcrparted3 mcrparted_4
2336 Filter: (a > '-1'::integer)
2337 -> Seq Scan on mcrparted4 mcrparted_5
2338 Filter: (a > '-1'::integer)
2339 -> Seq Scan on mcrparted5 mcrparted_6
2340 Filter: (a > '-1'::integer)
2341 -> Seq Scan on mcrparted_def mcrparted_7
2342 Filter: (a > '-1'::integer)
2345 explain (costs off) select * from mcrparted where a = 20 and abs(b) = 10 and c > 10; -- scans mcrparted4
2347 -----------------------------------------------------
2348 Seq Scan on mcrparted4 mcrparted
2349 Filter: ((c > 10) AND (a = 20) AND (abs(b) = 10))
2352 explain (costs off) select * from mcrparted where a = 20 and c > 20; -- scans mcrparted3, mcrparte4, mcrparte5, mcrparted_def
2354 ---------------------------------------------
2356 -> Seq Scan on mcrparted3 mcrparted_1
2357 Filter: ((c > 20) AND (a = 20))
2358 -> Seq Scan on mcrparted4 mcrparted_2
2359 Filter: ((c > 20) AND (a = 20))
2360 -> Seq Scan on mcrparted5 mcrparted_3
2361 Filter: ((c > 20) AND (a = 20))
2362 -> Seq Scan on mcrparted_def mcrparted_4
2363 Filter: ((c > 20) AND (a = 20))
2366 -- check that partitioned table Appends cope with being referenced in
2368 create table parted_minmax (a int, b varchar(16)) partition by range (a);
2369 create table parted_minmax1 partition of parted_minmax for values from (1) to (10);
2370 create index parted_minmax1i on parted_minmax1 (a, b);
2371 insert into parted_minmax values (1,'12345');
2372 explain (costs off) select min(a), max(a) from parted_minmax where b = '12345';
2374 ------------------------------------------------------------------------------------------------
2378 -> Index Only Scan using parted_minmax1i on parted_minmax1 parted_minmax
2379 Index Cond: ((a IS NOT NULL) AND (b = '12345'::text))
2382 -> Index Only Scan Backward using parted_minmax1i on parted_minmax1 parted_minmax_1
2383 Index Cond: ((a IS NOT NULL) AND (b = '12345'::text))
2386 select min(a), max(a) from parted_minmax where b = '12345';
2392 drop table parted_minmax;
2393 -- Test code that uses Append nodes in place of MergeAppend when the
2394 -- partition ordering matches the desired ordering.
2395 create index mcrparted_a_abs_c_idx on mcrparted (a, abs(b), c);
2396 -- MergeAppend must be used when a default partition exists
2397 explain (costs off) select * from mcrparted order by a, abs(b), c;
2399 -------------------------------------------------------------------------------
2401 Sort Key: mcrparted.a, (abs(mcrparted.b)), mcrparted.c
2402 -> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
2403 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
2404 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
2405 -> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
2406 -> Index Scan using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_5
2407 -> Index Scan using mcrparted5_a_abs_c_idx on mcrparted5 mcrparted_6
2408 -> Index Scan using mcrparted_def_a_abs_c_idx on mcrparted_def mcrparted_7
2411 drop table mcrparted_def;
2412 -- Append is used for a RANGE partitioned table with no default
2413 -- and no subpartitions
2414 explain (costs off) select * from mcrparted order by a, abs(b), c;
2416 -------------------------------------------------------------------------
2418 -> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
2419 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
2420 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
2421 -> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
2422 -> Index Scan using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_5
2423 -> Index Scan using mcrparted5_a_abs_c_idx on mcrparted5 mcrparted_6
2426 -- Append is used with subpaths in reverse order with backwards index scans
2427 explain (costs off) select * from mcrparted order by a desc, abs(b) desc, c desc;
2429 ----------------------------------------------------------------------------------
2431 -> Index Scan Backward using mcrparted5_a_abs_c_idx on mcrparted5 mcrparted_6
2432 -> Index Scan Backward using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_5
2433 -> Index Scan Backward using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
2434 -> Index Scan Backward using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
2435 -> Index Scan Backward using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
2436 -> Index Scan Backward using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
2439 -- check that Append plan is used containing a MergeAppend for sub-partitions
2440 -- that are unordered.
2441 drop table mcrparted5;
2442 create table mcrparted5 partition of mcrparted for values from (20, 20, 20) to (maxvalue, maxvalue, maxvalue) partition by list (a);
2443 create table mcrparted5a partition of mcrparted5 for values in(20);
2444 create table mcrparted5_def partition of mcrparted5 default;
2445 explain (costs off) select * from mcrparted order by a, abs(b), c;
2447 ---------------------------------------------------------------------------------------
2449 -> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
2450 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
2451 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
2452 -> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
2453 -> Index Scan using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_5
2455 Sort Key: mcrparted_7.a, (abs(mcrparted_7.b)), mcrparted_7.c
2456 -> Index Scan using mcrparted5a_a_abs_c_idx on mcrparted5a mcrparted_7
2457 -> Index Scan using mcrparted5_def_a_abs_c_idx on mcrparted5_def mcrparted_8
2460 drop table mcrparted5_def;
2461 -- check that an Append plan is used and the sub-partitions are flattened
2462 -- into the main Append when the sub-partition is unordered but contains
2463 -- just a single sub-partition.
2464 explain (costs off) select a, abs(b) from mcrparted order by a, abs(b), c;
2466 ---------------------------------------------------------------------------
2468 -> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
2469 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
2470 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
2471 -> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
2472 -> Index Scan using mcrparted4_a_abs_c_idx on mcrparted4 mcrparted_5
2473 -> Index Scan using mcrparted5a_a_abs_c_idx on mcrparted5a mcrparted_6
2476 -- check that Append is used when the sub-partitioned tables are pruned
2478 explain (costs off) select * from mcrparted where a < 20 order by a, abs(b), c;
2480 -------------------------------------------------------------------------
2482 -> Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
2483 Index Cond: (a < 20)
2484 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
2485 Index Cond: (a < 20)
2486 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
2487 Index Cond: (a < 20)
2488 -> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
2489 Index Cond: (a < 20)
2492 set enable_bitmapscan to off;
2493 set enable_sort to off;
2494 create table mclparted (a int) partition by list(a);
2495 create table mclparted1 partition of mclparted for values in(1);
2496 create table mclparted2 partition of mclparted for values in(2);
2497 create index on mclparted (a);
2498 -- Ensure an Append is used for a list partition with an order by.
2499 explain (costs off) select * from mclparted order by a;
2501 ------------------------------------------------------------------------
2503 -> Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_1
2504 -> Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_2
2507 -- Ensure a MergeAppend is used when a partition exists with interleaved
2508 -- datums in the partition bound.
2509 create table mclparted3_5 partition of mclparted for values in(3,5);
2510 create table mclparted4 partition of mclparted for values in(4);
2511 explain (costs off) select * from mclparted order by a;
2513 ----------------------------------------------------------------------------
2515 Sort Key: mclparted.a
2516 -> Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_1
2517 -> Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_2
2518 -> Index Only Scan using mclparted3_5_a_idx on mclparted3_5 mclparted_3
2519 -> Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_4
2522 explain (costs off) select * from mclparted where a in(3,4,5) order by a;
2524 ----------------------------------------------------------------------------
2526 Sort Key: mclparted.a
2527 -> Index Only Scan using mclparted3_5_a_idx on mclparted3_5 mclparted_1
2528 Index Cond: (a = ANY ('{3,4,5}'::integer[]))
2529 -> Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_2
2530 Index Cond: (a = ANY ('{3,4,5}'::integer[]))
2533 -- Introduce a NULL and DEFAULT partition so we can test more complex cases
2534 create table mclparted_null partition of mclparted for values in(null);
2535 create table mclparted_def partition of mclparted default;
2536 -- Append can be used providing we don't scan the interleaved partition
2537 explain (costs off) select * from mclparted where a in(1,2,4) order by a;
2539 ------------------------------------------------------------------------
2541 -> Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_1
2542 Index Cond: (a = ANY ('{1,2,4}'::integer[]))
2543 -> Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_2
2544 Index Cond: (a = ANY ('{1,2,4}'::integer[]))
2545 -> Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_3
2546 Index Cond: (a = ANY ('{1,2,4}'::integer[]))
2549 explain (costs off) select * from mclparted where a in(1,2,4) or a is null order by a;
2551 --------------------------------------------------------------------------------
2553 -> Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_1
2554 Filter: ((a = ANY ('{1,2,4}'::integer[])) OR (a IS NULL))
2555 -> Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_2
2556 Filter: ((a = ANY ('{1,2,4}'::integer[])) OR (a IS NULL))
2557 -> Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_3
2558 Filter: ((a = ANY ('{1,2,4}'::integer[])) OR (a IS NULL))
2559 -> Index Only Scan using mclparted_null_a_idx on mclparted_null mclparted_4
2560 Filter: ((a = ANY ('{1,2,4}'::integer[])) OR (a IS NULL))
2563 -- Test a more complex case where the NULL partition allows some other value
2564 drop table mclparted_null;
2565 create table mclparted_0_null partition of mclparted for values in(0,null);
2566 -- Ensure MergeAppend is used since 0 and NULLs are in the same partition.
2567 explain (costs off) select * from mclparted where a in(1,2,4) or a is null order by a;
2569 ------------------------------------------------------------------------------------
2571 Sort Key: mclparted.a
2572 -> Index Only Scan using mclparted_0_null_a_idx on mclparted_0_null mclparted_1
2573 Filter: ((a = ANY ('{1,2,4}'::integer[])) OR (a IS NULL))
2574 -> Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_2
2575 Filter: ((a = ANY ('{1,2,4}'::integer[])) OR (a IS NULL))
2576 -> Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_3
2577 Filter: ((a = ANY ('{1,2,4}'::integer[])) OR (a IS NULL))
2578 -> Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_4
2579 Filter: ((a = ANY ('{1,2,4}'::integer[])) OR (a IS NULL))
2582 explain (costs off) select * from mclparted where a in(0,1,2,4) order by a;
2584 ------------------------------------------------------------------------------------
2586 Sort Key: mclparted.a
2587 -> Index Only Scan using mclparted_0_null_a_idx on mclparted_0_null mclparted_1
2588 Index Cond: (a = ANY ('{0,1,2,4}'::integer[]))
2589 -> Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_2
2590 Index Cond: (a = ANY ('{0,1,2,4}'::integer[]))
2591 -> Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_3
2592 Index Cond: (a = ANY ('{0,1,2,4}'::integer[]))
2593 -> Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_4
2594 Index Cond: (a = ANY ('{0,1,2,4}'::integer[]))
2597 -- Ensure Append is used when the null partition is pruned
2598 explain (costs off) select * from mclparted where a in(1,2,4) order by a;
2600 ------------------------------------------------------------------------
2602 -> Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_1
2603 Index Cond: (a = ANY ('{1,2,4}'::integer[]))
2604 -> Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_2
2605 Index Cond: (a = ANY ('{1,2,4}'::integer[]))
2606 -> Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_3
2607 Index Cond: (a = ANY ('{1,2,4}'::integer[]))
2610 -- Ensure MergeAppend is used when the default partition is not pruned
2611 explain (costs off) select * from mclparted where a in(1,2,4,100) order by a;
2613 ------------------------------------------------------------------------------
2615 Sort Key: mclparted.a
2616 -> Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_1
2617 Index Cond: (a = ANY ('{1,2,4,100}'::integer[]))
2618 -> Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_2
2619 Index Cond: (a = ANY ('{1,2,4,100}'::integer[]))
2620 -> Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_3
2621 Index Cond: (a = ANY ('{1,2,4,100}'::integer[]))
2622 -> Index Only Scan using mclparted_def_a_idx on mclparted_def mclparted_4
2623 Index Cond: (a = ANY ('{1,2,4,100}'::integer[]))
2626 drop table mclparted;
2628 reset enable_bitmapscan;
2629 -- Ensure subplans which don't have a path with the correct pathkeys get
2630 -- sorted correctly.
2631 drop index mcrparted_a_abs_c_idx;
2632 create index on mcrparted1 (a, abs(b), c);
2633 create index on mcrparted2 (a, abs(b), c);
2634 create index on mcrparted3 (a, abs(b), c);
2635 create index on mcrparted4 (a, abs(b), c);
2636 explain (costs off) select * from mcrparted where a < 20 order by a, abs(b), c limit 1;
2638 -------------------------------------------------------------------------------
2642 Sort Key: mcrparted_1.a, (abs(mcrparted_1.b)), mcrparted_1.c
2643 -> Seq Scan on mcrparted0 mcrparted_1
2645 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
2646 Index Cond: (a < 20)
2647 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
2648 Index Cond: (a < 20)
2649 -> Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
2650 Index Cond: (a < 20)
2653 set enable_bitmapscan = 0;
2654 -- Ensure Append node can be used when the partition is ordered by some
2655 -- pathkeys which were deemed redundant.
2656 explain (costs off) select * from mcrparted where a = 10 order by a, abs(b), c;
2658 -------------------------------------------------------------------------
2660 -> Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_1
2661 Index Cond: (a = 10)
2662 -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_2
2663 Index Cond: (a = 10)
2666 reset enable_bitmapscan;
2667 drop table mcrparted;
2668 -- Ensure LIST partitions allow an Append to be used instead of a MergeAppend
2669 create table bool_lp (b bool) partition by list(b);
2670 create table bool_lp_true partition of bool_lp for values in(true);
2671 create table bool_lp_false partition of bool_lp for values in(false);
2672 create index on bool_lp (b);
2673 explain (costs off) select * from bool_lp order by b;
2675 ----------------------------------------------------------------------------
2677 -> Index Only Scan using bool_lp_false_b_idx on bool_lp_false bool_lp_1
2678 -> Index Only Scan using bool_lp_true_b_idx on bool_lp_true bool_lp_2
2682 -- Ensure const bool quals can be properly detected as redundant
2683 create table bool_rp (b bool, a int) partition by range(b,a);
2684 create table bool_rp_false_1k partition of bool_rp for values from (false,0) to (false,1000);
2685 create table bool_rp_true_1k partition of bool_rp for values from (true,0) to (true,1000);
2686 create table bool_rp_false_2k partition of bool_rp for values from (false,1000) to (false,2000);
2687 create table bool_rp_true_2k partition of bool_rp for values from (true,1000) to (true,2000);
2688 create index on bool_rp (b,a);
2689 explain (costs off) select * from bool_rp where b = true order by b,a;
2691 ----------------------------------------------------------------------------------
2693 -> Index Only Scan using bool_rp_true_1k_b_a_idx on bool_rp_true_1k bool_rp_1
2694 Index Cond: (b = true)
2695 -> Index Only Scan using bool_rp_true_2k_b_a_idx on bool_rp_true_2k bool_rp_2
2696 Index Cond: (b = true)
2699 explain (costs off) select * from bool_rp where b = false order by b,a;
2701 ------------------------------------------------------------------------------------
2703 -> Index Only Scan using bool_rp_false_1k_b_a_idx on bool_rp_false_1k bool_rp_1
2704 Index Cond: (b = false)
2705 -> Index Only Scan using bool_rp_false_2k_b_a_idx on bool_rp_false_2k bool_rp_2
2706 Index Cond: (b = false)
2709 explain (costs off) select * from bool_rp where b = true order by a;
2711 ----------------------------------------------------------------------------------
2713 -> Index Only Scan using bool_rp_true_1k_b_a_idx on bool_rp_true_1k bool_rp_1
2714 Index Cond: (b = true)
2715 -> Index Only Scan using bool_rp_true_2k_b_a_idx on bool_rp_true_2k bool_rp_2
2716 Index Cond: (b = true)
2719 explain (costs off) select * from bool_rp where b = false order by a;
2721 ------------------------------------------------------------------------------------
2723 -> Index Only Scan using bool_rp_false_1k_b_a_idx on bool_rp_false_1k bool_rp_1
2724 Index Cond: (b = false)
2725 -> Index Only Scan using bool_rp_false_2k_b_a_idx on bool_rp_false_2k bool_rp_2
2726 Index Cond: (b = false)
2730 -- Ensure an Append scan is chosen when the partition order is a subset of
2731 -- the required order.
2732 create table range_parted (a int, b int, c int) partition by range(a, b);
2733 create table range_parted1 partition of range_parted for values from (0,0) to (10,10);
2734 create table range_parted2 partition of range_parted for values from (10,10) to (20,20);
2735 create index on range_parted (a,b,c);
2736 explain (costs off) select * from range_parted order by a,b,c;
2738 -------------------------------------------------------------------------------------
2740 -> Index Only Scan using range_parted1_a_b_c_idx on range_parted1 range_parted_1
2741 -> Index Only Scan using range_parted2_a_b_c_idx on range_parted2 range_parted_2
2744 explain (costs off) select * from range_parted order by a desc,b desc,c desc;
2746 ----------------------------------------------------------------------------------------------
2748 -> Index Only Scan Backward using range_parted2_a_b_c_idx on range_parted2 range_parted_2
2749 -> Index Only Scan Backward using range_parted1_a_b_c_idx on range_parted1 range_parted_1
2752 drop table range_parted;
2753 -- Check that we allow access to a child table's statistics when the user
2754 -- has permissions only for the parent table.
2755 create table permtest_parent (a int, b text, c text) partition by list (a);
2756 create table permtest_child (b text, c text, a int) partition by list (b);
2757 create table permtest_grandchild (c text, b text, a int);
2758 alter table permtest_child attach partition permtest_grandchild for values in ('a');
2759 alter table permtest_parent attach partition permtest_child for values in (1);
2760 create index on permtest_parent (left(c, 3));
2761 insert into permtest_parent
2762 select 1, 'a', left(fipshash(i::text), 5) from generate_series(0, 100) i;
2763 analyze permtest_parent;
2764 create role regress_no_child_access;
2765 revoke all on permtest_grandchild from regress_no_child_access;
2766 grant select on permtest_parent to regress_no_child_access;
2767 set session authorization regress_no_child_access;
2768 -- without stats access, these queries would produce hash join plans:
2770 select * from permtest_parent p1 inner join permtest_parent p2
2771 on p1.a = p2.a and p1.c ~ 'a1$';
2773 ------------------------------------------
2775 Join Filter: (p1.a = p2.a)
2776 -> Seq Scan on permtest_grandchild p1
2777 Filter: (c ~ 'a1$'::text)
2778 -> Seq Scan on permtest_grandchild p2
2782 select * from permtest_parent p1 inner join permtest_parent p2
2783 on p1.a = p2.a and left(p1.c, 3) ~ 'a1$';
2785 ----------------------------------------------
2787 Join Filter: (p1.a = p2.a)
2788 -> Seq Scan on permtest_grandchild p1
2789 Filter: ("left"(c, 3) ~ 'a1$'::text)
2790 -> Seq Scan on permtest_grandchild p2
2793 reset session authorization;
2794 revoke all on permtest_parent from regress_no_child_access;
2795 grant select(a,c) on permtest_parent to regress_no_child_access;
2796 set session authorization regress_no_child_access;
2798 select p2.a, p1.c from permtest_parent p1 inner join permtest_parent p2
2799 on p1.a = p2.a and p1.c ~ 'a1$';
2801 ------------------------------------------
2803 Join Filter: (p1.a = p2.a)
2804 -> Seq Scan on permtest_grandchild p1
2805 Filter: (c ~ 'a1$'::text)
2806 -> Seq Scan on permtest_grandchild p2
2809 -- we will not have access to the expression index's stats here:
2811 select p2.a, p1.c from permtest_parent p1 inner join permtest_parent p2
2812 on p1.a = p2.a and left(p1.c, 3) ~ 'a1$';
2814 ----------------------------------------------------
2816 Hash Cond: (p2.a = p1.a)
2817 -> Seq Scan on permtest_grandchild p2
2819 -> Seq Scan on permtest_grandchild p1
2820 Filter: ("left"(c, 3) ~ 'a1$'::text)
2823 reset session authorization;
2824 revoke all on permtest_parent from regress_no_child_access;
2825 drop role regress_no_child_access;
2826 drop table permtest_parent;
2827 -- Verify that constraint errors across partition root / child are
2828 -- handled correctly (Bug #16293)
2829 CREATE TABLE errtst_parent (
2830 partid int not null,
2831 shdata int not null,
2832 data int NOT NULL DEFAULT 0,
2833 CONSTRAINT shdata_small CHECK(shdata < 3)
2834 ) PARTITION BY RANGE (partid);
2835 -- fast defaults lead to attribute mapping being used in one
2836 -- direction, but not the other
2837 CREATE TABLE errtst_child_fastdef (
2838 partid int not null,
2839 shdata int not null,
2840 CONSTRAINT shdata_small CHECK(shdata < 3)
2842 -- no remapping in either direction necessary
2843 CREATE TABLE errtst_child_plaindef (
2844 partid int not null,
2845 shdata int not null,
2846 data int NOT NULL DEFAULT 0,
2847 CONSTRAINT shdata_small CHECK(shdata < 3),
2850 -- remapping in both direction
2851 CREATE TABLE errtst_child_reorder (
2852 data int NOT NULL DEFAULT 0,
2853 shdata int not null,
2854 partid int not null,
2855 CONSTRAINT shdata_small CHECK(shdata < 3),
2858 ALTER TABLE errtst_child_fastdef ADD COLUMN data int NOT NULL DEFAULT 0;
2859 ALTER TABLE errtst_child_fastdef ADD CONSTRAINT errtest_child_fastdef_data_check CHECK (data < 10);
2860 ALTER TABLE errtst_parent ATTACH PARTITION errtst_child_fastdef FOR VALUES FROM (0) TO (10);
2861 ALTER TABLE errtst_parent ATTACH PARTITION errtst_child_plaindef FOR VALUES FROM (10) TO (20);
2862 ALTER TABLE errtst_parent ATTACH PARTITION errtst_child_reorder FOR VALUES FROM (20) TO (30);
2863 -- insert without child check constraint error
2864 INSERT INTO errtst_parent(partid, shdata, data) VALUES ( '0', '1', '5');
2865 INSERT INTO errtst_parent(partid, shdata, data) VALUES ('10', '1', '5');
2866 INSERT INTO errtst_parent(partid, shdata, data) VALUES ('20', '1', '5');
2867 -- insert with child check constraint error
2868 INSERT INTO errtst_parent(partid, shdata, data) VALUES ( '0', '1', '10');
2869 ERROR: new row for relation "errtst_child_fastdef" violates check constraint "errtest_child_fastdef_data_check"
2870 DETAIL: Failing row contains (0, 1, 10).
2871 INSERT INTO errtst_parent(partid, shdata, data) VALUES ('10', '1', '10');
2872 ERROR: new row for relation "errtst_child_plaindef" violates check constraint "errtst_child_plaindef_data_check"
2873 DETAIL: Failing row contains (10, 1, 10).
2874 INSERT INTO errtst_parent(partid, shdata, data) VALUES ('20', '1', '10');
2875 ERROR: new row for relation "errtst_child_reorder" violates check constraint "errtst_child_reorder_data_check"
2876 DETAIL: Failing row contains (20, 1, 10).
2877 -- insert with child not null constraint error
2878 INSERT INTO errtst_parent(partid, shdata, data) VALUES ( '0', '1', NULL);
2879 ERROR: null value in column "data" of relation "errtst_child_fastdef" violates not-null constraint
2880 DETAIL: Failing row contains (0, 1, null).
2881 INSERT INTO errtst_parent(partid, shdata, data) VALUES ('10', '1', NULL);
2882 ERROR: null value in column "data" of relation "errtst_child_plaindef" violates not-null constraint
2883 DETAIL: Failing row contains (10, 1, null).
2884 INSERT INTO errtst_parent(partid, shdata, data) VALUES ('20', '1', NULL);
2885 ERROR: null value in column "data" of relation "errtst_child_reorder" violates not-null constraint
2886 DETAIL: Failing row contains (20, 1, null).
2887 -- insert with shared check constraint error
2888 INSERT INTO errtst_parent(partid, shdata, data) VALUES ( '0', '5', '5');
2889 ERROR: new row for relation "errtst_child_fastdef" violates check constraint "shdata_small"
2890 DETAIL: Failing row contains (0, 5, 5).
2891 INSERT INTO errtst_parent(partid, shdata, data) VALUES ('10', '5', '5');
2892 ERROR: new row for relation "errtst_child_plaindef" violates check constraint "shdata_small"
2893 DETAIL: Failing row contains (10, 5, 5).
2894 INSERT INTO errtst_parent(partid, shdata, data) VALUES ('20', '5', '5');
2895 ERROR: new row for relation "errtst_child_reorder" violates check constraint "shdata_small"
2896 DETAIL: Failing row contains (20, 5, 5).
2897 -- within partition update without child check constraint violation
2899 UPDATE errtst_parent SET data = data + 1 WHERE partid = 0;
2900 UPDATE errtst_parent SET data = data + 1 WHERE partid = 10;
2901 UPDATE errtst_parent SET data = data + 1 WHERE partid = 20;
2903 -- within partition update with child check constraint violation
2904 UPDATE errtst_parent SET data = data + 10 WHERE partid = 0;
2905 ERROR: new row for relation "errtst_child_fastdef" violates check constraint "errtest_child_fastdef_data_check"
2906 DETAIL: Failing row contains (0, 1, 15).
2907 UPDATE errtst_parent SET data = data + 10 WHERE partid = 10;
2908 ERROR: new row for relation "errtst_child_plaindef" violates check constraint "errtst_child_plaindef_data_check"
2909 DETAIL: Failing row contains (10, 1, 15).
2910 UPDATE errtst_parent SET data = data + 10 WHERE partid = 20;
2911 ERROR: new row for relation "errtst_child_reorder" violates check constraint "errtst_child_reorder_data_check"
2912 DETAIL: Failing row contains (20, 1, 15).
2913 -- direct leaf partition update, without partition id violation
2915 UPDATE errtst_child_fastdef SET partid = 1 WHERE partid = 0;
2916 UPDATE errtst_child_plaindef SET partid = 11 WHERE partid = 10;
2917 UPDATE errtst_child_reorder SET partid = 21 WHERE partid = 20;
2919 -- direct leaf partition update, with partition id violation
2920 UPDATE errtst_child_fastdef SET partid = partid + 10 WHERE partid = 0;
2921 ERROR: new row for relation "errtst_child_fastdef" violates partition constraint
2922 DETAIL: Failing row contains (10, 1, 5).
2923 UPDATE errtst_child_plaindef SET partid = partid + 10 WHERE partid = 10;
2924 ERROR: new row for relation "errtst_child_plaindef" violates partition constraint
2925 DETAIL: Failing row contains (20, 1, 5).
2926 UPDATE errtst_child_reorder SET partid = partid + 10 WHERE partid = 20;
2927 ERROR: new row for relation "errtst_child_reorder" violates partition constraint
2928 DETAIL: Failing row contains (5, 1, 30).
2929 -- partition move, without child check constraint violation
2931 UPDATE errtst_parent SET partid = 10, data = data + 1 WHERE partid = 0;
2932 UPDATE errtst_parent SET partid = 20, data = data + 1 WHERE partid = 10;
2933 UPDATE errtst_parent SET partid = 0, data = data + 1 WHERE partid = 20;
2935 -- partition move, with child check constraint violation
2936 UPDATE errtst_parent SET partid = 10, data = data + 10 WHERE partid = 0;
2937 ERROR: new row for relation "errtst_child_plaindef" violates check constraint "errtst_child_plaindef_data_check"
2938 DETAIL: Failing row contains (10, 1, 15).
2939 UPDATE errtst_parent SET partid = 20, data = data + 10 WHERE partid = 10;
2940 ERROR: new row for relation "errtst_child_reorder" violates check constraint "errtst_child_reorder_data_check"
2941 DETAIL: Failing row contains (20, 1, 15).
2942 UPDATE errtst_parent SET partid = 0, data = data + 10 WHERE partid = 20;
2943 ERROR: new row for relation "errtst_child_fastdef" violates check constraint "errtest_child_fastdef_data_check"
2944 DETAIL: Failing row contains (0, 1, 15).
2945 -- partition move, without target partition
2946 UPDATE errtst_parent SET partid = 30, data = data + 10 WHERE partid = 20;
2947 ERROR: no partition of relation "errtst_parent" found for row
2948 DETAIL: Partition key of the failing row contains (partid) = (30).
2949 DROP TABLE errtst_parent;