--
-- Free Space Map test
--
SELECT current_setting('block_size')::integer AS blocksize,
current_setting('block_size')::integer / 8 AS strsize
\gset

CREATE TABLE fsm_check_size (num int, str text);

-- Fill 3 blocks with one record each
ALTER TABLE fsm_check_size SET (fillfactor=15);
INSERT INTO fsm_check_size SELECT i, rpad('', :strsize, 'a')
FROM generate_series(1,3) i;

-- There should be no FSM
VACUUM fsm_check_size;
SELECT pg_relation_size('fsm_check_size', 'main') / :blocksize AS heap_nblocks,
pg_relation_size('fsm_check_size', 'fsm') / :blocksize AS fsm_nblocks;

-- The following operations are for testing the functionality of the local
-- in-memory map. In particular, we want to be able to insert into some
-- other block than the one at the end of the heap, without using a FSM.

-- Fill most of the last block
ALTER TABLE fsm_check_size SET (fillfactor=100);
INSERT INTO fsm_check_size SELECT i, rpad('', :strsize, 'a')
FROM generate_series(101,105) i;

-- Make sure records can go into any block but the last one
ALTER TABLE fsm_check_size SET (fillfactor=30);

-- Insert large record and make sure it does not cause the relation to extend
INSERT INTO fsm_check_size VALUES (111, rpad('', :strsize, 'a'));

VACUUM fsm_check_size;
SELECT pg_relation_size('fsm_check_size', 'main') / :blocksize AS heap_nblocks,
pg_relation_size('fsm_check_size', 'fsm') / :blocksize AS fsm_nblocks;

-- Extend table with enough blocks to exceed the FSM threshold
DO $$
DECLARE curtid tid;
num int;
BEGIN
num = 11;
  LOOP
    INSERT INTO fsm_check_size VALUES (num, 'b') RETURNING ctid INTO curtid;
    EXIT WHEN curtid >= tid '(4, 0)';
    num = num + 1;
  END LOOP;
END;
$$;

VACUUM fsm_check_size;
SELECT pg_relation_size('fsm_check_size', 'fsm') / :blocksize AS fsm_nblocks;

-- Add long random string to extend TOAST table to 1 block
INSERT INTO fsm_check_size
VALUES(0, (SELECT string_agg(md5(chr(i)), '')
		   FROM generate_series(1, :blocksize / 100) i));

VACUUM fsm_check_size;
SELECT pg_relation_size(reltoastrelid, 'main') / :blocksize AS toast_nblocks,
pg_relation_size(reltoastrelid, 'fsm') / :blocksize AS toast_fsm_nblocks
FROM pg_class WHERE relname = 'fsm_check_size';

DROP TABLE fsm_check_size;
