mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
Add test cases for indexam operations not currently covered.
That includes VACUUM on GIN, GiST and SP-GiST indexes, and B-tree indexes large enough to cause page deletions in B-tree. Plus some other special cases. After this patch, the regression tests generate all different WAL record types. Not all branches within the redo functions are covered, but it's a step forward.
This commit is contained in:
parent
a016555361
commit
88fc719263
@ -127,3 +127,26 @@ select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
|
||||
RI_FKey_setnull_del
|
||||
(5 rows)
|
||||
|
||||
--
|
||||
-- Test B-tree page deletion. In particular, deleting a non-leaf page.
|
||||
--
|
||||
-- First create a tree that's at least four levels deep. The text inserted
|
||||
-- is long and poorly compressible. That way only a few index tuples fit on
|
||||
-- each page, allowing us to get a tall tree with fewer pages.
|
||||
create table btree_tall_tbl(id int4, t text);
|
||||
create index btree_tall_idx on btree_tall_tbl (id, t) with (fillfactor = 10);
|
||||
insert into btree_tall_tbl
|
||||
select g, g::text || '_' ||
|
||||
(select string_agg(md5(i::text), '_') from generate_series(1, 50) i)
|
||||
from generate_series(1, 100) g;
|
||||
-- Delete most entries, and vacuum. This causes page deletions.
|
||||
delete from btree_tall_tbl where id < 950;
|
||||
vacuum btree_tall_tbl;
|
||||
--
|
||||
-- Test B-tree insertion with a metapage update (XLOG_BTREE_INSERT_META
|
||||
-- WAL record type). This happens when a "fast root" page is split.
|
||||
--
|
||||
-- The vacuum above should've turned the leaf page into a fast root. We just
|
||||
-- need to insert some rows to cause the fast root page to split.
|
||||
insert into btree_tall_tbl (id, t)
|
||||
select g, repeat('x', 100) from generate_series(1, 500) g;
|
||||
|
23
src/test/regress/expected/gin.out
Normal file
23
src/test/regress/expected/gin.out
Normal file
@ -0,0 +1,23 @@
|
||||
--
|
||||
-- Test GIN indexes.
|
||||
--
|
||||
-- There are other tests to test different GIN opclassed. This is for testing
|
||||
-- GIN itself.
|
||||
-- Create and populate a test table with a GIN index.
|
||||
create table gin_test_tbl(i int4[]);
|
||||
create index gin_test_idx on gin_test_tbl using gin (i) with (fastupdate = on);
|
||||
insert into gin_test_tbl select array[1, 2, g] from generate_series(1, 20000) g;
|
||||
insert into gin_test_tbl select array[1, 3, g] from generate_series(1, 1000) g;
|
||||
vacuum gin_test_tbl; -- flush the fastupdate buffers
|
||||
-- Test vacuuming
|
||||
delete from gin_test_tbl where i @> array[2];
|
||||
vacuum gin_test_tbl;
|
||||
-- Disable fastupdate, and do more insertions. With fastupdate enabled, most
|
||||
-- insertions (by flushing the list pages) cause page splits. Without
|
||||
-- fastupdate, we get more churn in the GIN data leaf pages, and exercise the
|
||||
-- recompression codepaths.
|
||||
alter index gin_test_idx set (fastupdate = off);
|
||||
insert into gin_test_tbl select array[1, 2, g] from generate_series(1, 1000) g;
|
||||
insert into gin_test_tbl select array[1, 3, g] from generate_series(1, 1000) g;
|
||||
delete from gin_test_tbl where i @> array[2];
|
||||
vacuum gin_test_tbl;
|
19
src/test/regress/expected/gist.out
Normal file
19
src/test/regress/expected/gist.out
Normal file
@ -0,0 +1,19 @@
|
||||
--
|
||||
-- Test GiST indexes.
|
||||
--
|
||||
-- There are other tests to test different GiST opclasses. This is for
|
||||
-- testing GiST code itself. Vacuuming in particular.
|
||||
create table gist_point_tbl(id int4, p point);
|
||||
create index gist_pointidx on gist_point_tbl using gist(p);
|
||||
-- Insert enough data to create a tree that's a couple of levels deep.
|
||||
insert into gist_point_tbl (id, p)
|
||||
select g, point(g*10, g*10) from generate_series(1, 10000) g;
|
||||
insert into gist_point_tbl (id, p)
|
||||
select g+100000, point(g*10+1, g*10+1) from generate_series(1, 10000) g;
|
||||
-- To test vacuum, delete some entries from all over the index.
|
||||
delete from gist_point_tbl where id % 2 = 1;
|
||||
-- And also delete some concentration of values. (GiST doesn't currently
|
||||
-- attempt to delete pages even when they become empty, but if it did, this
|
||||
-- would exercise it)
|
||||
delete from gist_point_tbl where id < 10000;
|
||||
vacuum gist_point_tbl;
|
39
src/test/regress/expected/spgist.out
Normal file
39
src/test/regress/expected/spgist.out
Normal file
@ -0,0 +1,39 @@
|
||||
--
|
||||
-- Test SP-GiST indexes.
|
||||
--
|
||||
-- There are other tests to test different SP-GiST opclasses. This is for
|
||||
-- testing SP-GiST code itself.
|
||||
create table spgist_point_tbl(id int4, p point);
|
||||
create index spgist_point_idx on spgist_point_tbl using spgist(p);
|
||||
-- Test vacuum-root operation. It gets invoked when the root is also a leaf,
|
||||
-- i.e. the index is very small.
|
||||
insert into spgist_point_tbl (id, p)
|
||||
select g, point(g*10, g*10) from generate_series(1, 10) g;
|
||||
delete from spgist_point_tbl where id < 5;
|
||||
vacuum spgist_point_tbl;
|
||||
-- Insert more data, to make the index a few levels deep.
|
||||
insert into spgist_point_tbl (id, p)
|
||||
select g, point(g*10, g*10) from generate_series(1, 10000) g;
|
||||
insert into spgist_point_tbl (id, p)
|
||||
select g+100000, point(g*10+1, g*10+1) from generate_series(1, 10000) g;
|
||||
-- To test vacuum, delete some entries from all over the index.
|
||||
delete from spgist_point_tbl where id % 2 = 1;
|
||||
-- And also delete some concentration of values. (SP-GiST doesn't currently
|
||||
-- attempt to delete pages even when they become empty, but if it did, this
|
||||
-- would exercise it)
|
||||
delete from spgist_point_tbl where id < 10000;
|
||||
vacuum spgist_point_tbl;
|
||||
-- The point opclass's choose method only uses the spgMatchNode action,
|
||||
-- so the other actions are not tested by the above. Create an index using
|
||||
-- text opclass, which uses the others actions.
|
||||
create table spgist_text_tbl(id int4, t text);
|
||||
create index spgist_text_idx on spgist_text_tbl using spgist(t);
|
||||
insert into spgist_text_tbl (id, t)
|
||||
select g, 'f' || repeat('o', 100) || g from generate_series(1, 10000) g
|
||||
union all
|
||||
select g, 'baaaaaaaaaaaaaar' || g from generate_series(1, 1000) g;
|
||||
-- Do a lot of insertions that have to split an existing node. Hopefully
|
||||
-- one of these will cause the page to run out of space, causing the inner
|
||||
-- tuple to be moved to another page.
|
||||
insert into spgist_text_tbl (id, t)
|
||||
select -g, 'f' || repeat('o', 100-g) || 'surprise' from generate_series(1, 100) g;
|
@ -597,6 +597,7 @@ SELECT user_relns() AS user_relns
|
||||
bt_i4_heap
|
||||
bt_name_heap
|
||||
bt_txt_heap
|
||||
btree_tall_tbl
|
||||
c
|
||||
c_star
|
||||
char_tbl
|
||||
@ -622,6 +623,8 @@ SELECT user_relns() AS user_relns
|
||||
float4_tbl
|
||||
float8_tbl
|
||||
func_index_heap
|
||||
gin_test_tbl
|
||||
gist_point_tbl
|
||||
hash_f8_heap
|
||||
hash_i4_heap
|
||||
hash_name_heap
|
||||
@ -671,6 +674,8 @@ SELECT user_relns() AS user_relns
|
||||
road
|
||||
shighway
|
||||
slow_emp4000
|
||||
spgist_point_tbl
|
||||
spgist_text_tbl
|
||||
street
|
||||
stud_emp
|
||||
student
|
||||
@ -700,7 +705,7 @@ SELECT user_relns() AS user_relns
|
||||
tvvmv
|
||||
varchar_tbl
|
||||
xacttest
|
||||
(122 rows)
|
||||
(127 rows)
|
||||
|
||||
SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer')));
|
||||
name
|
||||
|
@ -83,7 +83,7 @@ test: select_into select_distinct select_distinct_on select_implicit select_havi
|
||||
# ----------
|
||||
# Another group of parallel tests
|
||||
# ----------
|
||||
test: brin privileges security_label collate matview lock replica_identity rowsecurity
|
||||
test: brin gin gist spgist privileges security_label collate matview lock replica_identity rowsecurity
|
||||
|
||||
# ----------
|
||||
# Another group of parallel tests
|
||||
|
@ -95,6 +95,10 @@ test: update
|
||||
test: delete
|
||||
test: namespace
|
||||
test: prepared_xacts
|
||||
test: brin
|
||||
test: gin
|
||||
test: gist
|
||||
test: spgist
|
||||
test: privileges
|
||||
test: security_label
|
||||
test: collate
|
||||
@ -103,7 +107,6 @@ test: lock
|
||||
test: replica_identity
|
||||
test: rowsecurity
|
||||
test: alter_generic
|
||||
test: brin
|
||||
test: misc
|
||||
test: psql
|
||||
test: async
|
||||
|
@ -64,3 +64,31 @@ select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
|
||||
set enable_indexscan to false;
|
||||
set enable_bitmapscan to true;
|
||||
select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
|
||||
|
||||
--
|
||||
-- Test B-tree page deletion. In particular, deleting a non-leaf page.
|
||||
--
|
||||
|
||||
-- First create a tree that's at least four levels deep. The text inserted
|
||||
-- is long and poorly compressible. That way only a few index tuples fit on
|
||||
-- each page, allowing us to get a tall tree with fewer pages.
|
||||
create table btree_tall_tbl(id int4, t text);
|
||||
create index btree_tall_idx on btree_tall_tbl (id, t) with (fillfactor = 10);
|
||||
insert into btree_tall_tbl
|
||||
select g, g::text || '_' ||
|
||||
(select string_agg(md5(i::text), '_') from generate_series(1, 50) i)
|
||||
from generate_series(1, 100) g;
|
||||
|
||||
-- Delete most entries, and vacuum. This causes page deletions.
|
||||
delete from btree_tall_tbl where id < 950;
|
||||
vacuum btree_tall_tbl;
|
||||
|
||||
--
|
||||
-- Test B-tree insertion with a metapage update (XLOG_BTREE_INSERT_META
|
||||
-- WAL record type). This happens when a "fast root" page is split.
|
||||
--
|
||||
|
||||
-- The vacuum above should've turned the leaf page into a fast root. We just
|
||||
-- need to insert some rows to cause the fast root page to split.
|
||||
insert into btree_tall_tbl (id, t)
|
||||
select g, repeat('x', 100) from generate_series(1, 500) g;
|
||||
|
29
src/test/regress/sql/gin.sql
Normal file
29
src/test/regress/sql/gin.sql
Normal file
@ -0,0 +1,29 @@
|
||||
--
|
||||
-- Test GIN indexes.
|
||||
--
|
||||
-- There are other tests to test different GIN opclassed. This is for testing
|
||||
-- GIN itself.
|
||||
|
||||
-- Create and populate a test table with a GIN index.
|
||||
create table gin_test_tbl(i int4[]);
|
||||
create index gin_test_idx on gin_test_tbl using gin (i) with (fastupdate = on);
|
||||
insert into gin_test_tbl select array[1, 2, g] from generate_series(1, 20000) g;
|
||||
insert into gin_test_tbl select array[1, 3, g] from generate_series(1, 1000) g;
|
||||
|
||||
vacuum gin_test_tbl; -- flush the fastupdate buffers
|
||||
|
||||
-- Test vacuuming
|
||||
delete from gin_test_tbl where i @> array[2];
|
||||
vacuum gin_test_tbl;
|
||||
|
||||
-- Disable fastupdate, and do more insertions. With fastupdate enabled, most
|
||||
-- insertions (by flushing the list pages) cause page splits. Without
|
||||
-- fastupdate, we get more churn in the GIN data leaf pages, and exercise the
|
||||
-- recompression codepaths.
|
||||
alter index gin_test_idx set (fastupdate = off);
|
||||
|
||||
insert into gin_test_tbl select array[1, 2, g] from generate_series(1, 1000) g;
|
||||
insert into gin_test_tbl select array[1, 3, g] from generate_series(1, 1000) g;
|
||||
|
||||
delete from gin_test_tbl where i @> array[2];
|
||||
vacuum gin_test_tbl;
|
25
src/test/regress/sql/gist.sql
Normal file
25
src/test/regress/sql/gist.sql
Normal file
@ -0,0 +1,25 @@
|
||||
--
|
||||
-- Test GiST indexes.
|
||||
--
|
||||
-- There are other tests to test different GiST opclasses. This is for
|
||||
-- testing GiST code itself. Vacuuming in particular.
|
||||
|
||||
create table gist_point_tbl(id int4, p point);
|
||||
create index gist_pointidx on gist_point_tbl using gist(p);
|
||||
|
||||
-- Insert enough data to create a tree that's a couple of levels deep.
|
||||
insert into gist_point_tbl (id, p)
|
||||
select g, point(g*10, g*10) from generate_series(1, 10000) g;
|
||||
|
||||
insert into gist_point_tbl (id, p)
|
||||
select g+100000, point(g*10+1, g*10+1) from generate_series(1, 10000) g;
|
||||
|
||||
-- To test vacuum, delete some entries from all over the index.
|
||||
delete from gist_point_tbl where id % 2 = 1;
|
||||
|
||||
-- And also delete some concentration of values. (GiST doesn't currently
|
||||
-- attempt to delete pages even when they become empty, but if it did, this
|
||||
-- would exercise it)
|
||||
delete from gist_point_tbl where id < 10000;
|
||||
|
||||
vacuum gist_point_tbl;
|
50
src/test/regress/sql/spgist.sql
Normal file
50
src/test/regress/sql/spgist.sql
Normal file
@ -0,0 +1,50 @@
|
||||
--
|
||||
-- Test SP-GiST indexes.
|
||||
--
|
||||
-- There are other tests to test different SP-GiST opclasses. This is for
|
||||
-- testing SP-GiST code itself.
|
||||
|
||||
create table spgist_point_tbl(id int4, p point);
|
||||
create index spgist_point_idx on spgist_point_tbl using spgist(p);
|
||||
|
||||
-- Test vacuum-root operation. It gets invoked when the root is also a leaf,
|
||||
-- i.e. the index is very small.
|
||||
insert into spgist_point_tbl (id, p)
|
||||
select g, point(g*10, g*10) from generate_series(1, 10) g;
|
||||
delete from spgist_point_tbl where id < 5;
|
||||
vacuum spgist_point_tbl;
|
||||
|
||||
-- Insert more data, to make the index a few levels deep.
|
||||
insert into spgist_point_tbl (id, p)
|
||||
select g, point(g*10, g*10) from generate_series(1, 10000) g;
|
||||
insert into spgist_point_tbl (id, p)
|
||||
select g+100000, point(g*10+1, g*10+1) from generate_series(1, 10000) g;
|
||||
|
||||
-- To test vacuum, delete some entries from all over the index.
|
||||
delete from spgist_point_tbl where id % 2 = 1;
|
||||
|
||||
-- And also delete some concentration of values. (SP-GiST doesn't currently
|
||||
-- attempt to delete pages even when they become empty, but if it did, this
|
||||
-- would exercise it)
|
||||
delete from spgist_point_tbl where id < 10000;
|
||||
|
||||
vacuum spgist_point_tbl;
|
||||
|
||||
|
||||
-- The point opclass's choose method only uses the spgMatchNode action,
|
||||
-- so the other actions are not tested by the above. Create an index using
|
||||
-- text opclass, which uses the others actions.
|
||||
|
||||
create table spgist_text_tbl(id int4, t text);
|
||||
create index spgist_text_idx on spgist_text_tbl using spgist(t);
|
||||
|
||||
insert into spgist_text_tbl (id, t)
|
||||
select g, 'f' || repeat('o', 100) || g from generate_series(1, 10000) g
|
||||
union all
|
||||
select g, 'baaaaaaaaaaaaaar' || g from generate_series(1, 1000) g;
|
||||
|
||||
-- Do a lot of insertions that have to split an existing node. Hopefully
|
||||
-- one of these will cause the page to run out of space, causing the inner
|
||||
-- tuple to be moved to another page.
|
||||
insert into spgist_text_tbl (id, t)
|
||||
select -g, 'f' || repeat('o', 100-g) || 'surprise' from generate_series(1, 100) g;
|
Loading…
x
Reference in New Issue
Block a user