blob: 83aa84b8e694e20fcdc4419925cee45a962d0d44 [file]
-- We rely on pageinspect to perform white-box testing for summarization.
-- White-box tests are necessary to ensure that summarization is done
-- successfully (to avoid cases where ranges have brin data tuples without
-- values or where the range is not covered by the revmap etc)
-- Turn off sequential scans to force usage of BRIN indexes for scans.
SET enable_seqscan TO off;
SET
-- Ensure that we can summarize the last partial range in case it was extended
-- by another transaction, while summarization was in flight.
CREATE TABLE brin_range_extended_heap(i int) USING heap;
CREATE
CREATE INDEX ON brin_range_extended_heap USING brin(i) WITH (pages_per_range=5);
CREATE
-- Insert 9 blocks of data on 1 QE; 8 blocks full, 1 block with 1 tuple.
SELECT populate_pages('brin_range_extended_heap', 1, tid '(8, 0)');
populate_pages
----------------
(1 row)
-- Set up to suspend execution when will attempt to summarize the final partial
-- range below: [5, 8].
SELECT gp_inject_fault('summarize_last_partial_range', 'suspend', dbid) FROM gp_segment_configuration WHERE content = 1 AND role = 'p';
gp_inject_fault
-----------------
Success:
(1 row)
1&: SELECT brin_summarize_new_values('brin_range_extended_heap_i_idx'); <waiting ...>
SELECT gp_wait_until_triggered_fault('summarize_last_partial_range', 1, dbid) FROM gp_segment_configuration WHERE content = 1 AND role = 'p';
gp_wait_until_triggered_fault
-------------------------------
Success:
(1 row)
-- Sanity: We should only have 1 (placeholder) tuple inserted (for the final
-- partial range [5, 8]).
1U: SELECT blkno, brin_page_type(get_raw_page('brin_range_extended_heap_i_idx', blkno)) FROM generate_series(0, nblocks('brin_range_extended_heap_i_idx') - 1) blkno;
blkno | brin_page_type
-------+----------------
0 | meta
1 | revmap
2 | regular
(3 rows)
1U: SELECT * FROM brin_revmap_data(get_raw_page('brin_range_extended_heap_i_idx', 1)) WHERE pages != '(0,0)' order by 1;
pages
-------
(2,1)
(2,2)
(2 rows)
1U: SELECT * FROM brin_page_items(get_raw_page('brin_range_extended_heap_i_idx', 2), 'brin_range_extended_heap_i_idx') ORDER BY blknum, attnum;
itemoffset | blknum | attnum | allnulls | hasnulls | placeholder | value
------------+--------+--------+----------+----------+-------------+----------
1 | 0 | 1 | f | f | f | {1 .. 1}
2 | 5 | 1 | t | f | t |
(2 rows)
-- Extend the last partial range by 1 block.
SELECT populate_pages('brin_range_extended_heap', 20, tid '(9, 0)');
populate_pages
----------------
(1 row)
SELECT gp_inject_fault('summarize_last_partial_range', 'reset', dbid) FROM gp_segment_configuration WHERE content = 1 AND role = 'p';
gp_inject_fault
-----------------
Success:
(1 row)
1<: <... completed>
brin_summarize_new_values
---------------------------
1
(1 row)
-- Sanity: We should have the final full range [5, 9] summarized with both
-- existing tuples and the tuples from the concurrent insert.
1U: SELECT blkno, brin_page_type(get_raw_page('brin_range_extended_heap_i_idx', blkno)) FROM generate_series(0, nblocks('brin_range_extended_heap_i_idx') - 1) blkno;
blkno | brin_page_type
-------+----------------
0 | meta
1 | revmap
2 | regular
(3 rows)
1U: SELECT * FROM brin_revmap_data(get_raw_page('brin_range_extended_heap_i_idx', 1)) WHERE pages != '(0,0)' order by 1;
pages
-------
(2,1)
(2,2)
(2 rows)
1U: SELECT * FROM brin_page_items(get_raw_page('brin_range_extended_heap_i_idx', 2), 'brin_range_extended_heap_i_idx') ORDER BY blknum, attnum;
itemoffset | blknum | attnum | allnulls | hasnulls | placeholder | value
------------+--------+--------+----------+----------+-------------+-----------
1 | 0 | 1 | f | f | f | {1 .. 1}
2 | 5 | 1 | f | f | f | {1 .. 20}
(2 rows)
-- Test build/summarize with aborted rows.
CREATE TABLE brin_abort_heap(i int);
CREATE
CREATE INDEX ON brin_abort_heap USING brin(i) WITH (pages_per_range=1);
CREATE
BEGIN;
BEGIN
-- Create 3 blocks all on 1 QE, in 1 aoseg: 2 blocks full, 1 block with 1 tuple.
SELECT populate_pages('brin_abort_heap', 1, tid '(2, 0)');
populate_pages
----------------
(1 row)
ABORT;
ABORT
-- Sanity: There is 1 revmap page and 1 data page, with 1 range (summarized).
-- This first range being summarized highlights a difference with AO/CO tables.
1U: SELECT blkno, brin_page_type(get_raw_page('brin_abort_heap_i_idx', blkno)) FROM generate_series(0, nblocks('brin_abort_heap_i_idx') - 1) blkno;
blkno | brin_page_type
-------+----------------
0 | meta
1 | revmap
2 | regular
(3 rows)
1U: SELECT * FROM brin_revmap_data(get_raw_page('brin_abort_heap_i_idx', 1)) WHERE pages != '(0,0)' order by 1;
pages
-------
(2,1)
(1 row)
1U: SELECT * FROM brin_page_items(get_raw_page('brin_abort_heap_i_idx', 2), 'brin_abort_heap_i_idx') ORDER BY blknum, attnum;
itemoffset | blknum | attnum | allnulls | hasnulls | placeholder | value
------------+--------+--------+----------+----------+-------------+----------
1 | 0 | 1 | f | f | f | {1 .. 1}
(1 row)
-- Summarize over the aborted rows.
SELECT brin_summarize_new_values('brin_abort_heap_i_idx');
brin_summarize_new_values
---------------------------
2
(1 row)
-- Sanity: There is 1 revmap page and 1 data page, with 3 ranges. The two new
-- ranges have empty range tuples as a result of explicit summarization over
-- aborted tuples.
1U: SELECT blkno, brin_page_type(get_raw_page('brin_abort_heap_i_idx', blkno)) FROM generate_series(0, nblocks('brin_abort_heap_i_idx') - 1) blkno;
blkno | brin_page_type
-------+----------------
0 | meta
1 | revmap
2 | regular
(3 rows)
1U: SELECT * FROM brin_revmap_data(get_raw_page('brin_abort_heap_i_idx', 1)) WHERE pages != '(0,0)' order by 1;
pages
-------
(2,1)
(2,2)
(2,3)
(3 rows)
1U: SELECT * FROM brin_page_items(get_raw_page('brin_abort_heap_i_idx', 2), 'brin_abort_heap_i_idx') ORDER BY blknum, attnum;
itemoffset | blknum | attnum | allnulls | hasnulls | placeholder | value
------------+--------+--------+----------+----------+-------------+----------
1 | 0 | 1 | f | f | f | {1 .. 1}
2 | 1 | 1 | t | f | f |
3 | 2 | 1 | t | f | f |
(3 rows)
-- Sanity: Scan should only return the 1st block and ignore the blocks for which
-- we have the empty tuples, in the tidbitmap.
SELECT gp_inject_fault_infinite('brin_bitmap_page_added', 'skip', dbid) FROM gp_segment_configuration WHERE content = 1 AND role = 'p';
gp_inject_fault_infinite
--------------------------
Success:
(1 row)
SELECT count(*) FROM brin_abort_heap WHERE i = 1;
count
-------
0
(1 row)
SELECT gp_inject_fault('brin_bitmap_page_added', 'status', dbid) FROM gp_segment_configuration WHERE content = 1 AND role = 'p';
gp_inject_fault
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Success: fault name:'brin_bitmap_page_added' fault type:'skip' ddl statement:'' database name:'' table name:'' start occurrence:'1' end occurrence:'-1' extra arg:'0' fault injection state:'triggered' num times hit:'1'
(1 row)
SELECT gp_inject_fault('brin_bitmap_page_added', 'reset', dbid) FROM gp_segment_configuration WHERE content = 1 AND role = 'p';
gp_inject_fault
-----------------
Success:
(1 row)
-- Now, add some committed rows.
SELECT populate_pages('brin_abort_heap', 20, tid '(3, 0)');
populate_pages
----------------
(1 row)
-- Summarize to include the committed rows.
SELECT brin_summarize_new_values('brin_abort_heap_i_idx');
brin_summarize_new_values
---------------------------
1
(1 row)
-- Sanity: There is 1 revmap page and 1 data page, with 4 ranges. The first range
-- and the last two ranges (covering the committed rows) have non-empty tuples.
1U: SELECT blkno, brin_page_type(get_raw_page('brin_abort_heap_i_idx', blkno)) FROM generate_series(0, nblocks('brin_abort_heap_i_idx') - 1) blkno;
blkno | brin_page_type
-------+----------------
0 | meta
1 | revmap
2 | regular
(3 rows)
1U: SELECT * FROM brin_revmap_data(get_raw_page('brin_abort_heap_i_idx', 1)) WHERE pages != '(0,0)' order by 1;
pages
-------
(2,1)
(2,2)
(2,3)
(2,4)
(4 rows)
1U: SELECT * FROM brin_page_items(get_raw_page('brin_abort_heap_i_idx', 2), 'brin_abort_heap_i_idx') ORDER BY blknum, attnum;
itemoffset | blknum | attnum | allnulls | hasnulls | placeholder | value
------------+--------+--------+----------+----------+-------------+------------
1 | 0 | 1 | f | f | f | {1 .. 1}
2 | 1 | 1 | t | f | f |
3 | 2 | 1 | f | f | f | {20 .. 20}
4 | 3 | 1 | f | f | f | {20 .. 20}
(4 rows)
-- Sanity: Scan should only return the 2 blocks matching the predicate, in the tidbitmap.
SELECT gp_inject_fault_infinite('brin_bitmap_page_added', 'skip', dbid) FROM gp_segment_configuration WHERE content = 1 AND role = 'p';
gp_inject_fault_infinite
--------------------------
Success:
(1 row)
SELECT count(*) FROM brin_abort_heap WHERE i = 20;
count
-------
909
(1 row)
SELECT gp_inject_fault('brin_bitmap_page_added', 'status', dbid) FROM gp_segment_configuration WHERE content = 1 AND role = 'p';
gp_inject_fault
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Success: fault name:'brin_bitmap_page_added' fault type:'skip' ddl statement:'' database name:'' table name:'' start occurrence:'1' end occurrence:'-1' extra arg:'0' fault injection state:'triggered' num times hit:'2'
(1 row)
SELECT gp_inject_fault('brin_bitmap_page_added', 'reset', dbid) FROM gp_segment_configuration WHERE content = 1 AND role = 'p';
gp_inject_fault
-----------------
Success:
(1 row)
-- Drop and re-create the index to test build.
DROP INDEX brin_abort_heap_i_idx;
DROP
CREATE INDEX ON brin_abort_heap USING brin(i) WITH (pages_per_range=1);
CREATE
-- Sanity: There is 1 revmap page and 1 data page, with 4 ranges. Only the last
-- two ranges (covering the committed rows) have non-empty tuples.
1U: SELECT blkno, brin_page_type(get_raw_page('brin_abort_heap_i_idx', blkno)) FROM generate_series(0, nblocks('brin_abort_heap_i_idx') - 1) blkno;
blkno | brin_page_type
-------+----------------
0 | meta
1 | revmap
2 | regular
(3 rows)
1U: SELECT * FROM brin_revmap_data(get_raw_page('brin_abort_heap_i_idx', 1)) WHERE pages != '(0,0)' order by 1;
pages
-------
(2,1)
(2,2)
(2,3)
(2,4)
(4 rows)
1U: SELECT * FROM brin_page_items(get_raw_page('brin_abort_heap_i_idx', 2), 'brin_abort_heap_i_idx') ORDER BY blknum, attnum;
itemoffset | blknum | attnum | allnulls | hasnulls | placeholder | value
------------+--------+--------+----------+----------+-------------+------------
1 | 0 | 1 | t | f | f |
2 | 1 | 1 | t | f | f |
3 | 2 | 1 | f | f | f | {20 .. 20}
4 | 3 | 1 | f | f | f | {20 .. 20}
(4 rows)
-- Sanity: Scan should only return the 2 blocks matching the predicate, in the tidbitmap.
SELECT gp_inject_fault_infinite('brin_bitmap_page_added', 'skip', dbid) FROM gp_segment_configuration WHERE content = 1 AND role = 'p';
gp_inject_fault_infinite
--------------------------
Success:
(1 row)
SELECT count(*) FROM brin_abort_heap WHERE i = 20;
count
-------
909
(1 row)
SELECT gp_inject_fault('brin_bitmap_page_added', 'status', dbid) FROM gp_segment_configuration WHERE content = 1 AND role = 'p';
gp_inject_fault
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Success: fault name:'brin_bitmap_page_added' fault type:'skip' ddl statement:'' database name:'' table name:'' start occurrence:'1' end occurrence:'-1' extra arg:'0' fault injection state:'triggered' num times hit:'2'
(1 row)
SELECT gp_inject_fault('brin_bitmap_page_added', 'reset', dbid) FROM gp_segment_configuration WHERE content = 1 AND role = 'p';
gp_inject_fault
-----------------
Success:
(1 row)
RESET enable_seqscan;
RESET