1 CREATE EXTENSION pageinspect;
2 -- Use a temp table so that effects of VACUUM are predictable
3 CREATE TEMP TABLE test1 (a int, b int);
4 INSERT INTO test1 VALUES (16777217, 131584);
5 VACUUM (DISABLE_PAGE_SKIPPING) test1; -- set up FSM
6 -- The page contents can vary, so just test that it can be read
7 -- successfully, but don't keep the output.
8 SELECT octet_length(get_raw_page('test1', 'main', 0)) AS main_0;
14 SELECT octet_length(get_raw_page('test1', 'main', 1)) AS main_1;
15 ERROR: block number 1 is out of range for relation "test1"
16 SELECT octet_length(get_raw_page('test1', 'fsm', 0)) AS fsm_0;
22 SELECT octet_length(get_raw_page('test1', 'fsm', 1)) AS fsm_1;
28 SELECT octet_length(get_raw_page('test1', 'vm', 0)) AS vm_0;
34 SELECT octet_length(get_raw_page('test1', 'vm', 1)) AS vm_1;
35 ERROR: block number 1 is out of range for relation "test1"
36 SELECT octet_length(get_raw_page('test1', 'main', -1));
37 ERROR: invalid block number
38 SELECT octet_length(get_raw_page('xxx', 'main', 0));
39 ERROR: relation "xxx" does not exist
40 SELECT octet_length(get_raw_page('test1', 'xxx', 0));
41 ERROR: invalid fork name
42 HINT: Valid fork names are "main", "fsm", "vm", and "init".
43 SELECT get_raw_page('test1', 0) = get_raw_page('test1', 'main', 0);
49 SELECT pagesize, version FROM page_header(get_raw_page('test1', 0));
55 SELECT page_checksum(get_raw_page('test1', 0), 0) IS NOT NULL AS silly_checksum_test;
61 SELECT page_checksum(get_raw_page('test1', 0), -1);
62 ERROR: invalid block number
63 SELECT tuple_data_split('test1'::regclass, t_data, t_infomask, t_infomask2, t_bits)
64 FROM heap_page_items(get_raw_page('test1', 0));
66 -------------------------------
67 {"\\x01000001","\\x00020200"}
70 SELECT * FROM fsm_page_contents(get_raw_page('test1', 'fsm', 0));
90 -- If we freeze the only tuple on test1, the infomask should
91 -- always be the same in all test runs.
92 VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) test1;
93 SELECT t_infomask, t_infomask2, raw_flags, combined_flags
94 FROM heap_page_items(get_raw_page('test1', 0)),
95 LATERAL heap_tuple_infomask_flags(t_infomask, t_infomask2);
96 t_infomask | t_infomask2 | raw_flags | combined_flags
97 ------------+-------------+-----------------------------------------------------------+--------------------
98 2816 | 2 | {HEAP_XMIN_COMMITTED,HEAP_XMIN_INVALID,HEAP_XMAX_INVALID} | {HEAP_XMIN_FROZEN}
101 -- tests for decoding of combined flags
102 -- HEAP_XMAX_SHR_LOCK = (HEAP_XMAX_EXCL_LOCK | HEAP_XMAX_KEYSHR_LOCK)
103 SELECT * FROM heap_tuple_infomask_flags(x'0050'::int, 0);
104 raw_flags | combined_flags
105 ---------------------------------------------+----------------------
106 {HEAP_XMAX_KEYSHR_LOCK,HEAP_XMAX_EXCL_LOCK} | {HEAP_XMAX_SHR_LOCK}
109 -- HEAP_XMIN_FROZEN = (HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID)
110 SELECT * FROM heap_tuple_infomask_flags(x'0300'::int, 0);
111 raw_flags | combined_flags
112 -----------------------------------------+--------------------
113 {HEAP_XMIN_COMMITTED,HEAP_XMIN_INVALID} | {HEAP_XMIN_FROZEN}
116 -- HEAP_MOVED = (HEAP_MOVED_IN | HEAP_MOVED_OFF)
117 SELECT * FROM heap_tuple_infomask_flags(x'C000'::int, 0);
118 raw_flags | combined_flags
119 --------------------------------+----------------
120 {HEAP_MOVED_OFF,HEAP_MOVED_IN} | {HEAP_MOVED}
123 SELECT * FROM heap_tuple_infomask_flags(x'C000'::int, 0);
124 raw_flags | combined_flags
125 --------------------------------+----------------
126 {HEAP_MOVED_OFF,HEAP_MOVED_IN} | {HEAP_MOVED}
129 -- test all flags of t_infomask and t_infomask2
130 SELECT unnest(raw_flags)
131 FROM heap_tuple_infomask_flags(x'FFFF'::int, x'FFFF'::int) ORDER BY 1;
133 -----------------------
149 HEAP_XMAX_KEYSHR_LOCK
155 SELECT unnest(combined_flags)
156 FROM heap_tuple_infomask_flags(x'FFFF'::int, x'FFFF'::int) ORDER BY 1;
165 SELECT * FROM heap_tuple_infomask_flags(0, 0);
166 raw_flags | combined_flags
167 -----------+----------------
172 SELECT * FROM heap_tuple_infomask_flags(x'0010'::int, 0);
173 raw_flags | combined_flags
174 -------------------------+----------------
175 {HEAP_XMAX_KEYSHR_LOCK} | {}
179 -- check that using any of these functions with a partitioned table or index
181 create table test_partitioned (a int) partition by range (a);
182 create index test_partitioned_index on test_partitioned (a);
183 select get_raw_page('test_partitioned', 0); -- error about partitioned table
184 ERROR: cannot get raw page from relation "test_partitioned"
185 DETAIL: This operation is not supported for partitioned tables.
186 select get_raw_page('test_partitioned_index', 0); -- error about partitioned index
187 ERROR: cannot get raw page from relation "test_partitioned_index"
188 DETAIL: This operation is not supported for partitioned indexes.
189 -- a regular table which is a member of a partition set should work though
190 create table test_part1 partition of test_partitioned for values from ( 1 ) to (100);
191 select get_raw_page('test_part1', 0); -- get farther and error about empty table
192 ERROR: block number 0 is out of range for relation "test_part1"
193 drop table test_partitioned;
194 -- check null bitmap alignment for table whose number of attributes is multiple of 8
195 create table test8 (f1 int, f2 int, f3 int, f4 int, f5 int, f6 int, f7 int, f8 int);
196 insert into test8(f1, f8) values (x'7f00007f'::int, 0);
197 select t_bits, t_data from heap_page_items(get_raw_page('test8', 0));
199 ----------+--------------------
200 10000001 | \x7f00007f00000000
203 select tuple_data_split('test8'::regclass, t_data, t_infomask, t_infomask2, t_bits)
204 from heap_page_items(get_raw_page('test8', 0));
206 -------------------------------------------------------------
207 {"\\x7f00007f",NULL,NULL,NULL,NULL,NULL,NULL,"\\x00000000"}
211 -- Failure with incorrect page size
212 -- Suppress the DETAIL message, to allow the tests to work across various
215 SELECT fsm_page_contents('aaa'::bytea);
216 ERROR: invalid page size
217 SELECT page_checksum('bbb'::bytea, 0);
218 ERROR: invalid page size
219 SELECT page_header('ccc'::bytea);
220 ERROR: invalid page size
221 \set VERBOSITY default
222 -- Tests with all-zero pages.
223 SHOW block_size \gset
224 SELECT fsm_page_contents(decode(repeat('00', :block_size), 'hex'));
230 SELECT page_header(decode(repeat('00', :block_size), 'hex'));
232 -----------------------
233 (0/0,0,0,0,0,0,0,0,0)
236 SELECT page_checksum(decode(repeat('00', :block_size), 'hex'), 1);