blob: 6ea3f2f09f921ddd1008b4ebd6240f6802cce720 [file]
-- @Description Test scenario where a backend accesses AO table with a snapshot
-- that was acquired before vacuum.
--
DROP TABLE IF EXISTS ao;
DROP
CREATE TABLE ao (a INT, b INT) USING @amname@;
CREATE
INSERT INTO ao SELECT i as a, i as b FROM generate_series(1, 100) AS i;
INSERT 100
DELETE FROM ao WHERE a <= 30;
DELETE 30
create or replace function myfunc() returns bigint as $$ begin /* inside a function */ perform pg_sleep(10); /* inside a function */ return (select count(*) from ao); /* inside a function */ end; /* inside a function */ $$ stable language plpgsql;
CREATE
-- Launch function into the background.
1&: select myfunc(); <waiting ...>
-- Meanwhile, DELETE some rows and VACUUM. VACUUM should not recycle the
-- old tuple versions that are still needed by the function later. It will
-- compact the segfile, but keep the old segfile in AWAITING_DROP state.
2: DELETE FROM ao WHERE a <= 50;
DELETE 20
2: SELECT segno, tupcount, state FROM gp_ao_or_aocs_seg('ao');
segno | tupcount | state
-------+----------+-------
0 | 100 | 1
(1 row)
2: VACUUM ao;
VACUUM
2: SELECT segno, tupcount, state FROM gp_ao_or_aocs_seg('ao');
segno | tupcount | state
-------+----------+-------
0 | 100 | 2
1 | 50 | 1
(2 rows)
-- A second VACUUM shouldn't recycle them either.
2: VACUUM ao;
VACUUM
2: SELECT segno, tupcount, state FROM gp_ao_or_aocs_seg('ao');
segno | tupcount | state
-------+----------+-------
0 | 100 | 2
1 | 50 | 1
(2 rows)
1<: <... completed>
myfunc
--------
70
(1 row)
-- Now that the first transaction has finished, VACUUM can recycle.
2: VACUUM ao;
VACUUM
2: SELECT segno, tupcount, state FROM gp_ao_or_aocs_seg('ao');
segno | tupcount | state
-------+----------+-------
0 | 0 | 1
1 | 50 | 1
(2 rows)