Fix nbtree "deduce NOT NULL" scan key comment.
[pgsql.git] / contrib / amcheck / sql / check_btree.sql
blob68bd71b064fc03db25419ff1fc3c215114212b0e
1 CREATE TABLE bttest_a(id int8);
2 CREATE TABLE bttest_b(id int8);
3 CREATE TABLE bttest_multi(id int8, data int8);
4 CREATE TABLE delete_test_table (a bigint, b bigint, c bigint, d bigint);
6 -- Stabalize tests
7 ALTER TABLE bttest_a SET (autovacuum_enabled = false);
8 ALTER TABLE bttest_b SET (autovacuum_enabled = false);
9 ALTER TABLE bttest_multi SET (autovacuum_enabled = false);
10 ALTER TABLE delete_test_table SET (autovacuum_enabled = false);
12 INSERT INTO bttest_a SELECT * FROM generate_series(1, 100000);
13 INSERT INTO bttest_b SELECT * FROM generate_series(100000, 1, -1);
14 INSERT INTO bttest_multi SELECT i, i%2  FROM generate_series(1, 100000) as i;
16 CREATE INDEX bttest_a_idx ON bttest_a USING btree (id) WITH (deduplicate_items = ON);
17 CREATE INDEX bttest_b_idx ON bttest_b USING btree (id);
18 CREATE UNIQUE INDEX bttest_multi_idx ON bttest_multi
19 USING btree (id) INCLUDE (data);
21 CREATE ROLE regress_bttest_role;
23 -- verify permissions are checked (error due to function not callable)
24 SET ROLE regress_bttest_role;
25 SELECT bt_index_check('bttest_a_idx'::regclass);
26 SELECT bt_index_parent_check('bttest_a_idx'::regclass);
27 RESET ROLE;
29 -- we, intentionally, don't check relation permissions - it's useful
30 -- to run this cluster-wide with a restricted account, and as tested
31 -- above explicit permission has to be granted for that.
32 GRANT EXECUTE ON FUNCTION bt_index_check(regclass) TO regress_bttest_role;
33 GRANT EXECUTE ON FUNCTION bt_index_parent_check(regclass) TO regress_bttest_role;
34 GRANT EXECUTE ON FUNCTION bt_index_check(regclass, boolean) TO regress_bttest_role;
35 GRANT EXECUTE ON FUNCTION bt_index_parent_check(regclass, boolean) TO regress_bttest_role;
36 SET ROLE regress_bttest_role;
37 SELECT bt_index_check('bttest_a_idx');
38 SELECT bt_index_parent_check('bttest_a_idx');
39 RESET ROLE;
41 -- verify plain tables are rejected (error)
42 SELECT bt_index_check('bttest_a');
43 SELECT bt_index_parent_check('bttest_a');
45 -- verify non-existing indexes are rejected (error)
46 SELECT bt_index_check(17);
47 SELECT bt_index_parent_check(17);
49 -- verify wrong index types are rejected (error)
50 BEGIN;
51 CREATE INDEX bttest_a_brin_idx ON bttest_a USING brin(id);
52 SELECT bt_index_parent_check('bttest_a_brin_idx');
53 ROLLBACK;
55 -- normal check outside of xact
56 SELECT bt_index_check('bttest_a_idx');
57 -- more expansive tests
58 SELECT bt_index_check('bttest_a_idx', true);
59 SELECT bt_index_parent_check('bttest_b_idx', true);
61 BEGIN;
62 SELECT bt_index_check('bttest_a_idx');
63 SELECT bt_index_parent_check('bttest_b_idx');
64 -- make sure we don't have any leftover locks
65 SELECT * FROM pg_locks
66 WHERE relation = ANY(ARRAY['bttest_a', 'bttest_a_idx', 'bttest_b', 'bttest_b_idx']::regclass[])
67     AND pid = pg_backend_pid();
68 COMMIT;
70 -- Deduplication
71 TRUNCATE bttest_a;
72 INSERT INTO bttest_a SELECT 42 FROM generate_series(1, 2000);
73 SELECT bt_index_check('bttest_a_idx', true);
75 -- normal check outside of xact for index with included columns
76 SELECT bt_index_check('bttest_multi_idx');
77 -- more expansive tests for index with included columns
78 SELECT bt_index_parent_check('bttest_multi_idx', true, true);
80 -- repeat expansive tests for index built using insertions
81 TRUNCATE bttest_multi;
82 INSERT INTO bttest_multi SELECT i, i%2  FROM generate_series(1, 100000) as i;
83 SELECT bt_index_parent_check('bttest_multi_idx', true, true);
86 -- Test for multilevel page deletion/downlink present checks, and rootdescend
87 -- checks
89 INSERT INTO delete_test_table SELECT i, 1, 2, 3 FROM generate_series(1,80000) i;
90 ALTER TABLE delete_test_table ADD PRIMARY KEY (a,b,c,d);
91 -- Delete most entries, and vacuum, deleting internal pages and creating "fast
92 -- root"
93 DELETE FROM delete_test_table WHERE a < 79990;
94 VACUUM delete_test_table;
95 SELECT bt_index_parent_check('delete_test_table_pkey', true);
98 -- BUG #15597: must not assume consistent input toasting state when forming
99 -- tuple.  Bloom filter must fingerprint normalized index tuple representation.
101 CREATE TABLE toast_bug(buggy text);
102 ALTER TABLE toast_bug ALTER COLUMN buggy SET STORAGE extended;
103 CREATE INDEX toasty ON toast_bug(buggy);
105 -- pg_attribute entry for toasty.buggy (the index) will have plain storage:
106 UPDATE pg_attribute SET attstorage = 'p'
107 WHERE attrelid = 'toasty'::regclass AND attname = 'buggy';
109 -- Whereas pg_attribute entry for toast_bug.buggy (the table) still has extended storage:
110 SELECT attstorage FROM pg_attribute
111 WHERE attrelid = 'toast_bug'::regclass AND attname = 'buggy';
113 -- Insert compressible heap tuple (comfortably exceeds TOAST_TUPLE_THRESHOLD):
114 INSERT INTO toast_bug SELECT repeat('a', 2200);
115 -- Should not get false positive report of corruption:
116 SELECT bt_index_check('toasty', true);
119 -- Check that index expressions and predicates are run as the table's owner
121 TRUNCATE bttest_a;
122 INSERT INTO bttest_a SELECT * FROM generate_series(1, 1000);
123 ALTER TABLE bttest_a OWNER TO regress_bttest_role;
124 -- A dummy index function checking current_user
125 CREATE FUNCTION ifun(int8) RETURNS int8 AS $$
126 BEGIN
127         ASSERT current_user = 'regress_bttest_role',
128                 format('ifun(%s) called by %s', $1, current_user);
129         RETURN $1;
130 END;
131 $$ LANGUAGE plpgsql IMMUTABLE;
133 CREATE INDEX bttest_a_expr_idx ON bttest_a ((ifun(id) + ifun(0)))
134         WHERE ifun(id + 10) > ifun(10);
136 SELECT bt_index_check('bttest_a_expr_idx', true);
138 -- UNIQUE constraint check
139 SELECT bt_index_check('bttest_a_idx', heapallindexed => true, checkunique => true);
140 SELECT bt_index_check('bttest_b_idx', heapallindexed => false, checkunique => true);
141 SELECT bt_index_parent_check('bttest_a_idx', heapallindexed => true, rootdescend => true, checkunique => true);
142 SELECT bt_index_parent_check('bttest_b_idx', heapallindexed => true, rootdescend => false, checkunique => true);
144 -- Check that null values in an unique index are not treated as equal
145 CREATE TABLE bttest_unique_nulls (a serial, b int, c int UNIQUE);
146 INSERT INTO bttest_unique_nulls VALUES (generate_series(1, 10000), 2, default);
147 SELECT bt_index_check('bttest_unique_nulls_c_key', heapallindexed => true, checkunique => true);
148 CREATE INDEX on bttest_unique_nulls (b,c);
149 SELECT bt_index_check('bttest_unique_nulls_b_c_idx', heapallindexed => true, checkunique => true);
151 -- Check support of both 1B and 4B header sizes of short varlena datum
152 CREATE TABLE varlena_bug (v text);
153 ALTER TABLE varlena_bug ALTER column v SET storage plain;
154 INSERT INTO varlena_bug VALUES ('x');
155 COPY varlena_bug from stdin;
158 CREATE INDEX varlena_bug_idx on varlena_bug(v);
159 SELECT bt_index_check('varlena_bug_idx', true);
161 -- Also check that we compress varlena values, which were previously stored
162 -- uncompressed in index.
163 INSERT INTO varlena_bug VALUES (repeat('Test', 250));
164 ALTER TABLE varlena_bug ALTER COLUMN v SET STORAGE extended;
165 SELECT bt_index_check('varlena_bug_idx', true);
167 -- cleanup
168 DROP TABLE bttest_a;
169 DROP TABLE bttest_b;
170 DROP TABLE bttest_multi;
171 DROP TABLE delete_test_table;
172 DROP TABLE toast_bug;
173 DROP FUNCTION ifun(int8);
174 DROP TABLE bttest_unique_nulls;
175 DROP OWNED BY regress_bttest_role; -- permissions
176 DROP ROLE regress_bttest_role;
177 DROP TABLE varlena_bug;